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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 89e46d6d..8d2ebc7 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 7f70aba..630526f 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 0000000..47141c0 --- /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 v0.10.2 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 diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index 47141c0..1d01b30 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 v0.10.2 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 diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index 1d01b30..9f56913 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 v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 8d2ebc7..3e67e01 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 630526f..ee34741 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 0000000..ef6612e --- /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 v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 3e67e01..00b21db 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b4adc52..07d4bff 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 ef6612e..21e822e 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 v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 00b21db..ecae59c 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 21e822e..32710a9 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 32710a9..c31121e 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index c31121e..4f81943 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 4f81943..12bdcab 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 12bdcab..94b1655 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 94b1655..c44f281 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index c44f281..ad397f9 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index ad397f9..b1f2257 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b1f2257..6a357a8 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 6a357a8..f62f172 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index f62f172..4e0bd4e 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 4e0bd4e..b12f8b8 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -102,6 +102,19 @@ w83697hf_set_reg(unsigned char reg, unsigned char data) } 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) { w83697hf_unlock(); @@ -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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b12f8b8..b3dcc81 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 @@ -102,6 +102,12 @@ w83697hf_set_reg(unsigned char reg, unsigned char data) } static void +w83697hf_write_timeout(int timeout) +{ + w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ +} + +static void w83697hf_select_wdt(void) { w83697hf_unlock(); @@ -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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b3dcc81..2b3ce43 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 2b3ce43..1ea43bf 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -121,28 +121,13 @@ w83697hf_deselect_wdt(void) } 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 1ea43bf..78b6540 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 78b6540..21052de 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 v0.10.2 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 diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 21052de..7768b55 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 v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index ecae59c..847a260 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 v0.10.2 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 diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index b36a04a..d54d0ef 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 v0.10.2 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 diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index aaac94d..639d84f 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 v0.10.2 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 diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 639d84f..505aae9 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 v0.10.2 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 diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4c47c5b..c7309e9 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 v0.10.2 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 diff --git a/drivers/char/random.c b/drivers/char/random.c index 07f47a0..eb6b13f 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 1699eb9..7dd5c0e 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 v0.10.2 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 diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 09b06e6..7e3141f 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 v0.10.2 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 diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b6ef9ea..cbb9366 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 v0.10.2 From 4dfbb9d8c6cbfc32faa5c71145bd2a43e1f8237c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Oct 2006 01:45:14 -0400 Subject: Lockdep: add lockdep_set_class_and_subclass() and lockdep_set_subclass() This annotation makes it possible to assign a subclass on lock init. This annotation is meant to reduce the _nested() annotations by assigning a default subclass. One could do without this annotation and rely on lockdep_set_class() exclusively, but that would require a manual stack of struct lock_class_key objects. Signed-off-by: Peter Zijlstra Signed-off-by: Dmitry Torokhov diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 1314ca0..14fec2a 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -202,7 +202,7 @@ extern int lockdep_internal(void); */ extern void lockdep_init_map(struct lockdep_map *lock, const char *name, - struct lock_class_key *key); + struct lock_class_key *key, int subclass); /* * Reinitialize a lock key - for cases where there is special locking or @@ -211,9 +211,14 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name, * or they are too narrow (they suffer from a false class-split): */ #define lockdep_set_class(lock, key) \ - lockdep_init_map(&(lock)->dep_map, #key, key) + lockdep_init_map(&(lock)->dep_map, #key, key, 0) #define lockdep_set_class_and_name(lock, key, name) \ - lockdep_init_map(&(lock)->dep_map, name, key) + lockdep_init_map(&(lock)->dep_map, name, key, 0) +#define lockdep_set_class_and_subclass(lock, key, sub) \ + lockdep_init_map(&(lock)->dep_map, #key, key, sub) +#define lockdep_set_subclass(lock, sub) \ + lockdep_init_map(&(lock)->dep_map, #lock, \ + (lock)->dep_map.key, sub) /* * Acquire a lock. @@ -257,10 +262,12 @@ static inline int lockdep_internal(void) # define lock_release(l, n, i) do { } while (0) # define lockdep_init() do { } while (0) # define lockdep_info() do { } while (0) -# define lockdep_init_map(lock, name, key) do { (void)(key); } while (0) +# define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0) # define lockdep_set_class(lock, key) do { (void)(key); } while (0) # define lockdep_set_class_and_name(lock, key, name) \ do { (void)(key); } while (0) +#define lockdep_set_class_and_subclass(lock, key, sub) \ + do { (void)(key); } while (0) # define INIT_LOCKDEP # define lockdep_reset() do { debug_locks = 1; } while (0) # define lockdep_free_key_range(start, size) do { } while (0) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 4c05534..ba7156a 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -1177,7 +1177,7 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass) * itself, so actual lookup of the hash should be once per lock object. */ static inline struct lock_class * -register_lock_class(struct lockdep_map *lock, unsigned int subclass) +register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) { struct lockdep_subclass_key *key; struct list_head *hash_head; @@ -1249,7 +1249,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass) out_unlock_set: __raw_spin_unlock(&hash_lock); - if (!subclass) + if (!subclass || force) lock->class_cache = class; DEBUG_LOCKS_WARN_ON(class->subclass != subclass); @@ -1937,7 +1937,7 @@ void trace_softirqs_off(unsigned long ip) * Initialize a lock instance's lock-class mapping info: */ void lockdep_init_map(struct lockdep_map *lock, const char *name, - struct lock_class_key *key) + struct lock_class_key *key, int subclass) { if (unlikely(!debug_locks)) return; @@ -1957,6 +1957,8 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, lock->name = name; lock->key = key; lock->class_cache = NULL; + if (subclass) + register_lock_class(lock, subclass, 1); } EXPORT_SYMBOL_GPL(lockdep_init_map); @@ -1995,7 +1997,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, * Not cached yet or subclass? */ if (unlikely(!class)) { - class = register_lock_class(lock, subclass); + class = register_lock_class(lock, subclass, 0); if (!class) return 0; } diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c index e3203c6..1865164 100644 --- a/kernel/mutex-debug.c +++ b/kernel/mutex-debug.c @@ -91,7 +91,7 @@ void debug_mutex_init(struct mutex *lock, const char *name, * Make sure we are not reinitializing a held lock: */ debug_check_no_locks_freed((void *)lock, sizeof(*lock)); - lockdep_init_map(&lock->dep_map, name, key); + lockdep_init_map(&lock->dep_map, name, key, 0); #endif lock->owner = NULL; lock->magic = lock; diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index db4fed7..c4cfd6c 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -28,7 +28,7 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, * Make sure we are not reinitializing a held semaphore: */ debug_check_no_locks_freed((void *)sem, sizeof(*sem)); - lockdep_init_map(&sem->dep_map, name, key); + lockdep_init_map(&sem->dep_map, name, key, 0); #endif sem->activity = 0; spin_lock_init(&sem->wait_lock); diff --git a/lib/rwsem.c b/lib/rwsem.c index 901d0e7..cdb4e3d 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c @@ -19,7 +19,7 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, * Make sure we are not reinitializing a held semaphore: */ debug_check_no_locks_freed((void *)sem, sizeof(*sem)); - lockdep_init_map(&sem->dep_map, name, key); + lockdep_init_map(&sem->dep_map, name, key, 0); #endif sem->count = RWSEM_UNLOCKED_VALUE; spin_lock_init(&sem->wait_lock); diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index dafaf1d..b6c4f89 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -20,7 +20,7 @@ void __spin_lock_init(spinlock_t *lock, const char *name, * Make sure we are not reinitializing a held lock: */ debug_check_no_locks_freed((void *)lock, sizeof(*lock)); - lockdep_init_map(&lock->dep_map, name, key); + lockdep_init_map(&lock->dep_map, name, key, 0); #endif lock->raw_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; lock->magic = SPINLOCK_MAGIC; @@ -38,7 +38,7 @@ void __rwlock_init(rwlock_t *lock, const char *name, * Make sure we are not reinitializing a held lock: */ debug_check_no_locks_freed((void *)lock, sizeof(*lock)); - lockdep_init_map(&lock->dep_map, name, key); + lockdep_init_map(&lock->dep_map, name, key, 0); #endif lock->raw_lock = (raw_rwlock_t) __RAW_RW_LOCK_UNLOCKED; lock->magic = RWLOCK_MAGIC; diff --git a/net/core/sock.c b/net/core/sock.c index b77e155..d472db4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -823,7 +823,7 @@ static void inline sock_lock_init(struct sock *sk) af_family_slock_key_strings[sk->sk_family]); lockdep_init_map(&sk->sk_lock.dep_map, af_family_key_strings[sk->sk_family], - af_family_keys + sk->sk_family); + af_family_keys + sk->sk_family, 0); } /** -- cgit v0.10.2 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 diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index dcb16b5..e5b1b60 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 960fae3..480fdc5 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 3a697cc..b99c5ca 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 v0.10.2 From 9765d262b8230b735c4b2815b041c09a00833cf1 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 11 Oct 2006 22:29:51 +1000 Subject: [CRYPTO] api: fix crypto_alloc_base() return value This patch makes crypto_alloc_base() return proper return value. - If kzalloc() failure happens within __crypto_alloc_tfm(), crypto_alloc_base() returns NULL. But crypto_alloc_base() is supposed to return error code as pointer. So this patch makes it return -ENOMEM in that case. - crypto_alloc_base() is suppose to return -EINTR, if it is interrupted by signal. But it may not return -EINTR. Signed-off-by: Akinobu Mita Signed-off-by: Herbert Xu diff --git a/crypto/api.c b/crypto/api.c index 2e84d4b..4fb7fa4 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -331,7 +331,7 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags) tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags); tfm = kzalloc(tfm_size, GFP_KERNEL); if (tfm == NULL) - goto out; + goto out_err; tfm->__crt_alg = alg; @@ -355,6 +355,7 @@ cra_init_failed: crypto_exit_ops(tfm); out_free_tfm: kfree(tfm); +out_err: tfm = ERR_PTR(err); out: return tfm; @@ -414,14 +415,14 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) struct crypto_alg *alg; alg = crypto_alg_mod_lookup(alg_name, type, mask); - err = PTR_ERR(alg); - tfm = ERR_PTR(err); - if (IS_ERR(alg)) + if (IS_ERR(alg)) { + err = PTR_ERR(alg); goto err; + } tfm = __crypto_alloc_tfm(alg, 0); if (!IS_ERR(tfm)) - break; + return tfm; crypto_mod_put(alg); err = PTR_ERR(tfm); @@ -433,9 +434,9 @@ err: err = -EINTR; break; } - }; + } - return tfm; + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(crypto_alloc_base); -- cgit v0.10.2 From 3e082a910d217b2e7b186077ebf5a1126a68c62f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 28 Sep 2006 15:19:20 -0600 Subject: [SCSI] Add ability to scan scsi busses asynchronously Since it often takes around 20-30 seconds to scan a scsi bus, it's highly advantageous to do this in parallel with other things. The bulk of this patch is ensuring that devices don't change numbering, and that all devices are discovered prior to trying to start init. For those who build SCSI as modules, there's a new scsi_wait_scan module that will ensure all bus scans are finished. This patch only handles drivers which call scsi_scan_host. Fibre Channel, SAS, SATA, USB and Firewire all need additional work. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ff571f9..5a92ac0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1410,6 +1410,11 @@ and is between 256 and 4096 characters. It is defined in the file scsi_logging= [SCSI] + scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are + discovered. async scans them in kernel threads, + allowing boot to proceed. none ignores them, expecting + user space to do the scan. + selinux [SELINUX] Disable or enable SELinux at boot time. Format: { "0" | "1" } See security/selinux/Kconfig help text. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index bcca39c..a0a77fd 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -141,6 +141,8 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o # This goes last, so that "real" scsi devices probe earlier obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o +obj-$(CONFIG_SCSI) += scsi_wait_scan.o + scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_sysfs.o \ diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 5d023d4..f458c2f 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -39,6 +39,9 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) { }; #endif +/* scsi_scan.c */ +int scsi_complete_async_scans(void); + /* scsi_devinfo.c */ extern int scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index fd9e281..148e24c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -29,7 +29,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -87,6 +89,11 @@ module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); +static char scsi_scan_type[6] = "sync"; + +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); +MODULE_PARM_DESC(scan, "sync, async or none"); + /* * max_scsi_report_luns: the maximum number of LUNS that will be * returned from the REPORT LUNS command. 8 times this value must @@ -108,6 +115,68 @@ MODULE_PARM_DESC(inq_timeout, "Timeout (in seconds) waiting for devices to answer INQUIRY." " Default is 5. Some non-compliant devices need more."); +static DEFINE_SPINLOCK(async_scan_lock); +static LIST_HEAD(scanning_hosts); + +struct async_scan_data { + struct list_head list; + struct Scsi_Host *shost; + struct completion prev_finished; +}; + +/** + * scsi_complete_async_scans - Wait for asynchronous scans to complete + * + * Asynchronous scans add themselves to the scanning_hosts list. Once + * that list is empty, we know that the scans are complete. Rather than + * waking up periodically to check the state of the list, we pretend to be + * a scanning task by adding ourselves at the end of the list and going to + * sleep. When the task before us wakes us up, we take ourselves off the + * list and return. + */ +int scsi_complete_async_scans(void) +{ + struct async_scan_data *data; + + do { + if (list_empty(&scanning_hosts)) + return 0; + /* If we can't get memory immediately, that's OK. Just + * sleep a little. Even if we never get memory, the async + * scans will finish eventually. + */ + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + msleep(1); + } while (!data); + + data->shost = NULL; + init_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + /* Check that there's still somebody else on the list */ + if (list_empty(&scanning_hosts)) + goto done; + list_add_tail(&data->list, &scanning_hosts); + spin_unlock(&async_scan_lock); + + printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n"); + wait_for_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + list_del(&data->list); + done: + spin_unlock(&async_scan_lock); + + kfree(data); + return 0; +} + +#ifdef MODULE +/* Only exported for the benefit of scsi_wait_scan */ +EXPORT_SYMBOL_GPL(scsi_complete_async_scans); +#endif + /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command * @sdev: scsi device to send command to @@ -619,7 +688,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, - int *bflags) + int *bflags, int async) { /* * XXX do not save the inquiry, since it can change underneath us, @@ -795,7 +864,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, * register it and tell the rest of the kernel * about it. */ - if (scsi_sysfs_add_sdev(sdev) != 0) + if (!async && scsi_sysfs_add_sdev(sdev) != 0) return SCSI_SCAN_NO_RESPONSE; return SCSI_SCAN_LUN_PRESENT; @@ -964,7 +1033,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, goto out_free_result; } - res = scsi_add_lun(sdev, result, &bflags); + res = scsi_add_lun(sdev, result, &bflags, shost->async_scan); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { sdev->lockable = 0; @@ -1464,6 +1533,9 @@ void scsi_scan_target(struct device *parent, unsigned int channel, { struct Scsi_Host *shost = dev_to_shost(parent); + if (!shost->async_scan) + scsi_complete_async_scans(); + mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) __scsi_scan_target(parent, channel, id, lun, rescan); @@ -1509,6 +1581,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, "%s: <%u:%u:%u>\n", __FUNCTION__, channel, id, lun)); + if (!shost->async_scan) + scsi_complete_async_scans(); + if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) @@ -1529,14 +1604,130 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, return 0; } +static void scsi_sysfs_add_devices(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + shost_for_each_device(sdev, shost) { + if (scsi_sysfs_add_sdev(sdev) != 0) + scsi_destroy_sdev(sdev); + } +} + +/** + * scsi_prep_async_scan - prepare for an async scan + * @shost: the host which will be scanned + * Returns: a cookie to be passed to scsi_finish_async_scan() + * + * Tells the midlayer this host is going to do an asynchronous scan. + * It reserves the host's position in the scanning list and ensures + * that other asynchronous scans started after this one won't affect the + * ordering of the discovered devices. + */ +struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) +{ + struct async_scan_data *data; + + if (strncmp(scsi_scan_type, "sync", 4) == 0) + return NULL; + + if (shost->async_scan) { + printk("%s called twice for host %d", __FUNCTION__, + shost->host_no); + dump_stack(); + return NULL; + } + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto err; + data->shost = scsi_host_get(shost); + if (!data->shost) + goto err; + init_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + shost->async_scan = 1; + if (list_empty(&scanning_hosts)) + complete(&data->prev_finished); + list_add_tail(&data->list, &scanning_hosts); + spin_unlock(&async_scan_lock); + + return data; + + err: + kfree(data); + return NULL; +} + +/** + * scsi_finish_async_scan - asynchronous scan has finished + * @data: cookie returned from earlier call to scsi_prep_async_scan() + * + * All the devices currently attached to this host have been found. + * This function announces all the devices it has found to the rest + * of the system. + */ +void scsi_finish_async_scan(struct async_scan_data *data) +{ + struct Scsi_Host *shost; + + if (!data) + return; + + shost = data->shost; + if (!shost->async_scan) { + printk("%s called twice for host %d", __FUNCTION__, + shost->host_no); + dump_stack(); + return; + } + + wait_for_completion(&data->prev_finished); + + scsi_sysfs_add_devices(shost); + + spin_lock(&async_scan_lock); + shost->async_scan = 0; + list_del(&data->list); + if (!list_empty(&scanning_hosts)) { + struct async_scan_data *next = list_entry(scanning_hosts.next, + struct async_scan_data, list); + complete(&next->prev_finished); + } + spin_unlock(&async_scan_lock); + + scsi_host_put(shost); + kfree(data); +} + +static int do_scan_async(void *_data) +{ + struct async_scan_data *data = _data; + scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD, + SCAN_WILD_CARD, 0); + + scsi_finish_async_scan(data); + return 0; +} + /** * scsi_scan_host - scan the given adapter * @shost: adapter to scan **/ void scsi_scan_host(struct Scsi_Host *shost) { - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, - SCAN_WILD_CARD, 0); + struct async_scan_data *data; + + if (strncmp(scsi_scan_type, "none", 4) == 0) + return; + + data = scsi_prep_async_scan(shost); + if (!data) { + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, + SCAN_WILD_CARD, 0); + return; + } + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c new file mode 100644 index 0000000..8a63610 --- /dev/null +++ b/drivers/scsi/scsi_wait_scan.c @@ -0,0 +1,31 @@ +/* + * scsi_wait_scan.c + * + * Copyright (C) 2006 James Bottomley + * + * This is a simple module to wait until all the async scans are + * complete. The idea is to use it in initrd/initramfs scripts. You + * modprobe it after all the modprobes of the root SCSI drivers and it + * will wait until they have all finished scanning their busses before + * allowing the boot to proceed + */ + +#include +#include "scsi_priv.h" + +static int __init wait_scan_init(void) +{ + scsi_complete_async_scans(); + return 0; +} + +static void __exit wait_scan_exit(void) +{ +} + +MODULE_DESCRIPTION("SCSI wait for scans"); +MODULE_AUTHOR("James Bottomley"); +MODULE_LICENSE("GPL"); + +late_initcall(wait_scan_init); +module_exit(wait_scan_exit); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index b401c82..ebf31b1 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -223,13 +223,13 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, struct scsi_device *); /** - * shost_for_each_device - iterate over all devices of a host - * @sdev: iterator - * @host: host whiches devices we want to iterate over + * shost_for_each_device - iterate over all devices of a host + * @sdev: the &struct scsi_device to use as a cursor + * @shost: the &struct scsi_host to iterate over * - * This traverses over each devices of @shost. The devices have - * a reference that must be released by scsi_host_put when breaking - * out of the loop. + * Iterator that returns each device attached to @shost. This loop + * takes a reference on each device and releases it at the end. If + * you break out of the loop, you must call scsi_device_put(sdev). */ #define shost_for_each_device(sdev, shost) \ for ((sdev) = __scsi_iterate_devices((shost), NULL); \ @@ -237,17 +237,17 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, (sdev) = __scsi_iterate_devices((shost), (sdev))) /** - * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) - * @sdev: iterator - * @host: host whiches devices we want to iterate over + * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) + * @sdev: the &struct scsi_device to use as a cursor + * @shost: the &struct scsi_host to iterate over * - * This traverses over each devices of @shost. It does _not_ take a - * reference on the scsi_device, thus it the whole loop must be protected - * by shost->host_lock. + * Iterator that returns each device attached to @shost. It does _not_ + * take a reference on the scsi_device, so the whole loop must be + * protected by shost->host_lock. * - * Note: The only reason why drivers would want to use this is because - * they're need to access the device list in irq context. Otherwise you - * really want to use shost_for_each_device instead. + * Note: The only reason to use this is because you need to access the + * device list in interrupt context. Otherwise you really want to use + * shost_for_each_device instead. */ #define __shost_for_each_device(sdev, shost) \ list_for_each_entry((sdev), &((shost)->__devices), siblings) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 39c6f8c..ba5b3eb 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -552,6 +552,9 @@ struct Scsi_Host { /* task mgmt function in progress */ unsigned tmf_in_progress:1; + /* Asynchronous scan in progress */ + unsigned async_scan:1; + /* * Optional work queue to be utilized by the transport */ -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 505aae9..b6f29cb 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 v0.10.2 From 07646e217f473a3e6213f8228336a9046833d6aa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 11 Oct 2006 23:45:23 -0400 Subject: Lockdep: fix compile error in drivers/input/serio/serio.c lockdep_set_subclass() was missing in !LOCKDEP case Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 14fec2a..819f08f 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -268,6 +268,8 @@ static inline int lockdep_internal(void) do { (void)(key); } while (0) #define lockdep_set_class_and_subclass(lock, key, sub) \ do { (void)(key); } while (0) +#define lockdep_set_subclass(lock, sub) do { } while (0) + # define INIT_LOCKDEP # define lockdep_reset() do { debug_locks = 1; } while (0) # define lockdep_free_key_range(start, size) do { } while (0) -- cgit v0.10.2 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 diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 480fdc5..211943f 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 v0.10.2 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 diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 3f47ae5..a0af97e 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 v0.10.2 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 diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 90de5af..1dec00e 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 v0.10.2 From 2db02c0fe8519bd5985c6280896f4d719a6ae801 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Sep 2006 09:35:27 +0200 Subject: [WATCHDOG] includes for sample watchdog program. Add missing includes to sample watchdog program. Signed-off-by: Jean Delvare Signed-off-by: Wim Van Sebroeck diff --git a/Documentation/watchdog/src/watchdog-simple.c b/Documentation/watchdog/src/watchdog-simple.c index 85cf17c..47801bc 100644 --- a/Documentation/watchdog/src/watchdog-simple.c +++ b/Documentation/watchdog/src/watchdog-simple.c @@ -1,4 +1,6 @@ +#include #include +#include #include int main(int argc, const char *argv[]) { -- cgit v0.10.2 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 diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c7309e9..c2c9a86 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 v0.10.2 From 8f6cff98477edbcd8ae4976734ba7edd07bdd244 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 13 Oct 2006 12:42:36 -0500 Subject: JFS: pageno needs to be long diRead and diWrite are representing the page number as an unsigned int. This causes file system corruption on volumes larger than 16TB. Signed-off-by: Dave Kleikamp diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 489a3d6..ee9b473 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -318,7 +318,7 @@ int diRead(struct inode *ip) struct inomap *imap; int block_offset; int inodes_left; - uint pageno; + unsigned long pageno; int rel_inode; jfs_info("diRead: ino = %ld", ip->i_ino); @@ -606,7 +606,7 @@ int diWrite(tid_t tid, struct inode *ip) int block_offset; int inodes_left; struct metapage *mp; - uint pageno; + unsigned long pageno; int rel_inode; int dioffset; struct inode *ipimap; -- cgit v0.10.2 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 diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index c82e466..b430414 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 b983fc5..d96fc83 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 a2d6fd3..20e6825 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 2a1ac6c..df8595a 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 54fcd75..a4cdafc 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 cb1d94f..9b9f215 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 847a260..529f0a7 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 ee34741..3644049 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 4e7a114..0000000 --- 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 0000000..4e7a114 --- /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 v0.10.2 From 69f0304e174c765c624d75b79c35e49b7ba67ed4 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 5 Oct 2006 13:22:42 +0100 Subject: [ARM] 3888/1: add pxa27x SSP FSRT register bit definition This patch adds a register bit definition for the pxa27x SSP port Frame Sync Relative Timing (FSRT) bit. Signed-off-by: Liam Girdwood Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index f5cc65d..68731e0 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -1681,6 +1681,7 @@ #define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ #define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ +#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ #define SSPSP_DMYSTOP(x) (x << 23) /* Dummy Stop */ #define SSPSP_SFRMWDTH(x) (x << 16) /* Serial Frame Width */ #define SSPSP_SFRMDLY(x) (x << 9) /* Serial Frame Delay */ -- cgit v0.10.2 From 48e3becbee8906b44050c9300b668227b85f0c95 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Sun, 8 Oct 2006 19:52:30 +0100 Subject: [ARM] 3889/1: [Jornada7xx] Addition of correct SDRAM params into cpu-sa1110.c This adds correct sdram params for K4S281632B-1H and sets the jornada to use them by default. Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 6395977..90a4130 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -82,6 +82,14 @@ static struct sdram_params sdram_tbl[] __initdata = { .twr = 9, .refresh = 64000, .cas_latency = 3, + }, { /* Samsung K4S281632B-1H */ + .name = "K4S281632b-1H", + .rows = 12, + .tck = 10, + .trp = 20, + .twr = 10, + .refresh = 64000, + .cas_latency = 3, }, { /* Samsung KM416S4030CT */ .name = "KM416S4030CT", .rows = 13, @@ -366,6 +374,8 @@ static int __init sa1110_clk_init(void) if (machine_is_h3100()) name = "KM416S4030CT"; + if (machine_is_jornada720()) + name = "K4S281632B-1H"; } sdram = sa1110_find_sdram(name); -- cgit v0.10.2 From 8e25b84e76a0b2c117218405818cadd591512ff8 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Sun, 8 Oct 2006 20:00:53 +0100 Subject: [ARM] 3890/1: [Jornada7xx] Addition of MCU commands into jornada720.h This adds relevant MCU commands for the j7xx chipset. Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King diff --git a/include/asm-arm/arch-sa1100/jornada720.h b/include/asm-arm/arch-sa1100/jornada720.h index 1b8e8a3..3f37ca0 100644 --- a/include/asm-arm/arch-sa1100/jornada720.h +++ b/include/asm-arm/arch-sa1100/jornada720.h @@ -19,6 +19,20 @@ #define GPIO_JORNADA720_KEYBOARD_IRQ IRQ_GPIO0 #define GPIO_JORNADA720_MOUSE_IRQ IRQ_GPIO9 +/* MCU COMMANDS */ +#define MCU_GetBatteryData 0xc0 +#define MCU_GetScanKeyCode 0x90 +#define MCU_GetTouchSamples 0xa0 +#define MCU_GetContrast 0xD0 +#define MCU_SetContrast 0xD1 +#define MCU_GetBrightness 0xD2 +#define MCU_SetBrightness 0xD3 +#define MCU_ContrastOff 0xD8 +#define MCU_BrightnessOff 0xD9 +#define MCU_PWMOFF 0xDF +#define MCU_TxDummy 0x11 +#define MCU_ErrorCode 0x00 + #ifndef __ASSEMBLY__ void jornada720_mcu_init(void); -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 529f0a7..0187b11 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 v0.10.2 From 2326eb985b8844f44e150489c76f5cb56fa381b4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 15 Oct 2006 13:48:37 +0100 Subject: [ARM] Fix fallout from IRQ regs changes Some ARM platforms were still broken as a result of the IRQ register passing changes, mostly due to a missing linux/irq.h include. Signed-off-by: Russell King diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index fa5d497..1463330 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index ee80d62..142c33c 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -397,7 +397,7 @@ static void lubbock_mmc_poll(unsigned long data) if (LUB_IRQ_SET_CLR & (1 << 0)) mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE); else { - (void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data, NULL); + (void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data); enable_irq(LUBBOCK_SD_IRQ); } } diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c index 7899d3c..7c3289c 100644 --- a/arch/arm/oprofile/op_model_xscale.c +++ b/arch/arm/oprofile/op_model_xscale.c @@ -20,7 +20,8 @@ #include #include #include -#include +#include + #include #include "op_counter.h" -- cgit v0.10.2 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 diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index cb70970..befdd60 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 fd33c9c..5788dbc 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 8b18c00..28b2748 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 ca79b22..66121f6 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 v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 0187b11..d3e9998 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 3644049..e6a9f6f 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 0000000..a6d42cf --- /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 v0.10.2 From 18088748d2a493ce9f6adf0be7f833b04041807e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=E4nzer?= 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 diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 91b71e7..dffc193 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 v0.10.2 From e5267b4b376cfbdc4518abcc68d5a7fffb505638 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 10 Oct 2006 15:14:12 +1000 Subject: [POWERPC] Don't crash on cell with 2 BEs when !CONFIG_NUMA The SPU code will crash if CONFIG_NUMA is not set and SPUs are found on a non-0 node. This workaround will ignore those SPEs and just print an message in the kernel log. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ccfd0c4..d0fb959 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -781,6 +781,17 @@ static int __init create_spu(struct device_node *spe) if (!spu) goto out; + spu->node = find_spu_node_id(spe); + if (spu->node >= MAX_NUMNODES) { + printk(KERN_WARNING "SPE %s on node %d ignored," + " node number too big\n", spe->full_name, spu->node); + printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); + return -ENODEV; + } + spu->nid = of_node_to_nid(spe); + if (spu->nid == -1) + spu->nid = 0; + ret = spu_map_device(spu, spe); /* try old method */ if (ret) @@ -788,10 +799,6 @@ static int __init create_spu(struct device_node *spe) if (ret) goto out_free; - spu->node = find_spu_node_id(spe); - spu->nid = of_node_to_nid(spe); - if (spu->nid == -1) - spu->nid = 0; ret = spu_map_interrupts(spu, spe); if (ret) ret = spu_map_interrupts_old(spu, spe); -- cgit v0.10.2 From 654e4aee495bec1e4fc71ba1af25735da7cadc15 Mon Sep 17 00:00:00 2001 From: "Noguchi, Masato" Date: Tue, 10 Oct 2006 10:27:29 +0200 Subject: [POWERPC] spufs: fix support for read/write on cntl This fixes a memory leak introduced by "spufs: add support for read/write oncntl", which was missing a call to simple_attr_close. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index e0d7300..0de8e11 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -246,6 +246,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) static struct file_operations spufs_cntl_fops = { .open = spufs_cntl_open, + .release = simple_attr_close, .read = simple_attr_read, .write = simple_attr_write, .mmap = spufs_cntl_mmap, -- cgit v0.10.2 From ee4ea82c07fa8aa46037962ec3e8b40c5144b5eb Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 10 Oct 2006 11:53:26 -0500 Subject: [POWERPC] Add DOS partition table support to mpc834x_itx_defconfig The default configuration file for the MPC8349E-mITX reference board, mpc834x_itx_defconfig, did not include support for DOS partition table types. This support is necessary because the hard drive that comes with the ITX is formatted with this partition table type. Without this config option, no partitions on the drive can be mounted. Signed-off-by: Timur Tabi Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig index cd3535e..0561b73 100644 --- a/arch/powerpc/configs/mpc834x_itx_defconfig +++ b/arch/powerpc/configs/mpc834x_itx_defconfig @@ -1248,7 +1248,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y # CONFIG_LDM_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set -- cgit v0.10.2 From bb579cf1d413b930be0241987b848e0f0c1b292f Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 10 Oct 2006 14:37:29 -0700 Subject: [POWERPC] Off-by-one in /arch/ppc/platforms/mpc8* A find -iname \*.[ch] | xargs grep "> ARRAY_SIZE(" revealed several incorrect usages of ARRAY_SIZE in the mpc drivers. The last element in the array is always ARRAY_SIZE()-1, this patch modifies the bounds checks accordingly. Signed-off-by: Eric Sesterhenn Cc: Vitaly Bordug Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c index d7b3a6a..1f9ea368 100644 --- a/arch/ppc/platforms/mpc8272ads_setup.c +++ b/arch/ppc/platforms/mpc8272ads_setup.c @@ -196,7 +196,7 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev, bd_t* bi = (void*)__res; int fs_no = fsid_fcc1+pdev->id-1; - if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) { + if(fs_no >= ARRAY_SIZE(mpc82xx_enet_pdata)) { return; } @@ -222,7 +222,7 @@ static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev, int id = fs_uart_id_scc2fsid(idx); /* no need to alter anything if console */ - if ((id <= num) && (!pdev->dev.platform_data)) { + if ((id < num) && (!pdev->dev.platform_data)) { pinfo = &mpc8272_uart_pdata[id]; pinfo->uart_clk = bd->bi_intfreq; pdev->dev.platform_data = pinfo; diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c index 5f130dc..e95d2c1 100644 --- a/arch/ppc/platforms/mpc866ads_setup.c +++ b/arch/ppc/platforms/mpc866ads_setup.c @@ -259,7 +259,7 @@ static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) /* Get pointer to Communication Processor */ cp = cpmp; - if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) { + if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) { printk(KERN_ERR"No network-suitable #%d device on bus", fs_no); return; } @@ -305,7 +305,7 @@ static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev, int id = fs_uart_id_smc2fsid(idx); /* no need to alter anything if console */ - if ((id <= num) && (!pdev->dev.platform_data)) { + if ((id < num) && (!pdev->dev.platform_data)) { pinfo = &mpc866_uart_pdata[id]; pinfo->uart_clk = bd->bi_intfreq; pdev->dev.platform_data = pinfo; diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c index 0229314..f8161f3 100644 --- a/arch/ppc/platforms/mpc885ads_setup.c +++ b/arch/ppc/platforms/mpc885ads_setup.c @@ -263,7 +263,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) char *e; int i; - if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) { + if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) { printk(KERN_ERR"No network-suitable #%d device on bus", fs_no); return; } @@ -371,7 +371,7 @@ static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev, int id = fs_uart_id_smc2fsid(idx); /* no need to alter anything if console */ - if ((id <= num) && (!pdev->dev.platform_data)) { + if ((id < num) && (!pdev->dev.platform_data)) { pinfo = &mpc885_uart_pdata[id]; pinfo->uart_clk = bd->bi_intfreq; pdev->dev.platform_data = pinfo; -- cgit v0.10.2 From 7d2bd30f67e231920091d55d0fffc3a4bf43e68a Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Oct 2006 02:06:59 -0500 Subject: [POWERPC] ppc: Add missing calls to set_irq_regs In the timer_interrupt we were not calling set_irq_regs() and if we are profiling we will end up calling get_irq_regs(). This causes bad things to happen. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index d4b2cf7..18ee851 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -62,6 +62,7 @@ #include #include #include +#include #include @@ -129,6 +130,7 @@ void wakeup_decrementer(void) */ void timer_interrupt(struct pt_regs * regs) { + struct pt_regs *old_regs; int next_dec; unsigned long cpu = smp_processor_id(); unsigned jiffy_stamp = last_jiffy_stamp(cpu); @@ -137,6 +139,7 @@ void timer_interrupt(struct pt_regs * regs) if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); + old_regs = set_irq_regs(regs); irq_enter(); while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) { @@ -188,6 +191,7 @@ void timer_interrupt(struct pt_regs * regs) ppc_md.heartbeat(); irq_exit(); + set_irq_regs(old_regs); } /* -- cgit v0.10.2 From f5a37b066165f9938a93653f6940f3dc85ce751d Mon Sep 17 00:00:00 2001 From: Li Yang Date: Wed, 11 Oct 2006 19:04:22 +0800 Subject: [POWERPC] Fix MPC8360EMDS PB board support MPC8360EMDS PB support is broken as some code was missing in last submission. This patch adds missing code and makes MPC8360EMDS PB support working. Signed-off-by: Li Yang Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 0975e94..7edb6b4 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -32,6 +32,13 @@ config MPC834x_ITX Be aware that PCI initialization is the bootloader's responsiblilty. +config MPC8360E_PB + bool "Freescale MPC8360E PB" + select DEFAULT_UIMAGE + select QUICC_ENGINE + help + This option enables support for the MPC836x EMDS Processor Board. + endchoice config PPC_MPC832x @@ -46,4 +53,10 @@ config MPC834x select PPC_INDIRECT_PCI default y if MPC834x_SYS || MPC834x_ITX +config PPC_MPC836x + bool + select PPC_UDBG_16550 + select PPC_INDIRECT_PCI + default y if MPC8360E_PB + endmenu diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 9387a11..e60fd75 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -5,3 +5,4 @@ obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o +obj-$(CONFIG_MPC8360E_PB) += mpc8360e_pb.o diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c index c019190..1a523c8 100644 --- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c +++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -141,6 +142,24 @@ static void __init mpc8360_sys_setup_arch(void) #endif } +static int __init mpc8360_declare_of_platform_devices(void) +{ + struct device_node *np; + + for (np = NULL; (np = of_find_compatible_node(np, "network", + "ucc_geth")) != NULL;) { + int ucc_num; + char bus_id[BUS_ID_SIZE]; + + ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1; + snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num); + of_platform_device_create(np, bus_id, NULL); + } + + return 0; +} +device_initcall(mpc8360_declare_of_platform_devices); + void __init mpc8360_sys_init_IRQ(void) { -- cgit v0.10.2 From 8ba738c2bb8fb83c0c99f680444d3ffd4c178ca2 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Wed, 11 Oct 2006 19:27:57 +0800 Subject: [POWERPC] Add Makefile entry for MPC832x_mds support Add missing entry in Makefile for MPC832x MDS support. It also change white space to tab in MPC8360 entry. Signed-off-by: Li Yang Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index e60fd75..f1aa7e2 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -5,4 +5,5 @@ obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o -obj-$(CONFIG_MPC8360E_PB) += mpc8360e_pb.o +obj-$(CONFIG_MPC8360E_PB) += mpc8360e_pb.o +obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o -- cgit v0.10.2 From 60b2a46cd60c54bd6551ddfa01f0aab08ca58a5d Mon Sep 17 00:00:00 2001 From: Randy Vinson Date: Thu, 12 Oct 2006 13:36:23 -0700 Subject: [POWERPC] Fix IO Window Updates on P2P bridges. When update_bridge_base() updates the IO window on a PCI-to-PCI bridge, it fails to zero the upper 16 bits of the base and limit registers if the window size is less than 64K. This fixes it. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 9b49f86..0d9ff72 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -441,14 +441,14 @@ update_bridge_base(struct pci_bus *bus, int i) end = res->end - off; io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK; io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK; - if (end > 0xffff) { - pci_write_config_word(dev, PCI_IO_BASE_UPPER16, - start >> 16); - pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16, - end >> 16); + if (end > 0xffff) io_base_lo |= PCI_IO_RANGE_TYPE_32; - } else + else io_base_lo |= PCI_IO_RANGE_TYPE_16; + pci_write_config_word(dev, PCI_IO_BASE_UPPER16, + start >> 16); + pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16, + end >> 16); pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo); pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo); -- cgit v0.10.2 From 6c4841c2b6c32a134f9f36e5e08857138cc12b10 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Oct 2006 11:41:00 +1000 Subject: [POWERPC] Never panic when taking altivec exceptions from userspace At the moment we rely on a cpu feature bit or a firmware property to detect altivec. If we dont have either of these and the cpu does in fact support altivec we can cause a panic from userspace. It seems safer to always send a signal if we manage to get an 0xf20 exception from userspace. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index d9f10f2f..5ed4c2c 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -900,14 +900,13 @@ void kernel_fp_unavailable_exception(struct pt_regs *regs) void altivec_unavailable_exception(struct pt_regs *regs) { -#if !defined(CONFIG_ALTIVEC) if (user_mode(regs)) { /* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); return; } -#endif + printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); -- cgit v0.10.2 From 99f48610252b736908fa5bdea505a480368308d6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Oct 2006 12:13:12 +1000 Subject: [POWERPC] POWER6 has 6 PMCs Change ->num_pmcs to match the number of PMCs in POWER6. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 47a613c..95382f9 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -268,7 +268,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER6, .icache_bsize = 128, .dcache_bsize = 128, - .num_pmcs = 8, + .num_pmcs = 6, .oprofile_cpu_type = "ppc64/power6", .oprofile_type = PPC_OPROFILE_POWER4, .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, -- cgit v0.10.2 From 00ae36de49cc718d4122e1c8aac96fd1a5a2553c Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Oct 2006 12:17:16 +1000 Subject: [POWERPC] Better check in show_instructions Instead of just checking that an address is in the right range, use the provided __kernel_text_address() helper which covers both the kernel and module text sections. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 7b2f645..f3d4dd5 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -341,13 +341,6 @@ struct task_struct *__switch_to(struct task_struct *prev, static int instructions_to_print = 16; -#ifdef CONFIG_PPC64 -#define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \ - (REGION_ID(pc) != VMALLOC_REGION_ID)) -#else -#define BAD_PC(pc) ((pc) < KERNELBASE) -#endif - static void show_instructions(struct pt_regs *regs) { int i; @@ -366,7 +359,8 @@ static void show_instructions(struct pt_regs *regs) * bad address because the pc *should* only be a * kernel address. */ - if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) { + if (!__kernel_text_address(pc) || + __get_user(instr, (unsigned int __user *)pc)) { printk("XXXXXXXX "); } else { if (regs->nip == pc) -- cgit v0.10.2 From 284a940675a64df253e3dffc60b09bb4bbb149e4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Oct 2006 12:26:57 +1000 Subject: [POWERPC] Check for offline nodes in pci NUMA code During boot we bring up all memory and cpu nodes. Normally a PCI device will be in one of these online nodes, however in some weird setups it may not. We have only seen this in the lab but we may as well check for the case and fallback to -1 (all nodes). Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 78d3c0f..9bae8a5 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -199,8 +199,14 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) pci_setup_pci_controller(phb); phb->arch_data = dev; phb->is_dynamic = mem_init_done; - if (dev) - PHB_SET_NODE(phb, of_node_to_nid(dev)); + if (dev) { + int nid = of_node_to_nid(dev); + + if (nid < 0 || !node_online(nid)) + nid = -1; + + PHB_SET_NODE(phb, nid); + } return phb; } -- cgit v0.10.2 From be60358e948484e472c88bf8a2d77e644ff5ed83 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 13:53:32 -0700 Subject: [DECNET]: Use correct config option for routing by fwmark in compare_keys() Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index a2a43d8..491429c 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -269,7 +269,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | -#ifdef CONFIG_IP_ROUTE_FWMARK +#ifdef CONFIG_DECNET_ROUTE_FWMARK (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) | #endif (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | -- cgit v0.10.2 From f64ad5bb044326c6ebc6535d661c1abe78a0e5f2 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 14:07:52 -0700 Subject: [NETFILTER]: fix cut-and-paste error in exit functions Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index db9b896..39e1175 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -68,7 +68,7 @@ static int __init xt_nfqueue_init(void) static void __exit xt_nfqueue_fini(void) { - xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target)); + xt_unregister_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target)); } module_init(xt_nfqueue_init); diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 92a5726..a8f0305 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -147,7 +147,7 @@ static int __init xt_connmark_init(void) static void __exit xt_connmark_fini(void) { - xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); + xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); } module_init(xt_connmark_init); -- cgit v0.10.2 From f603b6ec50faabbabde53ae2e2ce774968524c40 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 14:08:11 -0700 Subject: [NETFILTER]: arp_tables: missing unregistration on module unload Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 17e1a68..0849f1c 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1196,6 +1196,8 @@ err1: static void __exit arp_tables_fini(void) { nf_unregister_sockopt(&arpt_sockopts); + xt_unregister_target(&arpt_error_target); + xt_unregister_target(&arpt_standard_target); xt_proto_fini(NF_ARP); } -- cgit v0.10.2 From a9f54596fa20be3edefaa0b24c8714edb945eeaa Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 14:08:26 -0700 Subject: [NETFILTER]: ipt_ECN/ipt_TOS: fix incorrect checksum update Even though the tos field is only a single byte large, the values need to be converted to net-endian for the checkum update so they are in the corrent byte position. Also fix incorrect endian annotations. Reported by Stephane Chazelas Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index 12a818a..1aa4517 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c @@ -28,7 +28,7 @@ static inline int set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) { struct iphdr *iph = (*pskb)->nh.iph; - __be16 oldtos; + u_int16_t oldtos; if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { if (!skb_make_writable(pskb, sizeof(struct iphdr))) @@ -37,8 +37,8 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) oldtos = iph->tos; iph->tos &= ~IPT_ECN_IP_MASK; iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); - iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos, - iph->check); + iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), + htons(iph->tos), iph->check); } return 1; } diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 6b8b14c..83b80b3 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c @@ -30,7 +30,7 @@ target(struct sk_buff **pskb, { const struct ipt_tos_target_info *tosinfo = targinfo; struct iphdr *iph = (*pskb)->nh.iph; - __be16 oldtos; + u_int16_t oldtos; if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { if (!skb_make_writable(pskb, sizeof(struct iphdr))) @@ -38,8 +38,8 @@ target(struct sk_buff **pskb, iph = (*pskb)->nh.iph; oldtos = iph->tos; iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; - iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos, - iph->check); + iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), + htons(iph->tos), iph->check); } return IPT_CONTINUE; } -- cgit v0.10.2 From c08de5d5308ae0d20290344551ddd9cea8ded661 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 14:08:41 -0700 Subject: [NETFILTER]: xt_CONNSECMARK: fix Kconfig dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONNSECMARK needs conntrack, add missing dependency to fix linking error with CONNSECMARK=y and CONNTRACK=m. Reported by Toralf Förster . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index ce94732..f619c65 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -209,7 +209,9 @@ config NETFILTER_XT_TARGET_SECMARK config NETFILTER_XT_TARGET_CONNSECMARK tristate '"CONNSECMARK" target support' - depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK) + depends on NETFILTER_XTABLES && \ + ((NF_CONNTRACK && NF_CONNTRACK_SECMARK) || \ + (IP_NF_CONNTRACK && IP_NF_CONNTRACK_SECMARK)) help The CONNSECMARK target copies security markings from packets to connections, and restores security markings from connections -- cgit v0.10.2 From 82b985434c5e9ceee772ca206889a856a7a4a200 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 12 Oct 2006 14:08:55 -0700 Subject: [NETFILTER]: Update MAINTAINERS entry Patches should go to myself CC netfilter-devel. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index a2b6d9f..208da3c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2049,11 +2049,13 @@ P: Marc Boucher P: James Morris P: Harald Welte P: Jozsef Kadlecsik -M: coreteam@netfilter.org +P: Patrick McHardy +M: kaber@trash.net +L: netfilter-devel@lists.netfilter.org +L: netfilter@lists.netfilter.org +L: coreteam@netfilter.org W: http://www.netfilter.org/ W: http://www.iptables.org/ -L: netfilter@lists.netfilter.org -L: netfilter-devel@lists.netfilter.org S: Supported NETLABEL -- cgit v0.10.2 From 9ea8cfd6aa74e710f0cb0731ecb9dee53fbebfb9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 12 Oct 2006 14:09:16 -0700 Subject: [NETFILTER]: ctnetlink: Remove debugging messages Remove (compilation-breaking) debugging messages introduced at early development stage. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 53b6dff..262d0d4 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -44,13 +44,6 @@ MODULE_LICENSE("GPL"); static char __initdata version[] = "0.90"; -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - - static inline int ctnetlink_dump_tuples_proto(struct sk_buff *skb, const struct ip_conntrack_tuple *tuple, @@ -398,7 +391,6 @@ nfattr_failure: static int ctnetlink_done(struct netlink_callback *cb) { - DEBUGP("entered %s\n", __FUNCTION__); if (cb->args[1]) ip_conntrack_put((struct ip_conntrack *)cb->args[1]); return 0; @@ -411,9 +403,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct ip_conntrack_tuple_hash *h; struct list_head *i; - DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, - cb->args[0], *id); - read_lock_bh(&ip_conntrack_lock); last = (struct ip_conntrack *)cb->args[1]; for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { @@ -452,7 +441,6 @@ out: if (last) ip_conntrack_put(last); - DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); return skb->len; } @@ -466,8 +454,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) { struct nfattr *tb[CTA_IP_MAX]; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_IP_MAX, attr); if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) @@ -481,8 +467,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) return -EINVAL; tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]); - DEBUGP("leaving\n"); - return 0; } @@ -503,8 +487,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, struct ip_conntrack_protocol *proto; int ret = 0; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) @@ -531,8 +513,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, struct nfattr *tb[CTA_TUPLE_MAX]; int err; - DEBUGP("entered %s\n", __FUNCTION__); - memset(tuple, 0, sizeof(*tuple)); nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); @@ -557,10 +537,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, else tuple->dst.dir = IP_CT_DIR_ORIGINAL; - DUMP_TUPLE(tuple); - - DEBUGP("leaving\n"); - return 0; } @@ -577,8 +553,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, struct nfattr *tb[CTA_PROTONAT_MAX]; struct ip_nat_protocol *npt; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) @@ -597,7 +571,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, ip_nat_proto_put(npt); - DEBUGP("leaving\n"); return 0; } @@ -613,8 +586,6 @@ ctnetlink_parse_nat(struct nfattr *nat, struct nfattr *tb[CTA_NAT_MAX]; int err; - DEBUGP("entered %s\n", __FUNCTION__); - memset(range, 0, sizeof(*range)); nfattr_parse_nested(tb, CTA_NAT_MAX, nat); @@ -640,7 +611,6 @@ ctnetlink_parse_nat(struct nfattr *nat, if (err < 0) return err; - DEBUGP("leaving\n"); return 0; } #endif @@ -650,8 +620,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) { struct nfattr *tb[CTA_HELP_MAX]; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_HELP_MAX, attr); if (!tb[CTA_HELP_NAME-1]) @@ -679,8 +647,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, struct ip_conntrack *ct; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_MAX, cta_min)) return -EINVAL; @@ -698,10 +664,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; h = ip_conntrack_find_get(&tuple, NULL); - if (!h) { - DEBUGP("tuple not found in conntrack hash\n"); + if (!h) return -ENOENT; - } ct = tuplehash_to_ctrack(h); @@ -716,7 +680,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, ct->timeout.function((unsigned long)ct); ip_conntrack_put(ct); - DEBUGP("leaving\n"); return 0; } @@ -731,8 +694,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, struct sk_buff *skb2 = NULL; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nlh->nlmsg_flags & NLM_F_DUMP) { struct nfgenmsg *msg = NLMSG_DATA(nlh); u32 rlen; @@ -770,11 +731,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; h = ip_conntrack_find_get(&tuple, NULL); - if (!h) { - DEBUGP("tuple not found in conntrack hash"); + if (!h) return -ENOENT; - } - DEBUGP("tuple found\n"); + ct = tuplehash_to_ctrack(h); err = -ENOMEM; @@ -795,7 +754,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) goto out; - DEBUGP("leaving\n"); return 0; free: @@ -866,8 +824,6 @@ ctnetlink_change_helper(struct ip_conntrack *ct, struct nfattr *cda[]) char *helpname; int err; - DEBUGP("entered %s\n", __FUNCTION__); - /* don't change helper of sibling connections */ if (ct->master) return -EINVAL; @@ -938,8 +894,6 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) { int err; - DEBUGP("entered %s\n", __FUNCTION__); - if (cda[CTA_HELP-1]) { err = ctnetlink_change_helper(ct, cda); if (err < 0) @@ -969,7 +923,6 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); #endif - DEBUGP("all done\n"); return 0; } @@ -981,8 +934,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[], struct ip_conntrack *ct; int err = -EINVAL; - DEBUGP("entered %s\n", __FUNCTION__); - ct = ip_conntrack_alloc(otuple, rtuple); if (ct == NULL || IS_ERR(ct)) return -ENOMEM; @@ -1017,7 +968,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[], if (ct->helper) ip_conntrack_helper_put(ct->helper); - DEBUGP("conntrack with id %u inserted\n", ct->id); return 0; err: @@ -1033,8 +983,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, struct ip_conntrack_tuple_hash *h = NULL; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_MAX, cta_min)) return -EINVAL; @@ -1058,7 +1006,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (h == NULL) { write_unlock_bh(&ip_conntrack_lock); - DEBUGP("no such conntrack, create new\n"); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) err = ctnetlink_create_conntrack(cda, &otuple, &rtuple); @@ -1074,7 +1021,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, /* We manipulate the conntrack inside the global conntrack table lock, * so there's no need to increase the refcount */ - DEBUGP("conntrack found\n"); err = -EEXIST; if (!(nlh->nlmsg_flags & NLM_F_EXCL)) err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda); @@ -1249,8 +1195,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct list_head *i; u_int32_t *id = (u_int32_t *) &cb->args[0]; - DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id); - read_lock_bh(&ip_conntrack_lock); list_for_each_prev(i, &ip_conntrack_expect_list) { exp = (struct ip_conntrack_expect *) i; @@ -1266,8 +1210,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) out: read_unlock_bh(&ip_conntrack_lock); - DEBUGP("leaving, last id=%llu\n", *id); - return skb->len; } @@ -1285,8 +1227,6 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, struct sk_buff *skb2; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) return -EINVAL; @@ -1437,8 +1377,6 @@ ctnetlink_create_expect(struct nfattr *cda[]) struct ip_conntrack *ct; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - /* caller guarantees that those three CTA_EXPECT_* exist */ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); if (err < 0) @@ -1490,8 +1428,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, struct ip_conntrack_expect *exp; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) return -EINVAL; @@ -1520,8 +1456,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, err = ctnetlink_change_expect(exp, cda); write_unlock_bh(&ip_conntrack_lock); - DEBUGP("leaving\n"); - return err; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 1721f7c..bd0156a 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -47,13 +47,6 @@ MODULE_LICENSE("GPL"); static char __initdata version[] = "0.93"; -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - - static inline int ctnetlink_dump_tuples_proto(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, @@ -410,7 +403,6 @@ static int ctnetlink_done(struct netlink_callback *cb) { if (cb->args[1]) nf_ct_put((struct nf_conn *)cb->args[1]); - DEBUGP("entered %s\n", __FUNCTION__); return 0; } @@ -425,9 +417,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; - DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, - cb->args[0], *id); - read_lock_bh(&nf_conntrack_lock); last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { @@ -471,7 +460,6 @@ out: if (last) nf_ct_put(last); - DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); return skb->len; } @@ -482,8 +470,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple) struct nf_conntrack_l3proto *l3proto; int ret = 0; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_IP_MAX, attr); l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); @@ -493,8 +479,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple) nf_ct_l3proto_put(l3proto); - DEBUGP("leaving\n"); - return ret; } @@ -510,8 +494,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, struct nf_conntrack_protocol *proto; int ret = 0; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) @@ -538,8 +520,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple, struct nfattr *tb[CTA_TUPLE_MAX]; int err; - DEBUGP("entered %s\n", __FUNCTION__); - memset(tuple, 0, sizeof(*tuple)); nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); @@ -566,10 +546,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple, else tuple->dst.dir = IP_CT_DIR_ORIGINAL; - NF_CT_DUMP_TUPLE(tuple); - - DEBUGP("leaving\n"); - return 0; } @@ -586,8 +562,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, struct nfattr *tb[CTA_PROTONAT_MAX]; struct ip_nat_protocol *npt; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) @@ -606,7 +580,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, ip_nat_proto_put(npt); - DEBUGP("leaving\n"); return 0; } @@ -622,8 +595,6 @@ ctnetlink_parse_nat(struct nfattr *nat, struct nfattr *tb[CTA_NAT_MAX]; int err; - DEBUGP("entered %s\n", __FUNCTION__); - memset(range, 0, sizeof(*range)); nfattr_parse_nested(tb, CTA_NAT_MAX, nat); @@ -649,7 +620,6 @@ ctnetlink_parse_nat(struct nfattr *nat, if (err < 0) return err; - DEBUGP("leaving\n"); return 0; } #endif @@ -659,8 +629,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) { struct nfattr *tb[CTA_HELP_MAX]; - DEBUGP("entered %s\n", __FUNCTION__); - nfattr_parse_nested(tb, CTA_HELP_MAX, attr); if (!tb[CTA_HELP_NAME-1]) @@ -690,8 +658,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, u_int8_t u3 = nfmsg->nfgen_family; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_MAX, cta_min)) return -EINVAL; @@ -709,10 +675,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; h = nf_conntrack_find_get(&tuple, NULL); - if (!h) { - DEBUGP("tuple not found in conntrack hash\n"); + if (!h) return -ENOENT; - } ct = nf_ct_tuplehash_to_ctrack(h); @@ -727,7 +691,6 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, ct->timeout.function((unsigned long)ct); nf_ct_put(ct); - DEBUGP("leaving\n"); return 0; } @@ -744,8 +707,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, u_int8_t u3 = nfmsg->nfgen_family; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nlh->nlmsg_flags & NLM_F_DUMP) { u32 rlen; @@ -779,11 +740,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, return err; h = nf_conntrack_find_get(&tuple, NULL); - if (!h) { - DEBUGP("tuple not found in conntrack hash"); + if (!h) return -ENOENT; - } - DEBUGP("tuple found\n"); + ct = nf_ct_tuplehash_to_ctrack(h); err = -ENOMEM; @@ -804,7 +763,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) goto out; - DEBUGP("leaving\n"); return 0; free: @@ -876,8 +834,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) char *helpname; int err; - DEBUGP("entered %s\n", __FUNCTION__); - if (!help) { /* FIXME: we need to reallocate and rehash */ return -EBUSY; @@ -954,8 +910,6 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[]) { int err; - DEBUGP("entered %s\n", __FUNCTION__); - if (cda[CTA_HELP-1]) { err = ctnetlink_change_helper(ct, cda); if (err < 0) @@ -985,7 +939,6 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif - DEBUGP("all done\n"); return 0; } @@ -997,8 +950,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[], struct nf_conn *ct; int err = -EINVAL; - DEBUGP("entered %s\n", __FUNCTION__); - ct = nf_conntrack_alloc(otuple, rtuple); if (ct == NULL || IS_ERR(ct)) return -ENOMEM; @@ -1028,7 +979,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[], add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); - DEBUGP("conntrack with id %u inserted\n", ct->id); return 0; err: @@ -1046,8 +996,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, u_int8_t u3 = nfmsg->nfgen_family; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_MAX, cta_min)) return -EINVAL; @@ -1071,7 +1019,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (h == NULL) { write_unlock_bh(&nf_conntrack_lock); - DEBUGP("no such conntrack, create new\n"); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) err = ctnetlink_create_conntrack(cda, &otuple, &rtuple); @@ -1087,7 +1034,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, /* We manipulate the conntrack inside the global conntrack table lock, * so there's no need to increase the refcount */ - DEBUGP("conntrack found\n"); err = -EEXIST; if (!(nlh->nlmsg_flags & NLM_F_EXCL)) err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda); @@ -1268,8 +1214,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; - DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id); - read_lock_bh(&nf_conntrack_lock); list_for_each_prev(i, &nf_conntrack_expect_list) { exp = (struct nf_conntrack_expect *) i; @@ -1287,8 +1231,6 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) out: read_unlock_bh(&nf_conntrack_lock); - DEBUGP("leaving, last id=%llu\n", *id); - return skb->len; } @@ -1308,8 +1250,6 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, u_int8_t u3 = nfmsg->nfgen_family; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) return -EINVAL; @@ -1460,8 +1400,6 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) struct nf_conn_help *help; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - /* caller guarantees that those three CTA_EXPECT_* exist */ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); if (err < 0) @@ -1516,8 +1454,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, u_int8_t u3 = nfmsg->nfgen_family; int err = 0; - DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) return -EINVAL; @@ -1546,8 +1482,6 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, err = ctnetlink_change_expect(exp, cda); write_unlock_bh(&nf_conntrack_lock); - DEBUGP("leaving\n"); - return err; } -- cgit v0.10.2 From 1a620698c29b5e18150ec04ace0609fb07d08d3e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 12 Oct 2006 14:45:38 -0700 Subject: [BRIDGE]: flush forwarding table when device carrier off Flush the forwarding table when carrier is lost. This helps for availability because we don't want to forward to a downed device and new packets may come in on other links. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 3a73b8c..d9f0486 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -128,7 +128,10 @@ void br_fdb_cleanup(unsigned long _data) mod_timer(&br->gc_timer, jiffies + HZ/10); } -void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) + +void br_fdb_delete_by_port(struct net_bridge *br, + const struct net_bridge_port *p, + int do_all) { int i; @@ -142,6 +145,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) if (f->dst != p) continue; + if (f->is_static && !do_all) + continue; /* * if multiple ports all have the same device address * then when one port is deleted, assign diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b1211d534..f753c40 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -163,7 +163,7 @@ static void del_nbp(struct net_bridge_port *p) br_stp_disable_port(p); spin_unlock_bh(&br->lock); - br_fdb_delete_by_port(br, p); + br_fdb_delete_by_port(br, p, 1); list_del_rcu(&p->list); @@ -448,7 +448,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) return 0; err2: - br_fdb_delete_by_port(br, p); + br_fdb_delete_by_port(br, p, 1); err1: kobject_del(&p->kobj); err0: diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c491fb2..74258d8 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -143,7 +143,7 @@ extern void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr); extern void br_fdb_cleanup(unsigned long arg); extern void br_fdb_delete_by_port(struct net_bridge *br, - struct net_bridge_port *p); + const struct net_bridge_port *p, int do_all); extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, const unsigned char *addr); extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 14cd025..d294224 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -113,6 +113,8 @@ void br_stp_disable_port(struct net_bridge_port *p) del_timer(&p->forward_delay_timer); del_timer(&p->hold_timer); + br_fdb_delete_by_port(br, p, 0); + br_configuration_update(br); br_port_state_selection(br); -- cgit v0.10.2 From 044a68ed8a692f643cf3c0a54c380a922584f34f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 11 Oct 2006 19:10:47 -0400 Subject: NetLabel: only deref the CIPSOv4 standard map fields when using standard mapping Fix several places in the CIPSO code where it was dereferencing fields which did not have valid pointers by moving those pointer dereferences into code blocks where the pointers are valid. Signed-off-by: Paul Moore Signed-off-by: James Morris diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index bde8cca..d19c9ac 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -773,13 +773,15 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, { int cat = -1; u32 bitmap_len_bits = bitmap_len * 8; - u32 cipso_cat_size = doi_def->map.std->cat.cipso_size; - u32 *cipso_array = doi_def->map.std->cat.cipso; + u32 cipso_cat_size; + u32 *cipso_array; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: return 0; case CIPSO_V4_MAP_STD: + cipso_cat_size = doi_def->map.std->cat.cipso_size; + cipso_array = doi_def->map.std->cat.cipso; for (;;) { cat = cipso_v4_bitmap_walk(bitmap, bitmap_len_bits, @@ -825,8 +827,8 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, u32 net_spot_max = 0; u32 host_clen_bits = host_cat_len * 8; u32 net_clen_bits = net_cat_len * 8; - u32 host_cat_size = doi_def->map.std->cat.local_size; - u32 *host_cat_array = doi_def->map.std->cat.local; + u32 host_cat_size; + u32 *host_cat_array; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: @@ -838,6 +840,8 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, memcpy(net_cat, host_cat, net_spot_max); return net_spot_max; case CIPSO_V4_MAP_STD: + host_cat_size = doi_def->map.std->cat.local_size; + host_cat_array = doi_def->map.std->cat.local; for (;;) { host_spot = cipso_v4_bitmap_walk(host_cat, host_clen_bits, @@ -893,8 +897,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, int net_spot = -1; u32 net_clen_bits = net_cat_len * 8; u32 host_clen_bits = host_cat_len * 8; - u32 net_cat_size = doi_def->map.std->cat.cipso_size; - u32 *net_cat_array = doi_def->map.std->cat.cipso; + u32 net_cat_size; + u32 *net_cat_array; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: @@ -903,6 +907,8 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, memcpy(host_cat, net_cat, net_cat_len); return net_cat_len; case CIPSO_V4_MAP_STD: + net_cat_size = doi_def->map.std->cat.cipso_size; + net_cat_array = doi_def->map.std->cat.cipso; for (;;) { net_spot = cipso_v4_bitmap_walk(net_cat, net_clen_bits, -- cgit v0.10.2 From bf0edf39296097f20c5fcc4919ed7d339194bd75 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 11 Oct 2006 19:10:48 -0400 Subject: NetLabel: better error handling involving mls_export_cat() Upon inspection it looked like the error handling for mls_export_cat() was rather poor. This patch addresses this by NULL'ing out kfree()'d pointers before returning and checking the return value of the function everywhere it is called. Signed-off-by: Paul Moore Signed-off-by: James Morris diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index cfed1d3..d539346 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -93,11 +93,15 @@ int ebitmap_export(const struct ebitmap *src, size_t bitmap_byte; unsigned char bitmask; + if (src->highbit == 0) { + *dst = NULL; + *dst_len = 0; + return 0; + } + bitmap_len = src->highbit / 8; if (src->highbit % 7) bitmap_len += 1; - if (bitmap_len == 0) - return -EINVAL; bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + sizeof(MAPTYPE), diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index c713af2..2cca8e2 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -640,8 +640,13 @@ int mls_export_cat(const struct context *context, { int rc = -EPERM; - if (!selinux_mls_enabled) + if (!selinux_mls_enabled) { + *low = NULL; + *low_len = 0; + *high = NULL; + *high_len = 0; return 0; + } if (low != NULL) { rc = ebitmap_export(&context->range.level[0].cat, @@ -661,10 +666,16 @@ int mls_export_cat(const struct context *context, return 0; export_cat_failure: - if (low != NULL) + if (low != NULL) { kfree(*low); - if (high != NULL) + *low = NULL; + *low_len = 0; + } + if (high != NULL) { kfree(*high); + *high = NULL; + *high_len = 0; + } return rc; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 18274b0..b1f6fb3 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2399,31 +2399,33 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) if (!ss_initialized) return 0; + netlbl_secattr_init(&secattr); + POLICY_RDLOCK; ctx = sidtab_search(&sidtab, sid); if (ctx == NULL) goto netlbl_socket_setsid_return; - netlbl_secattr_init(&secattr); secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], GFP_ATOMIC); mls_export_lvl(ctx, &secattr.mls_lvl, NULL); secattr.mls_lvl_vld = 1; - mls_export_cat(ctx, - &secattr.mls_cat, - &secattr.mls_cat_len, - NULL, - NULL); + rc = mls_export_cat(ctx, + &secattr.mls_cat, + &secattr.mls_cat_len, + NULL, + NULL); + if (rc != 0) + goto netlbl_socket_setsid_return; rc = netlbl_socket_setattr(sock, &secattr); if (rc == 0) sksec->nlbl_state = NLBL_LABELED; - netlbl_secattr_destroy(&secattr); - netlbl_socket_setsid_return: POLICY_RDUNLOCK; + netlbl_secattr_destroy(&secattr); return rc; } -- cgit v0.10.2 From ea614d7f4fb2d436b7a5ee490d1011615f6b38d5 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 11 Oct 2006 19:10:49 -0400 Subject: NetLabel: the CIPSOv4 passthrough mapping does not pass categories correctly The CIPSO passthrough mapping had a problem when sending categories which would cause no or incorrect categories to be sent on the wire with a packet. This patch fixes the problem which was a simple off-by-one bug. Signed-off-by: Paul Moore Signed-off-by: James Morris diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index d19c9ac..e2077a3 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -832,8 +832,8 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, switch (doi_def->type) { case CIPSO_V4_MAP_PASS: - net_spot_max = host_cat_len - 1; - while (net_spot_max > 0 && host_cat[net_spot_max] == 0) + net_spot_max = host_cat_len; + while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0) net_spot_max--; if (net_spot_max > net_cat_len) return -EINVAL; -- cgit v0.10.2 From 4663afe2c848e2abc8791202beecf40684f13eb4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Oct 2006 21:21:06 -0700 Subject: [NET]: reduce sizeof(struct inet_peer), cleanup, change in peer_check_expire() 1) shrink struct inet_peer on 64 bits platforms. diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 925573f..f13cc0c 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -19,7 +19,7 @@ struct inet_peer { struct inet_peer *avl_left, *avl_right; struct inet_peer *unused_next, **unused_prevp; - unsigned long dtime; /* the time of last use of not + __u32 dtime; /* the time of last use of not * referenced entries */ atomic_t refcnt; __be32 v4daddr; /* peer's address */ @@ -35,21 +35,8 @@ void inet_initpeers(void) __init; /* can be called with or without local BH being disabled */ struct inet_peer *inet_getpeer(__be32 daddr, int create); -extern spinlock_t inet_peer_unused_lock; -extern struct inet_peer **inet_peer_unused_tailp; /* can be called from BH context or outside */ -static inline void inet_putpeer(struct inet_peer *p) -{ - spin_lock_bh(&inet_peer_unused_lock); - if (atomic_dec_and_test(&p->refcnt)) { - p->unused_prevp = inet_peer_unused_tailp; - p->unused_next = NULL; - *inet_peer_unused_tailp = p; - inet_peer_unused_tailp = &p->unused_next; - p->dtime = jiffies; - } - spin_unlock_bh(&inet_peer_unused_lock); -} +extern void inet_putpeer(struct inet_peer *p); extern spinlock_t inet_peer_idlock; /* can be called with or without local BH being disabled */ diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index 2b1a54b..f072f38 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -94,10 +94,8 @@ int inet_peer_minttl = 120 * HZ; /* TTL under high load: 120 sec */ int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */ static struct inet_peer *inet_peer_unused_head; -/* Exported for inet_putpeer inline function. */ -struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head; -DEFINE_SPINLOCK(inet_peer_unused_lock); -#define PEER_MAX_CLEANUP_WORK 30 +static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head; +static DEFINE_SPINLOCK(inet_peer_unused_lock); static void peer_check_expire(unsigned long dummy); static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0); @@ -340,7 +338,8 @@ static int cleanup_once(unsigned long ttl) spin_lock_bh(&inet_peer_unused_lock); p = inet_peer_unused_head; if (p != NULL) { - if (time_after(p->dtime + ttl, jiffies)) { + __u32 delta = (__u32)jiffies - p->dtime; + if (delta < ttl) { /* Do not prune fresh entries. */ spin_unlock_bh(&inet_peer_unused_lock); return -1; @@ -432,7 +431,7 @@ out_free: /* Called with local BH disabled. */ static void peer_check_expire(unsigned long dummy) { - int i; + unsigned long now = jiffies; int ttl; if (peer_total >= inet_peer_threshold) @@ -441,7 +440,10 @@ static void peer_check_expire(unsigned long dummy) ttl = inet_peer_maxttl - (inet_peer_maxttl - inet_peer_minttl) / HZ * peer_total / inet_peer_threshold * HZ; - for (i = 0; i < PEER_MAX_CLEANUP_WORK && !cleanup_once(ttl); i++); + while (!cleanup_once(ttl)) { + if (jiffies != now) + break; + } /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime * interval depending on the total number of entries (more entries, @@ -455,3 +457,16 @@ static void peer_check_expire(unsigned long dummy) peer_total / inet_peer_threshold * HZ; add_timer(&peer_periodic_timer); } + +void inet_putpeer(struct inet_peer *p) +{ + spin_lock_bh(&inet_peer_unused_lock); + if (atomic_dec_and_test(&p->refcnt)) { + p->unused_prevp = inet_peer_unused_tailp; + p->unused_next = NULL; + *inet_peer_unused_tailp = p; + inet_peer_unused_tailp = &p->unused_next; + p->dtime = (__u32)jiffies; + } + spin_unlock_bh(&inet_peer_unused_lock); +} -- cgit v0.10.2 From 918049f0135854a1583f9b3b88f44dbf2b027329 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 Oct 2006 22:03:24 -0700 Subject: [XFRM]: Fix xfrm_state_num going negative. Missing counter bump when hashing in a new ACQ xfrm_state. Now that we have two spots to do the hash grow check, break it out into a helper function. Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 39b8bf3..84bbf84 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -614,6 +614,14 @@ out: return x; } +static void xfrm_hash_grow_check(int have_hash_collision) +{ + if (have_hash_collision && + (xfrm_state_hmask + 1) < xfrm_state_hashmax && + xfrm_state_num > xfrm_state_hmask) + schedule_work(&xfrm_hash_work); +} + static void __xfrm_state_insert(struct xfrm_state *x) { unsigned int h; @@ -642,10 +650,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) xfrm_state_num++; - if (x->bydst.next != NULL && - (xfrm_state_hmask + 1) < xfrm_state_hashmax && - xfrm_state_num > xfrm_state_hmask) - schedule_work(&xfrm_hash_work); + xfrm_hash_grow_check(x->bydst.next != NULL); } /* xfrm_state_lock is held */ @@ -753,6 +758,10 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re h = xfrm_src_hash(daddr, saddr, family); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); wake_up(&km_waitq); + + xfrm_state_num++; + + xfrm_hash_grow_check(x->bydst.next != NULL); } return x; -- cgit v0.10.2 From adaa70bbdfbc725e485179b06c8b23a20fbb7952 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 13 Oct 2006 15:01:03 -0700 Subject: [IPv6] rules: Use RT6_LOOKUP_F_HAS_SADDR and fix source based selectors Fixes rt6_lookup() to provide the source address in the flow and sets RT6_LOOKUP_F_HAS_SADDR whenever it is present in the flow. Avoids unnecessary prefix comparisons by checking for a prefix length first. Fixes the rule logic to not match packets if a source selector has been specified but no source address is available. Thanks to Kim Nordlund for working on this patch with me. Signed-off-by: Thomas Graf Acked-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index d8c1057..1896ecb 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -117,12 +117,15 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) { struct fib6_rule *r = (struct fib6_rule *) rule; - if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) + if (r->dst.plen && + !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) return 0; - if ((flags & RT6_LOOKUP_F_HAS_SADDR) && - !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) - return 0; + if (r->src.plen) { + if (!(flags & RT6_LOOKUP_F_HAS_SADDR) || + !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) + return 0; + } if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) return 0; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d6b4b4f..a1b0f07 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -529,13 +529,17 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, .nl_u = { .ip6_u = { .daddr = *daddr, - /* TODO: saddr */ }, }, }; struct dst_entry *dst; int flags = strict ? RT6_LOOKUP_F_IFACE : 0; + if (saddr) { + memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); + flags |= RT6_LOOKUP_F_HAS_SADDR; + } + dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); if (dst->error == 0) return (struct rt6_info *) dst; @@ -697,6 +701,7 @@ out2: void ip6_route_input(struct sk_buff *skb) { struct ipv6hdr *iph = skb->nh.ipv6h; + int flags = RT6_LOOKUP_F_HAS_SADDR; struct flowi fl = { .iif = skb->dev->ifindex, .nl_u = { @@ -711,7 +716,9 @@ void ip6_route_input(struct sk_buff *skb) }, .proto = iph->nexthdr, }; - int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0; + + if (rt6_need_strict(&iph->daddr)) + flags |= RT6_LOOKUP_F_IFACE; skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); } @@ -794,6 +801,9 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) if (rt6_need_strict(&fl->fl6_dst)) flags |= RT6_LOOKUP_F_IFACE; + if (!ipv6_addr_any(&fl->fl6_src)) + flags |= RT6_LOOKUP_F_HAS_SADDR; + return fib6_rule_lookup(fl, flags, ip6_pol_route_output); } @@ -1345,6 +1355,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, struct in6_addr *gateway, struct net_device *dev) { + int flags = RT6_LOOKUP_F_HAS_SADDR; struct ip6rd_flowi rdfl = { .fl = { .oif = dev->ifindex, @@ -1357,7 +1368,9 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, }, .gateway = *gateway, }; - int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0; + + if (rt6_need_strict(dest)) + flags |= RT6_LOOKUP_F_IFACE; return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); } -- cgit v0.10.2 From f1a95859a86fcdfd94f8b6dc3255d70d037e1caf Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Fri, 13 Oct 2006 15:03:34 -0700 Subject: [IPV6]: Remove bogus WARN_ON in Proxy-NA handling. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0304b5f..41a8a5f 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -967,8 +967,6 @@ static void ndisc_recv_na(struct sk_buff *skb) ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) { /* XXX: idev->cnf.prixy_ndp */ - WARN_ON(skb->dst != NULL && - ((struct rt6_info *)skb->dst)->rt6i_idev); goto out; } -- cgit v0.10.2 From 39c850863d5e36e72ecf9bc3537ec717bcce97fd Mon Sep 17 00:00:00 2001 From: Jan Dittmer Date: Fri, 13 Oct 2006 15:05:53 -0700 Subject: [IPV6] sit: Add missing MODULE_LICENSE This is missing the MODULE_LICENSE statements and taints the kernel upon loading. License is obvious from the beginning of the file. Signed-off-by: Jan Dittmer Signed-off-by: Joerg Roedel Signed-off-by: David S. Miller diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index dc5765b..b481a4d 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -853,3 +853,4 @@ int __init sit_init(void) module_init(sit_init); module_exit(sit_cleanup); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From e9c5702e3c5558dade169949abd730173e87ef9c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:30:22 +0200 Subject: [Bluetooth] Fix compat ioctl for BNEP, CMTP and HIDP There exists no attempt do deal with the fact that a structure with a uint32_t followed by a pointer is going to be different for 32-bit and 64-bit userspace. Any 32-bit process trying to use it will be failing with -EFAULT if it's lucky; suffering from having data dumped at a random address if it's not. Signed-off-by: David Woodhouse Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 28c5583..5d9d6f1 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long return 0; } +#ifdef CONFIG_COMPAT +static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + if (cmd == BNEPGETCONNLIST) { + struct bnep_connlist_req cl; + uint32_t uci; + int err; + + if (get_user(cl.cnum, (uint32_t __user *) arg) || + get_user(uci, (u32 __user *) (arg + 4))) + return -EFAULT; + + cl.ci = compat_ptr(uci); + + if (cl.cnum <= 0) + return -EINVAL; + + err = bnep_get_connlist(&cl); + + if (!err && put_user(cl.cnum, (uint32_t __user *) arg)) + err = -EFAULT; + + return err; + } + + return bnep_sock_ioctl(sock, cmd, arg); +} +#endif + static const struct proto_ops bnep_sock_ops = { - .family = PF_BLUETOOTH, - .owner = THIS_MODULE, - .release = bnep_sock_release, - .ioctl = bnep_sock_ioctl, - .bind = sock_no_bind, - .getname = sock_no_getname, - .sendmsg = sock_no_sendmsg, - .recvmsg = sock_no_recvmsg, - .poll = sock_no_poll, - .listen = sock_no_listen, - .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt, - .connect = sock_no_connect, - .socketpair = sock_no_socketpair, - .accept = sock_no_accept, - .mmap = sock_no_mmap + .family = PF_BLUETOOTH, + .owner = THIS_MODULE, + .release = bnep_sock_release, + .ioctl = bnep_sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = bnep_sock_compat_ioctl, +#endif + .bind = sock_no_bind, + .getname = sock_no_getname, + .sendmsg = sock_no_sendmsg, + .recvmsg = sock_no_recvmsg, + .poll = sock_no_poll, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .mmap = sock_no_mmap }; static struct proto bnep_proto = { diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 10ad7fd..0547edd 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -137,11 +138,43 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long return -EINVAL; } +#ifdef CONFIG_COMPAT +static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + if (cmd == CMTPGETCONNLIST) { + struct cmtp_connlist_req cl; + uint32_t uci; + int err; + + if (get_user(cl.cnum, (uint32_t __user *) arg) || + get_user(uci, (u32 __user *) (arg + 4))) + return -EFAULT; + + cl.ci = compat_ptr(uci); + + if (cl.cnum <= 0) + return -EINVAL; + + err = cmtp_get_connlist(&cl); + + if (!err && put_user(cl.cnum, (uint32_t __user *) arg)) + err = -EFAULT; + + return err; + } + + return cmtp_sock_ioctl(sock, cmd, arg); +} +#endif + static const struct proto_ops cmtp_sock_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .release = cmtp_sock_release, .ioctl = cmtp_sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = cmtp_sock_compat_ioctl, +#endif .bind = sock_no_bind, .getname = sock_no_getname, .sendmsg = sock_no_sendmsg, diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 099646e..6242446 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "hidp.h" @@ -143,11 +144,88 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long return -EINVAL; } +#ifdef CONFIG_COMPAT +struct compat_hidp_connadd_req { + int ctrl_sock; // Connected control socket + int intr_sock; // Connteted interrupt socket + __u16 parser; + __u16 rd_size; + compat_uptr_t rd_data; + __u8 country; + __u8 subclass; + __u16 vendor; + __u16 product; + __u16 version; + __u32 flags; + __u32 idle_to; + char name[128]; +}; + +static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + if (cmd == HIDPGETCONNLIST) { + struct hidp_connlist_req cl; + uint32_t uci; + int err; + + if (get_user(cl.cnum, (uint32_t __user *) arg) || + get_user(uci, (u32 __user *) (arg + 4))) + return -EFAULT; + + cl.ci = compat_ptr(uci); + + if (cl.cnum <= 0) + return -EINVAL; + + err = hidp_get_connlist(&cl); + + if (!err && put_user(cl.cnum, (uint32_t __user *) arg)) + err = -EFAULT; + + return err; + } else if (cmd == HIDPCONNADD) { + struct compat_hidp_connadd_req ca; + struct hidp_connadd_req __user *uca; + + uca = compat_alloc_user_space(sizeof(*uca)); + + if (copy_from_user(&ca, (void *) arg, sizeof(ca))) + return -EFAULT; + + if (put_user(ca.ctrl_sock, &uca->ctrl_sock) || + put_user(ca.intr_sock, &uca->intr_sock) || + put_user(ca.parser, &uca->parser) || + put_user(ca.rd_size, &uca->parser) || + put_user(compat_ptr(ca.rd_data), &uca->rd_data) || + put_user(ca.country, &uca->country) || + put_user(ca.subclass, &uca->subclass) || + put_user(ca.vendor, &uca->vendor) || + put_user(ca.product, &uca->product) || + put_user(ca.version, &uca->version) || + put_user(ca.flags, &uca->flags) || + put_user(ca.idle_to, &uca->idle_to) || + copy_to_user(&uca->name[0], &ca.name[0], 128)) + return -EFAULT; + + arg = (unsigned long) uca; + + /* Fall through. We don't actually write back any _changes_ + to the structure anyway, so there's no need to copy back + into the original compat version */ + } + + return hidp_sock_ioctl(sock, cmd, arg); +} +#endif + static const struct proto_ops hidp_sock_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .release = hidp_sock_release, .ioctl = hidp_sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = hidp_sock_compat_ioctl, +#endif .bind = sock_no_bind, .getname = sock_no_getname, .sendmsg = sock_no_sendmsg, -- cgit v0.10.2 From df5c37ea9a3820a9515d8204450aec00f48f8f88 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:30:45 +0200 Subject: [Bluetooth] Handle return values from driver core functions Some return values of the driver core register and create functions are not handled and so might cause unexpected problems. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 989b22d..c7e079d 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -242,10 +242,14 @@ static void add_conn(void *data) struct hci_conn *conn = data; int i; - device_register(&conn->dev); + if (device_register(&conn->dev) < 0) { + BT_ERR("Failed to register connection device"); + return; + } for (i = 0; conn_attrs[i]; i++) - device_create_file(&conn->dev, conn_attrs[i]); + if (device_create_file(&conn->dev, conn_attrs[i]) < 0) + BT_ERR("Failed to create connection attribute"); } void hci_conn_add_sysfs(struct hci_conn *conn) @@ -312,7 +316,8 @@ int hci_register_sysfs(struct hci_dev *hdev) return err; for (i = 0; bt_attrs[i]; i++) - device_create_file(dev, bt_attrs[i]); + if (device_create_file(dev, bt_attrs[i]) < 0) + BT_ERR("Failed to create device attribute"); return 0; } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index d56f60b..66fc621 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2216,7 +2216,8 @@ static int __init l2cap_init(void) goto error; } - class_create_file(bt_class, &class_attr_l2cap); + if (class_create_file(bt_class, &class_attr_l2cap) < 0) + BT_ERR("Failed to create L2CAP info file"); BT_INFO("L2CAP ver %s", VERSION); BT_INFO("L2CAP socket layer initialized"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 468df3b..ddc4e9d 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2058,7 +2058,8 @@ static int __init rfcomm_init(void) kernel_thread(rfcomm_run, NULL, CLONE_KERNEL); - class_create_file(bt_class, &class_attr_rfcomm_dlc); + if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) + BT_ERR("Failed to create RFCOMM info file"); rfcomm_init_sockets(); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 220fee0..530cc41 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -944,7 +944,8 @@ int __init rfcomm_init_sockets(void) if (err < 0) goto error; - class_create_file(bt_class, &class_attr_rfcomm); + if (class_create_file(bt_class, &class_attr_rfcomm) < 0) + BT_ERR("Failed to create RFCOMM info file"); BT_INFO("RFCOMM socket layer initialized"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 7714a2e..14b0f69 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -967,7 +967,8 @@ static int __init sco_init(void) goto error; } - class_create_file(bt_class, &class_attr_sco); + if (class_create_file(bt_class, &class_attr_sco) < 0) + BT_ERR("Failed to create SCO info file"); BT_INFO("SCO (Voice Link) ver %s", VERSION); BT_INFO("SCO socket layer initialized"); -- cgit v0.10.2 From e9c4bec63eac001651d6d30239dd4175cc3698ef Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:30:50 +0200 Subject: [Bluetooth] Make use of virtual devices tree The Bluetooth subsystem currently uses a platform device for devices with no parent. It is a better idea to use the new virtual devices tree for these. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index c7e079d..954eb74 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -299,11 +299,7 @@ int hci_register_sysfs(struct hci_dev *hdev) BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); dev->class = bt_class; - - if (hdev->parent) - dev->parent = hdev->parent; - else - dev->parent = &bt_platform->dev; + dev->parent = hdev->parent; strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); -- cgit v0.10.2 From 4c67bc74f016b0d360b8573e18969c0ff7926974 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:30:56 +0200 Subject: [Bluetooth] Support concurrent connect requests Most Bluetooth chips don't support concurrent connect requests, because this would involve a multiple baseband page with only one radio. In the case an upper layer like L2CAP requests a concurrent connect these chips return the error "Command Disallowed" for the second request. If this happens it the responsibility of the Bluetooth core to queue the request and try again after the previous connect attempt has been completed. Signed-off-by: Marcel Holtmann diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index df22efc..c0fc396 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -153,6 +153,7 @@ struct hci_conn { __u8 mode; __u8 type; __u8 out; + __u8 attempt; __u8 dev_class[3]; __u8 features[8]; __u16 interval; @@ -289,6 +290,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, return NULL; } +static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, + __u8 type, __u16 state) +{ + struct hci_conn_hash *h = &hdev->conn_hash; + struct list_head *p; + struct hci_conn *c; + + list_for_each(p, &h->list) { + c = list_entry(p, struct hci_conn, list); + if (c->type == type && c->state == state) + return c; + } + return NULL; +} + +void hci_acl_connect(struct hci_conn *conn); void hci_acl_disconn(struct hci_conn *conn, __u8 reason); void hci_add_sco(struct hci_conn *conn, __u16 handle); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 305a099..a91fee4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -48,7 +48,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.10" +#define VERSION "2.11" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 90e3a28..6cd5711 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -51,7 +51,7 @@ #define BT_DBG(D...) #endif -static void hci_acl_connect(struct hci_conn *conn) +void hci_acl_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn) conn->out = 1; conn->link_mode = HCI_LM_MASTER; + conn->attempt++; + memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; @@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn) cp.role_switch = 0x01; else cp.role_switch = 0x00; - + hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d43d0c8..65f0948 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -414,9 +414,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) if (status) { if (conn && conn->state == BT_CONNECT) { - conn->state = BT_CLOSED; - hci_proto_connect_cfm(conn, status); - hci_conn_del(conn); + if (status != 0x0c || conn->attempt > 2) { + conn->state = BT_CLOSED; + hci_proto_connect_cfm(conn, status); + hci_conn_del(conn); + } else + conn->state = BT_CONNECT2; } } else { if (!conn) { @@ -728,7 +731,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data; - struct hci_conn *conn; + struct hci_conn *conn, *pend; BT_DBG("%s", hdev->name); @@ -801,6 +804,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (ev->status) hci_conn_del(conn); + pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); + if (pend) + hci_acl_connect(pend); + hci_dev_unlock(hdev); } -- cgit v0.10.2 From e86070c83e9110e89800274385c013db602b1444 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:31:00 +0200 Subject: [Bluetooth] Disconnect HID interrupt channel first The Bluetooth HID specification demands that the interrupt channel shall be disconnected first. This is needed to pass the qualification tests. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 03b5dad..b2d6da6 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -510,11 +510,11 @@ static int hidp_session(void *arg) if (intr_sk->sk_state != BT_CONNECTED) wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ); - fput(session->ctrl_sock->file); + fput(session->intr_sock->file); wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ); - fput(session->intr_sock->file); + fput(session->ctrl_sock->file); __hidp_unlink_session(session); -- cgit v0.10.2 From b2cfcd75df77b80d9cc3fa84190a350dfa79eb93 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:31:05 +0200 Subject: [Bluetooth] Fix reference count when connection lookup fails When the connection lookup for the device structure fails, the reference count for the HCI device needs to be decremented. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 2312d05..4d3424c 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -528,12 +528,10 @@ static struct device *bnep_get_device(struct bnep_session *session) return NULL; conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); - if (!conn) - return NULL; hci_dev_put(hdev); - return &conn->dev; + return conn ? &conn->dev : NULL; } int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index b2d6da6..9a562cf 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -541,12 +541,10 @@ static struct device *hidp_get_device(struct hidp_session *session) return NULL; conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); - if (!conn) - return NULL; hci_dev_put(hdev); - return &conn->dev; + return conn ? &conn->dev : NULL; } static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 1958ad1..5833b87 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -172,12 +172,10 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev) return NULL; conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); - if (!conn) - return NULL; hci_dev_put(hdev); - return &conn->dev; + return conn ? &conn->dev : NULL; } static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) -- cgit v0.10.2 From cb19d9ea2ce2bcbe291d3d48e3501dc4f33ba627 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:31:10 +0200 Subject: [Bluetooth] Check if DLC is still attached to the TTY If the DLC device is no longer attached to the TTY device, then it makes no sense to go through with changing the termios settings. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 5833b87..b8e3a5f 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -765,6 +765,9 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) BT_DBG("tty %p termios %p", tty, old); + if (!dev) + return; + /* Handle turning off CRTSCTS */ if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) BT_DBG("Turning off CRTSCTS unsupported"); -- cgit v0.10.2 From 74da626a1098640ddc40c0e3481c0cd41e8ec1e9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:31:14 +0200 Subject: [Bluetooth] Add locking for bt_proto array manipulation The bt_proto array needs to be protected by some kind of locking to prevent a race condition between bt_sock_create and bt_sock_register. And in addition all calls to sk_alloc need to be made GFP_ATOMIC now. Signed-off-by: Masatake YAMATO Signed-off-by: Frederik Deweerdt Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index a91fee4..67df99e 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -53,36 +53,51 @@ /* Bluetooth sockets */ #define BT_MAX_PROTO 8 static struct net_proto_family *bt_proto[BT_MAX_PROTO]; +static DEFINE_RWLOCK(bt_proto_lock); int bt_sock_register(int proto, struct net_proto_family *ops) { + int err = 0; + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; + write_lock(&bt_proto_lock); + if (bt_proto[proto]) - return -EEXIST; + err = -EEXIST; + else + bt_proto[proto] = ops; - bt_proto[proto] = ops; - return 0; + write_unlock(&bt_proto_lock); + + return err; } EXPORT_SYMBOL(bt_sock_register); int bt_sock_unregister(int proto) { + int err = 0; + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; + write_lock(&bt_proto_lock); + if (!bt_proto[proto]) - return -ENOENT; + err = -ENOENT; + else + bt_proto[proto] = NULL; - bt_proto[proto] = NULL; - return 0; + write_unlock(&bt_proto_lock); + + return err; } EXPORT_SYMBOL(bt_sock_unregister); static int bt_sock_create(struct socket *sock, int proto) { - int err = 0; + int err; if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; @@ -92,11 +107,18 @@ static int bt_sock_create(struct socket *sock, int proto) request_module("bt-proto-%d", proto); } #endif + err = -EPROTONOSUPPORT; + + read_lock(&bt_proto_lock); + if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { err = bt_proto[proto]->create(sock, proto); module_put(bt_proto[proto]->owner); } + + read_unlock(&bt_proto_lock); + return err; } diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5d9d6f1..5563db1 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -214,7 +214,7 @@ static int bnep_sock_create(struct socket *sock, int protocol) if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1); + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1); if (!sk) return -ENOMEM; diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 0547edd..53295d3 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -205,7 +205,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol) if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1); + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1); if (!sk) return -ENOMEM; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 1a35d34..f26a9eb 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -618,7 +618,7 @@ static int hci_sock_create(struct socket *sock, int protocol) sock->ops = &hci_sock_ops; - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1); + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1); if (!sk) return -ENOMEM; diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 6242446..407fba4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -256,7 +256,7 @@ static int hidp_sock_create(struct socket *sock, int protocol) if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1); + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1); if (!sk) return -ENOMEM; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 66fc621..2b3dcb8 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -559,7 +559,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol) sock->ops = &l2cap_sock_ops; - sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL); + sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC); if (!sk) return -ENOMEM; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 530cc41..544d65b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -336,7 +336,8 @@ static int rfcomm_sock_create(struct socket *sock, int protocol) sock->ops = &rfcomm_sock_ops; - if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL))) + sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC); + if (!sk) return -ENOMEM; rfcomm_sock_init(sk, NULL); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 14b0f69..5d13d4f 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -452,7 +452,8 @@ static int sco_sock_create(struct socket *sock, int protocol) sock->ops = &sco_sock_ops; - if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL))) + sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC); + if (!sk) return -ENOMEM; sco_sock_init(sk, NULL); -- cgit v0.10.2 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 diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 67cdda4..5167517 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 v0.10.2 From d04c56f73c30a5e593202ecfcf25ed43d42363a2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 4 Oct 2006 16:47:49 +1000 Subject: [POWERPC] Lazy interrupt disabling for 64-bit machines This implements a lazy strategy for disabling interrupts. This means that local_irq_disable() et al. just clear the 'interrupts are enabled' flag in the paca. If an interrupt comes along, the interrupt entry code notices that interrupts are supposed to be disabled, and clears the EE bit in SRR1, clears the 'interrupts are hard-enabled' flag in the paca, and returns. This means that interrupts only actually get disabled in the processor when an interrupt comes along. When interrupts are enabled by local_irq_enable() et al., the code sets the interrupts-enabled flag in the paca, and then checks whether interrupts got hard-disabled. If so, it also sets the EE bit in the MSR to hard-enable the interrupts. This has the potential to improve performance, and also makes it easier to make a kernel that can boot on iSeries and on other 64-bit machines, since this lazy-disable strategy is very similar to the soft-disable strategy that iSeries already uses. This version renames paca->proc_enabled to paca->soft_enabled, and changes a couple of soft-disables in the kexec code to hard-disables, which should fix the crash that Michael Ellerman saw. This doesn't yet use a reserved CR field for the soft_enabled and hard_enabled flags. This applies on top of Stephen Rothwell's patches to make it possible to build a combined iSeries/other kernel. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d06f378..e965215 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -118,7 +118,8 @@ int main(void) DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); - DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); + DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); + DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 1af41f7..89b03c8 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs) if (!cpu_online(cpu)) return; - local_irq_disable(); + hard_irq_disable(); if (!cpu_isset(cpu, cpus_in_crash)) crash_save_this_cpu(regs, cpu); cpu_set(cpu, cpus_in_crash); @@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) * an SMP system. * The kernel is broken so disable interrupts. */ - local_irq_disable(); + hard_irq_disable(); for_each_irq(irq) { struct irq_desc *desc = irq_desc + irq; diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 748e74f..efda487 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -87,6 +87,10 @@ system_call_common: addi r9,r1,STACK_FRAME_OVERHEAD ld r11,exception_marker@toc(r2) std r11,-16(r9) /* "regshere" marker */ + li r10,1 + stb r10,PACASOFTIRQEN(r13) + stb r10,PACAHARDIRQEN(r13) + std r10,SOFTE(r1) #ifdef CONFIG_PPC_ISERIES BEGIN_FW_FTR_SECTION /* Hack for handling interrupts when soft-enabling on iSeries */ @@ -94,8 +98,6 @@ BEGIN_FW_FTR_SECTION andi. r10,r12,MSR_PR /* from kernel */ crand 4*cr0+eq,4*cr1+eq,4*cr0+eq beq hardware_interrupt_entry - lbz r10,PACAPROCENABLED(r13) - std r10,SOFTE(r1) END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif mfmsr r11 @@ -460,9 +462,9 @@ _GLOBAL(ret_from_except_lite) #endif restore: + ld r5,SOFTE(r1) #ifdef CONFIG_PPC_ISERIES BEGIN_FW_FTR_SECTION - ld r5,SOFTE(r1) cmpdi 0,r5,0 beq 4f /* Check for pending interrupts (iSeries) */ @@ -472,16 +474,16 @@ BEGIN_FW_FTR_SECTION beq+ 4f /* skip do_IRQ if no interrupts */ li r3,0 - stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ + stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */ ori r10,r10,MSR_EE mtmsrd r10 /* hard-enable again */ addi r3,r1,STACK_FRAME_OVERHEAD bl .do_IRQ b .ret_from_except_lite /* loop back and handle more */ - -4: stb r5,PACAPROCENABLED(r13) +4: END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif + stb r5,PACASOFTIRQEN(r13) ld r3,_MSR(r1) andi. r0,r3,MSR_RI @@ -538,25 +540,15 @@ do_work: /* Check that preempt_count() == 0 and interrupts are enabled */ lwz r8,TI_PREEMPT(r9) cmpwi cr1,r8,0 -#ifdef CONFIG_PPC_ISERIES -BEGIN_FW_FTR_SECTION ld r0,SOFTE(r1) cmpdi r0,0 -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) -#endif -BEGIN_FW_FTR_SECTION - andi. r0,r3,MSR_EE -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) crandc eq,cr1*4+eq,eq bne restore /* here we are preempting the current task */ 1: -#ifdef CONFIG_PPC_ISERIES -BEGIN_FW_FTR_SECTION li r0,1 - stb r0,PACAPROCENABLED(r13) -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) -#endif + stb r0,PACASOFTIRQEN(r13) + stb r0,PACAHARDIRQEN(r13) ori r10,r10,MSR_EE mtmsrd r10,1 /* reenable interrupts */ bl .preempt_schedule @@ -639,8 +631,7 @@ _GLOBAL(enter_rtas) /* There is no way it is acceptable to get here with interrupts enabled, * check it with the asm equivalent of WARN_ON */ - mfmsr r6 - andi. r0,r6,MSR_EE + lbz r0,PACASOFTIRQEN(r13) 1: tdnei r0,0 .section __bug_table,"a" .llong 1b,__LINE__ + 0x1000000, 1f, 2f @@ -649,7 +640,13 @@ _GLOBAL(enter_rtas) 1: .asciz __FILE__ 2: .asciz "enter_rtas" .previous - + + /* Hard-disable interrupts */ + mfmsr r6 + rldicl r7,r6,48,1 + rotldi r7,r7,16 + mtmsrd r7,1 + /* Unfortunately, the stack pointer and the MSR are also clobbered, * so they are saved in the PACA which allows us to restore * our original state after RTAS returns. diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 645c7f1..c93d9f3 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -35,9 +35,7 @@ #include #include -#ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE -#endif /* * We layout physical memory as follows: @@ -308,7 +306,9 @@ exception_marker: std r9,_LINK(r1); \ mfctr r10; /* save CTR in stackframe */ \ std r10,_CTR(r1); \ + lbz r10,PACASOFTIRQEN(r13); \ mfspr r11,SPRN_XER; /* save XER in stackframe */ \ + std r10,SOFTE(r1); \ std r11,_XER(r1); \ li r9,(n)+1; \ std r9,_TRAP(r1); /* set trap number */ \ @@ -343,6 +343,34 @@ label##_pSeries: \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) +#define MASKABLE_EXCEPTION_PSERIES(n, label) \ + . = n; \ + .globl label##_pSeries; \ +label##_pSeries: \ + HMT_MEDIUM; \ + mtspr SPRN_SPRG1,r13; /* save r13 */ \ + mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ + std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ + std r10,PACA_EXGEN+EX_R10(r13); \ + lbz r10,PACASOFTIRQEN(r13); \ + mfcr r9; \ + cmpwi r10,0; \ + beq masked_interrupt; \ + mfspr r10,SPRN_SPRG1; \ + std r10,PACA_EXGEN+EX_R13(r13); \ + std r11,PACA_EXGEN+EX_R11(r13); \ + std r12,PACA_EXGEN+EX_R12(r13); \ + clrrdi r12,r13,32; /* get high part of &label */ \ + mfmsr r10; \ + mfspr r11,SPRN_SRR0; /* save SRR0 */ \ + LOAD_HANDLER(r12,label##_common) \ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ + mtspr SPRN_SRR0,r12; \ + mfspr r12,SPRN_SRR1; /* and SRR1 */ \ + mtspr SPRN_SRR1,r10; \ + rfid; \ + b . /* prevent speculative execution */ + #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_iSeries; \ label##_iSeries: \ @@ -358,40 +386,32 @@ label##_iSeries: \ HMT_MEDIUM; \ mtspr SPRN_SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ - lbz r10,PACAPROCENABLED(r13); \ + lbz r10,PACASOFTIRQEN(r13); \ cmpwi 0,r10,0; \ beq- label##_iSeries_masked; \ EXCEPTION_PROLOG_ISERIES_2; \ b label##_common; \ -#ifdef DO_SOFT_DISABLE +#ifdef CONFIG_PPC_ISERIES #define DISABLE_INTS \ -BEGIN_FW_FTR_SECTION; \ - lbz r10,PACAPROCENABLED(r13); \ li r11,0; \ - std r10,SOFTE(r1); \ + stb r11,PACASOFTIRQEN(r13); \ +BEGIN_FW_FTR_SECTION; \ + stb r11,PACAHARDIRQEN(r13); \ +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ +BEGIN_FW_FTR_SECTION; \ mfmsr r10; \ - stb r11,PACAPROCENABLED(r13); \ ori r10,r10,MSR_EE; \ mtmsrd r10,1; \ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) -#define ENABLE_INTS \ -BEGIN_FW_FTR_SECTION; \ - lbz r10,PACAPROCENABLED(r13); \ - mfmsr r11; \ - std r10,SOFTE(r1); \ - ori r11,r11,MSR_EE; \ -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \ -BEGIN_FW_FTR_SECTION; \ - ld r12,_MSR(r1); \ - mfmsr r11; \ - rlwimi r11,r12,0,MSR_EE; \ -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ - mtmsrd r11,1 +#else +#define DISABLE_INTS \ + li r11,0; \ + stb r11,PACASOFTIRQEN(r13); \ + stb r11,PACAHARDIRQEN(r13) -#else /* hard enable/disable interrupts */ -#define DISABLE_INTS +#endif /* CONFIG_PPC_ISERIES */ #define ENABLE_INTS \ ld r12,_MSR(r1); \ @@ -399,8 +419,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ rlwimi r11,r12,0,MSR_EE; \ mtmsrd r11,1 -#endif - #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ .align 7; \ .globl label##_common; \ @@ -541,11 +559,11 @@ instruction_access_slb_pSeries: mfspr r12,SPRN_SRR1 /* and SRR1 */ b .slb_miss_realmode /* Rel. branch works in real mode */ - STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) + MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt) STD_EXCEPTION_PSERIES(0x600, alignment) STD_EXCEPTION_PSERIES(0x700, program_check) STD_EXCEPTION_PSERIES(0x800, fp_unavailable) - STD_EXCEPTION_PSERIES(0x900, decrementer) + MASKABLE_EXCEPTION_PSERIES(0x900, decrementer) STD_EXCEPTION_PSERIES(0xa00, trap_0a) STD_EXCEPTION_PSERIES(0xb00, trap_0b) @@ -597,7 +615,24 @@ system_call_pSeries: /*** pSeries interrupt support ***/ /* moved from 0xf00 */ - STD_EXCEPTION_PSERIES(., performance_monitor) + MASKABLE_EXCEPTION_PSERIES(., performance_monitor) + +/* + * An interrupt came in while soft-disabled; clear EE in SRR1, + * clear paca->hard_enabled and return. + */ +masked_interrupt: + stb r10,PACAHARDIRQEN(r13) + mtcrf 0x80,r9 + ld r9,PACA_EXGEN+EX_R9(r13) + mfspr r10,SPRN_SRR1 + rldicl r10,r10,48,1 /* clear MSR_EE */ + rotldi r10,r10,16 + mtspr SPRN_SRR1,r10 + ld r10,PACA_EXGEN+EX_R10(r13) + mfspr r13,SPRN_SPRG1 + rfid + b . .align 7 _GLOBAL(do_stab_bolted_pSeries) @@ -952,7 +987,8 @@ fast_exception_return: REST_8GPRS(2, r1) mfmsr r10 - clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ + rldicl r10,r10,48,1 /* clear EE */ + rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */ mtmsrd r10,1 mtspr SPRN_SRR1,r12 @@ -1877,11 +1913,16 @@ _GLOBAL(__secondary_start) /* enable MMU and jump to start_secondary */ LOAD_REG_ADDR(r3, .start_secondary_prolog) LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) -#ifdef DO_SOFT_DISABLE +#ifdef CONFIG_PPC_ISERIES BEGIN_FW_FTR_SECTION ori r4,r4,MSR_EE END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif +BEGIN_FW_FTR_SECTION + stb r7,PACASOFTIRQEN(r13) + stb r7,PACAHARDIRQEN(r13) +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) + mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 rfid @@ -2019,15 +2060,18 @@ _STATIC(start_here_common) /* Load up the kernel context */ 5: -#ifdef DO_SOFT_DISABLE -BEGIN_FW_FTR_SECTION li r5,0 - stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ + stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */ +#ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif +BEGIN_FW_FTR_SECTION + stb r5,PACAHARDIRQEN(r13) +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) bl .start_kernel diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 30de81d..ba31954 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) beqlr /* Go to NAP now */ + mfmsr r7 + rldicl r0,r7,48,1 + rotldi r0,r0,16 + mtmsrd r0,1 /* hard-disable interrupts */ + li r0,1 + stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */ + stb r0,PACAHARDIRQEN(r13) BEGIN_FTR_SECTION DSSALL sync @@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ ori r8,r8,_TLF_NAPPING /* so when we take an exception */ std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ - mfmsr r7 ori r7,r7,MSR_EE oris r7,r7,MSR_POW@h 1: sync diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5e37bf1..67b21a0 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -64,8 +64,9 @@ #include #include #include -#ifdef CONFIG_PPC_ISERIES +#ifdef CONFIG_PPC64 #include +#include #endif int __irq_offset_value; @@ -95,6 +96,27 @@ extern atomic_t ipi_sent; EXPORT_SYMBOL(irq_desc); int distribute_irqs = 1; + +void local_irq_restore(unsigned long en) +{ + get_paca()->soft_enabled = en; + if (!en) + return; + + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + if (get_paca()->lppaca_ptr->int_dword.any_int) + iseries_handle_interrupts(); + return; + } + + if (get_paca()->hard_enabled) + return; + /* need to hard-enable interrupts here */ + get_paca()->hard_enabled = en; + if ((int)mfspr(SPRN_DEC) < 0) + mtspr(SPRN_DEC, 1); + hard_irq_enable(); +} #endif /* CONFIG_PPC64 */ int show_interrupts(struct seq_file *p, void *v) diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 807193a..9179f07 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -49,6 +49,10 @@ #include #endif +#ifdef CONFIG_PPC64 +EXPORT_SYMBOL(local_irq_restore); +#endif + #ifdef CONFIG_PPC32 extern void transfer_to_handler(void); extern void do_IRQ(struct pt_regs *regs); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4b2e32e..b1b0cda 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -223,8 +223,8 @@ void early_setup_secondary(void) { struct paca_struct *lpaca = get_paca(); - /* Mark enabled in PACA */ - lpaca->proc_enabled = 0; + /* Mark interrupts enabled in PACA */ + lpaca->soft_enabled = 0; /* Initialize hash table for that CPU */ htab_initialize_secondary(); diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c index a220084..2430848 100644 --- a/arch/powerpc/platforms/iseries/ksyms.c +++ b/arch/powerpc/platforms/iseries/ksyms.c @@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4); EXPORT_SYMBOL(HvCall5); EXPORT_SYMBOL(HvCall6); EXPORT_SYMBOL(HvCall7); - -#ifdef CONFIG_SMP -EXPORT_SYMBOL(local_get_flags); -EXPORT_SYMBOL(local_irq_disable); -EXPORT_SYMBOL(local_irq_restore); -#endif diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index 7641fc7..2c6ff0f 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S @@ -19,39 +19,8 @@ .text -/* unsigned long local_save_flags(void) */ -_GLOBAL(local_get_flags) - lbz r3,PACAPROCENABLED(r13) - blr - -/* unsigned long local_irq_disable(void) */ -_GLOBAL(local_irq_disable) - lbz r3,PACAPROCENABLED(r13) - li r4,0 - stb r4,PACAPROCENABLED(r13) - blr /* Done */ - -/* void local_irq_restore(unsigned long flags) */ -_GLOBAL(local_irq_restore) - lbz r5,PACAPROCENABLED(r13) - /* Check if things are setup the way we want _already_. */ - cmpw 0,r3,r5 - beqlr - /* are we enabling interrupts? */ - cmpdi 0,r3,0 - stb r3,PACAPROCENABLED(r13) - beqlr - /* Check pending interrupts */ - /* A decrementer, IPI or PMC interrupt may have occurred - * while we were in the hypervisor (which enables) */ - ld r4,PACALPPACAPTR(r13) - ld r4,LPPACAANYINT(r4) - cmpdi r4,0 - beqlr - - /* - * Handle pending interrupts in interrupt context - */ +/* Handle pending interrupts in interrupt context */ +_GLOBAL(iseries_handle_interrupts) li r0,0x5555 sc blr diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index d403592..c4a1ab6 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -7,16 +7,30 @@ #ifdef __KERNEL__ #include +#include #include #include extern void timer_interrupt(struct pt_regs *); -#ifdef CONFIG_PPC_ISERIES +#ifdef CONFIG_PPC64 +#include + +static inline unsigned long local_get_flags(void) +{ + return get_paca()->soft_enabled; +} + +static inline unsigned long local_irq_disable(void) +{ + unsigned long flag = get_paca()->soft_enabled; + get_paca()->soft_enabled = 0; + barrier(); + return flag; +} -extern unsigned long local_get_flags(void); -extern unsigned long local_irq_disable(void); extern void local_irq_restore(unsigned long); +extern void iseries_handle_interrupts(void); #define local_irq_enable() local_irq_restore(1) #define local_save_flags(flags) ((flags) = local_get_flags()) @@ -24,17 +38,14 @@ extern void local_irq_restore(unsigned long); #define irqs_disabled() (local_get_flags() == 0) +#define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) +#define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) + #else #if defined(CONFIG_BOOKE) #define SET_MSR_EE(x) mtmsr(x) #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") -#elif defined(__powerpc64__) -#define SET_MSR_EE(x) __mtmsrd(x, 1) -#define local_irq_restore(flags) do { \ - __asm__ __volatile__("": : :"memory"); \ - __mtmsrd((flags), 1); \ -} while(0) #else #define SET_MSR_EE(x) mtmsr(x) #define local_irq_restore(flags) mtmsr(flags) @@ -81,7 +92,7 @@ static inline void local_irq_save_ptr(unsigned long *flags) #define local_irq_save(flags) local_irq_save_ptr(&flags) #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) -#endif /* CONFIG_PPC_ISERIES */ +#endif /* CONFIG_PPC64 */ #define mask_irq(irq) \ ({ \ diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0a4e5c9..0d3adc0 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -93,7 +93,8 @@ struct paca_struct { u64 stab_rr; /* stab/slb round-robin counter */ u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ - u8 proc_enabled; /* irq soft-enable flag */ + u8 soft_enabled; /* irq soft-enable flag */ + u8 hard_enabled; /* set if irqs are enabled in MSR */ u8 io_sync; /* writel() needs spin_unlock sync */ /* Stuff for accurate time accounting */ -- cgit v0.10.2 From 5b43d20a4d12d94f258bbbca5fa4df8ff8a17848 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 4 Oct 2006 23:41:41 -0500 Subject: [POWERPC] powerpc: Enable DEEPNAP power savings mode on 970MP Without this patch, on an idle system I get: cpu-power-0:21.638 cpu-power-1:27.102 cpu-power-2:29.343 cpu-power-3:25.784 Total: 103.8W With this patch: cpu-power-0:11.730 cpu-power-1:17.185 cpu-power-2:18.547 cpu-power-3:17.528 Total: 65.0W If I lower HZ to 100, I can get it as low as: cpu-power-0:10.938 cpu-power-1:16.021 cpu-power-2:17.245 cpu-power-3:16.145 Total: 60.2W Another (older) Quad G5 went from 54W to 39W at HZ=250. Coming back out of Deep Nap takes 40-70 cycles longer than coming back from just Nap (which already takes quite a while). I don't think it'll be a performance issue (interrupt latency on an idle system), but in case someone does measurements feel free to report them. Signed-off-by: Olof Johansson Acked-by: Michael Buesch Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S index 6525948..bf118c3 100644 --- a/arch/powerpc/kernel/cpu_setup_ppc970.S +++ b/arch/powerpc/kernel/cpu_setup_ppc970.S @@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970) rldimi r0,r11,52,8 /* set NAP and DPM */ li r11,0 rldimi r0,r11,32,31 /* clear EN_ATTN */ + b load_hids /* Jump to shared code */ + + +_GLOBAL(__setup_cpu_ppc970MP) + /* Do nothing if not running in HV mode */ + mfmsr r0 + rldicl. r0,r0,4,63 + beqlr + + mfspr r0,SPRN_HID0 + li r11,0x15 /* clear DOZE and SLEEP */ + rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */ + li r11,0 + rldimi r0,r11,32,31 /* clear EN_ATTN */ + +load_hids: mtspr SPRN_HID0,r0 mfspr r0,SPRN_HID0 mfspr r0,SPRN_HID0 diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 95382f9..f02b402 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -41,6 +41,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec); #endif /* CONFIG_PPC32 */ #ifdef CONFIG_PPC64 extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); extern void __restore_cpu_ppc970(void); #endif /* CONFIG_PPC64 */ @@ -221,7 +222,7 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_ppc970, + .cpu_setup = __setup_cpu_ppc970MP, .cpu_restore = __restore_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = PPC_OPROFILE_POWER4, -- cgit v0.10.2 From 0f03a43b8f0fc221986a46654282ec6a1e8c6d45 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 3 Oct 2006 16:57:44 +1000 Subject: [POWERPC] Remove todc code from ARCH=powerpc Apparently we've copied the todc drivers, for various RTCs used in embedded machines from ARCH=ppc to ARCH=powerpc, despite the fact that it's never used in the latter. This patch removes it. If we ever need these drivers (which we probably shouldn't now the RTC class stuff is in), we can transfer them one by one from ARCH=ppc, removing from the hideous abomination which is the todc "infrastructure". Signed-off-by: David Gibson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8b69104..7107d47 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -594,12 +594,6 @@ config TAU_AVERAGE If in doubt, say N here. -config PPC_TODC - depends on EMBEDDED6xx - bool "Generic Time-of-day Clock (TODC) support" - ---help--- - This adds support for many TODC/RTC chips. - endmenu source arch/powerpc/platforms/embedded6xx/Kconfig diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 91f052d..f15af0e 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o -obj-$(CONFIG_PPC_TODC) += todc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c deleted file mode 100644 index 0a65980..0000000 --- a/arch/powerpc/sysdev/todc.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 - * Real Time Clocks/Timekeepers. - * - * Author: Mark A. Greer - * - * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Depending on the hardware on your board and your board design, the - * RTC/NVRAM may be accessed either directly (like normal memory) or via - * address/data registers. If your board uses the direct method, set - * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and - * 'nvram_as1' NULL. If your board uses address/data regs to access nvram, - * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the - * address of the upper byte (leave NULL if using mc146818), and set - * 'nvram_data' to the address of the 8-bit data register. - * - * Note: Even though the documentation for the various RTC chips say that it - * take up to a second before it starts updating once the 'R' bit is - * cleared, they always seem to update even though we bang on it many - * times a second. This is true, except for the Dallas Semi 1746/1747 - * (possibly others). Those chips seem to have a real problem whenever - * we set the 'R' bit before reading them, they basically stop counting. - * --MAG - */ - -/* - * 'todc_info' should be initialized in your *_setup.c file to - * point to a fully initialized 'todc_info_t' structure. - * This structure holds all the register offsets for your particular - * TODC/RTC chip. - * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you. - */ - -#ifdef RTC_FREQ_SELECT -#undef RTC_FREQ_SELECT -#define RTC_FREQ_SELECT control_b /* Register A */ -#endif - -#ifdef RTC_CONTROL -#undef RTC_CONTROL -#define RTC_CONTROL control_a /* Register B */ -#endif - -#ifdef RTC_INTR_FLAGS -#undef RTC_INTR_FLAGS -#define RTC_INTR_FLAGS watchdog /* Register C */ -#endif - -#ifdef RTC_VALID -#undef RTC_VALID -#define RTC_VALID interrupts /* Register D */ -#endif - -/* Access routines when RTC accessed directly (like normal memory) */ -u_char -todc_direct_read_val(int addr) -{ - return readb((void __iomem *)(todc_info->nvram_data + addr)); -} - -void -todc_direct_write_val(int addr, unsigned char val) -{ - writeb(val, (void __iomem *)(todc_info->nvram_data + addr)); - return; -} - -/* Access routines for accessing m48txx type chips via addr/data regs */ -u_char -todc_m48txx_read_val(int addr) -{ - outb(addr, todc_info->nvram_as0); - outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); - return inb(todc_info->nvram_data); -} - -void -todc_m48txx_write_val(int addr, unsigned char val) -{ - outb(addr, todc_info->nvram_as0); - outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); - outb(val, todc_info->nvram_data); - return; -} - -/* Access routines for accessing mc146818 type chips via addr/data regs */ -u_char -todc_mc146818_read_val(int addr) -{ - outb_p(addr, todc_info->nvram_as0); - return inb_p(todc_info->nvram_data); -} - -void -todc_mc146818_write_val(int addr, unsigned char val) -{ - outb_p(addr, todc_info->nvram_as0); - outb_p(val, todc_info->nvram_data); -} - - -/* - * Routines to make RTC chips with NVRAM buried behind an addr/data pair - * have the NVRAM and clock regs appear at the same level. - * The NVRAM will appear to start at addr 0 and the clock regs will appear - * to start immediately after the NVRAM (actually, start at offset - * todc_info->nvram_size). - */ -static inline u_char -todc_read_val(int addr) -{ - u_char val; - - if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { - if (addr < todc_info->nvram_size) { /* NVRAM */ - ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); - val = ppc_md.rtc_read_val(todc_info->nvram_data_reg); - } else { /* Clock Reg */ - addr -= todc_info->nvram_size; - val = ppc_md.rtc_read_val(addr); - } - } else - val = ppc_md.rtc_read_val(addr); - - return val; -} - -static inline void -todc_write_val(int addr, u_char val) -{ - if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { - if (addr < todc_info->nvram_size) { /* NVRAM */ - ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); - ppc_md.rtc_write_val(todc_info->nvram_data_reg, val); - } else { /* Clock Reg */ - addr -= todc_info->nvram_size; - ppc_md.rtc_write_val(addr, val); - } - } else - ppc_md.rtc_write_val(addr, val); -} - -/* - * TODC routines - * - * There is some ugly stuff in that there are assumptions for the mc146818. - * - * Assumptions: - * - todc_info->control_a has the offset as mc146818 Register B reg - * - todc_info->control_b has the offset as mc146818 Register A reg - * - m48txx control reg's write enable or 'W' bit is same as - * mc146818 Register B 'SET' bit (i.e., 0x80) - * - * These assumptions were made to make the code simpler. - */ -long __init -todc_time_init(void) -{ - u_char cntl_b; - - if (!ppc_md.rtc_read_val) - ppc_md.rtc_read_val = ppc_md.nvram_read_val; - if (!ppc_md.rtc_write_val) - ppc_md.rtc_write_val = ppc_md.nvram_write_val; - - cntl_b = todc_read_val(todc_info->control_b); - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - if ((cntl_b & 0x70) != 0x20) { - printk(KERN_INFO "TODC real-time-clock was stopped." - " Now starting..."); - cntl_b &= ~0x70; - cntl_b |= 0x20; - } - - todc_write_val(todc_info->control_b, cntl_b); - } else if (todc_info->rtc_type == TODC_TYPE_DS17285) { - u_char mode; - - mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A); - /* Make sure countdown clear is not set */ - mode &= ~0x40; - /* Enable oscillator, extended register set */ - mode |= 0x30; - todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode); - - } else if (todc_info->rtc_type == TODC_TYPE_DS1501) { - u_char month; - - todc_info->enable_read = TODC_DS1501_CNTL_B_TE; - todc_info->enable_write = TODC_DS1501_CNTL_B_TE; - - month = todc_read_val(todc_info->month); - - if ((month & 0x80) == 0x80) { - printk(KERN_INFO "TODC %s %s\n", - "real-time-clock was stopped.", - "Now starting..."); - month &= ~0x80; - todc_write_val(todc_info->month, month); - } - - cntl_b &= ~TODC_DS1501_CNTL_B_TE; - todc_write_val(todc_info->control_b, cntl_b); - } else { /* must be a m48txx type */ - u_char cntl_a; - - todc_info->enable_read = TODC_MK48TXX_CNTL_A_R; - todc_info->enable_write = TODC_MK48TXX_CNTL_A_W; - - cntl_a = todc_read_val(todc_info->control_a); - - /* Check & clear STOP bit in control B register */ - if (cntl_b & TODC_MK48TXX_DAY_CB) { - printk(KERN_INFO "TODC %s %s\n", - "real-time-clock was stopped.", - "Now starting..."); - - cntl_a |= todc_info->enable_write; - cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */ - - todc_write_val(todc_info->control_a, cntl_a); - todc_write_val(todc_info->control_b, cntl_b); - } - - /* Make sure READ & WRITE bits are cleared. */ - cntl_a &= ~(todc_info->enable_write | todc_info->enable_read); - todc_write_val(todc_info->control_a, cntl_a); - } - - return 0; -} - -/* - * There is some ugly stuff in that there are assumptions that for a mc146818, - * the todc_info->control_a has the offset of the mc146818 Register B reg and - * that the register'ss 'SET' bit is the same as the m48txx's write enable - * bit in the control register of the m48txx (i.e., 0x80). - * - * It was done to make the code look simpler. - */ -void -todc_get_rtc_time(struct rtc_time *tm) -{ - uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0; - uint limit, i; - u_char save_control, uip = 0; - extern void GregorianDay(struct rtc_time *); - - spin_lock(&rtc_lock); - save_control = todc_read_val(todc_info->control_a); - - if (todc_info->rtc_type != TODC_TYPE_MC146818) { - limit = 1; - - switch (todc_info->rtc_type) { - case TODC_TYPE_DS1553: - case TODC_TYPE_DS1557: - case TODC_TYPE_DS1743: - case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ - case TODC_TYPE_DS1747: - case TODC_TYPE_DS17285: - break; - default: - todc_write_val(todc_info->control_a, - (save_control | todc_info->enable_read)); - } - } else - limit = 100000000; - - for (i=0; irtc_type == TODC_TYPE_MC146818) - uip = todc_read_val(todc_info->RTC_FREQ_SELECT); - - sec = todc_read_val(todc_info->seconds) & 0x7f; - min = todc_read_val(todc_info->minutes) & 0x7f; - hour = todc_read_val(todc_info->hours) & 0x3f; - mday = todc_read_val(todc_info->day_of_month) & 0x3f; - mon = todc_read_val(todc_info->month) & 0x1f; - year = todc_read_val(todc_info->year) & 0xff; - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - uip |= todc_read_val(todc_info->RTC_FREQ_SELECT); - if ((uip & RTC_UIP) == 0) - break; - } - } - - if (todc_info->rtc_type != TODC_TYPE_MC146818) { - switch (todc_info->rtc_type) { - case TODC_TYPE_DS1553: - case TODC_TYPE_DS1557: - case TODC_TYPE_DS1743: - case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ - case TODC_TYPE_DS1747: - case TODC_TYPE_DS17285: - break; - default: - save_control &= ~(todc_info->enable_read); - todc_write_val(todc_info->control_a, save_control); - } - } - spin_unlock(&rtc_lock); - - if ((todc_info->rtc_type != TODC_TYPE_MC146818) - || ((save_control & RTC_DM_BINARY) == 0) - || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(mday); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - if ((year + 1900) < 1970) { - year += 100; - } - - tm->tm_sec = sec; - tm->tm_min = min; - tm->tm_hour = hour; - tm->tm_mday = mday; - tm->tm_mon = mon; - tm->tm_year = year; - - GregorianDay(tm); -} - -int -todc_set_rtc_time(struct rtc_time *tm) -{ - u_char save_control, save_freq_select = 0; - - spin_lock(&rtc_lock); - save_control = todc_read_val(todc_info->control_a); - - /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */ - todc_write_val(todc_info->control_a, - (save_control | todc_info->enable_write)); - save_control &= ~(todc_info->enable_write); /* in case it was set */ - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT); - todc_write_val(todc_info->RTC_FREQ_SELECT, - save_freq_select | RTC_DIV_RESET2); - } - - if ((todc_info->rtc_type != TODC_TYPE_MC146818) - || ((save_control & RTC_DM_BINARY) == 0) - || RTC_ALWAYS_BCD) { - BIN_TO_BCD(tm->tm_sec); - BIN_TO_BCD(tm->tm_min); - BIN_TO_BCD(tm->tm_hour); - BIN_TO_BCD(tm->tm_mon); - BIN_TO_BCD(tm->tm_mday); - BIN_TO_BCD(tm->tm_year); - } - - todc_write_val(todc_info->seconds, tm->tm_sec); - todc_write_val(todc_info->minutes, tm->tm_min); - todc_write_val(todc_info->hours, tm->tm_hour); - todc_write_val(todc_info->month, tm->tm_mon); - todc_write_val(todc_info->day_of_month, tm->tm_mday); - todc_write_val(todc_info->year, tm->tm_year); - - todc_write_val(todc_info->control_a, save_control); - - if (todc_info->rtc_type == TODC_TYPE_MC146818) - todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select); - - spin_unlock(&rtc_lock); - return 0; -} diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h deleted file mode 100644 index 60a8c39..0000000 --- a/include/asm-powerpc/todc.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Definitions for the M48Txx and mc146818 series of Time of day/Real Time - * Clock chips. - * - * Author: Mark A. Greer - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -/* - * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips. - * Purpose is to make one generic file that handles all of these chips instead - * of every platform implementing the same code over & over again. - */ - -#ifndef __PPC_KERNEL_TODC_H -#define __PPC_KERNEL_TODC_H - -typedef struct { - uint rtc_type; /* your particular chip */ - - /* - * Following are the addresses of the AS0, AS1, and DATA registers - * of these chips. Note that these are board-specific. - */ - unsigned int nvram_as0; - unsigned int nvram_as1; - unsigned int nvram_data; - - /* - * Define bits to stop external set of regs from changing so - * the chip can be read/written reliably. - */ - unsigned char enable_read; - unsigned char enable_write; - - /* - * Following is the number of AS0 address bits. This is normally - * 8 but some bad hardware routes address lines incorrectly. - */ - int as0_bits; - - int nvram_size; /* Size of NVRAM on chip */ - int sw_flags; /* Software control flags */ - - /* Following are the register offsets for the particular chip */ - int year; - int month; - int day_of_month; - int day_of_week; - int hours; - int minutes; - int seconds; - int control_b; - int control_a; - int watchdog; - int interrupts; - int alarm_date; - int alarm_hour; - int alarm_minutes; - int alarm_seconds; - int century; - int flags; - - /* - * Some RTC chips have their NVRAM buried behind a addr/data pair of - * regs on the first level/clock registers. The following fields - * are the addresses for those addr/data regs. - */ - int nvram_addr_reg; - int nvram_data_reg; -} todc_info_t; - -/* - * Define the types of TODC/RTC variants that are supported in - * arch/ppc/kernel/todc_time.c - * Make a new one of these for any chip somehow differs from what's already - * defined. That way, if you ever need to put in code to touch those - * bits/registers in todc_time.c, you can put it inside an - * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break - * anyone else. - */ -#define TODC_TYPE_MK48T35 1 -#define TODC_TYPE_MK48T37 2 -#define TODC_TYPE_MK48T59 3 -#define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */ -#define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */ -#define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */ -#define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */ -#define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */ -#define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */ -#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */ -#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */ -#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */ -#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */ -#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */ - -/* - * Bit to clear/set to enable reads/writes to the chip - */ -#define TODC_MK48TXX_CNTL_A_R 0x40 -#define TODC_MK48TXX_CNTL_A_W 0x80 -#define TODC_MK48TXX_DAY_CB 0x80 - -#define TODC_DS1501_CNTL_B_TE 0x80 - -/* - * Define flag bits used by todc routines. - */ -#define TODC_FLAG_2_LEVEL_NVRAM 0x00000001 - -/* - * Define the values for the various RTC's that should to into the todc_info - * table. - * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only - * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set. - */ -#define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8 -#define TODC_TYPE_MK48T35_SW_FLAGS 0 -#define TODC_TYPE_MK48T35_YEAR 0x7fff -#define TODC_TYPE_MK48T35_MONTH 0x7ffe -#define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T35_HOURS 0x7ffb -#define TODC_TYPE_MK48T35_MINUTES 0x7ffa -#define TODC_TYPE_MK48T35_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T35_WATCHDOG 0x0000 -#define TODC_TYPE_MK48T35_INTERRUPTS 0x0000 -#define TODC_TYPE_MK48T35_ALARM_DATE 0x0000 -#define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000 -#define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000 -#define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000 -#define TODC_TYPE_MK48T35_CENTURY 0x0000 -#define TODC_TYPE_MK48T35_FLAGS 0x0000 -#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0 -#define TODC_TYPE_MK48T37_SW_FLAGS 0 -#define TODC_TYPE_MK48T37_YEAR 0x7fff -#define TODC_TYPE_MK48T37_MONTH 0x7ffe -#define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T37_HOURS 0x7ffb -#define TODC_TYPE_MK48T37_MINUTES 0x7ffa -#define TODC_TYPE_MK48T37_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7 -#define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6 -#define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5 -#define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4 -#define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3 -#define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2 -#define TODC_TYPE_MK48T37_CENTURY 0x7ff1 -#define TODC_TYPE_MK48T37_FLAGS 0x7ff0 -#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_MK48T59_SW_FLAGS 0 -#define TODC_TYPE_MK48T59_YEAR 0x1fff -#define TODC_TYPE_MK48T59_MONTH 0x1ffe -#define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_MK48T59_HOURS 0x1ffb -#define TODC_TYPE_MK48T59_MINUTES 0x1ffa -#define TODC_TYPE_MK48T59_SECONDS 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_B 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_A 0x1ff8 -#define TODC_TYPE_MK48T59_WATCHDOG 0x1fff -#define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff -#define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff -#define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff -#define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff -#define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff -#define TODC_TYPE_MK48T59_CENTURY 0x1fff -#define TODC_TYPE_MK48T59_FLAGS 0x1fff -#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1501_NVRAM_SIZE 0x100 -#define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b) -#define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a) -#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10 -#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13 - -#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_DS1553_SW_FLAGS 0 -#define TODC_TYPE_DS1553_YEAR 0x1fff -#define TODC_TYPE_DS1553_MONTH 0x1ffe -#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1553_HOURS 0x1ffb -#define TODC_TYPE_DS1553_MINUTES 0x1ffa -#define TODC_TYPE_DS1553_SECONDS 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7 -#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6 -#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5 -#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4 -#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3 -#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2 -#define TODC_TYPE_DS1553_CENTURY 0x1ff8 -#define TODC_TYPE_DS1553_FLAGS 0x1ff0 -#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0 -#define TODC_TYPE_DS1557_SW_FLAGS 0 -#define TODC_TYPE_DS1557_YEAR 0x7ffff -#define TODC_TYPE_DS1557_MONTH 0x7fffe -#define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1557_HOURS 0x7fffb -#define TODC_TYPE_DS1557_MINUTES 0x7fffa -#define TODC_TYPE_DS1557_SECONDS 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1557_WATCHDOG 0x7fff7 -#define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6 -#define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5 -#define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4 -#define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3 -#define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2 -#define TODC_TYPE_DS1557_CENTURY 0x7fff8 -#define TODC_TYPE_DS1557_FLAGS 0x7fff0 -#define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1557_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1643_SW_FLAGS 0 -#define TODC_TYPE_DS1643_YEAR 0x1fff -#define TODC_TYPE_DS1643_MONTH 0x1ffe -#define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1643_HOURS 0x1ffb -#define TODC_TYPE_DS1643_MINUTES 0x1ffa -#define TODC_TYPE_DS1643_SECONDS 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1643_WATCHDOG 0x1fff -#define TODC_TYPE_DS1643_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1643_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1643_CENTURY 0x1ff8 -#define TODC_TYPE_DS1643_FLAGS 0x1fff -#define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1643_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */ -#define TODC_TYPE_DS1693_SW_FLAGS 0 -#define TODC_TYPE_DS1693_YEAR 0x09 -#define TODC_TYPE_DS1693_MONTH 0x08 -#define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_DS1693_HOURS 0x04 -#define TODC_TYPE_DS1693_MINUTES 0x02 -#define TODC_TYPE_DS1693_SECONDS 0x00 -#define TODC_TYPE_DS1693_CNTL_B 0x0b -#define TODC_TYPE_DS1693_CNTL_A 0x0a -#define TODC_TYPE_DS1693_WATCHDOG 0xff -#define TODC_TYPE_DS1693_INTERRUPTS 0xff -#define TODC_TYPE_DS1693_ALARM_DATE 0x49 -#define TODC_TYPE_DS1693_ALARM_HOUR 0x05 -#define TODC_TYPE_DS1693_ALARM_MINUTES 0x03 -#define TODC_TYPE_DS1693_ALARM_SECONDS 0x01 -#define TODC_TYPE_DS1693_CENTURY 0x48 -#define TODC_TYPE_DS1693_FLAGS 0xff -#define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1693_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1743_SW_FLAGS 0 -#define TODC_TYPE_DS1743_YEAR 0x1fff -#define TODC_TYPE_DS1743_MONTH 0x1ffe -#define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1743_HOURS 0x1ffb -#define TODC_TYPE_DS1743_MINUTES 0x1ffa -#define TODC_TYPE_DS1743_SECONDS 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1743_WATCHDOG 0x1fff -#define TODC_TYPE_DS1743_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1743_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1743_CENTURY 0x1ff8 -#define TODC_TYPE_DS1743_FLAGS 0x1fff -#define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1743_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8 -#define TODC_TYPE_DS1746_SW_FLAGS 0 -#define TODC_TYPE_DS1746_YEAR 0x1ffff -#define TODC_TYPE_DS1746_MONTH 0x1fffe -#define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */ -#define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */ -#define TODC_TYPE_DS1746_HOURS 0x1fffb -#define TODC_TYPE_DS1746_MINUTES 0x1fffa -#define TODC_TYPE_DS1746_SECONDS 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_B 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1746_WATCHDOG 0x00000 -#define TODC_TYPE_DS1746_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1746_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1746_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1746_CENTURY 0x00000 -#define TODC_TYPE_DS1746_FLAGS 0x00000 -#define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1746_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8 -#define TODC_TYPE_DS1747_SW_FLAGS 0 -#define TODC_TYPE_DS1747_YEAR 0x7ffff -#define TODC_TYPE_DS1747_MONTH 0x7fffe -#define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1747_HOURS 0x7fffb -#define TODC_TYPE_DS1747_MINUTES 0x7fffa -#define TODC_TYPE_DS1747_SECONDS 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1747_WATCHDOG 0x00000 -#define TODC_TYPE_DS1747_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1747_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1747_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1747_CENTURY 0x00000 -#define TODC_TYPE_DS1747_FLAGS 0x00000 -#define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1747_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */ -#define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A) -#define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B) -#define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C) -#define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D) -#define TODC_TYPE_DS17285_WATCHDOG 0 -#define TODC_TYPE_DS17285_INTERRUPTS 0 -#define TODC_TYPE_DS17285_ALARM_DATE 0 -#define TODC_TYPE_DS17285_CENTURY 0 -#define TODC_TYPE_DS17285_FLAGS 0 -#define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50 -#define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53 - -#define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */ -#define TODC_TYPE_MC146818_SW_FLAGS 0 -#define TODC_TYPE_MC146818_YEAR 0x09 -#define TODC_TYPE_MC146818_MONTH 0x08 -#define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_MC146818_HOURS 0x04 -#define TODC_TYPE_MC146818_MINUTES 0x02 -#define TODC_TYPE_MC146818_SECONDS 0x00 -#define TODC_TYPE_MC146818_CNTL_B 0x0a -#define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_MC146818_WATCHDOG 0 -#define TODC_TYPE_MC146818_INTERRUPTS 0x0c -#define TODC_TYPE_MC146818_ALARM_DATE 0xff -#define TODC_TYPE_MC146818_ALARM_HOUR 0x05 -#define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 -#define TODC_TYPE_MC146818_ALARM_SECONDS 0x01 -#define TODC_TYPE_MC146818_CENTURY 0xff -#define TODC_TYPE_MC146818_FLAGS 0xff -#define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MC146818_NVRAM_DATA_REG 0 - -#define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */ -#define TODC_TYPE_PC97307_SW_FLAGS 0 -#define TODC_TYPE_PC97307_YEAR 0x09 -#define TODC_TYPE_PC97307_MONTH 0x08 -#define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_PC97307_HOURS 0x04 -#define TODC_TYPE_PC97307_MINUTES 0x02 -#define TODC_TYPE_PC97307_SECONDS 0x00 -#define TODC_TYPE_PC97307_CNTL_B 0x0a -#define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_PC97307_WATCHDOG 0x0c -#define TODC_TYPE_PC97307_INTERRUPTS 0x0d -#define TODC_TYPE_PC97307_ALARM_DATE 0xff -#define TODC_TYPE_PC97307_ALARM_HOUR 0x05 -#define TODC_TYPE_PC97307_ALARM_MINUTES 0x03 -#define TODC_TYPE_PC97307_ALARM_SECONDS 0x01 -#define TODC_TYPE_PC97307_CENTURY 0xff -#define TODC_TYPE_PC97307_FLAGS 0xff -#define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0 -#define TODC_TYPE_PC97307_NVRAM_DATA_REG 0 - -/* - * Define macros to allocate and init the todc_info_t table that will - * be used by the todc_time.c routines. - */ -#define TODC_ALLOC() \ - static todc_info_t todc_info_alloc; \ - todc_info_t *todc_info = &todc_info_alloc; - -#define TODC_INIT(clock_type, as0, as1, data, bits) { \ - todc_info->rtc_type = clock_type; \ - \ - todc_info->nvram_as0 = (unsigned int)(as0); \ - todc_info->nvram_as1 = (unsigned int)(as1); \ - todc_info->nvram_data = (unsigned int)(data); \ - \ - todc_info->as0_bits = (bits); \ - \ - todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \ - todc_info->sw_flags = clock_type ##_SW_FLAGS; \ - \ - todc_info->year = clock_type ##_YEAR; \ - todc_info->month = clock_type ##_MONTH; \ - todc_info->day_of_month = clock_type ##_DOM; \ - todc_info->day_of_week = clock_type ##_DOW; \ - todc_info->hours = clock_type ##_HOURS; \ - todc_info->minutes = clock_type ##_MINUTES; \ - todc_info->seconds = clock_type ##_SECONDS; \ - todc_info->control_b = clock_type ##_CNTL_B; \ - todc_info->control_a = clock_type ##_CNTL_A; \ - todc_info->watchdog = clock_type ##_WATCHDOG; \ - todc_info->interrupts = clock_type ##_INTERRUPTS; \ - todc_info->alarm_date = clock_type ##_ALARM_DATE; \ - todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \ - todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \ - todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \ - todc_info->century = clock_type ##_CENTURY; \ - todc_info->flags = clock_type ##_FLAGS; \ - \ - todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \ - todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \ -} - -extern todc_info_t *todc_info; - -unsigned char todc_direct_read_val(int addr); -void todc_direct_write_val(int addr, unsigned char val); -unsigned char todc_m48txx_read_val(int addr); -void todc_m48txx_write_val(int addr, unsigned char val); -unsigned char todc_mc146818_read_val(int addr); -void todc_mc146818_write_val(int addr, unsigned char val); - -long todc_time_init(void); -void todc_get_rtc_time(struct rtc_time *); -int todc_set_rtc_time(struct rtc_time *); -void todc_calibrate_decr(void); - -#endif /* __PPC_KERNEL_TODC_H */ -- cgit v0.10.2 From 035223fb28791f0eb0d5719727355d3f6817d228 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 5 Oct 2006 11:35:10 -0700 Subject: [POWERPC] Make pSeries_lpar_hpte_insert static Change the powerpc hpte_insert routines now called through ppc_md to static scope. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index c90f124..6f1016a 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep) clear_bit(HPTE_LOCK_BIT, word); } -long native_hpte_insert(unsigned long hpte_group, unsigned long va, +static long native_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) { diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1820a0b..721436d 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -282,7 +282,7 @@ void vpa_init(int cpu) } } -long pSeries_lpar_hpte_insert(unsigned long hpte_group, +static long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) @@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. */ -void pSeries_lpar_flush_hash_range(unsigned long number, int local) +static void pSeries_lpar_flush_hash_range(unsigned long number, int local) { int i; unsigned long flags = 0; diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index c3fc7a2..41c8c9c 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -248,21 +248,6 @@ extern void hpte_init_native(void); extern void hpte_init_lpar(void); extern void hpte_init_iSeries(void); -extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - -extern long native_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - -extern long iSeries_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - extern void stabs_alloc(void); extern void slb_initialize(void); extern void slb_flush_and_rebolt(void); -- cgit v0.10.2 From 43518407d57f1b685f5a9f1a981734ce66a21f76 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 16 Oct 2006 21:28:58 +1000 Subject: [CRYPTO] api: Select cryptomgr where needed Since cryptomgr is the only way to construct algorithm instances for now it makes sense to let the templates depend on it as otherwise it may be left off inadvertently. Signed-off-by: Herbert Xu diff --git a/crypto/Kconfig b/crypto/Kconfig index 1e2f39c..cbae839 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -27,7 +27,6 @@ config CRYPTO_HASH config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" select CRYPTO_ALGAPI - default m help Create default cryptographic template instantiations such as cbc(aes). @@ -35,6 +34,7 @@ config CRYPTO_MANAGER config CRYPTO_HMAC tristate "HMAC support" select CRYPTO_HASH + select CRYPTO_MANAGER help HMAC: Keyed-Hashing for Message Authentication (RFC2104). This is required for IPSec. @@ -131,6 +131,7 @@ config CRYPTO_TGR192 config CRYPTO_ECB tristate "ECB support" select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER default m help ECB: Electronic CodeBook mode @@ -140,6 +141,7 @@ config CRYPTO_ECB config CRYPTO_CBC tristate "CBC support" select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER default m help CBC: Cipher Block Chaining mode -- cgit v0.10.2 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 diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 052e812..7ce7761 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 v0.10.2 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 diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 1d0470c..30175c7 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 v0.10.2 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 diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c0edb66..7bac86d 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 v0.10.2 From 29da7eb0ec69245c6e9b4eb5bdaa04af685f5c4f Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 16 Oct 2006 14:10:49 +0100 Subject: [PATCH] FRV: Use the correct preemption primitives in kmap_atomic() and co Use inc/dec_preempt_count() rather than preempt_enable/disable() and manually add in the compiler barriers that were provided by the latter. This makes FRV consistent with other archs. Furthermore, the compiler barrier effects are now there unconditionally - at least as far as preemption is concerned - because we don't want the compiler moving memory accesses out of the section of code in which the mapping is in force - in effect the kmap_atomic() must imply a LOCK-class barrier and the kunmap_atomic() must imply an UNLOCK-class barrier to the compiler. Signed-off-by: David Howells Acked-by: Peter Zijlstra Signed-off-by: Linus Torvalds diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h index e2247c2..0f390f4 100644 --- a/include/asm-frv/highmem.h +++ b/include/asm-frv/highmem.h @@ -82,11 +82,11 @@ extern struct page *kmap_atomic_to_page(void *ptr); dampr = paddr | xAMPRx_L | xAMPRx_M | xAMPRx_S | xAMPRx_SS_16Kb | xAMPRx_V; \ \ if (type != __KM_CACHE) \ - asm volatile("movgs %0,dampr"#ampr :: "r"(dampr)); \ + asm volatile("movgs %0,dampr"#ampr :: "r"(dampr) : "memory"); \ else \ asm volatile("movgs %0,iampr"#ampr"\n" \ "movgs %0,dampr"#ampr"\n" \ - :: "r"(dampr) \ + :: "r"(dampr) : "memory" \ ); \ \ asm("movsg damlr"#ampr",%0" : "=r"(damlr)); \ @@ -104,7 +104,7 @@ extern struct page *kmap_atomic_to_page(void *ptr); asm volatile("movgs %0,tplr \n" \ "movgs %1,tppr \n" \ "tlbpr %0,gr0,#2,#1" \ - : : "r"(damlr), "r"(dampr)); \ + : : "r"(damlr), "r"(dampr) : "memory"); \ \ /*printk("TLB: SECN sl=%d L=%08lx P=%08lx\n", slot, damlr, dampr);*/ \ \ @@ -115,7 +115,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) { unsigned long paddr; - preempt_disable(); + inc_preempt_count(); paddr = page_to_phys(page); switch (type) { @@ -138,16 +138,16 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) } } -#define __kunmap_atomic_primary(type, ampr) \ -do { \ - asm volatile("movgs gr0,dampr"#ampr"\n"); \ - if (type == __KM_CACHE) \ - asm volatile("movgs gr0,iampr"#ampr"\n"); \ +#define __kunmap_atomic_primary(type, ampr) \ +do { \ + asm volatile("movgs gr0,dampr"#ampr"\n" ::: "memory"); \ + if (type == __KM_CACHE) \ + asm volatile("movgs gr0,iampr"#ampr"\n" ::: "memory"); \ } while(0) -#define __kunmap_atomic_secondary(slot, vaddr) \ -do { \ - asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr)); \ +#define __kunmap_atomic_secondary(slot, vaddr) \ +do { \ + asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory"); \ } while(0) static inline void kunmap_atomic(void *kvaddr, enum km_type type) @@ -170,7 +170,8 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) default: BUG(); } - preempt_enable(); + dec_preempt_count(); + preempt_check_resched(); } #endif /* !__ASSEMBLY__ */ -- cgit v0.10.2 From 39af114377bf80d2a88e47be33d578d1fa9b0775 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 16 Oct 2006 09:01:46 -0700 Subject: [PATCH] fix epoll_pwait when EPOLL=n Fixes http://bugzilla.kernel.org/show_bug.cgi?id=7371 sys_epoll_pwait needs to be listed as a conditional (weak) entry point for CONFIG_EPOLL=n. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 7a3b2e75..0e53314 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -49,6 +49,7 @@ cond_syscall(compat_sys_get_robust_list); cond_syscall(sys_epoll_create); cond_syscall(sys_epoll_ctl); cond_syscall(sys_epoll_wait); +cond_syscall(sys_epoll_pwait); cond_syscall(sys_semget); cond_syscall(sys_semop); cond_syscall(sys_semtimedop); -- cgit v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index dc1ebea..9e7bd94 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index e37c568..30409e1 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index 29958b6..28c087b 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 12cefa6..b4ffaa7 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 7c43669..06d5020 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 v0.10.2 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 diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0e6f35f..39a9f8c 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 v0.10.2 From 0f6f65f607b6d516fa001e8cdf5a2618c81372f5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 16 Oct 2006 21:14:51 +0100 Subject: [ARM] Update mach-types Signed-off-by: Russell King diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index b02af1d..579c69a 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -4,7 +4,7 @@ # # Up to date versions of this file can be obtained from: # -# http://www.arm.linux.org.uk/developer/machines/?action=download +# http://www.arm.linux.org.uk/developer/machines/download.php # # Please do not send patches to this file; it is automatically generated! # To add an entry into this database, please see Documentation/arm/README, @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sat Sep 23 13:20:43 2006 +# Last update: Mon Oct 16 21:13:36 2006 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1157,3 +1157,17 @@ adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143 oti4110 MACH_OTI4110 OTI4110 1144 hme_pxa MACH_HME_PXA HME_PXA 1145 deisterdca MACH_DEISTERDCA DEISTERDCA 1146 +ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147 +ces_mtr MACH_CES_MTR CES_MTR 1148 +tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149 +everest MACH_EVEREST EVEREST 1150 +pnx4010 MACH_PNX4010 PNX4010 1151 +oxnas MACH_OXNAS OXNAS 1152 +fiori MACH_FIORI FIORI 1153 +ml1200 MACH_ML1200 ML1200 1154 +cactus MACH_CACTUS CACTUS 1155 +nb2xxx MACH_NB2XXX NB2XXX 1156 +hw6900 MACH_HW6900 HW6900 1157 +cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158 +quicksilver MACH_QUICKSILVER QUICKSILVER 1159 +uplat926 MACH_UPLAT926 UPLAT926 1160 -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index bad3452..0f047d4 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index c3f90c8..2ddbec6 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 9b7b15c..d27016f 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 425b3a5..617b672 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 589f6d2..cf51c87 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 82bfddb..e8419cf 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 addea1c..33aff4f 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 2aa779d..23068a8 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 0f047d4..7776b5c 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 76e3aed..978ed09 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 e04bcad..ea16078 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 7776b5c..a94c6d8 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 v0.10.2 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 diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 0a33c8a..9d5427a 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 v0.10.2 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 diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index b779c7d..336caba 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 v0.10.2 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 diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 30057a3..36b29ff 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 v0.10.2 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 diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 9d5427a..e0710fa 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 31eed85..0c07b8b 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 0b381d7..7fbfc9e 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 v0.10.2 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 diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index e0710fa..efcdaf1 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index e393681..149b369 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 5e5c58b..6a7822e 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 92a72f5..f5d7677 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 v0.10.2 From 6684e59aa3cf6cb7ebf04ea2953198500c93b0a9 Mon Sep 17 00:00:00 2001 From: Laurent Riffard Date: Thu, 12 Oct 2006 00:17:36 +0200 Subject: [PATCH] sotftmac: fix a slab corruption in WEP restricted key association Fix a slab corruption in ieee80211softmac_auth(). The size of a buffer was miscomputed. see http://bugzilla.kernel.org/show_bug.cgi?id=7245 Acked-by: Daniel Drake Signed-off-by: Laurent Riffard Signed-off-by: John W. Linville diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index e8419cf..b969310 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -304,7 +304,7 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, 2 + /* Auth Transaction Seq */ 2 + /* Status Code */ /* Challenge Text IE */ - is_shared_response ? 0 : 1 + 1 + net->challenge_len + (is_shared_response ? 1 + 1 + net->challenge_len : 0) ); if (unlikely((*pkt) == NULL)) return 0; -- cgit v0.10.2 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 diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig index a347316..34d4fde 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 8562821..83d2e90 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 v0.10.2 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 diff --git a/drivers/Kconfig b/drivers/Kconfig index 263e86d..f394634 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 f3fe287..244f7eb 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 fa7acc2..b6c045d 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 9a91c1e..c9e98ab 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 0000000..1c3c14a --- /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 98ce88d..ff4fa25 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 34d4fde..c66ba9a 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 2cda011..693db8b 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 83d2e90..0000000 --- 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 v0.10.2 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 diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f2864cc..06784ad 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 v0.10.2 From ca268c691de95612981b93e58899c1d73fdb6b47 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 17 Oct 2006 00:09:28 -0700 Subject: [PATCH] lockdep: increase max allowed recursion depth In general, lockdep warnings are intended to be non-fatal, so I have put in various practical limits on internal data structure failure modes. We haven't had a /single/ lockdep-internal crash ever since lockdep went upstream [the unwinder crashes are outside of lockdep], and that's largely due to the good internal checks it does. Recursion within the dependency graph is currently limited to 20, that's probably not enough on some many-CPU boxes - this patch doubles it to 40. I have written the lockdep functions to have as small stackframes as possible, so 40 should be OK too. (The practical recursion limit should be somewhere between 100 and 200 entries. If we hit that then I'll change the algorithm to be iteration-based. Graph walking logic is so easy to program via recursion, so i'd like to keep recursion as long as possible.) Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 805a322..d1a3b2c 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -575,6 +575,8 @@ static noinline int print_circular_bug_tail(void) return 0; } +#define RECURSION_LIMIT 40 + static int noinline print_infinite_recursion_bug(void) { __raw_spin_unlock(&hash_lock); @@ -595,7 +597,7 @@ check_noncircular(struct lock_class *source, unsigned int depth) debug_atomic_inc(&nr_cyclic_check_recursions); if (depth > max_recursion_depth) max_recursion_depth = depth; - if (depth >= 20) + if (depth >= RECURSION_LIMIT) return print_infinite_recursion_bug(); /* * Check this lock's dependency list: @@ -645,7 +647,7 @@ find_usage_forwards(struct lock_class *source, unsigned int depth) if (depth > max_recursion_depth) max_recursion_depth = depth; - if (depth >= 20) + if (depth >= RECURSION_LIMIT) return print_infinite_recursion_bug(); debug_atomic_inc(&nr_find_usage_forwards_checks); @@ -684,7 +686,7 @@ find_usage_backwards(struct lock_class *source, unsigned int depth) if (depth > max_recursion_depth) max_recursion_depth = depth; - if (depth >= 20) + if (depth >= RECURSION_LIMIT) return print_infinite_recursion_bug(); debug_atomic_inc(&nr_find_usage_backwards_checks); -- cgit v0.10.2 From b9f5d8040b470e4f74e3266ece2969ef06d0f8aa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 17 Oct 2006 00:09:30 -0700 Subject: [PATCH] New MMC maintainer I will be taking over after Russell King as the new maintainer of the MMC layer. Signed-off-by: Pierre Ossman Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 208da3c..5305dd6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2012,8 +2012,11 @@ L: linux-kernel@vger.kernel.org W: http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html S: Maintained -MULTIMEDIA CARD (MMC) SUBSYSTEM -S: Orphan +MULTIMEDIA CARD (MMC) AND SECURE DIGITAL (SD) SUBSYSTEM +P: Pierre Ossman +M: drzeus-mmc@drzeus.cx +L: linux-kernel@vger.kernel.org +S: Maintained MULTISOUND SOUND DRIVER P: Andrew Veliath -- cgit v0.10.2 From 3f4a0b917ce72ef47e438d354c433eb645218e87 Mon Sep 17 00:00:00 2001 From: john stultz Date: Tue, 17 Oct 2006 00:09:32 -0700 Subject: [PATCH] i386 Time: Avoid PIT SMP lockups Avoid possible PIT livelock issues seen on SMP systems (and reported by Andi), by not allowing it as a clocksource on SMP boxes. However, since the PIT may no longer be present, we have to properly handle the cases where SMP systems have TSC skew and fall back from the TSC. Since the PIT isn't there, it would "fall back" to the TSC again. So this changes the jiffies rating to 1, and the TSC-bad rating value to 0. Thus you will get the following behavior priority on i386 systems: tsc [if present & stable] hpet [if present] cyclone [if present] acpi_pm [if present] pit [if UP] jiffies Rather then the current more complicated: tsc [if present & stable] hpet [if present] cyclone [if present] acpi_pm [if present] pit [if cpus < 4] tsc [if present & unstable] jiffies Signed-off-by: John Stultz Cc: Andi Kleen Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c index 477b24d..9a0060b 100644 --- a/arch/i386/kernel/i8253.c +++ b/arch/i386/kernel/i8253.c @@ -109,7 +109,7 @@ static struct clocksource clocksource_pit = { static int __init init_pit_clocksource(void) { - if (num_possible_cpus() > 4) /* PIT does not scale! */ + if (num_possible_cpus() > 1) /* PIT does not scale! */ return 0; clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index b8fa0a8..fbc9582 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c @@ -349,8 +349,8 @@ static int tsc_update_callback(void) int change = 0; /* check to see if we should switch to the safe clocksource: */ - if (clocksource_tsc.rating != 50 && check_tsc_unstable()) { - clocksource_tsc.rating = 50; + if (clocksource_tsc.rating != 0 && check_tsc_unstable()) { + clocksource_tsc.rating = 0; clocksource_reselect(); change = 1; } @@ -461,7 +461,7 @@ static int __init init_tsc_clocksource(void) clocksource_tsc.shift); /* lower the rating if we already know its unstable: */ if (check_tsc_unstable()) - clocksource_tsc.rating = 50; + clocksource_tsc.rating = 0; init_timer(&verify_tsc_freq_timer); verify_tsc_freq_timer.function = verify_tsc_freq; diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index 126bb30..a99b2a6 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -57,7 +57,7 @@ static cycle_t jiffies_read(void) struct clocksource clocksource_jiffies = { .name = "jiffies", - .rating = 0, /* lowest rating*/ + .rating = 1, /* lowest valid rating*/ .read = jiffies_read, .mask = 0xffffffff, /*32bits*/ .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ -- cgit v0.10.2 From 5eb30790d4ccd3409240a80eaf9ab76b4fb75fd8 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 17 Oct 2006 00:09:35 -0700 Subject: [PATCH] null dereference in fs/jbd2/journal.c This is Eric Sesterhenn's jbd patch applied to jbd2. Commit: 41716c7c21b15e7ecf14f0caf1eef3980707fb74 His words: Since commit d1807793e1e7e502e3dc047115e9dbc3b50e4534 we dereference a NULL pointer. Coverity id #1432. We set journal to NULL, and use it directly afterwards. Signed-off-by: Dave Kleikamp Cc: Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 10db92c..c60f378 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -725,6 +725,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, __FUNCTION__); kfree(journal); journal = NULL; + goto out; } journal->j_dev = bdev; journal->j_fs_dev = fs_dev; @@ -735,7 +736,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, J_ASSERT(bh != NULL); journal->j_sb_buffer = bh; journal->j_superblock = (journal_superblock_t *)bh->b_data; - +out: return journal; } -- cgit v0.10.2 From a649fd9271773dd0f78e2b9f347bcceecb8827f9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:36 -0700 Subject: [PATCH] invalidate: remove_mapping() fix If remove_mapping() failed to remove the page from its mapping, don't go and mark it not uptodate! Makes kernel go dead. (Actually, I don't think the ClearPageUptodate is needed there at all). Says Nick Piggin: "Right, it isn't needed because at this point the page is guaranteed by remove_mapping to have no references (except us) and cannot pick up any new ones because it is removed from pagecache. We can delete it." Signed-off-by: Andrew Morton Acked-by: Nick Piggin Signed-off-by: Linus Torvalds diff --git a/mm/truncate.c b/mm/truncate.c index 11ca480..e07b1e6 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -96,7 +96,6 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) return 0; ret = remove_mapping(mapping, page); - ClearPageUptodate(page); return ret; } diff --git a/mm/vmscan.c b/mm/vmscan.c index eca7031..af73c14 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -378,6 +378,12 @@ static pageout_t pageout(struct page *page, struct address_space *mapping) return PAGE_CLEAN; } +/* + * Attempt to detach a locked page from its ->mapping. If it is dirty or if + * someone else has a ref on the page, abort and return 0. If it was + * successfully detached, return 1. Assumes the caller has a single ref on + * this page. + */ int remove_mapping(struct address_space *mapping, struct page *page) { BUG_ON(!PageLocked(page)); -- cgit v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index 57fa64f..f7f1908 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 v0.10.2 From ac08c26492a0ad4d94a25bd47d5630cd38337069 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Oct 2006 00:09:39 -0700 Subject: [PATCH] posix-cpu-timers: prevent signal delivery starvation The integer divisions in the timer accounting code can round the result down to 0. Adding 0 is without effect and the signal delivery stops. Clamp the division result to minimum 1 to avoid this. Problem was reported by Seongbae Park , who provided also an inital patch. Roland sayeth: I have had some more time to think about the problem, and to reproduce it using Toyo's test case. For the record, if my understanding of the problem is correct, this happens only in one very particular case. First, the expiry time has to be so soon that in cputime_t units (usually 1s/HZ ticks) it's < nthreads so the division yields zero. Second, it only affects each thread that is so new that its CPU time accumulation is zero so now+0 is still zero and ->it_*_expires winds up staying zero. For the VIRT and PROF clocks when cputime_t is tick granularity (or the SCHED clock on configurations where sched_clock's value only advances on clock ticks), this is not hard to arrange with new threads starting up and blocking before they accumulate a whole tick of CPU time. That's what happens in Toyo's test case. Note that in general it is fine for that division to round down to zero, and set each thread's expiry time to its "now" time. The problem only arises with thread's whose "now" value is still zero, so that now+0 winds up 0 and is interpreted as "not set" instead of ">= now". So it would be a sufficient and more precise fix to just use max(ticks, 1) inside the loop when setting each it_*_expires value. But, it does no harm to round the division up to one and always advance every thread's expiry time. If the thread didn't already fire timers for the expiry time of "now", there is no expectation that it will do so before the next tick anyway. So I followed Thomas's patch in lifting the max out of the loops. This patch also covers the reload cases, which are harder to write a test for (and I didn't try). I've tested it with Toyo's case and it fixes that. [toyoa@mvista.com: fix: min_t -> max_t] Signed-off-by: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Roland McGrath Cc: Daniel Walker Cc: Toyo Abe Cc: john stultz Cc: Roman Zippel Cc: Seongbae Park Cc: Peter Mattis Cc: Rohit Seth Cc: Martin Bligh Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 479b16b..7c3e1e6 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -88,6 +88,19 @@ static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, } /* + * Divide and limit the result to res >= 1 + * + * This is necessary to prevent signal delivery starvation, when the result of + * the division would be rounded down to 0. + */ +static inline cputime_t cputime_div_non_zero(cputime_t time, unsigned long div) +{ + cputime_t res = cputime_div(time, div); + + return max_t(cputime_t, res, 1); +} + +/* * Update expiry time from increment, and increase overrun count, * given the current clock sample. */ @@ -483,8 +496,8 @@ static void process_timer_rebalance(struct task_struct *p, BUG(); break; case CPUCLOCK_PROF: - left = cputime_div(cputime_sub(expires.cpu, val.cpu), - nthreads); + left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), + nthreads); do { if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(prof_ticks(t), left); @@ -498,8 +511,8 @@ static void process_timer_rebalance(struct task_struct *p, } while (t != p); break; case CPUCLOCK_VIRT: - left = cputime_div(cputime_sub(expires.cpu, val.cpu), - nthreads); + left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), + nthreads); do { if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(virt_ticks(t), left); @@ -515,6 +528,7 @@ static void process_timer_rebalance(struct task_struct *p, case CPUCLOCK_SCHED: nsleft = expires.sched - val.sched; do_div(nsleft, nthreads); + nsleft = max_t(unsigned long long, nsleft, 1); do { if (likely(!(t->flags & PF_EXITING))) { ns = t->sched_time + nsleft; @@ -1159,12 +1173,13 @@ static void check_process_timers(struct task_struct *tsk, prof_left = cputime_sub(prof_expires, utime); prof_left = cputime_sub(prof_left, stime); - prof_left = cputime_div(prof_left, nthreads); + prof_left = cputime_div_non_zero(prof_left, nthreads); virt_left = cputime_sub(virt_expires, utime); - virt_left = cputime_div(virt_left, nthreads); + virt_left = cputime_div_non_zero(virt_left, nthreads); if (sched_expires) { sched_left = sched_expires - sched_time; do_div(sched_left, nthreads); + sched_left = max_t(unsigned long long, sched_left, 1); } else { sched_left = 0; } -- cgit v0.10.2 From 0187f879ee8d4b914e74ffa3cc5df268311fc2d2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:41 -0700 Subject: [PATCH] PROC_NUMBUF is wrong Actually, the decimal representation of a 32-bit signed number can take 12 bytes, including the \0. And then some code adds a \n as well, so let's give it 13 bytes. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 82da55b..26a8f841 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -86,7 +86,7 @@ /* Worst case buffer size needed for holding an integer. */ -#define PROC_NUMBUF 10 +#define PROC_NUMBUF 13 struct pid_entry { int len; -- cgit v0.10.2 From aaa248f6c9c81b2683db7dbb0689cd5ed1c86d88 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 00:09:42 -0700 Subject: [PATCH] rename net_random to random32 Make net_random() more widely available by calling it random32 akpm: hopefully this will permit the removal of carta_random32. That needs confirmation from Stephane - this code looks somewhat more computationally expensive, and has a different (ie: callee-stateful) interface. [akpm@osdl.org: lots of build fixes, cleanups] Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller Cc: Stephane Eranian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/net.h b/include/linux/net.h index c257f71..15c733b 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -19,6 +19,7 @@ #define _LINUX_NET_H #include +#include #include struct poll_table_struct; @@ -193,9 +194,9 @@ extern int sock_map_fd(struct socket *sock); extern struct socket *sockfd_lookup(int fd, int *err); #define sockfd_put(sock) fput(sock->file) extern int net_ratelimit(void); -extern unsigned long net_random(void); -extern void net_srandom(unsigned long); -extern void net_random_init(void); + +#define net_random() random32() +#define net_srandom(seed) srandom32(seed) extern int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t len); diff --git a/include/linux/random.h b/include/linux/random.h index 5d6456b..0248b30 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -69,6 +69,9 @@ extern struct file_operations random_fops, urandom_fops; unsigned int get_random_int(void); unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len); +u32 random32(void); +void srandom32(u32 seed); + #endif /* __KERNEL___ */ #endif /* _LINUX_RANDOM_H */ diff --git a/lib/Makefile b/lib/Makefile index 59070db..4b8052f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o kobject_uevent.o klist.o -obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o +obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o random32.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/random32.c b/lib/random32.c new file mode 100644 index 0000000..4a15ce5 --- /dev/null +++ b/lib/random32.c @@ -0,0 +1,142 @@ +/* + This is a maximally equidistributed combined Tausworthe generator + based on code from GNU Scientific Library 1.5 (30 Jun 2004) + + x_n = (s1_n ^ s2_n ^ s3_n) + + s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19)) + s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25)) + s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11)) + + The period of this generator is about 2^88. + + From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe + Generators", Mathematics of Computation, 65, 213 (1996), 203--213. + + This is available on the net from L'Ecuyer's home page, + + http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps + ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps + + There is an erratum in the paper "Tables of Maximally + Equidistributed Combined LFSR Generators", Mathematics of + Computation, 68, 225 (1999), 261--269: + http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps + + ... the k_j most significant bits of z_j must be non- + zero, for each j. (Note: this restriction also applies to the + computer code given in [4], but was mistakenly not mentioned in + that paper.) + + This affects the seeding procedure by imposing the requirement + s1 > 1, s2 > 7, s3 > 15. + +*/ + +#include +#include +#include +#include + +struct rnd_state { + u32 s1, s2, s3; +}; + +static DEFINE_PER_CPU(struct rnd_state, net_rand_state); + +static u32 __random32(struct rnd_state *state) +{ +#define TAUSWORTHE(s,a,b,c,d) ((s&c)<>b) + + state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12); + state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4); + state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17); + + return (state->s1 ^ state->s2 ^ state->s3); +} + +static void __set_random32(struct rnd_state *state, unsigned long s) +{ + if (s == 0) + s = 1; /* default seed is 1 */ + +#define LCG(n) (69069 * n) + state->s1 = LCG(s); + state->s2 = LCG(state->s1); + state->s3 = LCG(state->s2); + + /* "warm it up" */ + __random32(state); + __random32(state); + __random32(state); + __random32(state); + __random32(state); + __random32(state); +} + +/** + * random32 - pseudo random number generator + * + * A 32 bit pseudo-random number is generated using a fast + * algorithm suitable for simulation. This algorithm is NOT + * considered safe for cryptographic use. + */ +u32 random32(void) +{ + unsigned long r; + struct rnd_state *state = &get_cpu_var(net_rand_state); + r = __random32(state); + put_cpu_var(state); + return r; +} +EXPORT_SYMBOL(random32); + +/** + * srandom32 - add entropy to pseudo random number generator + * @seed: seed value + * + * Add some additional seeding to the random32() pool. + * Note: this pool is per cpu so it only affects current CPU. + */ +void srandom32(u32 entropy) +{ + struct rnd_state *state = &get_cpu_var(net_rand_state); + __set_random32(state, state->s1 ^ entropy); + put_cpu_var(state); +} +EXPORT_SYMBOL(srandom32); + +/* + * Generate some initially weak seeding values to allow + * to start the random32() engine. + */ +static int __init random32_init(void) +{ + int i; + + for_each_possible_cpu(i) { + struct rnd_state *state = &per_cpu(net_rand_state,i); + __set_random32(state, i + jiffies); + } + return 0; +} +core_initcall(random32_init); + +/* + * Generate better values after random number generator + * is fully initalized. + */ +static int __init random32_reseed(void) +{ + int i; + unsigned long seed; + + for_each_possible_cpu(i) { + struct rnd_state *state = &per_cpu(net_rand_state,i); + + get_random_bytes(&seed, sizeof(seed)); + __set_random32(state, seed); + } + return 0; +} +late_initcall(random32_reseed); diff --git a/net/core/dev.c b/net/core/dev.c index 4d891be..81c426a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3502,8 +3502,6 @@ static int __init net_dev_init(void) BUG_ON(!dev_boot_phase); - net_random_init(); - if (dev_proc_init()) goto out; diff --git a/net/core/utils.c b/net/core/utils.c index 94c5d76..d93fe64 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -30,119 +30,6 @@ #include #include -/* - This is a maximally equidistributed combined Tausworthe generator - based on code from GNU Scientific Library 1.5 (30 Jun 2004) - - x_n = (s1_n ^ s2_n ^ s3_n) - - s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19)) - s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25)) - s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11)) - - The period of this generator is about 2^88. - - From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe - Generators", Mathematics of Computation, 65, 213 (1996), 203--213. - - This is available on the net from L'Ecuyer's home page, - - http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps - ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps - - There is an erratum in the paper "Tables of Maximally - Equidistributed Combined LFSR Generators", Mathematics of - Computation, 68, 225 (1999), 261--269: - http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps - - ... the k_j most significant bits of z_j must be non- - zero, for each j. (Note: this restriction also applies to the - computer code given in [4], but was mistakenly not mentioned in - that paper.) - - This affects the seeding procedure by imposing the requirement - s1 > 1, s2 > 7, s3 > 15. - -*/ -struct nrnd_state { - u32 s1, s2, s3; -}; - -static DEFINE_PER_CPU(struct nrnd_state, net_rand_state); - -static u32 __net_random(struct nrnd_state *state) -{ -#define TAUSWORTHE(s,a,b,c,d) ((s&c)<>b) - - state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12); - state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4); - state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17); - - return (state->s1 ^ state->s2 ^ state->s3); -} - -static void __net_srandom(struct nrnd_state *state, unsigned long s) -{ - if (s == 0) - s = 1; /* default seed is 1 */ - -#define LCG(n) (69069 * n) - state->s1 = LCG(s); - state->s2 = LCG(state->s1); - state->s3 = LCG(state->s2); - - /* "warm it up" */ - __net_random(state); - __net_random(state); - __net_random(state); - __net_random(state); - __net_random(state); - __net_random(state); -} - - -unsigned long net_random(void) -{ - unsigned long r; - struct nrnd_state *state = &get_cpu_var(net_rand_state); - r = __net_random(state); - put_cpu_var(state); - return r; -} - - -void net_srandom(unsigned long entropy) -{ - struct nrnd_state *state = &get_cpu_var(net_rand_state); - __net_srandom(state, state->s1^entropy); - put_cpu_var(state); -} - -void __init net_random_init(void) -{ - int i; - - for_each_possible_cpu(i) { - struct nrnd_state *state = &per_cpu(net_rand_state,i); - __net_srandom(state, i+jiffies); - } -} - -static int net_random_reseed(void) -{ - int i; - unsigned long seed; - - for_each_possible_cpu(i) { - struct nrnd_state *state = &per_cpu(net_rand_state,i); - - get_random_bytes(&seed, sizeof(seed)); - __net_srandom(state, seed); - } - return 0; -} -late_initcall(net_random_reseed); - int net_msg_cost = 5*HZ; int net_msg_burst = 10; @@ -153,10 +40,7 @@ int net_ratelimit(void) { return __printk_ratelimit(net_msg_cost, net_msg_burst); } - -EXPORT_SYMBOL(net_random); EXPORT_SYMBOL(net_ratelimit); -EXPORT_SYMBOL(net_srandom); /* * Convert an ASCII string to binary IP. -- cgit v0.10.2 From 5c496374a72320279ddb86291ef709e090a5d531 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:44 -0700 Subject: [PATCH] remove carta_random32 This library function should be in obj-y and not in lib-y. But when we do that it clashes unpleasantly with the assembly-language implementation in the ia64 architecture. Instead of trying to fix it all up, just remove the generic carta_random32 in the expectation that the recently-made-generic random32() will suffice. If/when perfmon is migrated to random32, ia64's private carta_random32 implementation can also be removed. Cc: Stephane Eranian Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/Makefile b/lib/Makefile index 4b8052f..cf98fab 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,7 +5,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \ - sha1.o irq_regs.o carta_random32.o + sha1.o irq_regs.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o diff --git a/lib/carta_random32.c b/lib/carta_random32.c deleted file mode 100644 index ca82df7..0000000 --- a/lib/carta_random32.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2002-2006 Hewlett-Packard Development Company, L.P. - * Contributed by David Mosberger-Tang - * - * This program 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. - * - * 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 - -/* - * Fast, simple, yet decent quality random number generator based on - * a paper by David G. Carta ("Two Fast Implementations of the - * `Minimal Standard' Random Number Generator," Communications of the - * ACM, January, 1990). - */ -u64 carta_random32 (u64 seed) -{ -# define A 16807 -# define M ((u32) 1 << 31) - u64 s, prod = A * seed, p, q; - - p = (prod >> 31) & (M - 1); - q = (prod >> 0) & (M - 1); - s = p + q; - if (s >= M) - s -= M - 1; - return s; -} -EXPORT_SYMBOL_GPL(carta_random32); -- cgit v0.10.2 From 91828a405ae454a9503c41a7744f6ff877a80714 Mon Sep 17 00:00:00 2001 From: "David M. Grimes" Date: Tue, 17 Oct 2006 00:09:45 -0700 Subject: [PATCH] knfsd: add nfs-export support to tmpfs We need to encode a decode the 'file' part of a handle. We simply use the inode number and generation number to construct the filehandle. The generation number is the time when the file was created. As inode numbers cycle through the full 32 bits before being reused, there is no real chance of the same inum being allocated to different files in the same second so this is suitably unique. Using time-of-day rather than e.g. jiffies makes it less likely that the same filehandle can be created after a reboot. In order to be able to decode a filehandle we need to be able to lookup by inum, which means that the inode needs to be added to the inode hash table (tmpfs doesn't currently hash inodes as there is never a need to lookup by inum). To avoid overhead when not exporting, we only hash an inode when it is first exported. This requires a lock to ensure it isn't hashed twice. This code is separate from the patch posted in June06 from Atal Shargorodsky which provided the same functionality, but does borrow slightly from it. Locking comment: Most filesystems that hash their inodes do so at the point where the 'struct inode' is initialised, and that has suitable locking (I_NEW). Here in shmem, we are hashing the inode later, the first time we need an NFS file handle for it. We no longer have I_NEW to ensure only one thread tries to add it to the hash table. Cc: Atal Shargorodsky Cc: Gilad Ben-Yossef Signed-off-by: David M. Grimes Signed-off-by: Neil Brown Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/shmem.c b/mm/shmem.c index bb8ca7e..b378f66 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1362,6 +1362,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_generation = get_seconds(); info = SHMEM_I(inode); memset(info, 0, (char *)inode - (char *)info); spin_lock_init(&info->lock); @@ -1956,6 +1957,85 @@ static struct xattr_handler *shmem_xattr_handlers[] = { }; #endif +static struct dentry *shmem_get_parent(struct dentry *child) +{ + return ERR_PTR(-ESTALE); +} + +static int shmem_match(struct inode *ino, void *vfh) +{ + __u32 *fh = vfh; + __u64 inum = fh[2]; + inum = (inum << 32) | fh[1]; + return ino->i_ino == inum && fh[0] == ino->i_generation; +} + +static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh) +{ + struct dentry *de = NULL; + struct inode *inode; + __u32 *fh = vfh; + __u64 inum = fh[2]; + inum = (inum << 32) | fh[1]; + + inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh); + if (inode) { + de = d_find_alias(inode); + iput(inode); + } + + return de? de: ERR_PTR(-ESTALE); +} + +static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh, + int len, int type, + int (*acceptable)(void *context, struct dentry *de), + void *context) +{ + if (len < 3) + return ERR_PTR(-ESTALE); + + return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, + context); +} + +static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, + int connectable) +{ + struct inode *inode = dentry->d_inode; + + if (*len < 3) + return 255; + + if (hlist_unhashed(&inode->i_hash)) { + /* Unfortunately insert_inode_hash is not idempotent, + * so as we hash inodes here rather than at creation + * time, we need a lock to ensure we only try + * to do it once + */ + static DEFINE_SPINLOCK(lock); + spin_lock(&lock); + if (hlist_unhashed(&inode->i_hash)) + __insert_inode_hash(inode, + inode->i_ino + inode->i_generation); + spin_unlock(&lock); + } + + fh[0] = inode->i_generation; + fh[1] = inode->i_ino; + fh[2] = ((__u64)inode->i_ino) >> 32; + + *len = 3; + return 1; +} + +static struct export_operations shmem_export_ops = { + .get_parent = shmem_get_parent, + .get_dentry = shmem_get_dentry, + .encode_fh = shmem_encode_fh, + .decode_fh = shmem_decode_fh, +}; + static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes, int *policy, nodemask_t *policy_nodes) @@ -2128,6 +2208,7 @@ static int shmem_fill_super(struct super_block *sb, &inodes, &policy, &policy_nodes)) return -EINVAL; } + sb->s_export_op = &shmem_export_ops; #else sb->s_flags |= MS_NOUSER; #endif -- cgit v0.10.2 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 diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 27c9d05..c287a9a 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 v0.10.2 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 diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 0b20dfa..d941707 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 v0.10.2 From 286e1ea3ac1ca4f503ebbb3020bdb0cbe6adffac Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:57 -0700 Subject: [PATCH] vmalloc(): don't pass __GFP_ZERO to slab A recent change to the vmalloc() code accidentally resulted in us passing __GFP_ZERO into the slab allocator. But we only wanted __GFP_ZERO for the actual pages whcih are being vmalloc()ed, and passing __GFP_ZERO into slab is not a rational thing to ask for. Cc: Jonathan Corbet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 750ab6e..1133dd3 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -428,8 +428,11 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, if (array_size > PAGE_SIZE) { pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node); area->flags |= VM_VPAGES; - } else - pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node); + } else { + pages = kmalloc_node(array_size, + (gfp_mask & ~(__GFP_HIGHMEM | __GFP_ZERO)), + node); + } area->pages = pages; if (!area->pages) { remove_vm_area(area->addr); -- cgit v0.10.2 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 diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 526387d..e67144c 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 v0.10.2 From c60099bfe3a5e6fa22a930627689b3769c52153f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:59 -0700 Subject: [PATCH] swsusp: fix memory leaks My fancy new swsusp IO code had a big memory leak. It's somewhat invisible because the whole mem_map[] gets overwritten after resume, but it can cause us to get low on memory during the actual suspend process. Cc: "Rafael J. Wysocki" Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 9b2ee53..1a3b0dd 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -425,7 +425,8 @@ static int submit(int rw, pgoff_t page_off, struct page *page, bio_set_pages_dirty(bio); bio_put(bio); } else { - get_page(page); + if (rw == READ) + get_page(page); /* These pages are freed later */ bio->bi_private = *bio_chain; *bio_chain = bio; submit_bio(rw | (1 << BIO_RW_SYNC), bio); -- cgit v0.10.2 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 diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index d0b88d0..7e1bd95 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 v0.10.2 From 308ba5fcf89b6e328f9290067181c1e4d772fdc9 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 17 Oct 2006 00:10:02 -0700 Subject: [PATCH] fix `make headers_install' Fix this: make[3]: *** No rule to make target `/mnt/md0/devel/linux-git/include/linux/version.h', needed by `/mnt/md0/devel/linux-git-obj/usr/include/linux/version.h'. Stop. make[2]: *** [linux] Error 2 make[1]: *** [headers_install] Error 2 Signed-off-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 6a026f6..4241e0d 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -168,7 +168,7 @@ $(objhdr-y) $(header-y) $(unifdef-y): $(KBUILDFILES) $(call cmd,gen) else -$(objhdr-y) : $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES) +$(objhdr-y) : $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(objtree)/$(obj)/%.h $(KBUILDFILES) $(call cmd,o_hdr_install) $(header-y) : $(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES) -- cgit v0.10.2 From a460e745e8f9c75a0525ff94154a0629f9d3e05d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 17 Oct 2006 00:10:03 -0700 Subject: [PATCH] genirq: clean up irq-flow-type naming Introduce desc->name and eliminate the handle_irq_name() hack. Add set_irq_chip_and_handler_name() to set the flow type and name at once. Signed-off-by: Ingo Molnar Acked-by: Thomas Gleixner Cc: "Eric W. Biederman" Cc: Matthew Wilcox Cc: Kyle McMartin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index d53eafb..62996cd 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -113,7 +113,8 @@ void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); io_apic_irqs &= ~(1<name); - seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); + seq_printf(p, "-%-8s", irq_desc[i].name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index 0612a33..c4ef801 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -178,7 +178,8 @@ void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); io_apic_irqs &= ~(1<name); - seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); + seq_printf(p, "-%-8s", irq_desc[i].name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) diff --git a/include/linux/irq.h b/include/linux/irq.h index c64f3cc..775f5a7 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -141,6 +141,7 @@ struct irq_chip { * @pending_mask: pending rebalanced interrupts * @dir: /proc/irq/ procfs entry * @affinity_entry: /proc/irq/smp_affinity procfs entry on SMP + * @name: flow handler name for /proc/interrupts output * * Pad this out to 32 bytes for cache and indexing reasons. */ @@ -165,8 +166,9 @@ struct irq_desc { cpumask_t pending_mask; #endif #ifdef CONFIG_PROC_FS - struct proc_dir_entry *dir; + struct proc_dir_entry *dir; #endif + const char *name; } ____cacheline_aligned; extern struct irq_desc irq_desc[NR_IRQS]; @@ -272,12 +274,6 @@ extern void fastcall handle_percpu_irq(unsigned int irq, struct irq_desc *desc); extern void fastcall handle_bad_irq(unsigned int irq, struct irq_desc *desc); /* - * Get a descriptive string for the highlevel handler, for - * /proc/interrupts output: - */ -extern const char *handle_irq_name(irq_flow_handler_t handle); - -/* * Monolithic do_IRQ implementation. * (is an explicit fastcall, because i386 4KSTACKS calls it from assembly) */ @@ -326,10 +322,12 @@ extern struct irq_chip no_irq_chip; extern struct irq_chip dummy_irq_chip; extern void -set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, - irq_flow_handler_t handle); +set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, + irq_flow_handler_t handle, const char *name); + extern void -__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained); +__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, + const char *name); /* * Set a highlevel flow handler for a given IRQ: @@ -337,7 +335,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained); static inline void set_irq_handler(unsigned int irq, irq_flow_handler_t handle) { - __set_irq_handler(irq, handle, 0); + __set_irq_handler(irq, handle, 0, NULL); } /* @@ -349,7 +347,7 @@ static inline void set_irq_chained_handler(unsigned int irq, irq_flow_handler_t handle) { - __set_irq_handler(irq, handle, 1); + __set_irq_handler(irq, handle, 1, NULL); } /* Handle dynamic irq creation and destruction */ diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 11c9969..2d0dc3e 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -499,7 +499,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) #endif /* CONFIG_SMP */ void -__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained) +__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, + const char *name) { struct irq_desc *desc; unsigned long flags; @@ -540,6 +541,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained) desc->depth = 1; } desc->handle_irq = handle; + desc->name = name; if (handle != handle_bad_irq && is_chained) { desc->status &= ~IRQ_DISABLED; @@ -555,30 +557,13 @@ set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, irq_flow_handler_t handle) { set_irq_chip(irq, chip); - __set_irq_handler(irq, handle, 0); + __set_irq_handler(irq, handle, 0, NULL); } -/* - * Get a descriptive string for the highlevel handler, for - * /proc/interrupts output: - */ -const char * -handle_irq_name(irq_flow_handler_t handle) +void +set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, + irq_flow_handler_t handle, const char *name) { - if (handle == handle_level_irq) - return "level "; - if (handle == handle_fasteoi_irq) - return "fasteoi"; - if (handle == handle_edge_irq) - return "edge "; - if (handle == handle_simple_irq) - return "simple "; -#ifdef CONFIG_SMP - if (handle == handle_percpu_irq) - return "percpu "; -#endif - if (handle == handle_bad_irq) - return "bad "; - - return NULL; + set_irq_chip(irq, chip); + __set_irq_handler(irq, handle, 0, name); } -- cgit v0.10.2 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 diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 5fec626..cc10af0 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 v0.10.2 From 9ffbb9162312fd8113037cb3d94f787f06bbfa9a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:06 -0700 Subject: [PATCH] fuse: fix hang on SMP Fuse didn't always call i_size_write() with i_mutex held which caused rare hangs on SMP/32bit. This bug has been present since fuse-2.2, well before being merged into mainline. The simplest solution is to protect i_size_write() with the per-connection spinlock. Using i_mutex for this purpose would require some restructuring of the code and I'm not even sure it's always safe to acquire i_mutex in all places i_size needs to be set. Since most of vmtruncate is already duplicated for other reasons, duplicate the remaining part as well, making all i_size_write() calls internal to fuse. Using i_size_write() was unnecessary in fuse_init_inode(), since this function is only called on a newly created locked inode. Reported by a few people over the years, but special thanks to Dana Henriksen who was persistent enough in helping me debug it. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8605155..a8f65c1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -935,14 +935,30 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) } } +static void fuse_vmtruncate(struct inode *inode, loff_t offset) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + int need_trunc; + + spin_lock(&fc->lock); + need_trunc = inode->i_size > offset; + i_size_write(inode, offset); + spin_unlock(&fc->lock); + + if (need_trunc) { + struct address_space *mapping = inode->i_mapping; + unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); + truncate_inode_pages(mapping, offset); + } +} + /* * Set attributes, and at the same time refresh them. * * Truncation is slightly complicated, because the 'truncate' request * may fail, in which case we don't want to touch the mapping. - * vmtruncate() doesn't allow for this case. So do the rlimit - * checking by hand and call vmtruncate() only after the file has - * actually been truncated. + * vmtruncate() doesn't allow for this case, so do the rlimit checking + * and the actual truncation by hand. */ static int fuse_setattr(struct dentry *entry, struct iattr *attr) { @@ -993,12 +1009,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) make_bad_inode(inode); err = -EIO; } else { - if (is_truncate) { - loff_t origsize = i_size_read(inode); - i_size_write(inode, outarg.attr.size); - if (origsize > outarg.attr.size) - vmtruncate(inode, outarg.attr.size); - } + if (is_truncate) + fuse_vmtruncate(inode, outarg.attr.size); fuse_change_attributes(inode, &outarg.attr); fi->i_time = time_to_jiffies(outarg.attr_valid, outarg.attr_valid_nsec); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 1836268..2bb5ace 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -481,8 +481,10 @@ static int fuse_commit_write(struct file *file, struct page *page, err = -EIO; if (!err) { pos += count; - if (pos > i_size_read(inode)) + spin_lock(&fc->lock); + if (pos > inode->i_size) i_size_write(inode, pos); + spin_unlock(&fc->lock); if (offset == 0 && to == PAGE_CACHE_SIZE) { clear_page_dirty(page); @@ -586,8 +588,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, } fuse_put_request(fc, req); if (res > 0) { - if (write && pos > i_size_read(inode)) - i_size_write(inode, pos); + if (write) { + spin_lock(&fc->lock); + if (pos > inode->i_size) + i_size_write(inode, pos); + spin_unlock(&fc->lock); + } *ppos = pos; } fuse_invalidate_attr(inode); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7d0a9ae..8e10616 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -109,6 +109,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) { + struct fuse_conn *fc = get_fuse_conn(inode); if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) invalidate_inode_pages(inode->i_mapping); @@ -117,7 +118,9 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) inode->i_nlink = attr->nlink; inode->i_uid = attr->uid; inode->i_gid = attr->gid; + spin_lock(&fc->lock); i_size_write(inode, attr->size); + spin_unlock(&fc->lock); inode->i_blocks = attr->blocks; inode->i_atime.tv_sec = attr->atime; inode->i_atime.tv_nsec = attr->atimensec; @@ -130,7 +133,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) { inode->i_mode = attr->mode & S_IFMT; - i_size_write(inode, attr->size); + inode->i_size = attr->size; if (S_ISREG(inode->i_mode)) { fuse_init_common(inode); fuse_init_file_inode(inode); -- cgit v0.10.2 From 7762f5a0b709b415fda132258ad37b9f2a1db994 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:07 -0700 Subject: [PATCH] document i_size_write locking rules Unless someone reads the documentation for write_seqcount_{begin,end} it is not obvious, that i_size_write() needs locking. Especially, that lack of such locking can result in a system hang. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/fs.h b/include/linux/fs.h index 34406ed..661c7c5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -656,7 +656,11 @@ static inline loff_t i_size_read(struct inode *inode) #endif } - +/* + * NOTE: unlike i_size_read(), i_size_write() does need locking around it + * (normally i_mutex), otherwise on 32bit/SMP an update of i_size_seqcount + * can be lost, resulting in subsequent i_size_read() calls spinning forever. + */ static inline void i_size_write(struct inode *inode, loff_t i_size) { #if BITS_PER_LONG==32 && defined(CONFIG_SMP) -- cgit v0.10.2 From 8da5ff23ce0a84d9845b01e6fe5047e17836bf5a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:08 -0700 Subject: [PATCH] fuse: locking fix for nlookup An inode could be returned by independent parallel lookups, in this case an update of the lookup counter could be lost resulting in a memory leak in userspace. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index a8f65c1..7ecfe95 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -163,7 +163,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) fuse_send_forget(fc, req, outarg.nodeid, 1); return 0; } + spin_lock(&fc->lock); fi->nlookup ++; + spin_unlock(&fc->lock); } fuse_put_request(fc, req); if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 8e10616..e911423 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -195,7 +195,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, } fi = get_fuse_inode(inode); + spin_lock(&fc->lock); fi->nlookup ++; + spin_unlock(&fc->lock); fuse_change_attributes(inode, attr); return inode; } -- cgit v0.10.2 From 265126ba9e1f8e217e61d1017c6609f76828aa7a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:09 -0700 Subject: [PATCH] fuse: fix spurious BUG Fix a spurious BUG in an unlikely race, where at least three parallel lookups return the same inode, but with different file type. This has not yet been observed in real life. Allowing unlimited retries could delay fuse_iget() indefinitely, but this is really for the broken userspace filesystem to worry about. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e911423..4ee8f72 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -172,7 +172,6 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, struct inode *inode; struct fuse_inode *fi; struct fuse_conn *fc = get_fuse_conn_super(sb); - int retried = 0; retry: inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); @@ -186,11 +185,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, fuse_init_inode(inode, attr); unlock_new_inode(inode); } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { - BUG_ON(retried); /* Inode has changed type, any I/O on the old should fail */ make_bad_inode(inode); iput(inode); - retried = 1; goto retry; } -- cgit v0.10.2 From d2a85164aaa8d514ef5efbf5d05746e85dd13ddd Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:11 -0700 Subject: [PATCH] fuse: fix handling of moved directory Fuse considered it an error (EIO) if lookup returned a directory inode, to which a dentry already refered. This is because directory aliases are not allowed. But in a network filesystem this could happen legitimately, if a directory is moved on a remote client. This patch attempts to relax the restriction by trying to first evict the offending alias from the cache. If this fails, it still returns an error (EBUSY). A rarer situation is if an mkdir races with an indenpendent lookup, which finds the newly created directory already moved. In this situation the mkdir should return success, but that would be incorrect, since the dentry cannot be instantiated, so return EBUSY. Previously checking for a directory alias and instantiation of the dentry weren't done atomically in lookup/mkdir, hence two such calls racing with each other could create aliased directories. To prevent this introduce a new per-connection mutex: fuse_conn->inst_mutex, which is taken for instantiations with a directory inode. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 7ecfe95..9d0ef5e1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -177,22 +177,6 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) return 1; } -/* - * Check if there's already a hashed alias of this directory inode. - * If yes, then lookup and mkdir must not create a new alias. - */ -static int dir_alias(struct inode *inode) -{ - if (S_ISDIR(inode->i_mode)) { - struct dentry *alias = d_find_alias(inode); - if (alias) { - dput(alias); - return 1; - } - } - return 0; -} - static int invalid_nodeid(u64 nodeid) { return !nodeid || nodeid == FUSE_ROOT_ID; @@ -208,6 +192,24 @@ static int valid_mode(int m) S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); } +/* + * Add a directory inode to a dentry, ensuring that no other dentry + * refers to this inode. Called with fc->inst_mutex. + */ +static int fuse_d_add_directory(struct dentry *entry, struct inode *inode) +{ + struct dentry *alias = d_find_alias(inode); + if (alias) { + /* This tries to shrink the subtree below alias */ + fuse_invalidate_entry(alias); + dput(alias); + if (!list_empty(&inode->i_dentry)) + return -EBUSY; + } + d_add(entry, inode); + return 0; +} + static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { @@ -243,11 +245,17 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, if (err && err != -ENOENT) return ERR_PTR(err); - if (inode && dir_alias(inode)) { - iput(inode); - return ERR_PTR(-EIO); - } - d_add(entry, inode); + if (inode && S_ISDIR(inode->i_mode)) { + mutex_lock(&fc->inst_mutex); + err = fuse_d_add_directory(entry, inode); + mutex_unlock(&fc->inst_mutex); + if (err) { + iput(inode); + return ERR_PTR(err); + } + } else + d_add(entry, inode); + entry->d_op = &fuse_dentry_operations; if (!err) fuse_change_timeout(entry, &outarg); @@ -403,12 +411,22 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, } fuse_put_request(fc, req); - if (dir_alias(inode)) { - iput(inode); - return -EIO; - } + if (S_ISDIR(inode->i_mode)) { + struct dentry *alias; + mutex_lock(&fc->inst_mutex); + alias = d_find_alias(inode); + if (alias) { + /* New directory must have moved since mkdir */ + mutex_unlock(&fc->inst_mutex); + dput(alias); + iput(inode); + return -EBUSY; + } + d_instantiate(entry, inode); + mutex_unlock(&fc->inst_mutex); + } else + d_instantiate(entry, inode); - d_instantiate(entry, inode); fuse_change_timeout(entry, &outarg); fuse_invalidate_attr(dir); return 0; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 69c7750..91edb89 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -239,6 +239,9 @@ struct fuse_conn { /** Lock protecting accessess to members of this structure */ spinlock_t lock; + /** Mutex protecting against directory alias creation */ + struct mutex inst_mutex; + /** Refcount */ atomic_t count; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 4ee8f72..fc42035 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -379,6 +379,7 @@ static struct fuse_conn *new_conn(void) fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (fc) { spin_lock_init(&fc->lock); + mutex_init(&fc->inst_mutex); atomic_set(&fc->count, 1); init_waitqueue_head(&fc->waitq); init_waitqueue_head(&fc->blocked_waitq); @@ -398,8 +399,10 @@ static struct fuse_conn *new_conn(void) void fuse_conn_put(struct fuse_conn *fc) { - if (atomic_dec_and_test(&fc->count)) + if (atomic_dec_and_test(&fc->count)) { + mutex_destroy(&fc->inst_mutex); kfree(fc); + } } struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) -- cgit v0.10.2 From e956edd0523b6b48ed367c63b0c82d8f4c447a58 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 17 Oct 2006 00:10:12 -0700 Subject: [PATCH] fuse: fix dereferencing dentry parent There's no locking for ->d_revalidate, so fuse_dentry_revalidate() should use dget_parent() instead of simply dereferencing ->d_parent. Due to topology changes in the directory tree the parent could become negative or be destroyed while being used. There hasn't been any reports about this yet. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 9d0ef5e1..cfc8f81 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -138,6 +138,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) struct fuse_entry_out outarg; struct fuse_conn *fc; struct fuse_req *req; + struct dentry *parent; /* Doesn't hurt to "reset" the validity timeout */ fuse_invalidate_entry_cache(entry); @@ -151,8 +152,10 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) if (IS_ERR(req)) return 0; - fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg); + parent = dget_parent(entry); + fuse_lookup_init(req, parent->d_inode, entry, &outarg); request_send(fc, req); + dput(parent); err = req->out.h.error; /* Zero nodeid is same as -ENOENT */ if (!err && !outarg.nodeid) -- cgit v0.10.2 From dc730e173785e29b297aa605786c94adaffe2544 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 17 Oct 2006 00:10:13 -0700 Subject: [PATCH] knfsd: nfsd4: fix owner-override on open If a client creates a file using an open which sets the mode to 000, or if a chmod changes permissions after a file is opened, then situations may arise where an NFS client knows that some IO is permitted (because a process holds the file open), but the NFS server does not (because it doesn't know about the open, and only sees that the IO conflicts with the current mode of the file). As a hack to solve this problem, NFS servers normally allow the owner to override permissions on IO. The client can still enforce correct permissions-checking on open by performing an explicit access check. In NFSv4 the client can rely on the explicit on-the-wire open instead of an access check. Therefore we should not be allowing the owner to override permissions on an over-the-wire open! However, we should still allow the owner to override permissions in the case where the client is claiming an open that it already made either before a reboot, or while it was holding a delegation. Thanks to Jim Rees for reporting the bug. Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 8333db1..a05d337 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -68,20 +68,18 @@ fh_dup2(struct svc_fh *dst, struct svc_fh *src) } static int -do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) +do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode) { - int accmode, status; + int status; if (open->op_truncate && !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) return nfserr_inval; - accmode = MAY_NOP; if (open->op_share_access & NFS4_SHARE_ACCESS_READ) - accmode = MAY_READ; + accmode |= MAY_READ; if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE) accmode |= (MAY_WRITE | MAY_TRUNC); - accmode |= MAY_OWNER_OVERRIDE; status = fh_verify(rqstp, current_fh, S_IFREG, accmode); @@ -124,7 +122,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size); - status = do_open_permission(rqstp, current_fh, open); + status = do_open_permission(rqstp, current_fh, open, MAY_NOP); } fh_put(&resfh); @@ -155,7 +153,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && (open->op_iattr.ia_size == 0); - status = do_open_permission(rqstp, current_fh, open); + status = do_open_permission(rqstp, current_fh, open, MAY_OWNER_OVERRIDE); return status; } -- cgit v0.10.2 From 9801d8a39cfe6c34f39f9552a246a6bd002e735e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 17 Oct 2006 00:10:14 -0700 Subject: [PATCH] knfsd: nfsd4: fix open permission checking We weren't actually checking for SHARE_ACCESS_WRITE, with the result that the owner could open a non-writeable file for write! Continue to allow DENY_WRITE only with write access. Thanks to Jim Rees for reporting the bug. Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a05d337..d1fac68 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -78,8 +78,10 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs if (open->op_share_access & NFS4_SHARE_ACCESS_READ) accmode |= MAY_READ; - if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE) + if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) accmode |= (MAY_WRITE | MAY_TRUNC); + if (open->op_share_deny & NFS4_SHARE_DENY_WRITE) + accmode |= MAY_WRITE; status = fh_verify(rqstp, current_fh, S_IFREG, accmode); -- cgit v0.10.2 From 0942176f4353ffebcd6e3f95abce9fd8e24f2cb1 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 17 Oct 2006 00:10:16 -0700 Subject: [PATCH] knfsd: nfsd4: Fix error handling in nfsd's callback client Coverity noticed that the error handling code in the NFSv4 callback client sets cb->cb_client to NULL, then calls rpc_shutdown_client with the NULL pointer. Coverity: #cid 1397 Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index f6ca9fb..324a278 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -421,7 +421,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) /* Create RPC client */ cb->cb_client = rpc_create(&args); - if (!cb->cb_client) { + if (IS_ERR(cb->cb_client)) { dprintk("NFSD: couldn't create callback client\n"); goto out_err; } @@ -448,10 +448,10 @@ nfsd4_probe_callback(struct nfs4_client *clp) out_rpciod: atomic_dec(&clp->cl_count); rpciod_down(); - cb->cb_client = NULL; out_clnt: rpc_shutdown_client(cb->cb_client); out_err: + cb->cb_client = NULL; dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); } -- cgit v0.10.2 From 4481d1038f4116f3f5c307d919e6dc815a3acbb9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 17 Oct 2006 00:10:17 -0700 Subject: [PATCH] knfsd: Fix bug in recent lockd patches that can cause reclaim to fail When an nfs server shuts down, lockd needs to release all the locks even though the client still holds them. It should therefore not 'unmonitor' the clients, so that the files in nfs/sm will still be there when the nfs server restarts, so that those clients will be told to reclaim their locks. However the hosts are fully unmonitored, so statd may well remove the files. lockd has a test for 'sm_sticky' and avoid the unmonitor call if it is set, but it is currently not set. So set it when tearing down lockd. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 514f5f2..c5f9113 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -324,7 +324,16 @@ nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other) static int nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy) { - return host->h_server; + if (host->h_server) { + /* we are destroying locks even though the client + * hasn't asked us too, so don't unmonitor the + * client + */ + if (host->h_nsmhandle) + host->h_nsmhandle->sm_sticky = 1; + return 1; + } else + return 0; } /* -- cgit v0.10.2 From d343fce148a4eee24a907a05c4101d3268045aae Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 17 Oct 2006 00:10:18 -0700 Subject: [PATCH] knfsd: Allow lockd to drop replies as appropriate It is possible for the ->fopen callback from lockd into nfsd to find that an answer cannot be given straight away (an upcall is needed) and so the request has to be 'dropped', to be retried later. That error status is not currently propagated back. So: Change nlm_fopen to return nlm error codes (rather than a private protocol) and define a new nlm_drop_reply code. Cause nlm_drop_reply to cause the rpc request to get rpc_drop_reply when this error comes back. Cause svc_process to drop a request which returns a status of rpc_drop_reply. [akpm@osdl.org: fix warning storm] Cc: Marc Eshel Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index fa370f6..399ad11 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -96,7 +96,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now check for conflicting locks */ resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); @@ -126,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; #if 0 /* If supplied state doesn't match current state, we assume it's @@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Try to cancel request. */ resp->status = nlmsvc_cancel_blocked(file, &argp->lock); @@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to remove the lock */ resp->status = nlmsvc_unlock(file, &argp->lock); @@ -339,7 +339,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to create the share */ resp->status = nlmsvc_share_file(host, file, argp); @@ -372,7 +372,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to lock the file */ resp->status = nlmsvc_unshare_file(host, file, argp); diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 75b2c81..6a931f4 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -59,7 +59,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; - u32 error; + u32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) @@ -88,6 +88,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, no_locks: if (host) nlm_release_host(host); + if (error) + return error; return nlm_lck_denied_nolocks; } @@ -122,7 +124,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now check for conflicting locks */ resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); @@ -153,7 +155,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; #if 0 /* If supplied state doesn't match current state, we assume it's @@ -196,7 +198,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Try to cancel request. */ resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); @@ -229,7 +231,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to remove the lock */ resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); @@ -368,7 +370,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to create the share */ resp->status = cast_status(nlmsvc_share_file(host, file, argp)); @@ -401,7 +403,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to unshare the file */ resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index c5f9113..7dac96e 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -135,12 +135,6 @@ out_unlock: out_free: kfree(file); -#ifdef CONFIG_LOCKD_V4 - if (nfserr == 1) - nfserr = nlm4_stale_fh; - else -#endif - nfserr = nlm_lck_denied; goto out_unlock; } diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 7b889ff..9b9e7e1 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -39,18 +39,20 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) fh_put(&fh); rqstp->rq_client = NULL; exp_readunlock(); - /* nlm and nfsd don't share error codes. - * we invent: 0 = no error - * 1 = stale file handle - * 2 = other error + /* We return nlm error codes as nlm doesn't know + * about nfsd, but nfsd does know about nlm.. */ switch (nfserr) { case nfs_ok: return 0; + case nfserr_dropit: + return nlm_drop_reply; +#ifdef CONFIG_LOCKD_V4 case nfserr_stale: - return 1; + return nlm4_stale_fh; +#endif default: - return 2; + return nlm_lck_denied; } } diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 81e3a18..aa50d89 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -10,6 +10,11 @@ #define LINUX_LOCKD_BIND_H #include +/* need xdr-encoded error codes too, so... */ +#include +#ifdef CONFIG_LOCKD_V4 +#include +#endif /* Dummy declarations */ struct svc_rqst; diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h index bb0a0f1..66fdae3 100644 --- a/include/linux/lockd/xdr.h +++ b/include/linux/lockd/xdr.h @@ -13,6 +13,8 @@ #include #include +struct svc_rqst; + #define NLM_MAXCOOKIELEN 32 #define NLM_MAXSTRLEN 1024 @@ -22,6 +24,8 @@ #define nlm_lck_blocked __constant_htonl(NLM_LCK_BLOCKED) #define nlm_lck_denied_grace_period __constant_htonl(NLM_LCK_DENIED_GRACE_PERIOD) +#define nlm_drop_reply __constant_htonl(30000) + /* Lock info passed via NLM */ struct nlm_lock { char * caller; diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index 1e65f2d..606cb21 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h @@ -56,7 +56,9 @@ enum rpc_accept_stat { RPC_PROG_MISMATCH = 2, RPC_PROC_UNAVAIL = 3, RPC_GARBAGE_ARGS = 4, - RPC_SYSTEM_ERR = 5 + RPC_SYSTEM_ERR = 5, + /* internal use only */ + RPC_DROP_REPLY = 60000, }; enum rpc_reject_stat { diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 953723b..ac69e55 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -74,6 +74,7 @@ struct xdr_buf { #define rpc_proc_unavail __constant_htonl(RPC_PROC_UNAVAIL) #define rpc_garbage_args __constant_htonl(RPC_GARBAGE_ARGS) #define rpc_system_err __constant_htonl(RPC_SYSTEM_ERR) +#define rpc_drop_reply __constant_htonl(RPC_DROP_REPLY) #define rpc_auth_ok __constant_htonl(RPC_AUTH_OK) #define rpc_autherr_badcred __constant_htonl(RPC_AUTH_BADCRED) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 2807fa0..eb44ec9 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -828,6 +828,11 @@ svc_process(struct svc_rqst *rqstp) *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); /* Encode reply */ + if (*statp == rpc_drop_reply) { + if (procp->pc_release) + procp->pc_release(rqstp, NULL, rqstp->rq_resp); + goto dropit; + } if (*statp == rpc_success && (xdr = procp->pc_encode) && !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) { dprintk("svc: failed to encode reply\n"); -- cgit v0.10.2 From 58ff407bee5a55f9c1188a3f9d70ffc79485183c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 17 Oct 2006 00:10:19 -0700 Subject: [PATCH] Fix IO error reporting on fsync() When IO error happens on metadata buffer, buffer is freed from memory and later fsync() is called, filesystems like ext2 fail to report EIO. We solve the problem by introducing a pointer to associated address space into the buffer_head. When a buffer is removed from a list of metadata buffers associated with an address space, IO error is transferred from the buffer to the address space, so that fsync can later report it. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/buffer.c b/fs/buffer.c index f65ef88..35527dc 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -452,6 +452,7 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate) bdevname(bh->b_bdev, b)); } set_bit(AS_EIO, &page->mapping->flags); + set_buffer_write_io_error(bh); clear_buffer_uptodate(bh); SetPageError(page); } @@ -571,6 +572,10 @@ EXPORT_SYMBOL(mark_buffer_async_write); static inline void __remove_assoc_queue(struct buffer_head *bh) { list_del_init(&bh->b_assoc_buffers); + WARN_ON(!bh->b_assoc_map); + if (buffer_write_io_error(bh)) + set_bit(AS_EIO, &bh->b_assoc_map->flags); + bh->b_assoc_map = NULL; } int inode_has_buffers(struct inode *inode) @@ -669,6 +674,7 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode) spin_lock(&buffer_mapping->private_lock); list_move_tail(&bh->b_assoc_buffers, &mapping->private_list); + bh->b_assoc_map = mapping; spin_unlock(&buffer_mapping->private_lock); } } @@ -765,7 +771,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) spin_lock(lock); while (!list_empty(list)) { bh = BH_ENTRY(list->next); - list_del_init(&bh->b_assoc_buffers); + __remove_assoc_queue(bh); if (buffer_dirty(bh) || buffer_locked(bh)) { list_add(&bh->b_assoc_buffers, &tmp); if (buffer_dirty(bh)) { @@ -786,7 +792,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) while (!list_empty(&tmp)) { bh = BH_ENTRY(tmp.prev); - __remove_assoc_queue(bh); + list_del_init(&bh->b_assoc_buffers); get_bh(bh); spin_unlock(lock); wait_on_buffer(bh); @@ -1167,6 +1173,7 @@ void __bforget(struct buffer_head *bh) spin_lock(&buffer_mapping->private_lock); list_del_init(&bh->b_assoc_buffers); + bh->b_assoc_map = NULL; spin_unlock(&buffer_mapping->private_lock); } __brelse(bh); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 131ffd3..5d9fb0e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -69,6 +69,8 @@ struct buffer_head { bh_end_io_t *b_end_io; /* I/O completion */ void *b_private; /* reserved for b_end_io */ struct list_head b_assoc_buffers; /* associated with another mapping */ + struct address_space *b_assoc_map; /* mapping this buffer is + associated with */ atomic_t b_count; /* users using this buffer_head */ }; -- cgit v0.10.2 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 diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index aecbbe2..3c17112 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 179c287..29a8818a 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 v0.10.2 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 diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c index ac06f10..d96c687 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 7bd4d85..91f95d1 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 v0.10.2 From eee44cca665aa1a5663e6a00c2bdfc275739dac5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:23 -0700 Subject: [PATCH] fs/partitions/check: add sysfs error handling Handle errors thrown in disk_sysfs_symlinks(), and propagate back to caller. The callers and associated functions don't do a real good job of handling kobject errors anyway (add_partition, register_disk, rescan_partitions), so this should do until something better comes along. Signed-off-by: Jeff Garzik Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 51c6a74..6fb4b61 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -376,18 +376,48 @@ static char *make_block_name(struct gendisk *disk) return name; } -static void disk_sysfs_symlinks(struct gendisk *disk) +static int disk_sysfs_symlinks(struct gendisk *disk) { struct device *target = get_device(disk->driverfs_dev); + int err; + char *disk_name = NULL; + if (target) { - char *disk_name = make_block_name(disk); - sysfs_create_link(&disk->kobj,&target->kobj,"device"); - if (disk_name) { - sysfs_create_link(&target->kobj,&disk->kobj,disk_name); - kfree(disk_name); + disk_name = make_block_name(disk); + if (!disk_name) { + err = -ENOMEM; + goto err_out; } + + err = sysfs_create_link(&disk->kobj, &target->kobj, "device"); + if (err) + goto err_out_disk_name; + + err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name); + if (err) + goto err_out_dev_link; } - sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem"); + + err = sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, + "subsystem"); + if (err) + goto err_out_disk_name_lnk; + + kfree(disk_name); + + return 0; + +err_out_disk_name_lnk: + if (target) { + sysfs_remove_link(&target->kobj, disk_name); +err_out_dev_link: + sysfs_remove_link(&disk->kobj, "device"); +err_out_disk_name: + kfree(disk_name); +err_out: + put_device(target); + } + return err; } /* Not exported, helper to add_disk(). */ @@ -406,7 +436,11 @@ void register_disk(struct gendisk *disk) *s = '!'; if ((err = kobject_add(&disk->kobj))) return; - disk_sysfs_symlinks(disk); + err = disk_sysfs_symlinks(disk); + if (err) { + kobject_del(&disk->kobj); + return; + } disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ -- cgit v0.10.2 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 diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 09b714f..3b58d3d 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 v0.10.2 From 3864c4894a7f4c03d69a90082a5bb0ab10e437ab Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 17 Oct 2006 00:10:26 -0700 Subject: [PATCH] lockdep: annotate i386 apm Lockdep doesn't like to enable interrupts when they are enabled already. BUG: warning at kernel/lockdep.c:1814/trace_hardirqs_on() (Not tainted) [] show_trace_log_lvl+0x58/0x16a [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] trace_hardirqs_on+0xa2/0x11e [] apm_bios_call_simple+0xcd/0xfd [] apm+0x92/0x5b1 [] kernel_thread_helper+0x5/0xb DWARF2 unwinder stuck at kernel_thread_helper+0x5/0xb Leftover inexact backtrace: [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] trace_hardirqs_on+0xa2/0x11e [] apm_bios_call_simple+0xcd/0xfd [] apm+0x92/0x5b1 [] kernel_thread_helper+0x5/0xb Signed-off-by: Peter Zijlstra Cc: Stephen Rothwell Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index b42f2d9..2af6585 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -540,11 +540,30 @@ static inline void apm_restore_cpus(cpumask_t mask) * Also, we KNOW that for the non error case of apm_bios_call, there * is no useful data returned in the low order 8 bits of eax. */ -#define APM_DO_CLI \ - if (apm_info.allow_ints) \ - local_irq_enable(); \ - else \ + +static inline unsigned long __apm_irq_save(void) +{ + unsigned long flags; + local_save_flags(flags); + if (apm_info.allow_ints) { + if (irqs_disabled_flags(flags)) + local_irq_enable(); + } else + local_irq_disable(); + + return flags; +} + +#define apm_irq_save(flags) \ + do { flags = __apm_irq_save(); } while (0) + +static inline void apm_irq_restore(unsigned long flags) +{ + if (irqs_disabled_flags(flags)) local_irq_disable(); + else if (irqs_disabled()) + local_irq_enable(); +} #ifdef APM_ZERO_SEGS # define APM_DECL_SEGS \ @@ -596,12 +615,11 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; - local_save_flags(flags); - APM_DO_CLI; + apm_irq_save(flags); APM_DO_SAVE_SEGS; apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); APM_DO_RESTORE_SEGS; - local_irq_restore(flags); + apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); @@ -640,12 +658,11 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; - local_save_flags(flags); - APM_DO_CLI; + apm_irq_save(flags); APM_DO_SAVE_SEGS; error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); APM_DO_RESTORE_SEGS; - local_irq_restore(flags); + apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); -- cgit v0.10.2 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 diff --git a/drivers/block/rd.c b/drivers/block/rd.c index a3f64bf..485aa87 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 v0.10.2 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 diff --git a/drivers/char/epca.c b/drivers/char/epca.c index c3f9558..706733c 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 v0.10.2 From 3f3fd3c055853d11295a1ec6cdc81e37e2182d16 Mon Sep 17 00:00:00 2001 From: Greg Banks Date: Tue, 17 Oct 2006 00:10:30 -0700 Subject: [PATCH] kbuild: allow multi-word $M in Makefile.modpost Some people want to do crazy things like pass multiple directories as the value of $(SUBDIRS) or $M. Mostly this kinda works, except that Makefile.modpost constructs a modpost commandline which fails modpost's argument parsing. This patch fixes that little wrinkle. Signed-off-by: Greg Banks Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 6c5469b..65e0a79 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -44,7 +44,7 @@ include scripts/Kbuild.include include scripts/Makefile.lib kernelsymfile := $(objtree)/Module.symvers -modulesymfile := $(KBUILD_EXTMOD)/Module.symvers +modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers # Step 1), find all modules listed in $(MODVERDIR)/ __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) -- cgit v0.10.2 From 91b943ee4afa2037678dc1db30b89baef0e17090 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 17 Oct 2006 00:10:32 -0700 Subject: [PATCH] Add entry.S labels to tag file Add functions defined using ENTRY macro to the tags file. Signed-off-by: Aneesh Kumar K.V Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 703d40a..62a1343 100644 --- a/Makefile +++ b/Makefile @@ -1319,7 +1319,8 @@ define xtags $(all-sources) | xargs $1 -a \ -I __initdata,__exitdata,__acquires,__releases \ -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ - --extra=+f --c-kinds=+px; \ + --extra=+f --c-kinds=+px \ + --regex-asm='/ENTRY\(([^)]*)\).*/\1/'; \ $(all-kconfigs) | xargs $1 -a \ --langdef=kconfig \ --language-force=kconfig \ -- cgit v0.10.2 From bea493a031fe3337f4fe5479e8e865513828ea76 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 17 Oct 2006 00:10:33 -0700 Subject: [PATCH] rt-mutex: fixup rt-mutex debug code BUG: warning at kernel/rtmutex-debug.c:125/rt_mutex_debug_task_free() (Not tainted) [] show_trace_log_lvl+0x58/0x16a [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] rt_mutex_debug_task_free+0x35/0x6a [] free_task+0x15/0x24 [] copy_process+0x12bd/0x1324 [] do_fork+0x42/0x113 [] sys_fork+0x19/0x1b [] syscall_call+0x7/0xb In copy_process(), dup_task_struct() also duplicates the ->pi_lock, ->pi_waiters and ->pi_blocked_on members. rt_mutex_debug_task_free() called from free_task() validates these members. However free_task() can be invoked before these members are reset for the new task. Move the initialization code before the first bail that can hit free_task(). Signed-off-by: Peter Zijlstra Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 7dc6140..29ebb30 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -984,6 +984,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (!p) goto fork_out; + rt_mutex_init_task(p); + #ifdef CONFIG_TRACE_IRQFLAGS DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); @@ -1088,8 +1090,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->lockdep_recursion = 0; #endif - rt_mutex_init_task(p); - #ifdef CONFIG_DEBUG_MUTEXES p->blocked_on = NULL; /* not blocked yet */ #endif -- cgit v0.10.2 From bd5349cfd2b9bbb10a3dbcd3fe5cbaabe0b2ab9e Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 17 Oct 2006 00:10:35 -0700 Subject: [PATCH] Convert cpu hotplug notifiers to use raw_notifier instead of blocking_notifier The use of blocking notifier by _cpu_up and _cpu_down in cpu.c has two problem. 1/ An interaction with the workqueue notifier causes lockdep to spit a warning. 2/ A notifier could conceivable be added or removed while _cpu_up or _cpu_down are in process. As each notifier is called twice (prepare then commit/abort) this could be unhealthy. To fix to we simply take cpu_add_remove_lock while adding or removing notifiers to/from the list. This makes the 'blocking' usage unnecessary as all accesses to cpu_chain are now protected by cpu_add_remove_lock. So change "blocking" to "raw" in all relevant places. This fixes 1. Credit: Andrew Morton Cc: Rusty Russell Cc: Michal Piotrowski (reporter) Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/cpu.c b/kernel/cpu.c index 32c9662..27dd3ee 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -19,7 +19,7 @@ static DEFINE_MUTEX(cpu_add_remove_lock); static DEFINE_MUTEX(cpu_bitmask_lock); -static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain); +static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain); /* If set, cpu_up and cpu_down will return -EBUSY and do nothing. * Should always be manipulated under cpu_add_remove_lock @@ -68,7 +68,11 @@ EXPORT_SYMBOL_GPL(unlock_cpu_hotplug); /* Need to know about CPUs going up/down? */ int __cpuinit register_cpu_notifier(struct notifier_block *nb) { - return blocking_notifier_chain_register(&cpu_chain, nb); + int ret; + mutex_lock(&cpu_add_remove_lock); + ret = raw_notifier_chain_register(&cpu_chain, nb); + mutex_unlock(&cpu_add_remove_lock); + return ret; } #ifdef CONFIG_HOTPLUG_CPU @@ -77,7 +81,9 @@ EXPORT_SYMBOL(register_cpu_notifier); void unregister_cpu_notifier(struct notifier_block *nb) { - blocking_notifier_chain_unregister(&cpu_chain, nb); + mutex_lock(&cpu_add_remove_lock); + raw_notifier_chain_unregister(&cpu_chain, nb); + mutex_unlock(&cpu_add_remove_lock); } EXPORT_SYMBOL(unregister_cpu_notifier); @@ -126,7 +132,7 @@ static int _cpu_down(unsigned int cpu) if (!cpu_online(cpu)) return -EINVAL; - err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, + err = raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, (void *)(long)cpu); if (err == NOTIFY_BAD) { printk("%s: attempt to take down CPU %u failed\n", @@ -146,7 +152,7 @@ static int _cpu_down(unsigned int cpu) if (IS_ERR(p)) { /* CPU didn't die: tell everyone. Can't complain. */ - if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, + if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, (void *)(long)cpu) == NOTIFY_BAD) BUG(); @@ -169,7 +175,7 @@ static int _cpu_down(unsigned int cpu) put_cpu(); /* CPU is completely dead: tell everyone. Too late to complain. */ - if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD, + if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu) == NOTIFY_BAD) BUG(); @@ -206,7 +212,7 @@ static int __devinit _cpu_up(unsigned int cpu) if (cpu_online(cpu) || !cpu_present(cpu)) return -EINVAL; - ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); + ret = raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); if (ret == NOTIFY_BAD) { printk("%s: attempt to bring up CPU %u failed\n", __FUNCTION__, cpu); @@ -223,11 +229,11 @@ static int __devinit _cpu_up(unsigned int cpu) BUG_ON(!cpu_online(cpu)); /* Now call notifier in preparation. */ - blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); + raw_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); out_notify: if (ret != 0) - blocking_notifier_call_chain(&cpu_chain, + raw_notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); return ret; -- cgit v0.10.2 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 diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index 160f22f..8bbe33a 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 461e831..729df40 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 c4301e8..fcd4992 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 1c0d54a..1fadf01 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 v0.10.2 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 diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index fabbd46..23afba4 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 d699fe5..0d458a8 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 v0.10.2 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 diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c3d79ee..69aee26 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 v0.10.2 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 diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index d10c8b8..b6f9476 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 e4823ab2..785b085 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 6649f8b..730bbd0 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 23afba4..c3ae2ed 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 94f2148..6ead5e1 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 v0.10.2 From 7281c248f797723f66244b7ecef204620f664648 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:49:50 +0100 Subject: [ARM] switch to new pci_get_bus_and_slot API Signed-off-by: Alan Cox Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c index a6f1480..9ee6383 100644 --- a/arch/arm/mach-ixp2000/ixdp2400.c +++ b/arch/arm/mach-ixp2000/ixdp2400.c @@ -133,11 +133,13 @@ static void ixdp2400_pci_postinit(void) struct pci_dev *dev; if (ixdp2x00_master_npu()) { - dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN); + dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); + pci_dev_put(dev) } else { - dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN); + dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); + pci_dev_put(dev) ixdp2x00_slave_pci_postinit(); } diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c index 91d36d9..70d247f 100644 --- a/arch/arm/mach-ixp2000/ixdp2800.c +++ b/arch/arm/mach-ixp2000/ixdp2800.c @@ -261,14 +261,16 @@ int __init ixdp2800_pci_init(void) pci_common_init(&ixdp2800_pci); if (ixdp2x00_master_npu()) { - dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); + dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); + pci_dev_put(dev); ixdp2800_master_enable_slave(); ixdp2800_master_wait_for_slave_bus_scan(); } else { - dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); + dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); + pci_dev_put(dev); } } diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c index af48cb5..aa26550 100644 --- a/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/arch/arm/mach-ixp2000/ixdp2x00.c @@ -241,11 +241,14 @@ void ixdp2x00_slave_pci_postinit(void) /* * Remove PMC device is there is one */ - if((dev = pci_find_slot(1, IXDP2X00_PMC_DEVFN))) + if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) { pci_remove_bus_device(dev); + pci_dev_put(dev); + } - dev = pci_find_slot(0, IXDP2X00_21555_DEVFN); + dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN); pci_remove_bus_device(dev); + pci_dev_put(dev); } /************************************************************************** -- cgit v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c10e7f5..9e31efe 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 9e31efe..bd5ccae 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bd5ccae..2747e2f 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2747e2f..88b12e8 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 v0.10.2 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. diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 43d2acc..0a8d821 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 88b12e8..6a594b0 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6a594b0..20a8c34 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 20a8c34..b8f2021 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 0a8d821..3f05492 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b8f2021..6eddd0f 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6eddd0f..c193383 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c193383..67ecd66 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 v0.10.2 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 diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 3f05492..6d2a23f 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 v0.10.2 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 diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 2d12837..a7d29bd 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 v0.10.2 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 diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 23b95b2..34b7a31 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 aac6ec5..9030994 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 2012213..1b20722 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 35e3fab..e51c1ed8 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 4632727..62e46dc 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 6aac39f..bbc3082 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 v0.10.2 From 3bbe486b361b317ac7103378ed3d1aab4779715e Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 17 Oct 2006 14:28:16 -0700 Subject: [IA64] perfmon fix for global IRQ fix Missed one piece of ia64 fallout from the global IRQ patch 7d12e780e003f93433d49ce78cfedf4b4c52adc5 Perfmon interrupt handler needs to use get_irq_regs() too. Acked-by: stephane eranian Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 281004f..3aaede0 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -5558,12 +5558,13 @@ report_spurious2: } static irqreturn_t -pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) +pfm_interrupt_handler(int irq, void *arg) { unsigned long start_cycles, total_cycles; unsigned long min, max; int this_cpu; int ret; + struct pt_regs *regs = get_irq_regs(); this_cpu = get_cpu(); if (likely(!pfm_alt_intr_handler)) { -- cgit v0.10.2 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 diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 295f459..71437db 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 7b3840e..1cf08f0 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 d233c37..3c27f9b 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 aa31d22..92726fe 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 ceae7bf..a1d9ce0 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 v0.10.2 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 diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 3c27f9b..31379b8 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 v0.10.2 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 diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 31379b8..3498b89 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 v0.10.2 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 diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 2c19f19..392a512 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 v0.10.2 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 diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ec4d1d7..daecdf0 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 v0.10.2 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 diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 957d4ad..9ef9075 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 v0.10.2 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 diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 9ef9075..7c906a4 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); @@ -872,6 +900,42 @@ static void kaweth_tx_timeout(struct net_device *net) } /**************************************************************** + * 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 ****************************************************************/ static int kaweth_probe( -- cgit v0.10.2 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 diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 82cb22f..2dbb774 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 v0.10.2 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 diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index f5434b1..68b5d0d 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 v0.10.2 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 diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 68b5d0d..88585da 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 v0.10.2 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 diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 88585da..5705298 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 v0.10.2 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 diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index daecdf0..9a9012f 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c9a8d50..0a846e4 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 v0.10.2 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 diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 309073f..ab091fa 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 v0.10.2 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 diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 7c7b507..c870c80 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 v0.10.2 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 diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 3892a9e..e656563 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 v0.10.2 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 diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a161d70..809d465 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 v0.10.2 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 diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 0eb26a2..37d1f4e 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 v0.10.2 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 diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 45ee692..226bf3d 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 v0.10.2 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 diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 3ebb901..40ba76a 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 v0.10.2 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 diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 40ba76a..3b2d137 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 v0.10.2 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 diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 82ce035..f6971b8 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 24bd348..af6d061 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 v0.10.2 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 diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 724822c..fed92be 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 v0.10.2 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 diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 0540596..454a186 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 160f19d..7b51964 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 0000000..0266090 --- /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 v0.10.2 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 diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index c73dd22..5edd053 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 0266090..23a8066 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 af6d061..decc1b1 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 c0746f0..743947c 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 v0.10.2 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 diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 5edd053..881841e 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 23a8066..6240b97 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 decc1b1..cf3d20e 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 743947c..07c70ab 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 v0.10.2 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 diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 97d57cf..825bf88 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 21cd226..20db364 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 71437db..d946d52 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 33cd91d..0000000 --- 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 c29658f..a74bf86 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 2be70fa..11dc595 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 0000000..33cd91d --- /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 v0.10.2 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 diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5076b9d..8ca6d3f 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 8dce833..a5047dc 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 0000000..82cd15b --- /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 v0.10.2 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 diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index aecd633..af2934e 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0a846e4..0093d9f 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 v0.10.2 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 diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 37d1f4e..9b591b8 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 v0.10.2 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 diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 021be39..5b71962 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0093d9f..802f3a3 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 v0.10.2 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 diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index ab091fa..ec63b0e 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 802f3a3..37ed8e0 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 v0.10.2 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 diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 392a512..ba93c72 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a6738a8..feabda7 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 v0.10.2 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 diff --git a/Documentation/input/xpad.txt b/Documentation/input/xpad.txt index b9111a7..5427bdf 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 cebb6c4..6a12a94 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 v0.10.2 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 diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 5705298..f6b9f7e 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 v0.10.2 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 diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index f26c1cd..2902742 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 v0.10.2 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 diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index d954daa..7cfe0e5 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 v0.10.2 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 diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 486c741..bbf6532 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 v0.10.2 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 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d3dc1a1..bd76b4c 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 v0.10.2 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 diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 8ca6d3f..9a6ec1b 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 ba93c72..7f5d546 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 d29638d..39799d2 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 v0.10.2 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 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 39799d2..6bdb117 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 v0.10.2 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 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 6bdb117..ea16572 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 v0.10.2 From ffc45571dfb4b70e7eda8d97f64a05f5e5a992ac Mon Sep 17 00:00:00 2001 From: Aron Griffis Date: Tue, 17 Oct 2006 00:28:15 -0400 Subject: [IA64] move ioremap/ioremap_nocache under __KERNEL__ I noticed these are declared extern outside of __KERNEL__, but surely they wouldn't be available to userland since they're defined in ioremap.c. Am I missing something here? If I'm right about this, then there's probably a good deal of other stuff in io.h that could move inside __KERNEL__, but at least this is a start. Signed-off-by: Aron Griffis Signed-off-by: Tony Luck diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index 43bfff6..855c30a 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h @@ -417,6 +417,8 @@ __writeq (unsigned long val, volatile void __iomem *addr) # define outl_p outl #endif +# ifdef __KERNEL__ + extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); @@ -430,8 +432,6 @@ iounmap (volatile void __iomem *addr) #define dmi_iounmap(x,l) iounmap(x) #define dmi_alloc(l) kmalloc(l, GFP_ATOMIC) -# ifdef __KERNEL__ - /* * String version of IO memory access ops: */ -- cgit v0.10.2 From accaddb27a2d544e38e10ff2a2782b33bbbad913 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 16 Oct 2006 12:56:54 -0500 Subject: [IA64] - Allow IPIs in timer loop Allow pending IPIs to interrupt a timer interrupt that is looping in the do_timer() "while" loop in timer_interrupt(). (Interrupts are allowed at only 1 spot in the code). Signed-off-by: Jack Steiner Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 41169a9..39e0cd3 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -84,6 +84,12 @@ timer_interrupt (int irq, void *dev_id) if (time_after(new_itm, ia64_get_itc())) break; + + /* + * Allow IPIs to interrupt the timer loop. + */ + local_irq_enable(); + local_irq_disable(); } do { -- cgit v0.10.2 From c12fb1885787dcc2e20c4b88149e1e607e1293b2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 12 Oct 2006 16:20:59 -0600 Subject: [IA64] remove unused PAL_CALL_IC_OFF Linux maps PAL instructions with an ITR, but uses a DTC for PAL data. Section 11.10.2.1.3, "Making PAL Procedures Calls in Physical or Virtual Mode," of the SDM (rev 2.2), says we must therefore make all PAL calls with PSR.ic = 1 so that Linux can handle any TLB faults. PAL_CALL_IC_OFF is currently unused, and as long as we use the ITR + DTC strategy, we can't use it. So remove it. I also removed the code in ia64_pal_call_static() that conditionally cleared PSR.ic. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index ebaf1e6..5f50e6b 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -50,12 +50,10 @@ END(ia64_pal_default_handler) * * in0 Index of PAL service * in1 - in3 Remaining PAL arguments - * in4 1 ==> clear psr.ic, 0 ==> don't clear psr.ic - * */ GLOBAL_ENTRY(ia64_pal_call_static) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) - alloc loc1 = ar.pfs,5,5,0,0 + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4) + alloc loc1 = ar.pfs,4,5,0,0 movl loc2 = pal_entry_point 1: { mov r28 = in0 @@ -64,7 +62,6 @@ GLOBAL_ENTRY(ia64_pal_call_static) } ;; ld8 loc2 = [loc2] // loc2 <- entry point - tbit.nz p6,p7 = in4, 0 adds r8 = 1f-1b,r8 mov loc4=ar.rsc // save RSE configuration ;; @@ -74,13 +71,11 @@ GLOBAL_ENTRY(ia64_pal_call_static) .body mov r30 = in2 -(p6) rsm psr.i | psr.ic mov r31 = in3 mov b7 = loc2 -(p7) rsm psr.i + rsm psr.i ;; -(p6) srlz.i mov rp = r8 br.cond.sptk.many b7 1: mov psr.l = loc3 diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h index 2c8fd92..4283ddc 100644 --- a/include/asm-ia64/pal.h +++ b/include/asm-ia64/pal.h @@ -764,7 +764,7 @@ struct ia64_pal_retval { * (generally 0) MUST be passed. Reserved parameters are not optional * parameters. */ -extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64, u64); +extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64); extern struct ia64_pal_retval ia64_pal_call_stacked (u64, u64, u64, u64); extern struct ia64_pal_retval ia64_pal_call_phys_static (u64, u64, u64, u64); extern struct ia64_pal_retval ia64_pal_call_phys_stacked (u64, u64, u64, u64); @@ -774,14 +774,7 @@ extern void ia64_load_scratch_fpregs (struct ia64_fpreg *); #define PAL_CALL(iprv,a0,a1,a2,a3) do { \ struct ia64_fpreg fr[6]; \ ia64_save_scratch_fpregs(fr); \ - iprv = ia64_pal_call_static(a0, a1, a2, a3, 0); \ - ia64_load_scratch_fpregs(fr); \ -} while (0) - -#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) do { \ - struct ia64_fpreg fr[6]; \ - ia64_save_scratch_fpregs(fr); \ - iprv = ia64_pal_call_static(a0, a1, a2, a3, 1); \ + iprv = ia64_pal_call_static(a0, a1, a2, a3); \ ia64_load_scratch_fpregs(fr); \ } while (0) -- cgit v0.10.2 From 4d5a31977cc69be8786e0033d5c148e5c62ae949 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 12 Oct 2006 16:21:17 -0600 Subject: [IA64] reformat pal.S to fit in 80 columns, fix typos Reformat to fit in 80 columns. Fix a couple typos. Remove a couple unused labels. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index 5f50e6b..0b53344 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -21,11 +21,12 @@ pal_entry_point: .text /* - * Set the PAL entry point address. This could be written in C code, but we do it here - * to keep it all in one module (besides, it's so trivial that it's + * Set the PAL entry point address. This could be written in C code, but we + * do it here to keep it all in one module (besides, it's so trivial that it's * not a big deal). * - * in0 Address of the PAL entry point (text address, NOT a function descriptor). + * in0 Address of the PAL entry point (text address, NOT a function + * descriptor). */ GLOBAL_ENTRY(ia64_pal_handler_init) alloc r3=ar.pfs,1,0,0,0 @@ -36,9 +37,9 @@ GLOBAL_ENTRY(ia64_pal_handler_init) END(ia64_pal_handler_init) /* - * Default PAL call handler. This needs to be coded in assembly because it uses - * the static calling convention, i.e., the RSE may not be used and calls are - * done via "br.cond" (not "br.call"). + * Default PAL call handler. This needs to be coded in assembly because it + * uses the static calling convention, i.e., the RSE may not be used and + * calls are done via "br.cond" (not "br.call"). */ GLOBAL_ENTRY(ia64_pal_default_handler) mov r8=-1 @@ -91,8 +92,8 @@ END(ia64_pal_call_static) * Make a PAL call using the stacked registers calling convention. * * Inputs: - * in0 Index of PAL service - * in2 - in3 Remaning PAL arguments + * in0 Index of PAL service + * in2 - in3 Remaining PAL arguments */ GLOBAL_ENTRY(ia64_pal_call_stacked) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4) @@ -126,18 +127,18 @@ END(ia64_pal_call_stacked) * Make a physical mode PAL call using the static registers calling convention. * * Inputs: - * in0 Index of PAL service - * in2 - in3 Remaning PAL arguments + * in0 Index of PAL service + * in2 - in3 Remaining PAL arguments * * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel. * So we don't need to clear them. */ -#define PAL_PSR_BITS_TO_CLEAR \ - (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT | \ - IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \ +#define PAL_PSR_BITS_TO_CLEAR \ + (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT |\ + IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \ IA64_PSR_DFL | IA64_PSR_DFH) -#define PAL_PSR_BITS_TO_SET \ +#define PAL_PSR_BITS_TO_SET \ (IA64_PSR_BN) @@ -173,7 +174,7 @@ GLOBAL_ENTRY(ia64_pal_call_phys_static) ;; andcm r16=loc3,r16 // removes bits to clear from psr br.call.sptk.many rp=ia64_switch_mode_phys -.ret1: mov rp = r8 // install return address (physical) + mov rp = r8 // install return address (physical) mov loc5 = r19 mov loc6 = r20 br.cond.sptk.many b7 @@ -183,7 +184,6 @@ GLOBAL_ENTRY(ia64_pal_call_phys_static) mov r19=loc5 mov r20=loc6 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode -.ret2: mov psr.l = loc3 // restore init PSR mov ar.pfs = loc1 @@ -198,8 +198,8 @@ END(ia64_pal_call_phys_static) * Make a PAL call using the stacked registers in physical mode. * * Inputs: - * in0 Index of PAL service - * in2 - in3 Remaning PAL arguments + * in0 Index of PAL service + * in2 - in3 Remaining PAL arguments */ GLOBAL_ENTRY(ia64_pal_call_phys_stacked) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) @@ -207,7 +207,7 @@ GLOBAL_ENTRY(ia64_pal_call_phys_stacked) movl loc2 = pal_entry_point 1: { mov r28 = in0 // copy procedure index - mov loc0 = rp // save rp + mov loc0 = rp // save rp } .body ;; @@ -240,7 +240,7 @@ GLOBAL_ENTRY(ia64_pal_call_phys_stacked) mov r16=loc3 // r16= original psr mov r19=loc5 mov r20=loc6 - br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode + br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode mov psr.l = loc3 // restore init PSR mov ar.pfs = loc1 @@ -252,10 +252,11 @@ GLOBAL_ENTRY(ia64_pal_call_phys_stacked) END(ia64_pal_call_phys_stacked) /* - * Save scratch fp scratch regs which aren't saved in pt_regs already (fp10-fp15). + * Save scratch fp scratch regs which aren't saved in pt_regs already + * (fp10-fp15). * - * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch - * regs fp-low partition. + * NOTE: We need to do this since firmware (SAL and PAL) may use any of the + * scratch regs fp-low partition. * * Inputs: * in0 Address of stack storage for fp regs -- cgit v0.10.2 From 8611342f3dda0e13970e724129a8e2066de1362e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 9 Oct 2006 05:24:57 -0400 Subject: [IA64] update sn2_defconfig The current sn2_defconfig is obsolete, in particular the recent ATA changes are a pain, so here's a patch to get things in sync ... at least for a day or two :) Update sn_defconfig to match current community kernel tree. Signed-off-by: Jes Sorensen Signed-off-by: Tony Luck diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 0f14a82..64e951d 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -1,8 +1,9 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc3 -# Thu Apr 27 11:48:23 2006 +# Linux kernel version: 2.6.19-rc1 +# Mon Oct 9 10:53:59 2006 # +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options @@ -18,16 +19,22 @@ CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +CONFIG_TASKSTATS=y +# CONFIG_TASK_DELAY_ACCT is not set +# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_CPUSETS=y CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_TASK_XACCT=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -40,6 +47,8 @@ CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -58,6 +67,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # @@ -89,7 +99,7 @@ CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_IA64_UNCACHED_ALLOCATOR=y -CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set # CONFIG_IA64_DIG is not set # CONFIG_IA64_HP_ZX1 is not set @@ -116,6 +126,7 @@ CONFIG_FORCE_MAX_ZONEORDER=17 CONFIG_SMP=y CONFIG_NR_CPUS=1024 # CONFIG_HOTPLUG_CPU is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_SCHED_SMT=y CONFIG_PREEMPT=y CONFIG_SELECT_MEMORY_MODEL=y @@ -128,6 +139,7 @@ CONFIG_NEED_MULTIPLE_NODES=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -135,15 +147,24 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y CONFIG_NUMA=y CONFIG_NODES_SHIFT=10 +CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y CONFIG_SGI_SN=y +# CONFIG_IA64_ESI is not set + +# +# SN Devices +# +CONFIG_SGI_IOC4=y +CONFIG_SGI_IOC3=y # # Firmware Drivers @@ -159,6 +180,7 @@ CONFIG_BINFMT_ELF=y CONFIG_PM=y # CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set +# CONFIG_PM_SYSFS_DEPRECATED is not set # # ACPI (Advanced Configuration and Power Interface) Support @@ -166,6 +188,7 @@ CONFIG_PM=y CONFIG_ACPI=y # CONFIG_ACPI_BUTTON is not set # CONFIG_ACPI_FAN is not set +# CONFIG_ACPI_DOCK is not set # CONFIG_ACPI_PROCESSOR is not set CONFIG_ACPI_NUMA=y CONFIG_ACPI_BLACKLIST_YEAR=0 @@ -185,7 +208,12 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCIEAER=y # CONFIG_PCI_MSI is not set +# CONFIG_PCI_MULTITHREAD_PROBE is not set # CONFIG_PCI_DEBUG is not set # @@ -215,6 +243,9 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -231,19 +262,31 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=m CONFIG_INET_TCP_DIAG=m # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set # CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -269,7 +312,6 @@ CONFIG_IPV6=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -298,6 +340,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -335,6 +378,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set CONFIG_ATA_OVER_ETH=m @@ -381,6 +425,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_IT821X is not set @@ -404,6 +449,7 @@ CONFIG_IDEDMA_AUTO=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y # @@ -425,12 +471,14 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m CONFIG_SCSI_SAS_ATTRS=y +CONFIG_SCSI_SAS_LIBSAS=y +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set # # SCSI low-level drivers @@ -443,46 +491,82 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set -# CONFIG_SCSI_SATA_SVW is not set -# CONFIG_SCSI_ATA_PIIX is not set -# CONFIG_SCSI_SATA_MV is not set -# CONFIG_SCSI_SATA_NV is not set -# CONFIG_SCSI_PDC_ADMA is not set -# CONFIG_SCSI_SATA_QSTOR is not set -# CONFIG_SCSI_SATA_PROMISE is not set -# CONFIG_SCSI_SATA_SX4 is not set -# CONFIG_SCSI_SATA_SIL is not set -# CONFIG_SCSI_SATA_SIL24 is not set -# CONFIG_SCSI_SATA_SIS is not set -# CONFIG_SCSI_SATA_ULI is not set -# CONFIG_SCSI_SATA_VIA is not set -CONFIG_SCSI_SATA_VITESSE=y +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set CONFIG_SCSI_QLOGIC_1280=y CONFIG_SCSI_QLA_FC=y -CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y -# CONFIG_SCSI_QLA21XX is not set -CONFIG_SCSI_QLA22XX=y -CONFIG_SCSI_QLA2300=y -CONFIG_SCSI_QLA2322=y -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set # +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +CONFIG_ATA=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +CONFIG_SATA_VITESSE=y +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# # Multi-device support (RAID and LVM) # CONFIG_MD=y @@ -491,12 +575,12 @@ CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y # CONFIG_MD_RAID10 is not set -CONFIG_MD_RAID5=y +CONFIG_MD_RAID456=y # CONFIG_MD_RAID5_RESHAPE is not set -# CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=y # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m @@ -563,6 +647,7 @@ CONFIG_NETDEVICES=y # CONFIG_SK98LIN is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set # # Ethernet (10000 Mbit) @@ -571,6 +656,7 @@ CONFIG_CHELSIO_T1=m # CONFIG_IXGB is not set CONFIG_S2IO=m # CONFIG_S2IO_NAPI is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -612,6 +698,7 @@ CONFIG_NET_POLL_CONTROLLER=y # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -646,6 +733,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -659,10 +747,12 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set CONFIG_SGI_SNSC=y CONFIG_SGI_TIOCX=y CONFIG_SGI_MBCS=m +CONFIG_MSPEC=y # # Serial drivers @@ -701,6 +791,7 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set # CONFIG_AGP_VIA is not set CONFIG_AGP_SGI_TIOCA=y # CONFIG_DRM is not set @@ -730,7 +821,6 @@ CONFIG_MMTIMER=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support @@ -741,6 +831,7 @@ CONFIG_MMTIMER=y # # Misc devices # +# CONFIG_TIFM_CORE is not set # # Multimedia devices @@ -756,6 +847,7 @@ CONFIG_MMTIMER=y # # Graphics support # +CONFIG_FIRMWARE_EDID=y # CONFIG_FB is not set # @@ -764,6 +856,7 @@ CONFIG_MMTIMER=y CONFIG_VGA_CONSOLE=y # CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -794,6 +887,7 @@ CONFIG_USB=m CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=m # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -843,6 +937,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -874,15 +969,18 @@ CONFIG_USB_MON=y # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set @@ -919,18 +1017,15 @@ CONFIG_USB_MON=y CONFIG_INFINIBAND=m # CONFIG_INFINIBAND_USER_MAD is not set CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_MTHCA_DEBUG=y +# CONFIG_INFINIBAND_AMSO1100 is not set CONFIG_INFINIBAND_IPOIB=m CONFIG_INFINIBAND_IPOIB_DEBUG=y # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set CONFIG_INFINIBAND_SRP=m - -# -# SN Devices -# -CONFIG_SGI_IOC4=y -CONFIG_SGI_IOC3=y +# CONFIG_INFINIBAND_ISER is not set # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -942,6 +1037,19 @@ CONFIG_SGI_IOC3=y # CONFIG_RTC_CLASS is not set # +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# # File systems # CONFIG_EXT2_FS=y @@ -965,15 +1073,16 @@ CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y CONFIG_XFS_QUOTA=y # CONFIG_XFS_SECURITY is not set CONFIG_XFS_POSIX_ACL=y CONFIG_XFS_RT=y +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set @@ -1007,8 +1116,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -1046,7 +1157,7 @@ CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y +CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m @@ -1056,7 +1167,9 @@ CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1129,6 +1242,10 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y # +# Distributed Lock Manager +# + +# # Library routines # # CONFIG_CRC_CCITT is not set @@ -1138,9 +1255,11 @@ CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m CONFIG_GENERIC_ALLOCATOR=y +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1152,20 +1271,26 @@ CONFIG_GENERIC_PENDING_IRQ=y # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_PREEMPT=y -# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_IA64_GRANULE_16MB=y @@ -1186,6 +1311,10 @@ CONFIG_SYSVIPC_COMPAT=y # Cryptographic options # CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=m CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set @@ -1195,6 +1324,8 @@ CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set -- cgit v0.10.2 From 219902677351665bf0513115592a6dd665cf06e8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 29 Sep 2006 12:58:31 -0600 Subject: [IA64] remove unused acpi_kbd_controller_present, acpi_legacy_devices Nobody uses either one anymore. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 32c3abed..73ef4a85 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -64,9 +64,6 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); EXPORT_SYMBOL(pm_power_off); -unsigned char acpi_kbd_controller_present = 1; -unsigned char acpi_legacy_devices; - unsigned int acpi_cpei_override; unsigned int acpi_cpei_phys_cpuid; @@ -628,12 +625,6 @@ static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size) fadt = (struct fadt_descriptor *)fadt_header; - if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) - acpi_kbd_controller_present = 0; - - if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES) - acpi_legacy_devices = 1; - acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; } diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 5f2dcba..7a2d824 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -65,7 +65,6 @@ extern void sn_timer_init(void); extern unsigned long last_time_offset; extern void (*ia64_mark_idle) (int); extern void snidle(int); -extern unsigned char acpi_kbd_controller_present; extern unsigned long long (*ia64_printk_clock)(void); unsigned long sn_rtc_cycles_per_second; @@ -452,17 +451,6 @@ void __init sn_setup(char **cmdline_p) ia64_printk_clock = ia64_sn2_printk_clock; - /* - * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard - * support here so we don't have to listen to failed keyboard probe - * messages. - */ - if (is_shub1() && version <= 0x0209 && acpi_kbd_controller_present) { - printk(KERN_INFO "Disabling legacy keyboard support as prom " - "is too old and doesn't provide FADT\n"); - acpi_kbd_controller_present = 0; - } - printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); /* -- cgit v0.10.2 From 9b3377f9921766b6193861d0e3194854b1d765fe Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 16 Oct 2006 16:17:43 -0500 Subject: [IA64] Count resched interrupts Count the number of "resched" interrupts that each cpu receives. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 68339dd0..9c6dafa 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -180,7 +180,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (!IS_RESCHEDULE(vector)) { + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; + else { ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); @@ -225,7 +227,9 @@ void ia64_process_pending_intr(void) * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (!IS_RESCHEDULE(vector)) { + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; + else { struct pt_regs *old_regs = set_irq_regs(NULL); ia64_setreg(_IA64_REG_CR_TPR, vector); @@ -258,11 +262,22 @@ void ia64_process_pending_intr(void) #ifdef CONFIG_SMP extern irqreturn_t handle_IPI (int irq, void *dev_id); +static irqreturn_t dummy_handler (int irq, void *dev_id) +{ + BUG(); +} + static struct irqaction ipi_irqaction = { .handler = handle_IPI, .flags = IRQF_DISABLED, .name = "IPI" }; + +static struct irqaction resched_irqaction = { + .handler = dummy_handler, + .flags = SA_INTERRUPT, + .name = "resched" +}; #endif void @@ -287,6 +302,7 @@ init_IRQ (void) register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); + register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); #endif #ifdef CONFIG_PERFMON pfm_init_percpu(); -- cgit v0.10.2 From b0a779debd56514b2b5de7617a1643e5dac2d4dd Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 18 Oct 2006 10:11:22 +1000 Subject: [POWERPC] Make sure interrupt enable gets restored properly The lazy IRQ disable patch missed a couple of places where the interrupt enable flags need to be restored correctly. First, we weren't restoring the paca->hard_enabled flag on interrupt exit. Instead of saving it on entry, we compute it from the MSR_EE bit in the MSR we are restoring at exit. Secondly, the MMU hash miss code was clearing both paca->soft_enabled and paca->hard_enabled but not restoring them in the case where hash_page was able to resolve the miss from the Linux page tables. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index efda487..86e2bdd 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -489,6 +489,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) andi. r0,r3,MSR_RI beq- unrecov_restore + /* extract EE bit and use it to restore paca->hard_enabled */ + rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ + stb r4,PACAHARDIRQEN(r13) + andi. r0,r3,MSR_PR /* diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index c93d9f3..d289005 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -961,10 +961,18 @@ bad_stack: * any task or sent any task a signal, you should use * ret_from_except or ret_from_except_lite instead of this. */ +fast_exc_return_irq: /* restores irq state too */ + ld r3,SOFTE(r1) + ld r12,_MSR(r1) + stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */ + rldicl r4,r12,49,63 /* get MSR_EE to LSB */ + stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */ + b 1f + .globl fast_exception_return fast_exception_return: ld r12,_MSR(r1) - ld r11,_NIP(r1) +1: ld r11,_NIP(r1) andi. r3,r12,MSR_RI /* check if RI is set */ beq- unrecov_fer @@ -1361,6 +1369,16 @@ BEGIN_FW_FTR_SECTION * interrupts if necessary. */ beq .ret_from_except_lite +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) +#endif +BEGIN_FW_FTR_SECTION + /* + * Here we have interrupts hard-disabled, so it is sufficient + * to restore paca->{soft,hard}_enable and get out. + */ + beq fast_exc_return_irq /* Return from exception on success */ +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) + /* For a hash failure, we don't bother re-enabling interrupts */ ble- 12f @@ -1372,14 +1390,6 @@ BEGIN_FW_FTR_SECTION ld r3,SOFTE(r1) bl .local_irq_restore b 11f -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) -#endif -BEGIN_FW_FTR_SECTION - beq fast_exception_return /* Return from exception on success */ - ble- 12f /* Failure return from hash_page */ - - /* fall through */ -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) /* Here we have a page fault that hash_page can't handle. */ _GLOBAL(handle_page_fault) -- cgit v0.10.2 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 diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 7cfe0e5..3acc896 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 v0.10.2 From 7341df16a1f228be833e918cb42534a34381a37e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Oct 2006 00:24:14 -0700 Subject: [SPARC]: Kill BOOTME_SINGLE. Unused, but still allow the '-s' boot option to be passed down to init. Based upon patches by Martin Habets. Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index f5ee1ac..383526a 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -103,7 +103,6 @@ void prom_sync_me(void) unsigned int boot_flags __initdata = 0; #define BOOTME_DEBUG 0x1 -#define BOOTME_SINGLE 0x2 /* Exported for mm/init.c:paging_init. */ unsigned long cmdline_memory_size __initdata = 0; @@ -132,7 +131,6 @@ static void __init process_switch(char c) boot_flags |= BOOTME_DEBUG; break; case 's': - boot_flags |= BOOTME_SINGLE; break; case 'h': prom_printf("boot_flags_init: Halt!\n"); diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index cc8ad48..bf033b3 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -74,7 +74,6 @@ prom_console_write(struct console *con, const char *s, unsigned n) unsigned int boot_flags = 0; #define BOOTME_DEBUG 0x1 -#define BOOTME_SINGLE 0x2 /* Exported for mm/init.c:paging_init. */ unsigned long cmdline_memory_size = 0; @@ -102,7 +101,6 @@ static void __init process_switch(char c) boot_flags |= BOOTME_DEBUG; break; case 's': - boot_flags |= BOOTME_SINGLE; break; case 'h': prom_printf("boot_flags_init: Halt!\n"); -- cgit v0.10.2 From 5aee87c43e3a71a4aa4e72b0dc2180e4952c0848 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Oct 2006 19:04:44 -0700 Subject: [SPARC64]: Fix PCI memory space root resource on Hummingbird. For Hummingbird PCI controllers, we should create the root PCI memory space resource as the full 4GB area, and then allocate the IOMMU DMA translation window out of there. The old code just assumed that the IOMMU DMA translation base to the top of the 4GB area was unusable. This is not true on many systems such as SB100 and SB150, where the IOMMU DMA translation window sits at 0xc0000000->0xdfffffff. So what would happen is that any device mapped by the firmware at the top section 0xe0000000->0xffffffff would get remapped by Linux somewhere else leading to all kinds of problems and boot failures. While we're here, report more cases of OBP resource assignment conflicts. The only truly valid ones are ROM resource conflicts. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 7a59cc7..827ae30 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -330,19 +330,6 @@ __init get_device_resource(struct linux_prom_pci_registers *ap, return res; } -static int __init pdev_resource_collisions_expected(struct pci_dev *pdev) -{ - if (pdev->vendor != PCI_VENDOR_ID_SUN) - return 0; - - if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 || - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 1; - - return 0; -} - static void __init pdev_record_assignments(struct pci_pbm_info *pbm, struct pci_dev *pdev) { @@ -400,19 +387,23 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm, pbm->parent->resource_adjust(pdev, res, root); if (request_resource(root, res) < 0) { + int rnum; + /* OK, there is some conflict. But this is fine * since we'll reassign it in the fixup pass. * - * We notify the user that OBP made an error if it - * is a case we don't expect. + * Do not print the warning for ROM resources + * as such a conflict is quite common and + * harmless as the ROM bar is disabled. */ - if (!pdev_resource_collisions_expected(pdev)) { - printk(KERN_ERR "PCI: Address space collision on region %ld " + rnum = (res - &pdev->resource[0]); + if (rnum != PCI_ROM_RESOURCE) + printk(KERN_ERR "PCI: Resource collision, " + "region %d " "[%016lx:%016lx] of device %s\n", - (res - &pdev->resource[0]), + rnum, res->start, res->end, pci_name(pdev)); - } } } } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 6ec5698..de7f785 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p, &pbm->mem_space); } -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) { struct pci_pbm_info *pbm; struct device_node *node; @@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp node = node->sibling; } if (simbas_found == 0) { + struct resource *rp; + /* No APBs underneath, probably this is a hummingbird * system. */ @@ -1302,8 +1304,10 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.flags = IORESOURCE_IO; - pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE; - pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL; + pbm->mem_space.start = + (p->pbm_A.controller_regs + SABRE_MEMSPACE); + pbm->mem_space.end = + (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); pbm->mem_space.flags = IORESOURCE_MEM; if (request_resource(&ioport_resource, &pbm->io_space) < 0) { @@ -1315,6 +1319,17 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp prom_halt(); } + rp = kmalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) { + prom_printf("Cannot allocate IOMMU resource.\n"); + prom_halt(); + } + rp->name = "IOMMU"; + rp->start = pbm->mem_space.start + (unsigned long) dma_start; + rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; + rp->flags = IORESOURCE_BUSY; + request_resource(&pbm->mem_space, rp); + pci_register_legacy_regions(&pbm->io_space, &pbm->mem_space); } @@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, char *model_name) /* * Look for APB underneath. */ - sabre_pbm_init(p, dp, vdma[0]); + sabre_pbm_init(p, dp, vdma[0], vdma[1]); } -- cgit v0.10.2 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 diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h index e21ec9b..ba7b865 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 466b484..7747bfd 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 6439b0c..18f8885 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 ed58bb4..9b827ce 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 1545b30..19aa84f 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 v0.10.2 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 diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 0d3660c..a54e414 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 6b6a855..fff4660 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 v0.10.2 From 9550e59c4587f637d9aa34689e32eea460e6f50c Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Tue, 17 Oct 2006 19:21:48 -0700 Subject: [SPARC]: Add sparc profiling support This patch adds profiling support to the sparc architecture. It is a copy of the sparc64 implementation. Signed-off-by: Martin Habets Signed-off-by: David S. Miller diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 9431e96..2f96610 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -289,6 +289,13 @@ endmenu source "fs/Kconfig" +menu "Instrumentation Support" + depends on EXPERIMENTAL + +source "arch/sparc/oprofile/Kconfig" + +endmenu + source "arch/sparc/Kconfig.debug" source "security/Kconfig" diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 4cdbb2d..f33c381 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -30,6 +30,8 @@ HEAD_Y := $(head-y) core-y += arch/sparc/kernel/ arch/sparc/mm/ arch/sparc/math-emu/ libs-y += arch/sparc/prom/ arch/sparc/lib/ +drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ + # Export what is needed by arch/sparc/boot/Makefile # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-) INIT_Y := $(patsubst %/, %/built-in.o, $(init-y)) diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7dcd1a1..6c7aa51 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -95,6 +95,8 @@ unsigned long profile_pc(struct pt_regs *regs) return pc; } +EXPORT_SYMBOL(profile_pc); + __volatile__ unsigned int *master_l10_counter; __volatile__ unsigned int *master_l10_limit; diff --git a/arch/sparc/oprofile/Kconfig b/arch/sparc/oprofile/Kconfig new file mode 100644 index 0000000..d8a8408 --- /dev/null +++ b/arch/sparc/oprofile/Kconfig @@ -0,0 +1,17 @@ +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + diff --git a/arch/sparc/oprofile/Makefile b/arch/sparc/oprofile/Makefile new file mode 100644 index 0000000..e9feca1 --- /dev/null +++ b/arch/sparc/oprofile/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) init.o diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c new file mode 100644 index 0000000..9ab815b --- /dev/null +++ b/arch/sparc/oprofile/init.c @@ -0,0 +1,23 @@ +/** + * @file init.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + */ + +#include +#include +#include +#include + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + return -ENODEV; +} + + +void oprofile_arch_exit(void) +{ +} -- cgit v0.10.2 From f6d7b8a7c9e21a58890a8532143e241409b78664 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Tue, 17 Oct 2006 19:23:23 -0700 Subject: [SPARC]: Sparc compilation fix with floppy enabled This patch fixes a typo to make kernel compilable when floppy driver for Sparc is build. Signed-off-by: Krzysztof Helt Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index b3b6680..c8cb211 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -351,7 +351,7 @@ void handler_irq(int irq, struct pt_regs * regs) } #ifdef CONFIG_BLK_DEV_FD -extern void floppy_interrupt(int irq, void *dev_id) +extern void floppy_interrupt(int irq, void *dev_id); void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) { -- cgit v0.10.2 From 73ed9a86cd77b6a3b46beec8d353ac3b0d4f50c1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Oct 2006 19:29:41 -0700 Subject: [SPARC64]: Update defconfig. Signed-off-by: David S. Miller diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index dcae559..2f4612f 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc1 -# Thu Oct 5 02:08:41 2006 +# Linux kernel version: 2.6.19-rc2 +# Tue Oct 17 19:29:20 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -217,6 +217,7 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=m CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set @@ -334,6 +335,12 @@ CONFIG_CDROM_PKTCDVD_WCACHE=y CONFIG_ATA_OVER_ETH=m # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -728,7 +735,6 @@ CONFIG_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -842,11 +848,6 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # -# Misc devices -# -# CONFIG_TIFM_CORE is not set - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -1104,7 +1105,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -1150,6 +1150,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1234,6 +1235,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1362,10 +1364,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_UTF8 is not set # -# Distributed Lock Manager -# - -# # Instrumentation Support # CONFIG_PROFILING=y @@ -1399,6 +1397,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_LIST is not set # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_LKDTM is not set # CONFIG_DEBUG_STACK_USAGE is not set -- cgit v0.10.2 From c888554bf95a5a0a6ac3e2389c6bf1e03e9480ba Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Mon, 16 Oct 2006 13:49:27 -0700 Subject: [POWERPC] More bootwrapper reorganization More reorganization of the bootwrapper: - Add dtb section to zImage - ft_init now called by platform_init - Pack a flat dt before calling kernel - Remove size parameter from free - printf only calls console_ops.write it its not NULL - Some cleanup Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index d719bb9..4184974 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -27,6 +27,8 @@ extern char _vmlinux_start[]; extern char _vmlinux_end[]; extern char _initrd_start[]; extern char _initrd_end[]; +extern char _dtb_start[]; +extern char _dtb_end[]; struct addr_range { unsigned long addr; @@ -250,10 +252,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2) flush_cache((void *)vmlinux.addr, vmlinux.size); } -void __attribute__ ((weak)) ft_init(void *dt_blob) -{ -} - /* A buffer that may be edited by tools operating on a zImage binary so as to * edit the command line passed to vmlinux (by setting /chosen/bootargs). * The buffer is put in it's own section so that tools may locate it easier. @@ -285,19 +283,12 @@ static void set_cmdline(char *buf) setprop(devp, "bootargs", buf, strlen(buf) + 1); } -/* Section where ft can be tacked on after zImage is built */ -union blobspace { - struct boot_param_header hdr; - char space[8*1024]; -} dt_blob __attribute__((__section__("__builtin_ft"))); - struct platform_ops platform_ops; struct dt_ops dt_ops; struct console_ops console_ops; void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) { - int have_dt = 0; kernel_entry_t kentry; char cmdline[COMMAND_LINE_SIZE]; @@ -306,15 +297,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) memset(&dt_ops, 0, sizeof(dt_ops)); memset(&console_ops, 0, sizeof(console_ops)); - /* Override the dt_ops and device tree if there was an flat dev - * tree attached to the zImage. - */ - if (dt_blob.hdr.magic == OF_DT_HEADER) { - have_dt = 1; - ft_init(&dt_blob); - } - - if (platform_init(promptr)) + if (platform_init(promptr, _dtb_start, _dtb_end)) exit(); if (console_ops.open && (console_ops.open() < 0)) exit(); @@ -342,8 +325,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) console_ops.close(); kentry = (kernel_entry_t) vmlinux.addr; - if (have_dt) + if (_dtb_end > _dtb_start) { + dt_ops.ft_pack(); kentry(dt_ops.ft_addr(), 0, NULL); + } else /* XXX initrd addr/size should be passed in properties */ kentry(a1, a2, promptr); diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 3a71845..0182f38 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c @@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len) call_prom("write", 3, 1, of_stdout_handle, buf, len); } -int platform_init(void *promptr) +int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) { - platform_ops.fixups = NULL; platform_ops.image_hdr = of_image_hdr; platform_ops.malloc = of_try_claim; - platform_ops.free = NULL; platform_ops.exit = of_exit; dt_ops.finddevice = of_finddevice; dt_ops.getprop = of_getprop; dt_ops.setprop = of_setprop; - dt_ops.translate_addr = NULL; console_ops.open = of_console_open; console_ops.write = of_console_write; - console_ops.edit_cmdline = NULL; - console_ops.close = NULL; - console_ops.data = NULL; prom = (int (*)(void *))promptr; return 0; diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 135eb4b..59832fb 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -22,7 +22,8 @@ struct platform_ops { void (*fixups)(void); void (*image_hdr)(const void *); void * (*malloc)(u32 size); - void (*free)(void *ptr, u32 size); + void (*free)(void *ptr); + void * (*realloc)(void *ptr, unsigned long size); void (*exit)(void); }; extern struct platform_ops platform_ops; @@ -30,12 +31,11 @@ extern struct platform_ops platform_ops; /* Device Tree operations */ struct dt_ops { void * (*finddevice)(const char *name); - int (*getprop)(const void *node, const char *name, void *buf, + int (*getprop)(const void *phandle, const char *name, void *buf, const int buflen); - int (*setprop)(const void *node, const char *name, + int (*setprop)(const void *phandle, const char *name, const void *buf, const int buflen); - u64 (*translate_addr)(const char *path, const u32 *in_addr, - const u32 addr_len); + void (*ft_pack)(void); unsigned long (*ft_addr)(void); }; extern struct dt_ops dt_ops; @@ -59,10 +59,13 @@ struct serial_console_data { void (*close)(void); }; -extern int platform_init(void *promptr); -extern void simple_alloc_init(void); -extern void ft_init(void *dt_blob); -extern int serial_console_init(void); +int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); +int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); +int serial_console_init(void); +int ns16550_console_init(void *devp, struct serial_console_data *scdp); +void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, + u32 max_allocs); + static inline void *finddevice(const char *name) { @@ -84,10 +87,10 @@ static inline void *malloc(u32 size) return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; } -static inline void free(void *ptr, u32 size) +static inline void free(void *ptr) { if (platform_ops.free) - platform_ops.free(ptr, size); + platform_ops.free(ptr); } static inline void exit(void) diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c index 6d5f638..0a9feeb 100644 --- a/arch/powerpc/boot/stdio.c +++ b/arch/powerpc/boot/stdio.c @@ -320,6 +320,7 @@ printf(const char *fmt, ...) va_start(args, fmt); n = vsprintf(sprint_buf, fmt, args); va_end(args); - console_ops.write(sprint_buf, n); + if (console_ops.write) + console_ops.write(sprint_buf, n); return n; } diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index eab7318..b5fb1fe 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -179,11 +179,11 @@ if [ -z "$cacheit" ]; then fi if [ -n "$initrd" ]; then - addsec $tmp "$initrd" initrd + addsec $tmp "$initrd" $isection fi if [ -n "$dtb" ]; then - addsec $tmp "$dtb" dtb + addsec $tmp "$dtb" .kernel:dtb fi if [ "$platform" != "miboot" ]; then diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S index 05f3238..a360905 100644 --- a/arch/powerpc/boot/zImage.coff.lds.S +++ b/arch/powerpc/boot/zImage.coff.lds.S @@ -21,6 +21,10 @@ SECTIONS *(.got2) __got2_end = .; + _dtb_start = .; + *(.kernel:dtb) + _dtb_end = .; + _vmlinux_start = .; *(.kernel:vmlinux.strip) _vmlinux_end = .; diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4b6bb3f..4be3c64 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -21,6 +21,11 @@ SECTIONS __got2_end = .; } + . = ALIGN(8); + _dtb_start = .; + .kernel:dtb : { *(.kernel:dtb) } + _dtb_end = .; + . = ALIGN(4096); _vmlinux_start = .; .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) } -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index 5948863..bf25d0a 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 v0.10.2 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 diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9997081..a4f861b 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 v0.10.2 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 diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 7c59bba..cdd0337 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 v0.10.2 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 diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 72794a7..65e6e7b 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 v0.10.2 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 diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 911f2ff..afed293 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 v0.10.2 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 diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index f6b2948..1b601b6 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index feabda7..45f44fe 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 v0.10.2 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 diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 8cc6c0e..04c6d92 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 v0.10.2 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 diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 67f384f..e6df492c 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 v0.10.2 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 diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 983be3e..fdb33cd 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 v0.10.2 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 diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 47f2792..06fc19a 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 v0.10.2 From 74d919465a93b6c2b928b29a8ed3e5e41adbfa93 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:55:54 -0400 Subject: [pci_ids] Add Quicknet XJ vendor/device ID's. Signed-off-by: Ben Collins diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f069df2..f3a168f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2351,3 +2351,5 @@ #define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 #define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 +#define PCI_VENDOR_ID_QUICKNET 0x15E2 +#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 -- cgit v0.10.2 From 1df23957ba2da6eb8c7a5c2ad7bb1d4732132873 Mon Sep 17 00:00:00 2001 From: Cedric Le Goater Date: Wed, 18 Oct 2006 18:30:41 +0200 Subject: [S390] fix vmlinux link when CONFIG_SYSIPC=n Fix the following compile error: CC init/version.o LD init/built-in.o LD .tmp_vmlinux1 arch/s390/kernel/built-in.o(.text+0xdba4): In function `sys32_ipc': : undefined reference to `compat_sys_semtimedop' arch/s390/kernel/built-in.o(.text+0xdbee): In function `sys32_ipc': : undefined reference to `compat_sys_semctl' arch/s390/kernel/built-in.o(.text+0xdc08): In function `sys32_ipc': : undefined reference to `compat_sys_msgsnd' arch/s390/kernel/built-in.o(.text+0xdc30): In function `sys32_ipc': : undefined reference to `compat_sys_msgrcv' arch/s390/kernel/built-in.o(.text+0xdc58): In function `sys32_ipc': : undefined reference to `compat_sys_msgctl' arch/s390/kernel/built-in.o(.text+0xdc76): In function `sys32_ipc': : undefined reference to `compat_sys_shmat' arch/s390/kernel/built-in.o(.text+0xdcb0): In function `sys32_ipc': : undefined reference to `compat_sys_shmctl' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Cedric Le Goater Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index e15e148..2001767 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -295,6 +295,7 @@ static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) * * This is really horribly ugly. */ +#ifdef CONFIG_SYSVIPC asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) { if (call >> 16) /* hack for backward compatibility */ @@ -338,6 +339,7 @@ asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) return -ENOSYS; } +#endif asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) { -- cgit v0.10.2 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 diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index fcaf28d..de3d085 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 v0.10.2 From f5956f84072804712cb7b663c5c64e9800180833 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 18 Oct 2006 18:30:45 +0200 Subject: [S390] Wire up epoll_pwait syscall. Signed-off-by: Heiko Carstens diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index e59baec..a4ceae3 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -320,3 +320,4 @@ SYSCALL(sys_tee,sys_tee,sys_tee_wrapper) SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper) NI_SYSCALL /* 310 sys_move_pages */ SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper) +SYSCALL(sys_epoll_pwait,sys_epoll_pwait,sys_ni_syscall) diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index a19238c..71d3c21 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -249,8 +249,9 @@ #define __NR_vmsplice 309 /* Number 310 is reserved for new sys_move_pages */ #define __NR_getcpu 311 +#define __NR_epoll_pwait 312 -#define NR_syscalls 312 +#define NR_syscalls 313 /* * There are some system calls that are not present on 64 bit, some -- cgit v0.10.2 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 diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 0648ce5..476aa1d 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 v0.10.2 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 diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index abd02ed..b9b0fc3 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 v0.10.2 From 833774849d50a59f58e9bdfc3d9c88e682b3596d Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 18 Oct 2006 18:30:51 +0200 Subject: [S390] Fix pte type checking. handle_pte_fault uses pte_present, pte_none and pte_file to find out the type of a pte. That is done without holding the page table lock. This clashes with the way how ptep_clear_flush removes active page table entries from the system. First the ipte instruction is used to invalidate the pte and remove all plt entries for the page. The ipte sets the hardware invalid bit without changing any other bit. After the ipte finished the pte is cleared. A concurrent fault can observe the the previously valid pte with the invalid bit set. With the current encoding of the different pte types an invalidated read-only pte can be misinterpreted as a swap-pte. Signed-off-by: Martin Schwidefsky diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 519f0a5..36bb6da 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -200,18 +200,45 @@ extern char empty_zero_page[PAGE_SIZE]; */ /* Hardware bits in the page table entry */ -#define _PAGE_RO 0x200 /* HW read-only */ -#define _PAGE_INVALID 0x400 /* HW invalid */ +#define _PAGE_RO 0x200 /* HW read-only bit */ +#define _PAGE_INVALID 0x400 /* HW invalid bit */ +#define _PAGE_SWT 0x001 /* SW pte type bit t */ +#define _PAGE_SWX 0x002 /* SW pte type bit x */ -/* Mask and six different types of pages. */ -#define _PAGE_TYPE_MASK 0x601 +/* Six different types of pages. */ #define _PAGE_TYPE_EMPTY 0x400 #define _PAGE_TYPE_NONE 0x401 -#define _PAGE_TYPE_SWAP 0x600 -#define _PAGE_TYPE_FILE 0x601 +#define _PAGE_TYPE_SWAP 0x403 +#define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ #define _PAGE_TYPE_RO 0x200 #define _PAGE_TYPE_RW 0x000 +/* + * PTE type bits are rather complicated. handle_pte_fault uses pte_present, + * pte_none and pte_file to find out the pte type WITHOUT holding the page + * table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to + * invalidate a given pte. ipte sets the hw invalid bit and clears all tlbs + * for the page. The page table entry is set to _PAGE_TYPE_EMPTY afterwards. + * This change is done while holding the lock, but the intermediate step + * of a previously valid pte with the hw invalid bit set can be observed by + * handle_pte_fault. That makes it necessary that all valid pte types with + * the hw invalid bit set must be distinguishable from the four pte types + * empty, none, swap and file. + * + * irxt ipte irxt + * _PAGE_TYPE_EMPTY 1000 -> 1000 + * _PAGE_TYPE_NONE 1001 -> 1001 + * _PAGE_TYPE_SWAP 1011 -> 1011 + * _PAGE_TYPE_FILE 11?1 -> 11?1 + * _PAGE_TYPE_RO 0100 -> 1100 + * _PAGE_TYPE_RW 0000 -> 1000 + * + * pte_none is true for bits combinations 1000, 1100 + * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 + * pte_file is true for bits combinations 1101, 1111 + * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid. + */ + #ifndef __s390x__ /* Bits in the segment table entry */ @@ -365,18 +392,21 @@ static inline int pmd_bad(pmd_t pmd) static inline int pte_none(pte_t pte) { - return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_EMPTY; + return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT); } static inline int pte_present(pte_t pte) { - return !(pte_val(pte) & _PAGE_INVALID) || - (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_NONE; + unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT | _PAGE_SWX; + return (pte_val(pte) & mask) == _PAGE_TYPE_NONE || + (!(pte_val(pte) & _PAGE_INVALID) && + !(pte_val(pte) & _PAGE_SWT)); } static inline int pte_file(pte_t pte) { - return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_FILE; + unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT; + return (pte_val(pte) & mask) == _PAGE_TYPE_FILE; } #define pte_same(a,b) (pte_val(a) == pte_val(b)) -- cgit v0.10.2 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 diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d0647d1..79ffef6 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 v0.10.2 From 9b10fe5b70878fb4b7e3e1b300f1bff0c73d4e2e Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 18 Oct 2006 18:30:55 +0200 Subject: [S390] cio: update documentation. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO index 59d1166..d684a6a 100644 --- a/Documentation/s390/CommonIO +++ b/Documentation/s390/CommonIO @@ -66,7 +66,7 @@ Command line parameters When a device is un-ignored, device recognition and sensing is performed and the device driver will be notified if possible, so the device will become - available to the system. + available to the system. Note that un-ignoring is performed asynchronously. You can also add ranges of devices to be ignored by piping to /proc/cio_ignore; "add , , ..." will ignore the diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt index d80e573..32a96cc 100644 --- a/Documentation/s390/cds.txt +++ b/Documentation/s390/cds.txt @@ -174,14 +174,10 @@ read_dev_chars() - Read Device Characteristics This routine returns the characteristics for the device specified. -The function is meant to be called with an irq handler in place; that is, +The function is meant to be called with the device already enabled; that is, at earliest during set_online() processing. -While the request is processed synchronously, the device interrupt -handler is called for final ending status. In case of error situations the -interrupt handler may recover appropriately. The device irq handler can -recognize the corresponding interrupts by the interruption parameter be -0x00524443. The ccw_device must not be locked prior to calling read_dev_chars(). +The ccw_device must not be locked prior to calling read_dev_chars(). The function may be called enabled or disabled. @@ -410,26 +406,7 @@ individual flag meanings. Usage Notes : -Prior to call ccw_device_start() the device driver must assure disabled state, -i.e. the I/O mask value in the PSW must be disabled. This can be accomplished -by calling local_save_flags( flags). The current PSW flags are preserved and -can be restored by local_irq_restore( flags) at a later time. - -If the device driver violates this rule while running in a uni-processor -environment an interrupt might be presented prior to the ccw_device_start() -routine returning to the device driver main path. In this case we will end in a -deadlock situation as the interrupt handler will try to obtain the irq -lock the device driver still owns (see below) ! - -The driver must assure to hold the device specific lock. This can be -accomplished by - -(i) spin_lock(get_ccwdev_lock(cdev)), or -(ii) spin_lock_irqsave(get_ccwdev_lock(cdev), flags) - -Option (i) should be used if the calling routine is running disabled for -I/O interrupts (see above) already. Option (ii) obtains the device gate und -puts the CPU into I/O disabled state by preserving the current PSW flags. +ccw_device_start() must be called disabled and with the ccw device lock held. The device driver is allowed to issue the next ccw_device_start() call from within its interrupt handler already. It is not required to schedule a @@ -488,7 +465,7 @@ int ccw_device_resume(struct ccw_device *cdev); cdev - ccw_device the resume operation is requested for -The resume_IO() function returns: +The ccw_device_resume() function returns: 0 - suspended channel program is resumed -EBUSY - status pending @@ -507,6 +484,8 @@ a long-running channel program or the device might require to initially issue a halt subchannel (HSCH) I/O command. For those purposes the ccw_device_halt() command is provided. +ccw_device_halt() must be called disabled and with the ccw device lock held. + int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm); @@ -517,7 +496,7 @@ intparm : interruption parameter; value is only used if no I/O The ccw_device_halt() function returns : - 0 - successful completion or request successfully initiated + 0 - request successfully initiated -EBUSY - the device is currently busy, or status pending. -ENODEV - cdev invalid. -EINVAL - The device is not operational or the ccw device is not online. @@ -533,6 +512,23 @@ can then perform an appropriate action. Prior to interrupt of an outstanding read to a network device (with or without PCI flag) a ccw_device_halt() is required to end the pending operation. +ccw_device_clear() - Terminage I/O Request Processing + +In order to terminate all I/O processing at the subchannel, the clear subchannel +(CSCH) command is used. It can be issued via ccw_device_clear(). + +ccw_device_clear() must be called disabled and with the ccw device lock held. + +int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm); + +cdev: ccw_device the clear operation is requested for +intparm: interruption parameter (see ccw_device_halt()) + +The ccw_device_clear() function returns: + + 0 - request successfully initiated +-ENODEV - cdev invalid +-EINVAL - The device is not operational or the ccw device is not online. Miscellaneous Support Routines diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt index 62c0823..77bf450 100644 --- a/Documentation/s390/driver-model.txt +++ b/Documentation/s390/driver-model.txt @@ -239,6 +239,9 @@ status - Can be 'online' or 'offline'. type - The physical type of the channel path. +shared - Whether the channel path is shared. + +cmg - The channel measurement group. 3. System devices ----------------- -- cgit v0.10.2 From ce9b18f5cdd628196ca13bb783e8dcd5ad29ceaa Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 18 Oct 2006 18:30:59 +0200 Subject: [S390] update default configuration Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/defconfig b/arch/s390/defconfig index a325739..c313e9a 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18 -# Wed Oct 4 19:45:46 2006 +# Linux kernel version: 2.6.19-rc2 +# Wed Oct 18 17:11:10 2006 # CONFIG_MMU=y CONFIG_LOCKDEP_SUPPORT=y @@ -211,6 +211,7 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_BEET=y # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set # CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set @@ -528,6 +529,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -646,10 +648,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set # -# Distributed Lock Manager -# - -# # Instrumentation Support # @@ -669,7 +667,6 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_DETECT_SOFTLOCKUP is not set # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y @@ -690,6 +687,7 @@ CONFIG_DEBUG_FS=y # CONFIG_FRAME_POINTER is not set # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y +CONFIG_HEADERS_CHECK=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_LKDTM is not set -- cgit v0.10.2 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 diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4d8aee1..446e9be 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index eaea9d3..b71f774 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 41290a1..f602b04 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index b71f774..30f021c 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 c67b7c3..f93e81e 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 f602b04..c206a3d 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 703a64a..1c551c6 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index c206a3d..372c63e 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 v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 23b599d..e542507 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 v0.10.2 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 diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 67fcd17..3656e03 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 bd6615b..b20a9b8 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 v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e542507..1d2ccda 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 v0.10.2 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 diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index b60d7e8..908b410 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -343,51 +343,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_ro 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. * * We pretend to bring them out of full D3 state, and restore the proper diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1d2ccda..371ab88 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 f5ee7ce..43e4a49 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 v0.10.2 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 diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index dc79b0a..379048f 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 v0.10.2 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 diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 037690e..b4da795 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 05a4f0f..aaeb112 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 446e9be..4826dd1 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c7103ac..7e7d490 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 4826dd1..bbe450f 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index bbe450f..83a5226 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 v0.10.2 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 diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f9fdc54..9fc9a34 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 v0.10.2 From 0cc2b3763e06e84ae5a90b63e03cc1d585a109d0 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 5 Oct 2006 10:24:42 +0200 Subject: PCI: Update MSI-HOWTO.txt according to pci_msi_supported() Update MSI-HOWTO.txt according to pci_msi_supported(). Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt index c70306a..5c34910 100644 --- a/Documentation/MSI-HOWTO.txt +++ b/Documentation/MSI-HOWTO.txt @@ -470,7 +470,68 @@ LOC: 324553 325068 ERR: 0 MIS: 0 -6. FAQ +6. MSI quirks + +Several PCI chipsets or devices are known to not support MSI. +The PCI stack provides 3 possible levels of MSI disabling: +* on a single device +* on all devices behind a specific bridge +* globally + +6.1. Disabling MSI on a single device + +Under some circumstances, it might be required to disable MSI on a +single device, It may be achived by either not calling pci_enable_msi() +or all, or setting the pci_dev->no_msi flag before (most of the time +in a quirk). + +6.2. Disabling MSI below a bridge + +The vast majority of MSI quirks are required by PCI bridges not +being able to route MSI between busses. In this case, MSI have to be +disabled on all devices behind this bridge. It is achieves by setting +the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge +subordinate bus. There is no need to set the same flag on bridges that +are below the broken brigde. When pci_enable_msi() is called to enable +MSI on a device, pci_msi_supported() takes care of checking the NO_MSI +flag in all parent busses of the device. + +Some bridges actually support dynamic MSI support enabling/disabling +by changing some bits in their PCI configuration space (especially +the Hypertransport chipsets such as the nVidia nForce and Serverworks +HT2000). It may then be required to update the NO_MSI flag on the +corresponding devices in the sysfs hierarchy. To enable MSI support +on device "0000:00:0e", do: + + echo 1 > /sys/bus/pci/devices/0000:00:0e/msi_bus + +To disable MSI support, echo 0 instead of 1. Note that it should be +used with caution since changing this value might break interrupts. + +6.3. Disabling MSI globally + +Some extreme cases may require to disable MSI globally on the system. +For now, the only known case is a Serverworks PCI-X chipsets (MSI are +not supported on several busses that are not all connected to the +chipset in the Linux PCI hierarchy). In the vast majority of other +cases, disabling only behind a specific bridge is enough. + +For debugging purpose, the user may also pass pci=nomsi on the kernel +command-line to explicitly disable MSI globally. But, once the appro- +priate quirks are added to the kernel, this option should not be +required anymore. + +6.4. Finding why MSI cannot be enabled on a device + +Assuming that MSI are not enabled on a device, you should look at +dmesg to find messages that quirks may output when disabling MSI +on some devices, some bridges or even globally. +Then, lspci -t gives the list of bridges above a device. Reading +/sys/bus/pci/devices/0000:00:0e/msi_bus will tell you whether MSI +are enabled (1) or disabled (0). In 0 is found in a single bridge +msi_bus file above the device, MSI cannot be enabled. + +7. FAQ Q1. Are there any limitations on using the MSI? -- cgit v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 371ab88..e8a7f1b 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 v0.10.2 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 diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d529462..2f13eba 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -140,6 +140,31 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) } /** + * 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 * @device: PCI device id to match, or %PCI_ANY_ID to match all device 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 5c604f5..09bf88f 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index e847f0d..f3852a6 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 v0.10.2 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 diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ff571f9..dd00fd5 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 68bce194..6d5ace8 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; @@ -118,6 +119,20 @@ void __devinit pcibios_fixup_bus(struct pci_bus *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) */ #ifdef __i386__ @@ -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 1814f74..ad065ce 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 a3b0a5e..e159d66 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 09bf88f..4689e2a 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 v0.10.2 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 diff --git a/MAINTAINERS b/MAINTAINERS index 5305dd6..9b6b882 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 772523d..a675a05 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 e2823ea..fa666d0 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 51cb9f8..270a33c 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 7fff07e..59c5b24 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 e2fef60..c57d9d5c 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 83e8e44..c44311a 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 d0a07d9..bd40aee 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 d06ab40..6845515 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 4afcaff..7b1beaa 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 ea040c3..298ad7f 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 1fc2599..5617cfd 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 3ec2ad7..79ff6b4 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 cf08789..298a6cf 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 0d96889..fc7c74d 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 5bab666..634f74d 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 aaeb112..e27907c 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 dba6d8c..612d963 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 a675a05..0000000 --- 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 fa666d0..f5d632e 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 30f021c..4fb12fc 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 2b9e10e..50bcd3f 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 db69be8..6c5be3f 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 7288a3e..141486d 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 f31d83c..b62ad31 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 7e7d490..ea2087c 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 0000000..a675a05 --- /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 v0.10.2 From acbd39fbc5d8757aa920c6045399374df7a6dd68 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 30 Sep 2006 22:41:43 -0400 Subject: Documentation: feature-removal-schedule typo Fix typo in newly added feature remove schedule item. Signed-off-by: Dominik Brodowski Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 24f3c63..1ac3c74 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -255,7 +255,7 @@ Who: Stephen Hemminger What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment -When: Oktober 2008 +When: October 2008 Why: The stacking of class devices makes these values misleading and inconsistent. Class devices should not carry any of these properties, and bus -- cgit v0.10.2 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 diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b5f43c3..ef7db69 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index b224bb4..aee3743 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 v0.10.2 From 722385f75efd82d9f480f0765a1e97a4d83cac0d Mon Sep 17 00:00:00 2001 From: Diego Calleja Date: Thu, 21 Sep 2006 22:37:10 +0200 Subject: HOWTO: bug report addition I suspect that not many people is subscribed to the bugzilla mailing list, not surprising since the URLs doesn't seem to be in the tree :) After fixing my english, I wonder if the following patch could be applied... Signed-off-by: Diego Calleja Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/HOWTO b/Documentation/HOWTO index d6f3dd1..8d51c14 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -395,6 +395,26 @@ bugme-janitor mailing list (every change in the bugzilla is mailed here) +Managing bug reports +-------------------- + +One of the best ways to put into practice your hacking skills is by fixing +bugs reported by other people. Not only you will help to make the kernel +more stable, you'll learn to fix real world problems and you will improve +your skills, and other developers will be aware of your presence. Fixing +bugs is one of the best ways to get merits among other developers, because +not many people like wasting time fixing other people's bugs. + +To work in the already reported bug reports, go to http://bugzilla.kernel.org. +If you want to be advised of the future bug reports, you can subscribe to the +bugme-new mailing list (only new bug reports are mailed here) or to the +bugme-janitor mailing list (every change in the bugzilla is mailed here) + + http://lists.osdl.org/mailman/listinfo/bugme-new + http://lists.osdl.org/mailman/listinfo/bugme-janitors + + + Mailing lists ------------- -- cgit v0.10.2 From e42344514c6e8ca7f5427da9b1407b56550dfa01 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Wed, 20 Sep 2006 16:38:00 +0900 Subject: sysfs: remove duplicated dput in sysfs_update_file Following function can drops d_count twice against one reference by lookup_one_len. /** * sysfs_update_file - update the modified timestamp on an object attribute. * @kobj: object we're acting for. * @attr: attribute descriptor. */ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) { struct dentry * dir = kobj->dentry; struct dentry * victim; int res = -ENOENT; mutex_lock(&dir->d_inode->i_mutex); victim = lookup_one_len(attr->name, dir, strlen(attr->name)); if (!IS_ERR(victim)) { /* make sure dentry is really there */ if (victim->d_inode && (victim->d_parent->d_inode == dir->d_inode)) { victim->d_inode->i_mtime = CURRENT_TIME; fsnotify_modify(victim); /** * Drop reference from initial sysfs_get_dentry(). */ dput(victim); res = 0; } else d_drop(victim); /** * Drop the reference acquired from sysfs_get_dentry() above. */ dput(victim); } mutex_unlock(&dir->d_inode->i_mutex); return res; } PCI-hotplug (drivers/pci/hotplug/pci_hotplug_core.c) is only user of this function. I confirmed that dentry of /sys/bus/pci/slots/XXX/* have negative d_count value. This patch removes unnecessary dput(). Signed-off-by: Hidetoshi Seto Acked-by: Maneesh Soni Signed-off-by: Greg Kroah-Hartman diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 146f1de..93218cc 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -483,11 +483,6 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) (victim->d_parent->d_inode == dir->d_inode)) { victim->d_inode->i_mtime = CURRENT_TIME; fsnotify_modify(victim); - - /** - * Drop reference from initial sysfs_get_dentry(). - */ - dput(victim); res = 0; } else d_drop(victim); -- cgit v0.10.2 From 97a501849d60f3dbb8bfcd2300cf65dd5ebc0355 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Wed, 20 Sep 2006 16:49:02 +0900 Subject: sysfs: update obsolete comment in sysfs_update_file And the obsolete comment should be updated (or totally removed). Signed-off-by: Hidetoshi Seto Signed-off-by: Greg Kroah-Hartman diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 93218cc..298303b 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -488,7 +488,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) d_drop(victim); /** - * Drop the reference acquired from sysfs_get_dentry() above. + * Drop the reference acquired from lookup_one_len() above. */ dput(victim); } -- cgit v0.10.2 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 diff --git a/drivers/base/class.c b/drivers/base/class.c index b32b77f..0ff267a 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 v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12173d1..b90f6e6 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 v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b90f6e6..d516f7d 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index aee3743..365f709 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 v0.10.2 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 diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 33c5cce..b2efbd4 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 v0.10.2 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 diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3ef9d51..28dccb7 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index 365f709..41f3dca 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 v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d516f7d..d7c5ea2 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 41f3dca..68ad11a 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 v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d7c5ea2..7d8a7ce 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 v0.10.2 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 diff --git a/drivers/base/dd.c b/drivers/base/dd.c index ef7db69..db01b95 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ed4258a..c2bc3ed 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6eebcb7..507c377 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 393b86a..fa0e8ca 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 1bc1cf9..8a7a081 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 39da28d..d1d8759 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 c2bc3ed..c7e05ed8 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 de08491..727c34d 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 c1434ed..1bba140 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 8a7a081..0c543d3 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 507c377..fa2d804 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 d1d8759..1aeb296 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 c7e05ed8..abf1d3c 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index fa2d804..1cec199 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 0c543d3..2b5256c 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 1aeb296..666797d 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 1cec199..4d79f1e 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 fa0e8ca..a7dbe6f 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 2b5256c..f5cab69 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 666797d..63c4560 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 abf1d3c..f51d87b 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 727c34d..13e634db 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 1bba140..f1cf266 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 63c4560..621fdbb 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 4d79f1e..7b11217 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 621fdbb..c0bdc1f 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 7b11217..b41fdfe 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 c0bdc1f..9ebc98a 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 f51d87b..7fd63d4 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9ebc98a..f2b8f55 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index a7dbe6f..196ae7a 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 f2b8f55..2d0bcdd 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 196ae7a..088acf4 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index b41fdfe..188bf09 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 188bf09..6d11122 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 088acf4..4259b52 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 f5cab69..e22b4c9 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 2d0bcdd..8a13b1a 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 7fd63d4..6125921 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 13e634db..a04b7d6 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 f1cf266..9626e0f 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 v0.10.2 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 diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 4259b52..d433f27 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 v0.10.2 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 diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 371ed4f..9e5f885 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 v0.10.2 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 diff --git a/Documentation/hwmon/adm9240 b/Documentation/hwmon/adm9240 index 35f618f..2c6f1fe 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 377961c..aad594a 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 v0.10.2 From 15fe25ca67234514d7cf41af28096c1330f44950 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 8 Oct 2006 21:59:54 +0200 Subject: hwmon: Fix documentation typos Fix typos in hardware monitoring documentation. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f index 28c5b7d..2ca69df 100644 --- a/Documentation/hwmon/f71805f +++ b/Documentation/hwmon/f71805f @@ -17,7 +17,7 @@ Thanks to Kris Chen from Fintek for answering technical questions and providing additional documentation. Thanks to Chris Lin from Jetway for providing wiring schematics and -anwsering technical questions. +answering technical questions. Description diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf index fae3b78..caa610a 100644 --- a/Documentation/hwmon/w83627ehf +++ b/Documentation/hwmon/w83627ehf @@ -26,7 +26,7 @@ fan control mode). Temperatures are measured in degrees Celsius and measurement resolution is 1 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when the temperature gets higher than high limit; it stays on until the temperature -falls below the Hysteresis value. +falls below the hysteresis value. Fan rotation speeds are reported in RPM (rotations per minute). An alarm is triggered if the rotation speed has dropped below a programmable limit. Fan @@ -67,9 +67,9 @@ Thermal Cruise mode If the temperature is in the range defined by: -pwm[1-4]_target - set target temperature, unit millidegree Celcius +pwm[1-4]_target - set target temperature, unit millidegree Celsius (range 0 - 127000) -pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000) +pwm[1-4]_tolerance - tolerance, unit millidegree Celsius (range 0 - 15000) there are no changes to fan speed. Once the temperature leaves the interval, fan speed increases (temp is higher) or decreases if lower than desired. -- cgit v0.10.2 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 diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1 index c15bbe6..04a1112 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 9b88b25..e0dede7 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 47132fd..beb881c 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 v0.10.2 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 diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp index bab445a..30d123b 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 5305dd6..595b34c 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 e0dede7..e76d919 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 v0.10.2 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 diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 833faa2..2257806 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 v0.10.2 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 diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index ac1b746..73bc2ff 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 a4584ec..fea9206 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 4380653..8ed59a2 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 v0.10.2 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 diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index fea9206..1232171 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 v0.10.2 From 065fd1772af2032bebdce006071df007c039734d Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:38:05 -0700 Subject: [TIPC]: Add missing unlock in port timeout code. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/port.c b/net/tipc/port.c index b9c8c6b..c1a1a76 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -505,8 +505,13 @@ static void port_timeout(unsigned long ref) struct port *p_ptr = tipc_port_lock(ref); struct sk_buff *buf = NULL; - if (!p_ptr || !p_ptr->publ.connected) + if (!p_ptr) + return; + + if (!p_ptr->publ.connected) { + tipc_port_unlock(p_ptr); return; + } /* Last probe answered ? */ if (p_ptr->probing_state == PROBING) { -- cgit v0.10.2 From 29ede244cc4cfb11432a0bffd158ba09e7b2c167 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:42:04 -0700 Subject: [TIPC]: Debug print buffer enhancements and fixes This change modifies TIPC's print buffer code as follows: 1) Now supports small print buffers (min. size reduced from 512 bytes to 64) 2) Now uses TIPC_NULL print buffer structure to indicate null device instead of NULL pointer (this simplified error handling) 3) Fixed misuse of console buffer structure by tipc_dump() 4) Added and corrected comments in various places Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/core.h b/net/tipc/core.h index 762aac2..47504ec 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -65,7 +65,7 @@ #define assert(i) BUG_ON(!(i)) struct tipc_msg; -extern struct print_buf *TIPC_CONS, *TIPC_LOG; +extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG; extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); void tipc_printf(struct print_buf *, const char *fmt, ...); @@ -94,11 +94,11 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); * here, or on a per .c file basis, by redefining these symbols. The following * print buffer options are available: * - * NULL : Output to null print buffer (i.e. print nowhere) - * TIPC_CONS : Output to system console - * TIPC_LOG : Output to TIPC log buffer - * &buf : Output to user-defined buffer (struct print_buf *) - * TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) ) + * TIPC_NULL : null buffer (i.e. print nowhere) + * TIPC_CONS : system console + * TIPC_LOG : TIPC log buffer + * &buf : user-defined buffer (struct print_buf *) + * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG)) */ #ifndef TIPC_OUTPUT @@ -106,7 +106,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #endif #ifndef DBG_OUTPUT -#define DBG_OUTPUT NULL +#define DBG_OUTPUT TIPC_NULL #endif #else @@ -136,7 +136,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #define TIPC_OUTPUT TIPC_CONS #undef DBG_OUTPUT -#define DBG_OUTPUT NULL +#define DBG_OUTPUT TIPC_NULL #endif diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 5513065..d8af4c2 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -1,8 +1,8 @@ /* - * net/tipc/dbg.c: TIPC print buffer routines for debuggign + * net/tipc/dbg.c: TIPC print buffer routines for debugging * * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,11 +38,12 @@ #include "config.h" #include "dbg.h" -#define MAX_STRING 512 - -static char print_string[MAX_STRING]; +static char print_string[TIPC_PB_MAX_STR]; static DEFINE_SPINLOCK(print_lock); +static struct print_buf null_buf = { NULL, 0, NULL, NULL }; +struct print_buf *TIPC_NULL = &null_buf; + static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; struct print_buf *TIPC_CONS = &cons_buf; @@ -62,68 +63,83 @@ struct print_buf *TIPC_LOG = &log_buf; /* * Locking policy when using print buffers. * - * 1) Routines of the form printbuf_XXX() rely on the caller to prevent - * simultaneous use of the print buffer(s) being manipulated. - * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of - * 'print_string' and to protect its print buffer(s). - * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s). - * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG. + * The following routines use 'print_lock' for protection: + * 1) tipc_printf() - to protect its print buffer(s) and 'print_string' + * 2) TIPC_TEE() - to protect its print buffer(s) + * 3) tipc_dump() - to protect its print buffer(s) and 'print_string' + * 4) tipc_log_XXX() - to protect TIPC_LOG + * + * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent + * simultaneous use of the print buffer(s) being manipulated. */ /** * tipc_printbuf_init - initialize print buffer to empty + * @pb: pointer to print buffer structure + * @raw: pointer to character array used by print buffer + * @size: size of character array + * + * Makes the print buffer a null device that discards anything written to it + * if the character array is too small (or absent). */ -void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz) +void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) { - if (!pb || !raw || (sz < (MAX_STRING + 1))) - return; - - pb->crs = pb->buf = raw; - pb->size = sz; + pb->buf = raw; + pb->crs = raw; + pb->size = size; pb->next = NULL; - pb->buf[0] = 0; - pb->buf[sz-1] = ~0; + + if (size < TIPC_PB_MIN_SIZE) { + pb->buf = NULL; + } else if (raw) { + pb->buf[0] = 0; + pb->buf[size-1] = ~0; + } } /** * tipc_printbuf_reset - reinitialize print buffer to empty state + * @pb: pointer to print buffer structure */ void tipc_printbuf_reset(struct print_buf *pb) { - if (pb && pb->buf) - tipc_printbuf_init(pb, pb->buf, pb->size); + tipc_printbuf_init(pb, pb->buf, pb->size); } /** * tipc_printbuf_empty - test if print buffer is in empty state + * @pb: pointer to print buffer structure + * + * Returns non-zero if print buffer is empty. */ int tipc_printbuf_empty(struct print_buf *pb) { - return (!pb || !pb->buf || (pb->crs == pb->buf)); + return (!pb->buf || (pb->crs == pb->buf)); } /** * tipc_printbuf_validate - check for print buffer overflow + * @pb: pointer to print buffer structure * * Verifies that a print buffer has captured all data written to it. * If data has been lost, linearize buffer and prepend an error message * - * Returns length of print buffer data string (including trailing NULL) + * Returns length of print buffer data string (including trailing NUL) */ int tipc_printbuf_validate(struct print_buf *pb) { - char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; + char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n"; char *cp_buf; struct print_buf cb; - if (!pb || !pb->buf) + if (!pb->buf) return 0; - if (pb->buf[pb->size - 1] == '\0') { + if (pb->buf[pb->size - 1] == 0) { cp_buf = kmalloc(pb->size, GFP_ATOMIC); if (cp_buf != NULL){ tipc_printbuf_init(&cb, cp_buf, pb->size); @@ -141,6 +157,8 @@ int tipc_printbuf_validate(struct print_buf *pb) /** * tipc_printbuf_move - move print buffer contents to another print buffer + * @pb_to: pointer to destination print buffer structure + * @pb_from: pointer to source print buffer structure * * Current contents of destination print buffer (if any) are discarded. * Source print buffer becomes empty if a successful move occurs. @@ -152,21 +170,22 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) /* Handle the cases where contents can't be moved */ - if (!pb_to || !pb_to->buf) + if (!pb_to->buf) return; - if (!pb_from || !pb_from->buf) { + if (!pb_from->buf) { tipc_printbuf_reset(pb_to); return; } if (pb_to->size < pb_from->size) { tipc_printbuf_reset(pb_to); - tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); + tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***"); return; } /* Copy data from char after cursor to end (if used) */ + len = pb_from->buf + pb_from->size - pb_from->crs - 2; if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { strcpy(pb_to->buf, pb_from->crs + 1); @@ -175,6 +194,7 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) pb_to->crs = pb_to->buf; /* Copy data from start to cursor (always) */ + len = pb_from->crs - pb_from->buf; strcpy(pb_to->crs, pb_from->buf); pb_to->crs += len; @@ -184,6 +204,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) /** * tipc_printf - append formatted output to print buffer chain + * @pb: pointer to chain of print buffers (may be NULL) + * @fmt: formatted info to be printed */ void tipc_printf(struct print_buf *pb, const char *fmt, ...) @@ -195,8 +217,8 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) spin_lock_bh(&print_lock); FORMAT(print_string, chars_to_add, fmt); - if (chars_to_add >= MAX_STRING) - strcpy(print_string, "*** STRING TOO LONG ***"); + if (chars_to_add >= TIPC_PB_MAX_STR) + strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); while (pb) { if (pb == TIPC_CONS) @@ -206,6 +228,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) if (chars_to_add <= chars_left) { strcpy(pb->crs, print_string); pb->crs += chars_to_add; + } else if (chars_to_add >= (pb->size - 1)) { + strcpy(pb->buf, print_string + chars_to_add + 1 + - pb->size); + pb->crs = pb->buf + pb->size - 1; } else { strcpy(pb->buf, print_string + chars_left); save_char = print_string[chars_left]; @@ -224,6 +250,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) /** * TIPC_TEE - perform next output operation on both print buffers + * @b0: pointer to chain of print buffers (may be NULL) + * @b1: pointer to print buffer to add to chain + * + * Returns pointer to print buffer chain. */ struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) @@ -232,8 +262,6 @@ struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) if (!b0 || (b0 == b1)) return b1; - if (!b1) - return b0; spin_lock_bh(&print_lock); while (pb->next) { @@ -256,7 +284,7 @@ static void print_to_console(char *crs, int len) int rest = len; while (rest > 0) { - int sz = rest < MAX_STRING ? rest : MAX_STRING; + int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR; char c = crs[sz]; crs[sz] = 0; @@ -275,36 +303,48 @@ static void printbuf_dump(struct print_buf *pb) { int len; + if (!pb->buf) { + printk("*** PRINT BUFFER NOT ALLOCATED ***"); + return; + } + /* Dump print buffer from char after cursor to end (if used) */ + len = pb->buf + pb->size - pb->crs - 2; if ((pb->buf[pb->size - 1] == 0) && (len > 0)) print_to_console(pb->crs + 1, len); /* Dump print buffer from start to cursor (always) */ + len = pb->crs - pb->buf; print_to_console(pb->buf, len); } /** * tipc_dump - dump non-console print buffer(s) to console + * @pb: pointer to chain of print buffers */ void tipc_dump(struct print_buf *pb, const char *fmt, ...) { + struct print_buf *pb_next; int len; spin_lock_bh(&print_lock); - FORMAT(TIPC_CONS->buf, len, fmt); - printk(TIPC_CONS->buf); + FORMAT(print_string, len, fmt); + printk(print_string); for (; pb; pb = pb->next) { - if (pb == TIPC_CONS) - continue; - printk("\n---- Start of dump,%s log ----\n\n", - (pb == TIPC_LOG) ? "global" : "local"); - printbuf_dump(pb); - tipc_printbuf_reset(pb); - printk("\n-------- End of dump --------\n"); + if (pb != TIPC_CONS) { + printk("\n---- Start of %s log dump ----\n\n", + (pb == TIPC_LOG) ? "global" : "local"); + printbuf_dump(pb); + tipc_printbuf_reset(pb); + printk("\n---- End of dump ----\n"); + } + pb_next = pb->next; + pb->next = NULL; + pb = pb_next; } spin_unlock_bh(&print_lock); } @@ -324,7 +364,8 @@ void tipc_log_stop(void) } /** - * tipc_log_reinit - set TIPC log print buffer to specified size + * tipc_log_reinit - (re)initialize TIPC log print buffer + * @log_size: print buffer size to use */ void tipc_log_reinit(int log_size) @@ -332,10 +373,11 @@ void tipc_log_reinit(int log_size) tipc_log_stop(); if (log_size) { - if (log_size <= MAX_STRING) - log_size = MAX_STRING + 1; + if (log_size < TIPC_PB_MIN_SIZE) + log_size = TIPC_PB_MIN_SIZE; spin_lock_bh(&print_lock); - tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size); + tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), + log_size); spin_unlock_bh(&print_lock); } } diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index 227f050..467c0bc7 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h @@ -2,7 +2,7 @@ * net/tipc/dbg.h: Include file for TIPC print buffer routines * * Copyright (c) 1997-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,14 @@ #ifndef _TIPC_DBG_H #define _TIPC_DBG_H +/** + * struct print_buf - TIPC print buffer structure + * @buf: pointer to character array containing print buffer contents + * @size: size of character array + * @crs: pointer to first unused space in character array (i.e. final NUL) + * @next: used to link print buffers when printing to more than one at a time + */ + struct print_buf { char *buf; u32 size; @@ -44,7 +52,10 @@ struct print_buf { struct print_buf *next; }; -void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz); +#define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ +#define TIPC_PB_MAX_STR 512 /* max printable string (with trailing NUL) */ + +void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size); void tipc_printbuf_reset(struct print_buf *pb); int tipc_printbuf_empty(struct print_buf *pb); int tipc_printbuf_validate(struct print_buf *pb); -- cgit v0.10.2 From eb5959c2bd290bf6c24ddf6d1f5ebcb496c54adb Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:43:54 -0700 Subject: [TIPC]: Stream socket can now send > 66000 bytes at a time The stream socket send code was not initializing some required fields of the temporary msghdr structure it was utilizing; this is now fixed. A check has also been added to detect if a user illegally specifies a destination address when sending on an established stream connection. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/socket.c b/net/tipc/socket.c index acfb852..ed900fe 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2,7 +2,7 @@ * net/tipc/socket.c: TIPC socket API * * Copyright (c) 2001-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2004-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -629,6 +629,9 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, return -ENOTCONN; } + if (unlikely(m->msg_name)) + return -EISCONN; + /* * Send each iovec entry using one or more messages * @@ -641,6 +644,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, curr_iovlen = m->msg_iovlen; my_msg.msg_iov = &my_iov; my_msg.msg_iovlen = 1; + my_msg.msg_flags = m->msg_flags; + my_msg.msg_name = NULL; bytes_sent = 0; while (curr_iovlen--) { -- cgit v0.10.2 From e91ed0bcdfc4812c0342d64281ee985213df07c3 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:44:59 -0700 Subject: [TIPC]: Added duplicate node address detection capability TIPC now rejects and logs link setup requests from node if the receiving node already has a functional link to that node on the associated interface, or if the requestor is using the same as the receiver. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 75a5968..39744a3 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -2,7 +2,7 @@ * net/tipc/bearer.c: TIPC bearer code * * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2004-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -191,14 +191,14 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) if ((i < media_count) && (m_ptr->addr2str != NULL)) { char addr_str[MAX_ADDR_STR]; - tipc_printf(pb, "%s(%s) ", m_ptr->name, + tipc_printf(pb, "%s(%s)", m_ptr->name, m_ptr->addr2str(a, addr_str, sizeof(addr_str))); } else { unchar *addr = (unchar *)&a->dev_addr; - tipc_printf(pb, "UNKNOWN(%u):", media_type); + tipc_printf(pb, "UNKNOWN(%u)", media_type); for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { - tipc_printf(pb, "%02x ", addr[i]); + tipc_printf(pb, "-%02x", addr[i]); } } } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index ee94de9..cc748d4 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -132,6 +132,28 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, } /** + * disc_dupl_alert - issue node address duplication alert + * @b_ptr: pointer to bearer detecting duplication + * @node_addr: duplicated node address + * @media_addr: media address advertised by duplicated node + */ + +static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, + struct tipc_media_addr *media_addr) +{ + char node_addr_str[16]; + char media_addr_str[64]; + struct print_buf pb; + + addr_string_fill(node_addr_str, node_addr); + tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); + tipc_media_addr_printf(&pb, media_addr); + tipc_printbuf_validate(&pb); + warn("Duplicate %s using %s seen on <%s>\n", + node_addr_str, media_addr_str, b_ptr->publ.name); +} + +/** * tipc_disc_recv_msg - handle incoming link setup message (request or response) * @buf: buffer containing message */ @@ -157,8 +179,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf) return; if (!tipc_addr_node_valid(orig)) return; - if (orig == tipc_own_addr) + if (orig == tipc_own_addr) { + if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr))) + disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); return; + } if (!in_scope(dest, tipc_own_addr)) return; if (is_slave(tipc_own_addr) && is_slave(orig)) @@ -190,6 +215,11 @@ void tipc_disc_recv_msg(struct sk_buff *buf) } addr = &link->media_addr; if (memcmp(addr, &media_addr, sizeof(*addr))) { + if (tipc_link_is_up(link) || (!link->started)) { + disc_dupl_alert(b_ptr, orig, &media_addr); + spin_unlock_bh(&n_ptr->lock); + return; + } warn("Resetting link <%s>, peer interface address changed\n", link->name); memcpy(addr, &media_addr, sizeof(*addr)); -- cgit v0.10.2 From cfb0c0890b200364c0886c0d9f0dc615f8114c43 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:47:18 -0700 Subject: [TIPC]: Optimize wakeup logic when socket has no waiting processes This patch adds a simple test so TIPC doesn't try waking up processes waiting on a socket if there are none waiting. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/socket.c b/net/tipc/socket.c index ed900fe..2a6a5a6 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1208,7 +1208,8 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) atomic_inc(&tipc_queue_size); skb_queue_tail(&sock->sk->sk_receive_queue, buf); - wake_up_interruptible(sock->sk->sk_sleep); + if (waitqueue_active(sock->sk->sk_sleep)) + wake_up_interruptible(sock->sk->sk_sleep); return TIPC_OK; } @@ -1223,7 +1224,8 @@ static void wakeupdispatch(struct tipc_port *tport) { struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; - wake_up_interruptible(tsock->sk.sk_sleep); + if (waitqueue_active(tsock->sk.sk_sleep)) + wake_up_interruptible(tsock->sk.sk_sleep); } /** -- cgit v0.10.2 From a3df92c73b92970dc4211189b87eb4cf874f5685 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:49:03 -0700 Subject: [TIPC]: Remove code bloat introduced by print buffer rework This patch allows the compiler to optimize out any code that tries to send debugging output to the null print buffer (TIPC_NULL), a capability that was unintentionally broken during the recent print buffer rework. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/core.h b/net/tipc/core.h index 47504ec..d1c3948 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -83,9 +83,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) -#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) -#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) -#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) +#define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) +#define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) +#define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) /* diff --git a/net/tipc/link.c b/net/tipc/link.c index 53bc8cb..1bb983c 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -132,7 +132,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, * allow the output from multiple links to be intermixed. For this reason * routines of the form "dbg_link_XXX()" have been created that will capture * debug info into a link's personal print buffer, which can then be dumped - * into the TIPC system log (LOG) upon request. + * into the TIPC system log (TIPC_LOG) upon request. * * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, @@ -141,7 +141,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, * when there is only a single link in the system being debugged. * * Notes: - * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) + * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE * - "l_ptr" must be valid when using dbg_link_XXX() macros */ @@ -159,13 +159,13 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, static void dbg_print_link(struct link *l_ptr, const char *str) { - if (DBG_OUTPUT) + if (DBG_OUTPUT != TIPC_NULL) link_print(l_ptr, DBG_OUTPUT, str); } static void dbg_print_buf_chain(struct sk_buff *root_buf) { - if (DBG_OUTPUT) { + if (DBG_OUTPUT != TIPC_NULL) { struct sk_buff *buf = root_buf; while (buf) { -- cgit v0.10.2 From 3a8d12142eab420ffcbbf3d1d2e637158e85aab8 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:50:20 -0700 Subject: [TIPC]: Add support for Ethernet VLANs This patch enhances TIPC's Ethernet support to include VLAN interfaces. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/core.c b/net/tipc/core.c index 0539a83..7f3f693 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -90,7 +90,7 @@ int tipc_random; atomic_t tipc_user_count = ATOMIC_INIT(0); const char tipc_alphabet[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; /* configurable TIPC parameters */ diff --git a/net/tipc/core.h b/net/tipc/core.h index d1c3948..4638947c 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -275,11 +275,15 @@ static inline void k_term_timer(struct timer_list *timer) /* * TIPC message buffer code * - * TIPC message buffer headroom leaves room for 14 byte Ethernet header, + * TIPC message buffer headroom reserves space for a link-level header + * (in case the message is sent off-node), * while ensuring TIPC header is word aligned for quicker access + * + * The largest header currently supported is 18 bytes, which is used when + * the standard 14 byte Ethernet header has 4 added bytes for VLAN info */ -#define BUF_HEADROOM 16u +#define BUF_HEADROOM 20u struct tipc_skb_cb { void *handle; -- cgit v0.10.2 From 08c31f7167b1bdc30cd0960b45d6f3076eb1f179 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:56:04 -0700 Subject: [TIPC]: Name publication events now delivered in chronological order This patch tivially re-orders the entries in TIPC's list of local publications so that applications will receive publication events in the order they were published. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index f0b063b..03bd659 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -122,7 +122,7 @@ void tipc_named_publish(struct publication *publ) struct sk_buff *buf; struct distr_item *item; - list_add(&publ->local_list, &publ_root); + list_add_tail(&publ->local_list, &publ_root); publ_cnt++; buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); -- cgit v0.10.2 From 2de07f6156fe664063207c010b3bd2500348884a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:57:13 -0700 Subject: [TIPC]: Fixed slow link reactivation when link tolerance is large This patch corrects an issue wherein a previouly failed node could not reestablish a links to a non-failing node in the TIPC network until the latter node detected the link failure itself (which might be configured to take up to 30 seconds). The non-failing node now responds to link setup requests from a previously failed node in at most 1 second, allowing it to detect the link failure more quickly. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/discover.c b/net/tipc/discover.c index cc748d4..3b0cd12 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -195,7 +195,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf) struct sk_buff *rbuf; struct tipc_media_addr *addr; struct node *n_ptr = tipc_node_find(orig); - int link_up; + int link_fully_up; + dbg(" in own cluster\n"); if (n_ptr == NULL) { n_ptr = tipc_node_create(orig); @@ -225,9 +226,9 @@ void tipc_disc_recv_msg(struct sk_buff *buf) memcpy(addr, &media_addr, sizeof(*addr)); tipc_link_reset(link); } - link_up = tipc_link_is_up(link); + link_fully_up = (link->state == WORKING_WORKING); spin_unlock_bh(&n_ptr->lock); - if ((type == DSC_RESP_MSG) || link_up) + if ((type == DSC_RESP_MSG) || link_fully_up) return; rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); if (rbuf != NULL) { -- cgit v0.10.2 From fc144deec6403c17e6d3f6a6574f701420f166ed Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 21:57:56 -0700 Subject: [TIPC]: Can now list multicast link on an isolated network node This patch fixes a minor bug that prevents "tipc-config -l" from displaying the multicast link if a TIPC node has never successfully established at least one unicast link. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/node.c b/net/tipc/node.c index fc6d096..886bda5 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -648,7 +648,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); - if (!tipc_nodes) + if (tipc_mode != TIPC_NET_MODE) return tipc_cfg_reply_none(); /* Get space for all unicast links + multicast link */ -- cgit v0.10.2 From eb409460b1abec0e2a1f9c9d07019f4157a6d6bc Mon Sep 17 00:00:00 2001 From: Lijun Chen Date: Mon, 16 Oct 2006 21:59:42 -0700 Subject: [TIPC]: Added subscription cancellation capability This patch allows a TIPC application to cancel an existing topology service subscription by re-requesting the subscription with the TIPC_SUB_CANCEL filter bit set. (All other bits of the cancel request must match the original subscription request.) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/include/linux/tipc.h b/include/linux/tipc.h index 243a15f..bea4694 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -129,6 +129,7 @@ static inline unsigned int tipc_node(__u32 addr) #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ +#define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */ #if 0 /* The following filter options are not currently implemented */ #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index c51600b..7a918f1 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -155,7 +155,7 @@ void tipc_subscr_report_overlap(struct subscription *sub, sub->seq.upper, found_lower, found_upper); if (!tipc_subscr_overlap(sub, found_lower, found_upper)) return; - if (!must && (sub->filter != TIPC_SUB_PORTS)) + if (!must && !(sub->filter & TIPC_SUB_PORTS)) return; subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); } @@ -176,6 +176,13 @@ static void subscr_timeout(struct subscription *sub) if (subscriber == NULL) return; + /* Validate timeout (in case subscription is being cancelled) */ + + if (sub->timeout == TIPC_WAIT_FOREVER) { + tipc_ref_unlock(subscriber_ref); + return; + } + /* Unlink subscription from name table */ tipc_nametbl_unsubscribe(sub); @@ -199,6 +206,20 @@ static void subscr_timeout(struct subscription *sub) } /** + * subscr_del - delete a subscription within a subscription list + * + * Called with subscriber locked. + */ + +static void subscr_del(struct subscription *sub) +{ + tipc_nametbl_unsubscribe(sub); + list_del(&sub->subscription_list); + kfree(sub); + atomic_dec(&topsrv.subscription_count); +} + +/** * subscr_terminate - terminate communication with a subscriber * * Called with subscriber locked. Routine must temporarily release this lock @@ -227,12 +248,9 @@ static void subscr_terminate(struct subscriber *subscriber) k_cancel_timer(&sub->timer); k_term_timer(&sub->timer); } - tipc_nametbl_unsubscribe(sub); - list_del(&sub->subscription_list); - dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", + dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n", sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); - kfree(sub); - atomic_dec(&topsrv.subscription_count); + subscr_del(sub); } /* Sever connection to subscriber */ @@ -253,6 +271,49 @@ static void subscr_terminate(struct subscriber *subscriber) } /** + * subscr_cancel - handle subscription cancellation request + * + * Called with subscriber locked. Routine must temporarily release this lock + * to enable the subscription timeout routine to finish without deadlocking; + * the lock is then reclaimed to allow caller to release it upon return. + * + * Note that fields of 's' use subscriber's endianness! + */ + +static void subscr_cancel(struct tipc_subscr *s, + struct subscriber *subscriber) +{ + struct subscription *sub; + struct subscription *sub_temp; + int found = 0; + + /* Find first matching subscription, exit if not found */ + + list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, + subscription_list) { + if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { + found = 1; + break; + } + } + if (!found) + return; + + /* Cancel subscription timer (if used), then delete subscription */ + + if (sub->timeout != TIPC_WAIT_FOREVER) { + sub->timeout = TIPC_WAIT_FOREVER; + spin_unlock_bh(subscriber->lock); + k_cancel_timer(&sub->timer); + k_term_timer(&sub->timer); + spin_lock_bh(subscriber->lock); + } + dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", + sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); + subscr_del(sub); +} + +/** * subscr_subscribe - create subscription for subscriber * * Called with subscriber locked @@ -263,6 +324,21 @@ static void subscr_subscribe(struct tipc_subscr *s, { struct subscription *sub; + /* Determine/update subscriber's endianness */ + + if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)) + subscriber->swap = 0; + else + subscriber->swap = 1; + + /* Detect & process a subscription cancellation request */ + + if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) { + s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap); + subscr_cancel(s, subscriber); + return; + } + /* Refuse subscription if global limit exceeded */ if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { @@ -281,13 +357,6 @@ static void subscr_subscribe(struct tipc_subscr *s, return; } - /* Determine/update subscriber's endianness */ - - if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE)) - subscriber->swap = 0; - else - subscriber->swap = 1; - /* Initialize subscription object */ memset(sub, 0, sizeof(*sub)); @@ -296,8 +365,8 @@ static void subscr_subscribe(struct tipc_subscr *s, sub->seq.upper = htohl(s->seq.upper, subscriber->swap); sub->timeout = htohl(s->timeout, subscriber->swap); sub->filter = htohl(s->filter, subscriber->swap); - if ((((sub->filter != TIPC_SUB_PORTS) - && (sub->filter != TIPC_SUB_SERVICE))) + if ((!(sub->filter & TIPC_SUB_PORTS) + == !(sub->filter & TIPC_SUB_SERVICE)) || (sub->seq.lower > sub->seq.upper)) { warn("Subscription rejected, illegal request\n"); kfree(sub); -- cgit v0.10.2 From 53cfd1e102c759c958f907ee40a58bec3fc5911a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 22:00:56 -0700 Subject: [TIPC]: Unrecognized configuration command now returns error message This patch causes TIPC to return an error message when it receives an unrecognized configuration command. (Previously, the sender received no feedback.) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/config.c b/net/tipc/config.c index 285e1bc..ed1351e 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -2,7 +2,7 @@ * net/tipc/config.c: TIPC configuration management code * * Copyright (c) 2002-2006, Ericsson AB - * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2004-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -613,7 +613,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); break; default: - rep_tlv_buf = NULL; + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (unknown command)"); break; } -- cgit v0.10.2 From 665d8669583e28c397d4333385d8f46ca5864048 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 16 Oct 2006 22:01:32 -0700 Subject: [TIPC]: Updated TIPC version number to 1.6.2 Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller diff --git a/net/tipc/core.c b/net/tipc/core.c index 7f3f693..6f5b7ee 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -57,7 +57,7 @@ void tipc_socket_stop(void); int tipc_netlink_start(void); void tipc_netlink_stop(void); -#define TIPC_MOD_VER "1.6.1" +#define TIPC_MOD_VER "1.6.2" #ifndef CONFIG_TIPC_ZONES #define CONFIG_TIPC_ZONES 3 -- cgit v0.10.2 From e320af1df4c47305e829e8e1a40e5fad0e5e9fba Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:05:55 -0700 Subject: [IPV6]: Remove struct pol_chain. Struct pol_chain has existed since at least the 2.2 kernel, but isn't used anymore. As the IPv6 policy routing is implemented in a totally different way in the current kernel, just get rid of it. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 6ca6b71..c14b70e 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -36,13 +36,6 @@ struct route_info { #define RT6_LOOKUP_F_REACHABLE 0x2 #define RT6_LOOKUP_F_HAS_SADDR 0x4 -struct pol_chain { - int type; - int priority; - struct fib6_node *rules; - struct pol_chain *next; -}; - extern struct rt6_info ip6_null_entry; #ifdef CONFIG_IPV6_MULTIPLE_TABLES -- cgit v0.10.2 From 23c435f7ff884caded4a1391ba2b308d465423c0 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:08:28 -0700 Subject: [SCTP]: Fix minor typo Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9deec43..9f34dec 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -821,7 +821,7 @@ out: * addrs is a pointer to an array of one or more socket addresses. Each * address is contained in its appropriate structure (i.e. struct * sockaddr_in or struct sockaddr_in6) the family of the address type - * must be used to distengish the address length (note that this + * must be used to distinguish the address length (note that this * representation is termed a "packed array" of addresses). The caller * specifies the number of addresses in the array with addrcnt. * -- cgit v0.10.2 From 4251320fa2ef93207fbefeb2eda2d265b84fc116 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:10:05 -0700 Subject: [IPV6]: Make sure error handling is done when calling ip6_route_output(). As ip6_route_output() never returns NULL, error checking must be done by looking at dst->error in stead of comparing dst against NULL. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 73cee2e..d400f8f 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -25,12 +25,14 @@ static struct dst_ops xfrm6_dst_ops; static struct xfrm_policy_afinfo xfrm6_policy_afinfo; -static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) +static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl) { - int err = 0; - *dst = (struct xfrm_dst*)ip6_route_output(NULL, fl); - if (!*dst) - err = -ENETUNREACH; + struct dst_entry *dst = ip6_route_output(NULL, fl); + int err = dst->error; + if (!err) + *xdst = (struct xfrm_dst *) dst; + else + dst_release(dst); return err; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 249e503..78071c6 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -215,17 +215,17 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, } dst = ip6_route_output(NULL, &fl); - if (dst) { + if (!dst->error) { struct rt6_info *rt; rt = (struct rt6_info *)dst; SCTP_DEBUG_PRINTK( "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); - } else { - SCTP_DEBUG_PRINTK("NO ROUTE\n"); + return dst; } - - return dst; + SCTP_DEBUG_PRINTK("NO ROUTE\n"); + dst_release(dst); + return NULL; } /* Returns the number of consecutive initial bits that match in the 2 ipv6 -- cgit v0.10.2 From e0eda7bbaae48ea56f1f1943ea90df72d459b9b0 Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:11:11 -0700 Subject: [IPV6]: Clean up BACKTRACK(). The fn check is unnecessary as fn can never be NULL in BACKTRACK(). Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a1b0f07..263c057 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -484,7 +484,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, do { \ if (rt == &ip6_null_entry) { \ struct fib6_node *pn; \ - while (fn) { \ + while (1) { \ if (fn->fn_flags & RTN_TL_ROOT) \ goto out; \ pn = fn->parent; \ -- cgit v0.10.2 From 264e91b68aff1e39b558123498f28bf5aa68b4ee Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:12:21 -0700 Subject: [IPV6]: Make IPV6_SUBTREES depend on IPV6_MULTIPLE_TABLES. As IPV6_SUBTREES can't work without IPV6_MULTIPLE_TABLES have IPV6_SUBTREES depend on it. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ef5eaad..6e48f52 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -175,9 +175,16 @@ config IPV6_TUNNEL If unsure, say N. +config IPV6_MULTIPLE_TABLES + bool "IPv6: Multiple Routing Tables" + depends on IPV6 && EXPERIMENTAL + select FIB_RULES + ---help--- + Support multiple routing tables. + config IPV6_SUBTREES bool "IPv6: source address based routing" - depends on IPV6 && EXPERIMENTAL + depends on IPV6_MULTIPLE_TABLES ---help--- Enable routing by source address or prefix. @@ -189,13 +196,6 @@ config IPV6_SUBTREES If unsure, say N. -config IPV6_MULTIPLE_TABLES - bool "IPv6: Multiple Routing Tables" - depends on IPV6 && EXPERIMENTAL - select FIB_RULES - ---help--- - Support multiple routing tables. - config IPV6_ROUTE_FWMARK bool "IPv6: use netfilter MARK value as routing key" depends on IPV6_MULTIPLE_TABLES && NETFILTER -- cgit v0.10.2 From 22e1e4d8dcb71762fcbe0c73d720aea8bb2013af Mon Sep 17 00:00:00 2001 From: Ville Nuorvala Date: Mon, 16 Oct 2006 22:14:26 -0700 Subject: [IPV6]: Always copy rt->u.dst.error when copying a rt6_info. Signed-off-by: Ville Nuorvala Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 263c057..aa96be8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -618,8 +618,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); rt->rt6i_dst.plen = 128; rt->rt6i_flags |= RTF_CACHE; - if (rt->rt6i_flags & RTF_REJECT) - rt->u.dst.error = ort->u.dst.error; rt->u.dst.flags |= DST_HOST; rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); } @@ -1540,6 +1538,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) rt->u.dst.output = ort->u.dst.output; memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); + rt->u.dst.error = ort->u.dst.error; rt->u.dst.dev = ort->u.dst.dev; if (rt->u.dst.dev) dev_hold(rt->u.dst.dev); -- cgit v0.10.2 From b52f070c9c3c09ed3b7f699280193aae7e25d816 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 18 Oct 2006 20:26:36 -0700 Subject: [IPv4] fib: Remove unused fib_config members Signed-off-by: Thomas Graf Signed-off-by: David S. Miller diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 8222914..949b932 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -21,17 +21,14 @@ #include struct fib_config { - u8 fc_family; u8 fc_dst_len; - u8 fc_src_len; u8 fc_tos; u8 fc_protocol; u8 fc_scope; u8 fc_type; - /* 1 byte unused */ + /* 3 bytes unused */ u32 fc_table; __be32 fc_dst; - __be32 fc_src; __be32 fc_gw; int fc_oif; u32 fc_flags; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 9c399a7..af0190d 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -482,9 +482,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, memset(cfg, 0, sizeof(*cfg)); rtm = nlmsg_data(nlh); - cfg->fc_family = rtm->rtm_family; cfg->fc_dst_len = rtm->rtm_dst_len; - cfg->fc_src_len = rtm->rtm_src_len; cfg->fc_tos = rtm->rtm_tos; cfg->fc_table = rtm->rtm_table; cfg->fc_protocol = rtm->rtm_protocol; @@ -501,9 +499,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, case RTA_DST: cfg->fc_dst = nla_get_be32(attr); break; - case RTA_SRC: - cfg->fc_src = nla_get_be32(attr); - break; case RTA_OIF: cfg->fc_oif = nla_get_u32(attr); break; -- cgit v0.10.2 From ae8064ac32d07f609114d73928cdef803be87134 Mon Sep 17 00:00:00 2001 From: John Heffner Date: Wed, 18 Oct 2006 20:36:48 -0700 Subject: [TCP]: Bound TSO defer time This patch limits the amount of time you will defer sending a TSO segment to less than two clock ticks, or the time between two acks, whichever is longer. On slow links, deferring causes significant bursts. See attached plots, which show RTT through a 1 Mbps link with a 100 ms RTT and ~100 ms queue for (a) non-TSO, (b) currnet TSO, and (c) patched TSO. This burstiness causes significant jitter, tends to overflow queues early (bad for short queues), and makes delay-based congestion control more difficult. Deferring by a couple clock ticks I believe will have a relatively small impact on performance. Signed-off-by: John Heffner Signed-off-by: David S. Miller diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 0e058a2..2d36f6d 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -342,6 +342,8 @@ struct tcp_sock { unsigned long last_synq_overflow; + __u32 tso_deferred; + /* Receiver side RTT estimation */ struct { __u32 rtt; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f22536e..ca40615 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ u32 send_win, cong_win, limit, in_flight; if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) - return 0; + goto send_now; if (icsk->icsk_ca_state != TCP_CA_Open) - return 0; + goto send_now; + + /* Defer for less than two clock ticks. */ + if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1) + goto send_now; in_flight = tcp_packets_in_flight(tp); @@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ /* If a full-sized TSO skb can be sent, do it. */ if (limit >= 65536) - return 0; + goto send_now; if (sysctl_tcp_tso_win_divisor) { u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); @@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ */ chunk /= sysctl_tcp_tso_win_divisor; if (limit >= chunk) - return 0; + goto send_now; } else { /* Different approach, try not to defer past a single * ACK. Receiver should ACK every other full sized @@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ * then send now. */ if (limit > tcp_max_burst(tp) * tp->mss_cache) - return 0; + goto send_now; } /* Ok, it looks like it is advisable to defer. */ + tp->tso_deferred = 1 | (jiffies<<1); + return 1; + +send_now: + tp->tso_deferred = 0; + return 0; } /* Create a new MTU probe if we are ready. -- cgit v0.10.2 From 3a31b9d2f2d98667832e87fa1853754ff062d6ef Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 18 Oct 2006 20:45:22 -0700 Subject: [DECNET]: Fix input routing bug This patch fixes a silly bug that has been in the input routing code for some time. It results in trying to send to a node directly when the origin of the packet is via the default router. Its been tested by Alan Kemmerer who reported the bug and its a fairly obvious fix for a typo. Signed-off-by: Steven Whitehouse Signed-off-by: Patrick Caulfield Signed-off-by: David S. Miller diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 491429c..23489f7 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1275,7 +1275,6 @@ static int dn_route_input_slow(struct sk_buff *skb) goto e_inval; res.type = RTN_LOCAL; - flags |= RTCF_DIRECTSRC; } else { __le16 src_map = fl.fld_src; free_res = 1; @@ -1346,7 +1345,7 @@ static int dn_route_input_slow(struct sk_buff *skb) goto make_route; /* Packet was intra-ethernet, so we know its on-link */ - if (cb->rt_flags | DN_RT_F_IE) { + if (cb->rt_flags & DN_RT_F_IE) { gateway = cb->src; flags |= RTCF_DIRECTSRC; goto make_route; -- cgit v0.10.2 From 9ce8ade015a3f82dbdf856df7a685878dd1cc0e1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 18 Oct 2006 20:46:54 -0700 Subject: [IPv6] route: Fix prohibit and blackhole routing decision Lookups resolving to ip6_blk_hole_entry must result in silently discarding the packets whereas an ip6_pkt_prohibit_entry is supposed to cause an ICMPV6_ADM_PROHIBITED message to be sent. Thanks to Kim Nordlund for noticing this bug. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aa96be8..5c00ca4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -94,6 +94,9 @@ static int ip6_dst_gc(void); static int ip6_pkt_discard(struct sk_buff *skb); static int ip6_pkt_discard_out(struct sk_buff *skb); +static int ip6_pkt_prohibit(struct sk_buff *skb); +static int ip6_pkt_prohibit_out(struct sk_buff *skb); +static int ip6_pkt_blk_hole(struct sk_buff *skb); static void ip6_link_failure(struct sk_buff *skb); static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); @@ -150,8 +153,8 @@ struct rt6_info ip6_prohibit_entry = { .obsolete = -1, .error = -EACCES, .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, - .input = ip6_pkt_discard, - .output = ip6_pkt_discard_out, + .input = ip6_pkt_prohibit, + .output = ip6_pkt_prohibit_out, .ops = &ip6_dst_ops, .path = (struct dst_entry*)&ip6_prohibit_entry, } @@ -170,8 +173,8 @@ struct rt6_info ip6_blk_hole_entry = { .obsolete = -1, .error = -EINVAL, .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, - .input = ip6_pkt_discard, - .output = ip6_pkt_discard_out, + .input = ip6_pkt_blk_hole, + .output = ip6_pkt_blk_hole, .ops = &ip6_dst_ops, .path = (struct dst_entry*)&ip6_blk_hole_entry, } @@ -1742,24 +1745,46 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) * Drop the packet on the floor */ -static int ip6_pkt_discard(struct sk_buff *skb) +static inline int ip6_pkt_drop(struct sk_buff *skb, int code) { int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); kfree_skb(skb); return 0; } +static int ip6_pkt_discard(struct sk_buff *skb) +{ + return ip6_pkt_drop(skb, ICMPV6_NOROUTE); +} + static int ip6_pkt_discard_out(struct sk_buff *skb) { skb->dev = skb->dst->dev; return ip6_pkt_discard(skb); } +static int ip6_pkt_prohibit(struct sk_buff *skb) +{ + return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); +} + +static int ip6_pkt_prohibit_out(struct sk_buff *skb) +{ + skb->dev = skb->dst->dev; + return ip6_pkt_prohibit(skb); +} + +static int ip6_pkt_blk_hole(struct sk_buff *skb) +{ + kfree_skb(skb); + return 0; +} + /* * Allocate a dst for local (unicast / anycast) address. */ -- cgit v0.10.2 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 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4178b4b1..93fbea1 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 v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 327836b..39e4833 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 v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 39e4833..7ba9dd2 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 v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7ba9dd2..8e39849 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 v0.10.2 From 6723ab549df777742801716d7aeea397e6e97f2c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Oct 2006 21:20:57 -0700 Subject: [IPV6]: Fix route.c warnings when multiple tables are disabled. Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5c00ca4..c953466 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -94,9 +94,6 @@ static int ip6_dst_gc(void); static int ip6_pkt_discard(struct sk_buff *skb); static int ip6_pkt_discard_out(struct sk_buff *skb); -static int ip6_pkt_prohibit(struct sk_buff *skb); -static int ip6_pkt_prohibit_out(struct sk_buff *skb); -static int ip6_pkt_blk_hole(struct sk_buff *skb); static void ip6_link_failure(struct sk_buff *skb); static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); @@ -144,6 +141,10 @@ struct rt6_info ip6_null_entry = { #ifdef CONFIG_IPV6_MULTIPLE_TABLES +static int ip6_pkt_prohibit(struct sk_buff *skb); +static int ip6_pkt_prohibit_out(struct sk_buff *skb); +static int ip6_pkt_blk_hole(struct sk_buff *skb); + struct rt6_info ip6_prohibit_entry = { .u = { .dst = { @@ -1768,6 +1769,8 @@ static int ip6_pkt_discard_out(struct sk_buff *skb) return ip6_pkt_discard(skb); } +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + static int ip6_pkt_prohibit(struct sk_buff *skb) { return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); @@ -1785,6 +1788,8 @@ static int ip6_pkt_blk_hole(struct sk_buff *skb) return 0; } +#endif + /* * Allocate a dst for local (unicast / anycast) address. */ -- cgit v0.10.2 From 6b0022305f80cf249de69e746f6f5ccf7ffc5b7c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 12 Oct 2006 17:07:45 +0900 Subject: sh: Proper show_stack/show_trace() implementation. This splits out some of the previous show_stack() implementation which was mostly doing the show_trace() work without actually dumping any of the stack contents. This now gets split in to two sections, where we do the fetching of the stack pointer and subsequent stack dumping in show_stack(), while moving the call trace in to show_trace(). Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 91516dc..a52b13a 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -105,7 +105,7 @@ void show_regs(struct pt_regs * regs) { printk("\n"); printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); - print_symbol("PC is at %s\n", regs->pc); + print_symbol("PC is at %s\n", instruction_pointer(regs)); printk("PC : %08lx SP : %08lx SR : %08lx ", regs->pc, regs->regs[15], regs->sr); #ifdef CONFIG_MMU @@ -130,15 +130,7 @@ void show_regs(struct pt_regs * regs) printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", regs->mach, regs->macl, regs->gbr, regs->pr); - /* - * If we're in kernel mode, dump the stack too.. - */ - if (!user_mode(regs)) { - extern void show_task(unsigned long *sp); - unsigned long sp = regs->regs[15]; - - show_task((unsigned long *)sp); - } + show_trace(NULL, (unsigned long *)regs->regs[15], regs); } /* diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index c2c597e..ffe127f 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -1,16 +1,15 @@ -/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $ - * - * linux/arch/sh/traps.c +/* + * 'traps.c' handles hardware traps and faults after we have saved some + * state in 'entry.S'. * * SuperH version: Copyright (C) 1999 Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf * Copyright (C) 2000 David Howells - * Copyright (C) 2002, 2003 Paul Mundt - */ - -/* - * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'entry.S'. + * Copyright (C) 2002 - 2006 Paul Mundt + * + * 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. */ #include #include @@ -53,13 +52,32 @@ #define TRAP_ILLEGAL_SLOT_INST 13 #endif -/* - * These constants are for searching for possible module text - * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is - * a guess of how much space is likely to be vmalloced. - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define MODULE_RANGE (8*1024*1024) +static void dump_mem(const char *str, unsigned long bottom, unsigned long top) +{ + unsigned long p; + int i; + + printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); + + for (p = bottom & ~31; p < top; ) { + printk("%04lx: ", p & 0xffff); + + for (i = 0; i < 8; i++, p += 4) { + unsigned int val; + + if (p < bottom || p >= top) + printk(" "); + else { + if (__get_user(val, (unsigned int __user *)p)) { + printk("\n"); + return; + } + printk("%08x ", val); + } + } + printk("\n"); + } +} DEFINE_SPINLOCK(die_lock); @@ -69,14 +87,28 @@ void die(const char * str, struct pt_regs * regs, long err) console_verbose(); spin_lock_irq(&die_lock); + bust_spinlocks(1); + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); + CHK_REMOTE_DEBUG(regs); + print_modules(); show_regs(regs); + + printk("Process: %s (pid: %d, stack limit = %p)\n", + current->comm, current->pid, task_stack_page(current) + 1); + + if (!user_mode(regs) || in_interrupt()) + dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + + (unsigned long)task_stack_page(current)); + + bust_spinlocks(0); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } -static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) +static inline void die_if_kernel(const char *str, struct pt_regs *regs, + long err) { if (!user_mode(regs)) die(str, regs, err); @@ -93,8 +125,7 @@ static int handle_unaligned_notify_count = 10; */ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) { - if (!user_mode(regs)) - { + if (!user_mode(regs)) { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->pc); if (fixup) { @@ -734,52 +765,43 @@ void __init trap_init(void) per_cpu_trap_init(); } -void show_stack(struct task_struct *tsk, unsigned long *sp) +void show_trace(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs) { - unsigned long *stack, addr; - unsigned long module_start = VMALLOC_START; - unsigned long module_end = VMALLOC_END; - int i = 1; + unsigned long addr; - if (!tsk) - tsk = current; - if (tsk == current) - sp = (unsigned long *)current_stack_pointer; - else - sp = (unsigned long *)tsk->thread.sp; - - stack = sp; + if (regs && user_mode(regs)) + return; printk("\nCall trace: "); #ifdef CONFIG_KALLSYMS printk("\n"); #endif - while (!kstack_end(stack)) { - addr = *stack++; - if (((addr >= (unsigned long)_text) && - (addr <= (unsigned long)_etext)) || - ((addr >= module_start) && (addr <= module_end))) { - /* - * For 80-columns display, 6 entry is maximum. - * NOTE: '[<8c00abcd>] ' consumes 13 columns . - */ -#ifndef CONFIG_KALLSYMS - if (i && ((i % 6) == 0)) - printk("\n "); -#endif - printk("[<%08lx>] ", addr); - print_symbol("%s\n", addr); - i++; - } + while (!kstack_end(sp)) { + addr = *sp++; + if (kernel_text_address(addr)) + print_ip_sym(addr); } printk("\n"); } -void show_task(unsigned long *sp) +void show_stack(struct task_struct *tsk, unsigned long *sp) { - show_stack(NULL, sp); + unsigned long stack; + + if (!tsk) + tsk = current; + if (tsk == current) + sp = (unsigned long *)current_stack_pointer; + else + sp = (unsigned long *)tsk->thread.sp; + + stack = (unsigned long)sp; + dump_mem("Stack: ", stack, THREAD_SIZE + + (unsigned long)task_stack_page(tsk)); + show_trace(tsk, sp, NULL); } void dump_stack(void) diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 4747738..45bb74e 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -255,6 +255,8 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); */ #define thread_saved_pc(tsk) (tsk->thread.pc) +void show_trace(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs); extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) ((tsk)->thread.pc) -- cgit v0.10.2 From 4a58eaca7ca68abea37d6d2a4ea7deb394906183 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 19 Oct 2006 16:15:13 +0900 Subject: sh: Remove board-specific ide.h headers. The driver that these were using never made it in to drivers/ide, so kill off the rest of the cruft. These will have to be reworked for board-specific platform devices through libata when they're added back through the setup code. Signed-off-by: Paul Mundt diff --git a/include/asm-sh/hp6xx/ide.h b/include/asm-sh/hp6xx/ide.h deleted file mode 100644 index 570395a..0000000 --- a/include/asm-sh/hp6xx/ide.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH_HP6XX_IDE_H -#define __ASM_SH_HP6XX_IDE_H - -#define IRQ_CFCARD 93 -#define IRQ_PCMCIA 94 - -#endif /* __ASM_SH_HP6XX_IDE_H */ - diff --git a/include/asm-sh/hs7751rvoip/ide.h b/include/asm-sh/hs7751rvoip/ide.h deleted file mode 100644 index 65ad1d0..0000000 --- a/include/asm-sh/hs7751rvoip/ide.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH_HS7751RVOIP_IDE_H -#define __ASM_SH_HS7751RVOIP_IDE_H - -/* Nothing to see here.. */ -#include - -#endif /* __ASM_SH_HS7751RVOIP_IDE_H */ - diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 28996f9..1837bdb 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -14,16 +14,6 @@ #include #include /* for pt_regs */ -#if defined(CONFIG_SH_HP6XX) || \ - defined(CONFIG_SH_RTS7751R2D) || \ - defined(CONFIG_SH_HS7751RVOIP) || \ - defined(CONFIG_SH_HS7751RVOIP) || \ - defined(CONFIG_SH_SH03) || \ - defined(CONFIG_SH_R7780RP) || \ - defined(CONFIG_SH_LANDISK) -#include -#endif - #ifndef CONFIG_CPU_SUBTYPE_SH7780 #define INTC_DMAC0_MSK 0 @@ -38,15 +28,6 @@ #define INTC_IPRD 0xffd00010UL #endif -#ifdef CONFIG_IDE -# ifndef IRQ_CFCARD -# define IRQ_CFCARD 14 -# endif -# ifndef IRQ_PCMCIA -# define IRQ_PCMCIA 15 -# endif -#endif - #define TIMER_IRQ 16 #define TIMER_IPR_ADDR INTC_IPRA #define TIMER_IPR_POS 3 diff --git a/include/asm-sh/landisk/ide.h b/include/asm-sh/landisk/ide.h deleted file mode 100644 index 6490e28..0000000 --- a/include/asm-sh/landisk/ide.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * modifed by kogiidena - * 2005.03.03 - */ - -#ifndef __ASM_SH_LANDISK_IDE_H -#define __ASM_SH_LANDISK_IDE_H - -/* Nothing to see here.. */ -#include -#define IRQ_CFCARD IRQ_FATA /* CF Card IRQ */ -#define IRQ_PCMCIA IRQ_ATA /* PCMCIA IRQ */ - -#endif /* __ASM_SH_LANDISK_IDE_H */ diff --git a/include/asm-sh/r7780rp/ide.h b/include/asm-sh/r7780rp/ide.h deleted file mode 100644 index a1ed78e..0000000 --- a/include/asm-sh/r7780rp/ide.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH_R7780RP_IDE_H -#define __ASM_SH_R7780RP_IDE_H - -/* Nothing to see here.. */ -#include - -#endif /* __ASM_SH_R7780RP_IDE_H */ - diff --git a/include/asm-sh/rts7751r2d/ide.h b/include/asm-sh/rts7751r2d/ide.h deleted file mode 100644 index 416f96b..0000000 --- a/include/asm-sh/rts7751r2d/ide.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH_RTS7751R2D_IDE_H -#define __ASM_SH_RTS7751R2D_IDE_H - -/* Nothing to see here.. */ -#include - -#endif /* __ASM_SH_RTS7751R2D_IDE_H */ - diff --git a/include/asm-sh/sh03/ide.h b/include/asm-sh/sh03/ide.h deleted file mode 100644 index 73ee92e..0000000 --- a/include/asm-sh/sh03/ide.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH_SH03_IDE_H -#define __ASM_SH_SH03_IDE_H - -#define IRQ_CFCARD 8 -#define IRQ_PCMCIA 8 - -#endif /* __ASM_SH_SH03_IDE_H */ -- cgit v0.10.2 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 diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c index 2191791..d146cda 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 83d3272..d194773 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 2d3a5b4..b5a9664 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 51f3f65..bb9aa0d 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 c617b18..943f93a 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 0414c15..1d997ff 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 db92d6e..311cccc 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 b544772..cbb4ea2 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 b941aa0..c331cae 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 135aa0b..f2507a8 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 c915e7a..cb0eb20 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 a7ce66c..509f548 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 20597a6..5c042d3 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 2f0c197..a31a1d1 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 bf1b28f..f7ea700 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 6e3ba9c6..eeea157 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 b68824c..4a518d9 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 e31c6c5..58fca31 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 3afb472..3dc4942 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 a1089a6..0000000 --- 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 f35134c..0000000 --- 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 2044476..0000000 --- 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 c4cff9d..0000000 --- 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 f95d9db..0000000 --- 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 796b8fc..0000000 --- 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 36ba138..0000000 --- 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 3b3b4da..51f5541 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 v0.10.2 From 1f666587dbf6bc660b23d8dd8abb6c572ce3eae5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 19 Oct 2006 16:20:25 +0900 Subject: sh: Fix exception_handling_table alignment. With the recent change ripping out interrupt_table, explicit padding of the table was missing, causing bad things to happen when manually inserting handlers in to the table. This problem particularly showed up in relation to do_fpu_state_restore() which was inserted quite deeply in to the table and ended up scribbling over a slab object. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index 6be46f0..ba3082d 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S @@ -4,7 +4,7 @@ * The SH-3 exception vector table. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003 - 2006 Paul Mundt * * 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 @@ -49,3 +49,10 @@ ENTRY(nmi_slot) #endif ENTRY(user_break_point_trap) .long break_point_trap /* 1E0 */ + + /* + * Pad the remainder of the table out, exceptions residing in far + * away offsets can be manually inserted in to their appropriate + * location via set_exception_table_{evt,vec}(). + */ + .balign 4096,0,4096 diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S index 3f4cd04..ac8ab57 100644 --- a/arch/sh/kernel/cpu/sh4/ex.S +++ b/arch/sh/kernel/cpu/sh4/ex.S @@ -4,7 +4,7 @@ * The SH-4 exception vector table. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003 - 2006 Paul Mundt * * 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 @@ -53,3 +53,10 @@ ENTRY(nmi_slot) #endif ENTRY(user_break_point_trap) .long break_point_trap /* 1E0 */ + + /* + * Pad the remainder of the table out, exceptions residing in far + * away offsets can be manually inserted in to their appropriate + * location via set_exception_table_{evt,vec}(). + */ + .balign 4096,0,4096 diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index ffe127f..53dfa55 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -11,27 +11,15 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ -#include #include -#include -#include #include -#include -#include -#include -#include #include -#include #include #include #include - +#include #include #include -#include -#include -#include -#include #ifdef CONFIG_SH_KGDB #include @@ -581,7 +569,10 @@ int is_dsp_inst(struct pt_regs *regs) #define is_dsp_inst(regs) (0) #endif /* CONFIG_SH_DSP */ -extern int do_fpu_inst(unsigned short, struct pt_regs*); +/* arch/sh/kernel/cpu/sh4/fpu.c */ +extern int do_fpu_inst(unsigned short, struct pt_regs *); +extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, struct pt_regs regs); asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, @@ -740,14 +731,20 @@ void __init per_cpu_trap_init(void) : "memory"); } -void __init trap_init(void) +void *set_exception_table_vec(unsigned int vec, void *handler) { extern void *exception_handling_table[]; + void *old_handler; + + old_handler = exception_handling_table[vec]; + exception_handling_table[vec] = handler; + return old_handler; +} - exception_handling_table[TRAP_RESERVED_INST] - = (void *)do_reserved_inst; - exception_handling_table[TRAP_ILLEGAL_SLOT_INST] - = (void *)do_illegal_slot_inst; +void __init trap_init(void) +{ + set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); + set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst); #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ defined(CONFIG_SH_FPU_EMU) @@ -756,9 +753,11 @@ void __init trap_init(void) * reserved. They'll be handled in the math-emu case, or faulted on * otherwise. */ - /* entry 64 corresponds to EXPEVT=0x800 */ - exception_handling_table[64] = (void *)do_reserved_inst; - exception_handling_table[65] = (void *)do_illegal_slot_inst; + set_exception_table_evt(0x800, do_reserved_inst); + set_exception_table_evt(0x820, do_illegal_slot_inst); +#elif defined(CONFIG_SH_FPU) + set_exception_table_evt(0x800, do_fpu_state_restore); + set_exception_table_evt(0x820, do_fpu_state_restore); #endif /* Setup VBR for boot cpu */ diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 6c1f8fd..3340126 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -353,6 +353,13 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, (unsigned long)_n_, sizeof(*(ptr))); \ }) +extern void *set_exception_table_vec(unsigned int vec, void *handler); + +static inline void *set_exception_table_evt(unsigned int evt, void *handler) +{ + return set_exception_table_vec(evt >> 5, handler); +} + /* XXX * disable hlt during certain critical i/o operations */ -- cgit v0.10.2 From c2a560f5334c55da1e8bfa17586cc1d4e7f8ed85 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 19 Oct 2006 17:31:22 +0900 Subject: sh: Add some missing board headers. Some of these were dropped in the header directory rework, add the few missing ones back in. Signed-off-by: Paul Mundt diff --git a/include/asm-sh/edosk7705.h b/include/asm-sh/edosk7705.h new file mode 100644 index 0000000..a1089a6 --- /dev/null +++ b/include/asm-sh/edosk7705.h @@ -0,0 +1,30 @@ +/* + * 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.h b/include/asm-sh/hp6xx.h new file mode 100644 index 0000000..f35134c --- /dev/null +++ b/include/asm-sh/hp6xx.h @@ -0,0 +1,80 @@ +#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/hs7751rvoip.h b/include/asm-sh/hs7751rvoip.h new file mode 100644 index 0000000..c4cff9d --- /dev/null +++ b/include/asm-sh/hs7751rvoip.h @@ -0,0 +1,54 @@ +#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.h b/include/asm-sh/r7780rp.h new file mode 100644 index 0000000..ddd67b6 --- /dev/null +++ b/include/asm-sh/r7780rp.h @@ -0,0 +1,173 @@ +#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_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_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.h b/include/asm-sh/rts7751r2d.h new file mode 100644 index 0000000..796b8fc --- /dev/null +++ b/include/asm-sh/rts7751r2d.h @@ -0,0 +1,74 @@ +#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.h b/include/asm-sh/shmin.h new file mode 100644 index 0000000..36ba138 --- /dev/null +++ b/include/asm-sh/shmin.h @@ -0,0 +1,9 @@ +#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 -- cgit v0.10.2 From 709bc44c31db4eeeec7dcf7d3f3fefd057adf7fb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 19 Oct 2006 17:32:56 +0900 Subject: sh: Updates for irq-flow-type naming changes. handle_irq_name() and set_irq_chip_and_handler() disappeared, update for desc->name and set_irq_chip_and_handler_name() use. Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c index cbb4ea2..aa15ec5 100644 --- a/arch/sh/boards/renesas/r7780rp/irq.c +++ b/arch/sh/boards/renesas/r7780rp/irq.c @@ -33,7 +33,7 @@ static void disable_r7780rp_irq(unsigned int irq) } static struct irq_chip r7780rp_irq_chip __read_mostly = { - .name = "r7780rp", + .name = "R7780RP", .mask = disable_r7780rp_irq, .unmask = enable_r7780rp_irq, .mask_ack = disable_r7780rp_irq, @@ -48,8 +48,8 @@ void __init init_r7780rp_IRQ(void) for (i = 0; i < 15; i++) { disable_irq_nosync(i); - set_irq_chip_and_handler(i, &r7780rp_irq_chip, - handle_level_irq); + set_irq_chip_and_handler_name(i, &r7780rp_irq_chip, + handle_level_irq, "level"); enable_r7780rp_irq(i); } } diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index d4b2bb7..212884a 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -31,7 +31,7 @@ static void enable_intc2_irq(unsigned int irq) } static struct irq_chip intc2_irq_chip = { - .typename = "intc2", + .name = "INTC2", .mask = disable_intc2_irq, .unmask = enable_intc2_irq, .mask_ack = disable_intc2_irq, @@ -64,7 +64,8 @@ void make_intc2_irq(struct intc2_data *p) local_irq_restore(flags); - set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); + set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip, + handle_level_irq, "level"); set_irq_chip_data(p->irq, p); enable_intc2_irq(p->irq); diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 8944abd..f799731 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -44,7 +44,7 @@ static void enable_ipr_irq(unsigned int irq) } static struct irq_chip ipr_irq_chip = { - .name = "ipr", + .name = "IPR", .mask = disable_ipr_irq, .unmask = enable_ipr_irq, .mask_ack = disable_ipr_irq, @@ -60,7 +60,8 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */ ipr_data.priority = priority; - set_irq_chip_and_handler(irq, &ipr_irq_chip, handle_level_irq); + set_irq_chip_and_handler_name(irq, &ipr_irq_chip, + handle_level_irq, "level"); set_irq_chip_data(irq, &ipr_data); enable_ipr_irq(irq); diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index acf2602..944128c 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -54,7 +54,7 @@ int show_interrupts(struct seq_file *p, void *v) for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); seq_printf(p, " %14s", irq_desc[i].chip->name); - seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); + seq_printf(p, "-%-8s", irq_desc[i].name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) -- cgit v0.10.2 From 55b7428303d390c53d3a1bc587de8592ce65900e Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Fri, 13 Oct 2006 13:37:35 +0200 Subject: [MIPS] Use kallsyms_lookup_size_offset() instead of kallsyms_lookup() This new routine doesn't lookup for symbol names. So we needn't to pass any char buffers or pointer since we don't care about names. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 9f307eb..ec8209f 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -358,10 +358,8 @@ static int __init frame_info_init(void) unsigned long size = 0; #ifdef CONFIG_KALLSYMS unsigned long ofs; - char *modname; - char namebuf[KSYM_NAME_LEN + 1]; - kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf); + kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs); #endif schedule_mfi.func = schedule; schedule_mfi.func_size = size; @@ -403,8 +401,6 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, { unsigned long stack_page; struct mips_frame_info info; - char *modname; - char namebuf[KSYM_NAME_LEN + 1]; unsigned long size, ofs; int leaf; extern void ret_from_irq(void); @@ -433,7 +429,7 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, } return 0; } - if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf)) + if (!kallsyms_lookup_size_offset(pc, &size, &ofs)) return 0; /* * Return ra if an exception occured at the first instruction -- cgit v0.10.2 From 22c56c3a03b377d21d8363f737aa2a855d892458 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 15 Oct 2006 09:15:19 +0100 Subject: [MIPS] Delete unneeded pt_regs forward declaration. Signed-off-by: Ralf Baechle diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h index 354e544..fa6b4aa 100644 --- a/arch/mips/oprofile/op_impl.h +++ b/arch/mips/oprofile/op_impl.h @@ -10,8 +10,6 @@ #ifndef OP_IMPL_H #define OP_IMPL_H 1 -struct pt_regs; - extern int null_perf_irq(void); extern int (*perf_irq)(void); -- cgit v0.10.2 From ba38cdf94285a1fc6a01fd493bdc5304bc83f61e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 15 Oct 2006 09:17:43 +0100 Subject: [MIPS] Malta: Fix uninitialized regs pointer. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 6244d0e..90ad5bf 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -131,7 +132,7 @@ static void corehi_irqdispatch(void) unsigned int intedge, intsteer, pcicmd, pcibadaddr; unsigned int pcimstat, intisr, inten, intpol; unsigned int intrcause,datalo,datahi; - struct pt_regs *regs; + struct pt_regs *regs = get_irq_regs(); printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); printk("epc : %08lx\nStatus: %08lx\n" -- cgit v0.10.2 From 36d98e79b798fb27e38b9be4f36c5a96025f9281 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 15 Oct 2006 09:19:58 +0100 Subject: [MIPS] A few more pt_regs fixups. Signed-off-by: Ralf Baechle diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index c4fae8f..626de44 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c @@ -849,7 +849,7 @@ au1xxx_dbdma_chan_free(u32 chanid) EXPORT_SYMBOL(au1xxx_dbdma_chan_free); static irqreturn_t -dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +dbdma_interrupt(int irq, void *dev_id) { u32 intstat; u32 chan_index; diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c index b7063fe..7dc9bf6 100644 --- a/arch/mips/oprofile/op_model_rm9000.c +++ b/arch/mips/oprofile/op_model_rm9000.c @@ -80,8 +80,7 @@ static void rm9000_cpu_stop(void *args) write_c0_perfcontrol(0); } -static irqreturn_t rm9000_perfcount_handler(int irq, void * dev_id, - struct pt_regs *regs) +static irqreturn_t rm9000_perfcount_handler(int irq, void * dev_id) { unsigned int control = read_c0_perfcontrol(); uint32_t counter1, counter2; diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index fd0932b..db80844 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -135,7 +135,7 @@ static inline void ip32_power_button(void) add_timer(&power_timer); } -static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ip32_rtc_int(int irq, void *dev_id) { volatile unsigned char reg_c; diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c index 992e0d8..d1a906e 100644 --- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c +++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c @@ -88,7 +88,7 @@ static void arm_tb(void) sbp.tb_armed = 1; } -static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sbprof_tb_intr(int irq, void *dev_id) { int i; DBG(printk(DEVNAME ": tb_intr\n")); @@ -138,7 +138,7 @@ static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t sbprof_pc_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sbprof_pc_intr(int irq, void *dev_id) { printk(DEVNAME ": unexpected pc_intr"); return IRQ_NONE; diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c index bb90649..45274bd 100644 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ b/arch/mips/sibyte/sb1250/bus_watcher.c @@ -171,7 +171,7 @@ static void create_proc_decoder(struct bw_stats_struct *stats) * notes: possible re-entry due to multiple sources * should check/indicate saturation */ -static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs) +static irqreturn_t sibyte_bw_int(int irq, void *data) { struct bw_stats_struct *stats = data; unsigned long cntr; -- cgit v0.10.2 From 53571ce47010562f5e67782ea00206f379a5cd65 Mon Sep 17 00:00:00 2001 From: Thiemo Seufer Date: Sun, 13 Aug 2006 00:53:29 +0100 Subject: [MIPS] Fix O32 personality(2) call with 0xffffffff argument. A sign extension bug did result in sys_personality being invoked with a 0xffffffffffffffffUL argument, so querying the current personality didn't work. Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 53f4171..7a3ebbe 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -1055,7 +1055,9 @@ asmlinkage long sys32_newuname(struct new_utsname __user * name) asmlinkage int sys32_personality(unsigned long personality) { int ret; - if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality &= 0xffffffff; + if (personality(current->personality) == PER_LINUX32 && + personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); if (ret == PER_LINUX32) -- cgit v0.10.2 From 089c7e7f2da7c3245de47377252683bd9edae738 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 16 Oct 2006 16:49:37 +0100 Subject: [MIPS] Use compat_sys_mount. This fixes mount problems with smbfs, ncpfs and NFSv4. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 6d9f187..8c453f8 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -280,7 +280,7 @@ EXPORT(sysn32_call_table) PTR sys_sync PTR sys_acct PTR sys32_settimeofday - PTR sys_mount /* 6160 */ + PTR compat_sys_mount /* 6160 */ PTR sys_umount PTR sys_swapon PTR sys_swapoff diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 2e6d067..d105917 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -226,7 +226,7 @@ sys_call_table: PTR sys_ni_syscall /* was sys_stat */ PTR sys_lseek PTR sys_getpid /* 4020 */ - PTR sys_mount + PTR compat_sys_mount PTR sys_oldumount PTR sys_setuid PTR sys_getuid -- cgit v0.10.2 From eea32d4c6e272b6c324c8c22df4c28274fcb5a21 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 16 Oct 2006 22:48:49 +0900 Subject: [MIPS] save_context_stack fix CONFIG_KALLSYMS=n case is obviously wrong, though it is harmless since CONFIG_KALLSYMS is always enabled with CONFIG_STACKTRACE for now. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 4aabe52..a586aba 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c @@ -57,7 +57,7 @@ static void save_context_stack(struct stack_trace *trace, pc = unwind_stack(task, &sp, pc, &ra); } while (pc); #else - save_raw_context_stack(sp); + save_raw_context_stack(trace, sp); #endif } -- cgit v0.10.2 From 94399ea62fc1047eded76b45b972e7850a800a1b Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 18 Oct 2006 23:27:29 +0900 Subject: [MIPS] More vr41xx pt_regs fixups Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h index dd3eb3d..88b492f 100644 --- a/include/asm-mips/vr41xx/vr41xx.h +++ b/include/asm-mips/vr41xx/vr41xx.h @@ -75,7 +75,7 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock); * Interrupt Control Unit */ extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign); -extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)); +extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)); #define PIUINT_COMMAND 0x0040 #define PIUINT_DATA 0x0020 -- cgit v0.10.2 From 00ddf2be159e3b96ba8872b407240e1bb449b75e Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 18 Oct 2006 23:36:15 +0900 Subject: [MIPS] Update pnx8500-jbs_defconfig In the current pnx8550-jbs_defconfig CONFIG_SGI_IP22 has been selected. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig index 26b0b98..280a800 100644 --- a/arch/mips/configs/pnx8550-jbs_defconfig +++ b/arch/mips/configs/pnx8550-jbs_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:18 2006 +# Linux kernel version: 2.6.19-rc2 +# Sat Oct 14 23:01:16 2006 # CONFIG_MIPS=y @@ -25,8 +25,6 @@ CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_ITE8172 is not set # CONFIG_MACH_JAZZ is not set # CONFIG_LASAT is not set # CONFIG_MIPS_ATLAS is not set @@ -41,13 +39,13 @@ CONFIG_MIPS=y # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set -# CONFIG_PNX8550_JBS is not set +CONFIG_PNX8550_JBS=y # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_QEMU is not set # CONFIG_MARKEINS is not set -CONFIG_SGI_IP22=y +# CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP32 is not set # CONFIG_SIBYTE_BIGSUR is not set @@ -67,25 +65,21 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_ARC=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_ARC32=y -CONFIG_BOOT_ELF32=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_PNX8550=y +CONFIG_SOC_PNX8550=y CONFIG_MIPS_L1_CACHE_SHIFT=5 -# CONFIG_ARC_CONSOLE is not set -CONFIG_ARC_PROMLIB=y # # CPU selection # -# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set @@ -93,7 +87,7 @@ CONFIG_ARC_PROMLIB=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set -CONFIG_CPU_R4X00=y +# CONFIG_CPU_R4X00 is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set @@ -104,12 +98,11 @@ CONFIG_CPU_R4X00=y # CONFIG_CPU_RM7000 is not set # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_R4X00=y -CONFIG_SYS_HAS_CPU_R5000=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y # # Kernel type @@ -120,17 +113,17 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_IP22_CPU_SCACHE=y +CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_VPE_LOADER is not set # CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -144,12 +137,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_HZ_48 is not set # CONFIG_HZ_100 is not set # CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set +CONFIG_HZ_250=y # CONFIG_HZ_256 is not set -CONFIG_HZ_1000=y +# CONFIG_HZ_1000 is not set # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=1000 +CONFIG_HZ=250 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -171,16 +164,20 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -189,12 +186,12 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -211,6 +208,7 @@ CONFIG_KMOD=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set @@ -231,8 +229,10 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # Bus options (PCI, PCMCIA, EISA, ISA, TC) # -CONFIG_HW_HAS_EISA=y -# CONFIG_EISA is not set +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +# CONFIG_PCI_MULTITHREAD_PROBE is not set +# CONFIG_PCI_DEBUG is not set CONFIG_MMU=y # @@ -243,6 +243,7 @@ CONFIG_MMU=y # # PCI Hotplug Support # +# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -265,6 +266,7 @@ CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -283,16 +285,18 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -318,7 +322,6 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -371,13 +374,20 @@ CONFIG_FW_LOADER=y # # Block devices # +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -386,6 +396,7 @@ CONFIG_BLK_DEV_INITRD=y # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y # @@ -404,8 +415,39 @@ CONFIG_BLK_DEV_IDESCSI=y # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_ARM is not set -# CONFIG_BLK_DEV_IDEDMA is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -414,6 +456,7 @@ CONFIG_IDE_GENERIC=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y # @@ -434,22 +477,54 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # -# SCSI Transport Attributes +# SCSI Transports # # CONFIG_SCSI_SPI_ATTRS is not set CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set # # SCSI low-level drivers # CONFIG_ISCSI_TCP=m -# CONFIG_SGIWD93_SCSI is not set -# CONFIG_SCSI_SATA is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -458,14 +533,19 @@ CONFIG_ISCSI_TCP=m # Fusion MPT device support # # CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # +# CONFIG_IEEE1394 is not set # # I2O device support # +# CONFIG_I2O is not set # # Network device support @@ -477,6 +557,11 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # PHY device support # # CONFIG_PHYLIB is not set @@ -486,20 +571,73 @@ CONFIG_NETDEVICES=y # CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set # CONFIG_DM9000 is not set -# CONFIG_SGISEEQ is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +CONFIG_8139TOO_TUNE_TWISTER=y +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set # # Ethernet (1000 Mbit) # +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices # +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -510,8 +648,11 @@ CONFIG_MII=y # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set +# CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set @@ -531,6 +672,7 @@ CONFIG_MII=y # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -556,6 +698,7 @@ CONFIG_INPUT=y CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set @@ -566,7 +709,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -577,7 +720,8 @@ CONFIG_VT_HW_CONSOLE_BINDING=y # # Non-8250 serial port support # -# CONFIG_SERIAL_IP22_ZILOG is not set +# CONFIG_SERIAL_IP3106 is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -591,16 +735,17 @@ CONFIG_LEGACY_PTY_COUNT=256 # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y # CONFIG_RTC is not set -# CONFIG_SGI_DS1286 is not set # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # +# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # @@ -631,35 +776,37 @@ CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_VT1211 is not set # CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices # +# CONFIG_TIFM_CORE is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +CONFIG_FIRMWARE_EDID=y # CONFIG_FB is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_SGI_NEWPORT_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -669,15 +816,131 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_TRANCEVIBRATOR is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set + +# +# USB DSL modem support +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -703,6 +966,7 @@ CONFIG_DUMMY_CONSOLE=y # # InfiniBand support # +# CONFIG_INFINIBAND is not set # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -733,10 +997,12 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -769,8 +1035,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y # CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set @@ -813,7 +1081,6 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -824,7 +1091,6 @@ CONFIG_SUNRPC=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_SGI_PARTITION=y # # Native Language Support @@ -880,6 +1146,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y @@ -893,13 +1160,17 @@ CONFIG_DEBUG_SLAB=y # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp" @@ -918,6 +1189,9 @@ CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp" # Cryptographic options # CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set @@ -927,6 +1201,8 @@ CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set -- cgit v0.10.2 From 0895b19ebdbb44d6d2eee0d7a138f07b2ddb04ec Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 18 Oct 2006 23:38:12 +0900 Subject: [MIPS] Update pnx8550-v2pci_defconfig In the current pnx8550-v2pci_defconfig CONFIG_SGI_IP22 has been selected. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig index e93266b..64b9fbf 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/mips/configs/pnx8550-v2pci_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:18 2006 +# Linux kernel version: 2.6.19-rc2 +# Sat Oct 14 23:12:15 2006 # CONFIG_MIPS=y @@ -25,8 +25,6 @@ CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_ITE8172 is not set # CONFIG_MACH_JAZZ is not set # CONFIG_LASAT is not set # CONFIG_MIPS_ATLAS is not set @@ -40,14 +38,14 @@ CONFIG_MIPS=y # CONFIG_MOMENCO_OCELOT_C is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set -# CONFIG_PNX8550_V2PCI is not set +CONFIG_PNX8550_V2PCI=y # CONFIG_PNX8550_JBS is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_QEMU is not set # CONFIG_MARKEINS is not set -CONFIG_SGI_IP22=y +# CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP32 is not set # CONFIG_SIBYTE_BIGSUR is not set @@ -67,25 +65,21 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_ARC=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_ARC32=y -CONFIG_BOOT_ELF32=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_PNX8550=y +CONFIG_SOC_PNX8550=y CONFIG_MIPS_L1_CACHE_SHIFT=5 -# CONFIG_ARC_CONSOLE is not set -CONFIG_ARC_PROMLIB=y # # CPU selection # -# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set @@ -93,7 +87,7 @@ CONFIG_ARC_PROMLIB=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set -CONFIG_CPU_R4X00=y +# CONFIG_CPU_R4X00 is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set @@ -104,12 +98,11 @@ CONFIG_CPU_R4X00=y # CONFIG_CPU_RM7000 is not set # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_R4X00=y -CONFIG_SYS_HAS_CPU_R5000=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y # # Kernel type @@ -120,17 +113,17 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_IP22_CPU_SCACHE=y +CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_VPE_LOADER is not set # CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -144,12 +137,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_HZ_48 is not set # CONFIG_HZ_100 is not set # CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set +CONFIG_HZ_250=y # CONFIG_HZ_256 is not set -CONFIG_HZ_1000=y +# CONFIG_HZ_1000 is not set # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=1000 +CONFIG_HZ=250 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -171,16 +164,20 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -188,12 +185,12 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -210,6 +207,7 @@ CONFIG_KMOD=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set @@ -230,8 +228,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # Bus options (PCI, PCMCIA, EISA, ISA, TC) # -CONFIG_HW_HAS_EISA=y -# CONFIG_EISA is not set +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +# CONFIG_PCI_MULTITHREAD_PROBE is not set CONFIG_MMU=y # @@ -242,6 +241,7 @@ CONFIG_MMU=y # # PCI Hotplug Support # +# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -264,6 +264,7 @@ CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -282,12 +283,14 @@ CONFIG_IP_PNP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" # # IP: Virtual Server Configuration @@ -300,12 +303,18 @@ CONFIG_IPV6_ROUTE_INFO=y # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set CONFIG_INET6_XFRM_MODE_TRANSPORT=m CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m # CONFIG_IPV6_TUNNEL is not set -CONFIG_NETWORK_SECMARK=y +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -318,9 +327,9 @@ CONFIG_NETFILTER_XTABLES=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_SECMARK=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETFILTER_XT_MATCH_DCCP=m +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m @@ -329,10 +338,10 @@ CONFIG_NETFILTER_XT_MATCH_MARK=m # CONFIG_NETFILTER_XT_MATCH_POLICY is not set CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set CONFIG_NETFILTER_XT_MATCH_REALM=m CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m @@ -373,7 +382,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -426,13 +434,20 @@ CONFIG_FW_LOADER=y # # Block devices # +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -441,6 +456,7 @@ CONFIG_BLK_DEV_INITRD=y # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y # @@ -459,9 +475,41 @@ CONFIG_IDEDISK_MULTI_MODE=y # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_ARM is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -469,6 +517,7 @@ CONFIG_IDE_GENERIC=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y # @@ -489,22 +538,59 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_LOGGING is not set # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=m CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set # # SCSI low-level drivers # CONFIG_ISCSI_TCP=m -# CONFIG_SGIWD93_SCSI is not set -# CONFIG_SCSI_SATA is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -513,14 +599,19 @@ CONFIG_ISCSI_TCP=m # Fusion MPT device support # # CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # +# CONFIG_IEEE1394 is not set # # I2O device support # +# CONFIG_I2O is not set # # Network device support @@ -532,6 +623,11 @@ CONFIG_NETDEVICES=y CONFIG_TUN=m # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # PHY device support # # CONFIG_PHYLIB is not set @@ -541,20 +637,73 @@ CONFIG_TUN=m # CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set # CONFIG_DM9000 is not set -# CONFIG_SGISEEQ is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=y +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set # # Ethernet (1000 Mbit) # +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices # +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -565,6 +714,8 @@ CONFIG_MII=y # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set @@ -575,6 +726,8 @@ CONFIG_PPP_DEFLATE=m CONFIG_PPP_MPPE=m # CONFIG_PPPOE is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set @@ -594,6 +747,7 @@ CONFIG_PPP_MPPE=m # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -616,6 +770,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set @@ -630,6 +785,7 @@ CONFIG_MOUSE_PS2=y CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set @@ -640,7 +796,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y # CONFIG_VT_CONSOLE is not set CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -650,6 +806,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set # CONFIG_SYNCLINKMP is not set +# CONFIG_SYNCLINK_GT is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set # CONFIG_SPECIALIX is not set @@ -665,7 +822,8 @@ CONFIG_SERIAL_NONSTANDARD=y # # Non-8250 serial port support # -# CONFIG_SERIAL_IP22_ZILOG is not set +# CONFIG_SERIAL_IP3106 is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -679,16 +837,17 @@ CONFIG_LEGACY_PTY_COUNT=256 # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y # CONFIG_RTC is not set -# CONFIG_SGI_DS1286 is not set # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # +# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # @@ -709,14 +868,30 @@ CONFIG_I2C_CHARDEV=m CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_ALGOPCF is not set # CONFIG_I2C_ALGOPCA is not set -# CONFIG_I2C_ALGO_SGI is not set # # I2C Hardware Bus support # +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set # CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set # @@ -776,9 +951,13 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set @@ -790,23 +969,25 @@ CONFIG_HWMON=y # # Misc devices # +# CONFIG_TIFM_CORE is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y +# CONFIG_FB_DDC is not set # CONFIG_FB_CFB_FILLRECT is not set # CONFIG_FB_CFB_COPYAREA is not set # CONFIG_FB_CFB_IMAGEBLIT is not set @@ -814,14 +995,32 @@ CONFIG_FB=y # CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set # CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_SMIVGX is not set +# CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_SGI_NEWPORT_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -839,15 +1038,129 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_TRANCEVIBRATOR is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -873,6 +1186,7 @@ CONFIG_DUMMY_CONSOLE=y # # InfiniBand support # +# CONFIG_INFINIBAND is not set # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -906,6 +1220,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -917,6 +1232,7 @@ CONFIG_XFS_FS=m # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -949,8 +1265,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y # CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set @@ -994,7 +1312,6 @@ CONFIG_SUNRPC=y CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1005,7 +1322,6 @@ CONFIG_SMB_FS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_SGI_PARTITION=y # # Native Language Support @@ -1061,11 +1377,13 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" @@ -1079,6 +1397,9 @@ CONFIG_CMDLINE="" # Cryptographic options # CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set @@ -1088,6 +1409,8 @@ CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set -- cgit v0.10.2 From e7a6f9c1f4e46f7fd776c6ee38bdb8f8ae131a82 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 18 Oct 2006 23:48:31 +0900 Subject: [MIPS] Update tb0287_defconfig Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig index ad7271b..f7e8194 100644 --- a/arch/mips/configs/tb0287_defconfig +++ b/arch/mips/configs/tb0287_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:21 2006 +# Linux kernel version: 2.6.19-rc2 +# Wed Oct 18 12:57:11 2006 # CONFIG_MIPS=y @@ -25,8 +25,6 @@ CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_ITE8172 is not set # CONFIG_MACH_JAZZ is not set # CONFIG_LASAT is not set # CONFIG_MIPS_ATLAS is not set @@ -72,11 +70,11 @@ CONFIG_TANBAC_TB0287=y # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set CONFIG_PCI_VR41XX=y -# CONFIG_VRC4173 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y @@ -123,8 +121,8 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_VPE_LOADER is not set CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y @@ -169,15 +167,19 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set # CONFIG_HOTPLUG is not set @@ -185,12 +187,12 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -208,6 +210,7 @@ CONFIG_KMOD=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set @@ -230,17 +233,16 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_HW_HAS_PCI=y CONFIG_PCI=y +# CONFIG_PCI_MULTITHREAD_PROBE is not set CONFIG_MMU=y # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set # # PCI Hotplug Support # -# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -263,6 +265,7 @@ CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -291,13 +294,10 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_TUNNEL=m CONFIG_INET_XFRM_MODE_TRANSPORT=m CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_ADVANCED=y - -# -# TCP congestion control -# CONFIG_TCP_CONG_BIC=y CONFIG_TCP_CONG_CUBIC=m CONFIG_TCP_CONG_WESTWOOD=m @@ -308,7 +308,13 @@ CONFIG_TCP_CONG_HTCP=m # CONFIG_TCP_CONG_SCALABLE is not set # CONFIG_TCP_CONG_LP is not set # CONFIG_TCP_CONG_VENO is not set -# CONFIG_TCP_CONG_COMPOUND is not set +CONFIG_DEFAULT_BIC=y +# CONFIG_DEFAULT_CUBIC is not set +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="bic" # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -338,7 +344,6 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -355,6 +360,7 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_IEEE80211 is not set +CONFIG_FIB_RULES=y # # Device Drivers @@ -365,7 +371,6 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set # CONFIG_SYS_HYPERVISOR is not set # @@ -403,6 +408,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -410,65 +416,14 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # ATA/ATAPI/MFM/RLL support # -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -CONFIG_BLK_DEV_SIIMAGE=y -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -489,12 +444,13 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_LOGGING is not set # -# SCSI Transport Attributes +# SCSI Transports # # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set # # SCSI low-level drivers @@ -507,21 +463,24 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -529,6 +488,59 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_DEBUG is not set # +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +CONFIG_ATA=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +CONFIG_PATA_SIL680=y +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -632,6 +644,7 @@ CONFIG_R8169=y # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set # # Ethernet (10000 Mbit) @@ -679,6 +692,7 @@ CONFIG_R8169=y # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -758,7 +772,6 @@ CONFIG_GPIO_VR41XX=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -784,12 +797,12 @@ CONFIG_GPIO_VR41XX=y # # Misc devices # +# CONFIG_TIFM_CORE is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -897,13 +910,13 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set # CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set # CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_LIBUSUAL is not set # @@ -932,6 +945,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -963,16 +977,17 @@ CONFIG_USB_MON=y # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set -# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set @@ -1041,6 +1056,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1052,6 +1068,7 @@ CONFIG_XFS_QUOTA=y # CONFIG_XFS_SECURITY is not set CONFIG_XFS_POSIX_ACL=y # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=m @@ -1082,8 +1099,10 @@ CONFIG_AUTOFS4_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set @@ -1123,7 +1142,6 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1150,11 +1168,13 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs" @@ -1170,10 +1190,6 @@ CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs" # CONFIG_CRYPTO is not set # -# Hardware crypto devices -# - -# # Library routines # # CONFIG_CRC_CCITT is not set -- cgit v0.10.2 From d2bcf87d0fcdc10d1be65b03fd032bec05efe49f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 18 Oct 2006 23:52:17 +0100 Subject: [MIPS] Reserve syscall numbers for kexec_load. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 61362e6..720fac3 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -652,7 +652,8 @@ einval: li v0, -EINVAL sys sys_vmsplice 4 sys sys_move_pages 6 sys sys_set_robust_list 2 - sys sys_get_robust_list 3 + sys sys_get_robust_list 3 /* 4310 */ + sys sys_ni_syscall 0 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 6c7b5ed..3a34f62 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -468,3 +468,4 @@ sys_call_table: PTR sys_move_pages PTR sys_set_robust_list PTR sys_get_robust_list + PTR sys_ni_syscall /* 5270 */ diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 8c453f8..67b92a1 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -394,3 +394,4 @@ EXPORT(sysn32_call_table) PTR sys_move_pages PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list + PTR sys_ni_syscall diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d105917..2875c4a 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -516,4 +516,5 @@ sys_call_table: PTR compat_sys_move_pages PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list /* 4310 */ + PTR sys_ni_syscall .size sys_call_table,.-sys_call_table diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index 685c914..30240a4 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -331,16 +331,17 @@ #define __NR_move_pages (__NR_Linux + 308) #define __NR_set_robust_list (__NR_Linux + 309) #define __NR_get_robust_list (__NR_Linux + 310) +#define __NR_kexec_load (__NR_Linux + 311) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 310 +#define __NR_Linux_syscalls 311 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 310 +#define __NR_O32_Linux_syscalls 311 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -618,16 +619,17 @@ #define __NR_move_pages (__NR_Linux + 267) #define __NR_set_robust_list (__NR_Linux + 268) #define __NR_get_robust_list (__NR_Linux + 269) +#define __NR_kexec_load (__NR_Linux + 270) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 269 +#define __NR_Linux_syscalls 270 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 269 +#define __NR_64_Linux_syscalls 270 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -909,16 +911,17 @@ #define __NR_move_pages (__NR_Linux + 271) #define __NR_set_robust_list (__NR_Linux + 272) #define __NR_get_robust_list (__NR_Linux + 273) +#define __NR_kexec_load (__NR_Linux + 274) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 273 +#define __NR_Linux_syscalls 274 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 273 +#define __NR_N32_Linux_syscalls 274 #ifdef __KERNEL__ -- cgit v0.10.2 From d89e36d8df547fde2beaea82211954868da2282d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 19 Oct 2006 14:21:47 +0100 Subject: [MIPS] Fix iounmap argument to const volatile. With the existing prototype the following code: const void __iomem *io = ioremap(); x = readb(io); iounmap(io); did result in a warning. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index 3101d1d..cea7d0e 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -176,7 +176,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) #define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1) -void __iounmap(volatile void __iomem *addr) +void __iounmap(const volatile void __iomem *addr) { struct vm_struct *p; diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h index c2d124b..bc5f3c5 100644 --- a/include/asm-mips/io.h +++ b/include/asm-mips/io.h @@ -172,7 +172,7 @@ extern unsigned long isa_slot_offset; #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags); -extern void __iounmap(volatile void __iomem *addr); +extern void __iounmap(const volatile void __iomem *addr); static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, unsigned long flags) @@ -279,7 +279,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, #define ioremap_uncached_accelerated(offset, size) \ __ioremap_mode((offset), (size), _CACHE_UNCACHED_ACCELERATED) -static inline void iounmap(volatile void __iomem *addr) +static inline void iounmap(const volatile void __iomem *addr) { #define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1) -- cgit v0.10.2 From 62752ee198dca9209b7dee504763e51b11e9e0ca Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 17 Oct 2006 10:31:38 +0200 Subject: [PATCH] Take i_mutex in splice_from_pipe() The splice_actor may be calling ->prepare_write() and ->commit_write(). We want i_mutex on the inode being written to before calling those so that we don't race i_size changes. The double locking behavior is done elsewhere in splice.c, and if we eventually want _nolock variants of generic_file_splice_write(), fs modules might have to replicate the nasty locking code. We introduce inode_double_lock() and inode_double_unlock() to consolidate the locking rules into one set of functions. Signed-off-by: Mark Fasheh Signed-off-by: Jens Axboe diff --git a/fs/inode.c b/fs/inode.c index d9a21d1..26cdb11 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1306,6 +1306,42 @@ void wake_up_inode(struct inode *inode) wake_up_bit(&inode->i_state, __I_LOCK); } +/* + * We rarely want to lock two inodes that do not have a parent/child + * relationship (such as directory, child inode) simultaneously. The + * vast majority of file systems should be able to get along fine + * without this. Do not use these functions except as a last resort. + */ +void inode_double_lock(struct inode *inode1, struct inode *inode2) +{ + if (inode1 == NULL || inode2 == NULL || inode1 == inode2) { + if (inode1) + mutex_lock(&inode1->i_mutex); + else if (inode2) + mutex_lock(&inode2->i_mutex); + return; + } + + if (inode1 < inode2) { + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); + } else { + mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); + } +} +EXPORT_SYMBOL(inode_double_lock); + +void inode_double_unlock(struct inode *inode1, struct inode *inode2) +{ + if (inode1) + mutex_unlock(&inode1->i_mutex); + + if (inode2 && inode2 != inode1) + mutex_unlock(&inode2->i_mutex); +} +EXPORT_SYMBOL(inode_double_unlock); + static __initdata unsigned long ihash_entries; static int __init set_ihash_entries(char *str) { diff --git a/fs/splice.c b/fs/splice.c index a567010..c1072b6 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -713,6 +713,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, { int ret, do_wakeup, err; struct splice_desc sd; + struct inode *inode = out->f_mapping->host; ret = 0; do_wakeup = 0; @@ -722,8 +723,13 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, sd.file = out; sd.pos = *ppos; - if (pipe->inode) - mutex_lock(&pipe->inode->i_mutex); + /* + * The actor worker might be calling ->prepare_write and + * ->commit_write. Most of the time, these expect i_mutex to + * be held. Since this may result in an ABBA deadlock with + * pipe->inode, we have to order lock acquiry here. + */ + inode_double_lock(inode, pipe->inode); for (;;) { if (pipe->nrbufs) { @@ -797,8 +803,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, pipe_wait(pipe); } - if (pipe->inode) - mutex_unlock(&pipe->inode->i_mutex); + inode_double_unlock(inode, pipe->inode); if (do_wakeup) { smp_mb(); @@ -1400,13 +1405,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, * grabbing by inode address. Otherwise two different processes * could deadlock (one doing tee from A -> B, the other from B -> A). */ - if (ipipe->inode < opipe->inode) { - mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_PARENT); - mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_CHILD); - } else { - mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_PARENT); - mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_CHILD); - } + inode_double_lock(ipipe->inode, opipe->inode); do { if (!opipe->readers) { @@ -1450,8 +1449,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, i++; } while (len); - mutex_unlock(&ipipe->inode->i_mutex); - mutex_unlock(&opipe->inode->i_mutex); + inode_double_unlock(ipipe->inode, opipe->inode); /* * If we put data in the output pipe, wakeup any potential readers. diff --git a/include/linux/fs.h b/include/linux/fs.h index 661c7c5..853a02f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -623,6 +623,9 @@ enum inode_i_mutex_lock_class I_MUTEX_QUOTA }; +extern void inode_double_lock(struct inode *inode1, struct inode *inode2); +extern void inode_double_unlock(struct inode *inode1, struct inode *inode2); + /* * NOTE: in a 32bit arch with a preemptable kernel and * an UP compile the i_size_read/write must be atomic -- cgit v0.10.2 From 6da61809822c22634a3de2dcb3c60283b836a88a Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 17 Oct 2006 18:43:07 +0200 Subject: [PATCH] Introduce generic_file_splice_write_nolock() This allows file systems to manage their own i_mutex locking while still re-using the generic_file_splice_write() logic. OCFS2 in particular wants this so that it can order cluster locks within i_mutex. Signed-off-by: Mark Fasheh Signed-off-by: Jens Axboe diff --git a/fs/splice.c b/fs/splice.c index c1072b6..68e20e6 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -707,13 +707,12 @@ out_ret: * key here is the 'actor' worker passed in that actually moves the data * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. */ -ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags, - splice_actor *actor) +static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, + struct file *out, loff_t *ppos, size_t len, + unsigned int flags, splice_actor *actor) { int ret, do_wakeup, err; struct splice_desc sd; - struct inode *inode = out->f_mapping->host; ret = 0; do_wakeup = 0; @@ -723,14 +722,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, sd.file = out; sd.pos = *ppos; - /* - * The actor worker might be calling ->prepare_write and - * ->commit_write. Most of the time, these expect i_mutex to - * be held. Since this may result in an ABBA deadlock with - * pipe->inode, we have to order lock acquiry here. - */ - inode_double_lock(inode, pipe->inode); - for (;;) { if (pipe->nrbufs) { struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; @@ -803,8 +794,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, pipe_wait(pipe); } - inode_double_unlock(inode, pipe->inode); - if (do_wakeup) { smp_mb(); if (waitqueue_active(&pipe->wait)) @@ -815,6 +804,69 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, return ret; } +ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags, + splice_actor *actor) +{ + ssize_t ret; + struct inode *inode = out->f_mapping->host; + + /* + * The actor worker might be calling ->prepare_write and + * ->commit_write. Most of the time, these expect i_mutex to + * be held. Since this may result in an ABBA deadlock with + * pipe->inode, we have to order lock acquiry here. + */ + inode_double_lock(inode, pipe->inode); + ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); + inode_double_unlock(inode, pipe->inode); + + return ret; +} + +/** + * generic_file_splice_write_nolock - generic_file_splice_write without mutexes + * @pipe: pipe info + * @out: file to write to + * @len: number of bytes to splice + * @flags: splice modifier flags + * + * Will either move or copy pages (determined by @flags options) from + * the given pipe inode to the given file. The caller is responsible + * for acquiring i_mutex on both inodes. + * + */ +ssize_t +generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + ssize_t ret; + int err; + + ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); + if (ret > 0) { + *ppos += ret; + + /* + * If file or inode is SYNC and we actually wrote some data, + * sync it. + */ + if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { + err = generic_osync_inode(inode, mapping, + OSYNC_METADATA|OSYNC_DATA); + + if (err) + ret = err; + } + } + + return ret; +} + +EXPORT_SYMBOL(generic_file_splice_write_nolock); + /** * generic_file_splice_write - splice data from a pipe to a file * @pipe: pipe info diff --git a/include/linux/fs.h b/include/linux/fs.h index 853a02f..d695ba2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1758,6 +1758,8 @@ extern ssize_t generic_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); extern ssize_t generic_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); +extern ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *, + struct file *, loff_t *, size_t, unsigned int); extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, loff_t *, size_t len, unsigned int flags); extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, -- cgit v0.10.2 From 01de85e057328ecbef36e108673b1e81059d54c1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Oct 2006 19:50:36 +0200 Subject: [PATCH] Add lockless helpers for remove_suid() Right now users have to grab i_mutex before calling remove_suid(), in the unlikely event that a call to ->setattr() may be needed. Split up the function in two parts: - One to check if we need to remove suid - One to actually remove it The first we can call lockless. Signed-off-by: Jens Axboe diff --git a/include/linux/fs.h b/include/linux/fs.h index d695ba2..2fe6e3f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1712,6 +1712,8 @@ extern void __iget(struct inode * inode); extern void clear_inode(struct inode *); extern void destroy_inode(struct inode *); extern struct inode *new_inode(struct super_block *); +extern int __remove_suid(struct dentry *, int); +extern int should_remove_suid(struct dentry *); extern int remove_suid(struct dentry *); extern void remove_dquot_ref(struct super_block *, int, struct list_head *); diff --git a/mm/filemap.c b/mm/filemap.c index 3464b68..7c7addb 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1884,11 +1884,10 @@ repeat: * if suid or (sgid and xgrp) * remove privs */ -int remove_suid(struct dentry *dentry) +int should_remove_suid(struct dentry *dentry) { mode_t mode = dentry->d_inode->i_mode; int kill = 0; - int result = 0; /* suid always must be killed */ if (unlikely(mode & S_ISUID)) @@ -1901,13 +1900,28 @@ int remove_suid(struct dentry *dentry) if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) kill |= ATTR_KILL_SGID; - if (unlikely(kill && !capable(CAP_FSETID))) { - struct iattr newattrs; + if (unlikely(kill && !capable(CAP_FSETID))) + return kill; - newattrs.ia_valid = ATTR_FORCE | kill; - result = notify_change(dentry, &newattrs); - } - return result; + return 0; +} + +int __remove_suid(struct dentry *dentry, int kill) +{ + struct iattr newattrs; + + newattrs.ia_valid = ATTR_FORCE | kill; + return notify_change(dentry, &newattrs); +} + +int remove_suid(struct dentry *dentry) +{ + int kill = should_remove_suid(dentry); + + if (unlikely(kill)) + return __remove_suid(dentry, kill); + + return 0; } EXPORT_SYMBOL(remove_suid); -- cgit v0.10.2 From 8c34e2d63231d4bf4852bac8521883944d770fe3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Oct 2006 19:43:22 +0200 Subject: [PATCH] Remove SUID when splicing into an inode Originally from Mark Fasheh generic_file_splice_write() does not remove S_ISUID or S_ISGID. This is inconsistent with the way we generally write to files. Signed-off-by: Mark Fasheh Signed-off-by: Jens Axboe diff --git a/fs/splice.c b/fs/splice.c index 68e20e6..49fb9f1 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -845,6 +845,10 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, ssize_t ret; int err; + err = remove_suid(out->f_dentry); + if (unlikely(err)) + return err; + ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { *ppos += ret; @@ -883,12 +887,21 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; ssize_t ret; + int err; + + err = should_remove_suid(out->f_dentry); + if (unlikely(err)) { + mutex_lock(&inode->i_mutex); + err = __remove_suid(out->f_dentry, err); + mutex_unlock(&inode->i_mutex); + if (err) + return err; + } ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { - struct inode *inode = mapping->host; - *ppos += ret; /* @@ -896,8 +909,6 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, * sync it. */ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { - int err; - mutex_lock(&inode->i_mutex); err = generic_osync_inode(inode, mapping, OSYNC_METADATA|OSYNC_DATA); -- cgit v0.10.2 From 98978edb6278f0fb30c8d636c6a79a28f9164cb9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 17 Oct 2006 10:54:36 -0400 Subject: [PATCH] wireless: WE-20 compatibility for ESSID and NICKN ioctls WE-21 changed the ABI for the SIOC[SG]IW{ESSID,NICKN} ioctls by dropping NULL termination. This patch adds compatibility code so that WE-21 can work properly with WE-20 (and older) tools. Signed-off-by: John W. Linville diff --git a/net/core/wireless.c b/net/core/wireless.c index ffff0da..cb1b872 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -748,11 +748,39 @@ static int ioctl_standard_call(struct net_device * dev, int extra_size; int user_length = 0; int err; + int essid_compat = 0; /* Calculate space needed by arguments. Always allocate * for max space. Easier, and won't last long... */ extra_size = descr->max_tokens * descr->token_size; + /* Check need for ESSID compatibility for WE < 21 */ + switch (cmd) { + case SIOCSIWESSID: + case SIOCGIWESSID: + case SIOCSIWNICKN: + case SIOCGIWNICKN: + if (iwr->u.data.length == descr->max_tokens + 1) + essid_compat = 1; + else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { + char essid[IW_ESSID_MAX_SIZE + 1]; + + err = copy_from_user(essid, iwr->u.data.pointer, + iwr->u.data.length * + descr->token_size); + if (err) + return -EFAULT; + + if (essid[iwr->u.data.length - 1] == '\0') + essid_compat = 1; + } + break; + default: + break; + } + + iwr->u.data.length -= essid_compat; + /* Check what user space is giving us */ if(IW_IS_SET(cmd)) { /* Check NULL pointer */ @@ -795,7 +823,8 @@ static int ioctl_standard_call(struct net_device * dev, #endif /* WE_IOCTL_DEBUG */ /* Create the kernel buffer */ - extra = kmalloc(extra_size, GFP_KERNEL); + /* kzalloc ensures NULL-termination for essid_compat */ + extra = kzalloc(extra_size, GFP_KERNEL); if (extra == NULL) { return -ENOMEM; } @@ -819,6 +848,8 @@ static int ioctl_standard_call(struct net_device * dev, /* Call the handler */ ret = handler(dev, &info, &(iwr->u), extra); + iwr->u.data.length += essid_compat; + /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { /* Check if there is enough buffer up there */ -- cgit v0.10.2 From e83f214e45a80459d2931ae1259ab5fae82c8a8e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Oct 2006 12:48:35 -0700 Subject: [SPARC64]: Compute dma_end argument to sabre_pbm_init() correctly. virtual-dma property layout is [start, size] not [start, end]. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index de7f785..94bb681 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1465,5 +1465,5 @@ void sabre_init(struct device_node *dp, char *model_name) /* * Look for APB underneath. */ - sabre_pbm_init(p, dp, vdma[0], vdma[1]); + sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]); } -- cgit v0.10.2 From 6bda57365a5fda4743d83a5987c6aab66e90771c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Oct 2006 23:00:35 -0700 Subject: [SPARC64]: Fix of_ioremap(). Use request_mem_region() if IORESOURCE_MEM. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index d822c7c..d3dfb2a 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -131,8 +131,13 @@ static int of_device_resume(struct device * dev) void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) { unsigned long ret = res->start + offset; + struct resource *r; - if (!request_region(ret, size, name)) + if (res->flags & IORESOURCE_MEM) + r = request_mem_region(ret, size, name); + else + r = request_region(ret, size, name); + if (!r) ret = 0; return (void __iomem *) ret; -- cgit v0.10.2 From 66a740572d7bcb18469e71cb014bfed3ff75a773 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 20 Oct 2006 15:30:55 +0900 Subject: sh: Convert INTC2 to IRQ table registration. Currently the INTC2 code contains a fixed IRQ table that it iterates through to set the handler type, we move this in to the CPU subtype setup code instead and allow for submitting the table that way. This drops the ST40 tables, as nothing has been happening with those processors, while converting the only existing users to use the new table directly (SH7760 and SH7780). Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index 212884a..74ca576 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -11,10 +11,9 @@ * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ #include -#include #include +#include #include -#include static void disable_intc2_irq(unsigned int irq) { @@ -45,151 +44,36 @@ static struct irq_chip intc2_irq_chip = { * PIO1 which is INTPRI00[19,16] and INTMSK00[13] * would be: ^ ^ ^ ^ * | | | | - * make_intc2_irq(84, 0, 16, 0, 13); + * { 84, 0, 16, 0, 13 }, + * + * in the intc2_data table. */ -void make_intc2_irq(struct intc2_data *p) +void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs) { - unsigned int flags; - unsigned long ipr; - - disable_irq_nosync(p->irq); - - /* Set the priority level */ - local_irq_save(flags); - - ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); - ipr &= ~(0xf << p->ipr_shift); - ipr |= p->priority << p->ipr_shift; - ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); - - local_irq_restore(flags); + int i; - set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip, - handle_level_irq, "level"); - set_irq_chip_data(p->irq, p); + for (i = 0; i < nr_irqs; i++) { + unsigned long ipr, flags; + struct intc2_data *p = table + i; - enable_intc2_irq(p->irq); -} + disable_irq_nosync(p->irq); -static struct intc2_data intc2_irq_table[] = { -#if defined(CONFIG_CPU_SUBTYPE_ST40) - {64, 0, 0, 0, 0, 13}, /* PCI serr */ - {65, 0, 4, 0, 1, 13}, /* PCI err */ - {66, 0, 4, 0, 2, 13}, /* PCI ad */ - {67, 0, 4, 0, 3, 13}, /* PCI pwd down */ - {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */ - {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */ - {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */ - {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */ - {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */ - {78, 0, 8, 0, 11, 13}, /* DMAC ERR */ - {80, 0, 12, 0, 12, 13}, /* PIO0 */ - {84, 0, 16, 0, 13, 13}, /* PIO1 */ - {88, 0, 20, 0, 14, 13}, /* PIO2 */ - {112, 4, 0, 4, 0, 13}, /* Mailbox */ - #ifdef CONFIG_CPU_SUBTYPE_ST40GX1 - {116, 4, 4, 4, 4, 13}, /* SSC0 */ - {120, 4, 8, 4, 8, 13}, /* IR Blaster */ - {124, 4, 12, 4, 12, 13}, /* USB host */ - {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */ - {132, 4, 20, 4, 20, 13}, /* UART0 */ - {134, 4, 20, 4, 22, 13}, /* UART2 */ - {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */ - {140, 4, 28, 4, 28, 13}, /* EMPI */ - {144, 8, 0, 8, 0, 13}, /* MAFE */ - {148, 8, 4, 8, 4, 13}, /* PWM */ - {152, 8, 8, 8, 8, 13}, /* SSC1 */ - {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */ - {160, 8, 16, 8, 16, 13}, /* USB target */ - {164, 8, 20, 8, 20, 13}, /* UART1 */ - {168, 8, 24, 8, 24, 13}, /* Teletext */ - {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */ - {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */ - {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */ -#endif -#elif defined(CONFIG_CPU_SUBTYPE_SH7760) -/* - * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0 - */ - /* INTPRIO0 | INTMSK0 */ - {48, 0, 28, 0, 31, 3}, /* IRQ 4 */ - {49, 0, 24, 0, 30, 3}, /* IRQ 3 */ - {50, 0, 20, 0, 29, 3}, /* IRQ 2 */ - {51, 0, 16, 0, 28, 3}, /* IRQ 1 */ - /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */ - /* INTPRIO4 | INTMSK0 */ - {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */ - {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */ - {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */ - {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */ - {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */ - {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */ - {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */ - {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */ - /* INTPRIO8 | INTMSK0 */ - {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */ - {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */ - {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */ - {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */ - {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */ - {65, 8, 24, 0, 16, 3}, /* LCDC */ - /* 66, 67 unused */ - {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */ - {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */ - {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */ - /* 71 unused */ - {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */ - {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */ - {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */ - {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */ - {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */ - {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */ - {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */ - {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */ - /* | INTMSK4 */ - {80, 8, 4, 4, 23, 3}, /* SIM_ERI */ - {81, 8, 4, 4, 22, 3}, /* SIM_RXI */ - {82, 8, 4, 4, 21, 3}, /* SIM_TXI */ - {83, 8, 4, 4, 20, 3}, /* SIM_TEI */ - {84, 8, 0, 4, 19, 3}, /* HSPII */ - /* INTPRIOC | INTMSK4 */ - /* 85-87 unused/reserved */ - {88, 12, 20, 4, 18, 3}, /* MMCI0 */ - {89, 12, 20, 4, 17, 3}, /* MMCI1 */ - {90, 12, 20, 4, 16, 3}, /* MMCI2 */ - {91, 12, 20, 4, 15, 3}, /* MMCI3 */ - {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/ - /* 93-107 reserved/undocumented */ - {108,12, 4, 4, 1, 3}, /* ADC */ - {109,12, 0, 4, 0, 3}, /* CMTI */ - /* 110-111 reserved/unused */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7780) - { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, - { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + /* Set the priority level */ + local_irq_save(flags); - { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + + p->ipr_offset); + ipr &= ~(0xf << p->ipr_shift); + ipr |= p->priority << p->ipr_shift; + ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + + p->ipr_offset); - { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, - { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, - { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, - { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, - { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, -#endif -}; + local_irq_restore(flags); -void __init init_IRQ_intc2(void) -{ - int i; + set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip, + handle_level_irq, "level"); + set_irq_chip_data(p->irq, p); - for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) - make_intc2_irq(intc2_irq_table + i); + enable_intc2_irq(p->irq); + } } diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index 97f1c9a..07e5377 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -51,3 +51,66 @@ static int __init sh7760_devices_setup(void) ARRAY_SIZE(sh7760_devices)); } __initcall(sh7760_devices_setup); + +/* + * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0 + */ +static struct intc2_data intc2_irq_table[] = { + /* INTPRIO0 | INTMSK0 */ + {48, 0, 28, 0, 31, 3}, /* IRQ 4 */ + {49, 0, 24, 0, 30, 3}, /* IRQ 3 */ + {50, 0, 20, 0, 29, 3}, /* IRQ 2 */ + {51, 0, 16, 0, 28, 3}, /* IRQ 1 */ + /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */ + /* INTPRIO4 | INTMSK0 */ + {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */ + {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */ + {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */ + {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */ + {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */ + {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */ + {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */ + {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */ + /* INTPRIO8 | INTMSK0 */ + {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */ + {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */ + {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */ + {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */ + {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */ + {65, 8, 24, 0, 16, 3}, /* LCDC */ + /* 66, 67 unused */ + {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */ + {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */ + {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */ + /* 71 unused */ + {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */ + {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */ + {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */ + {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */ + {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */ + {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */ + {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */ + {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */ + /* | INTMSK4 */ + {80, 8, 4, 4, 23, 3}, /* SIM_ERI */ + {81, 8, 4, 4, 22, 3}, /* SIM_RXI */ + {82, 8, 4, 4, 21, 3}, /* SIM_TXI */ + {83, 8, 4, 4, 20, 3}, /* SIM_TEI */ + {84, 8, 0, 4, 19, 3}, /* HSPII */ + /* INTPRIOC | INTMSK4 */ + /* 85-87 unused/reserved */ + {88, 12, 20, 4, 18, 3}, /* MMCI0 */ + {89, 12, 20, 4, 17, 3}, /* MMCI1 */ + {90, 12, 20, 4, 16, 3}, /* MMCI2 */ + {91, 12, 20, 4, 15, 3}, /* MMCI3 */ + {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/ + /* 93-107 reserved/undocumented */ + {108,12, 4, 4, 1, 3}, /* ADC */ + {109,12, 0, 4, 0, 3}, /* CMTI */ + /* 110-111 reserved/unused */ +}; + +void __init init_IRQ_intc2(void) +{ + make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table)); +} diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c index 72493f2..814ddb2 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c @@ -77,3 +77,30 @@ static int __init sh7780_devices_setup(void) ARRAY_SIZE(sh7780_devices)); } __initcall(sh7780_devices_setup); + +static struct intc2_data intc2_irq_table[] = { + { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, + { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, + { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, + { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, + { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + + { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + + { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, + { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, + { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, + { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, + { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, +}; + +void __init init_IRQ_intc2(void) +{ + make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table)); +} diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h index 895c578..19912ae 100644 --- a/include/asm-sh/irq-sh7780.h +++ b/include/asm-sh/irq-sh7780.h @@ -6,16 +6,6 @@ * * Copyright (C) 2004 Takashi SHUDO */ - -#ifdef CONFIG_IDE -# ifndef IRQ_CFCARD -# define IRQ_CFCARD 14 -# endif -# ifndef IRQ_PCMCIA -# define IRQ_PCMCIA 15 -# endif -#endif - #define INTC_BASE 0xffd00000 #define INTC_ICR0 (INTC_BASE+0x0) #define INTC_ICR1 (INTC_BASE+0x1c) diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 1837bdb..7596ab8 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -685,7 +685,7 @@ struct intc2_data { unsigned char priority; }; -void make_intc2_irq(struct intc2_data *); +void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs); void init_IRQ_intc2(void); #endif diff --git a/include/asm-sh/r7780rp.h b/include/asm-sh/r7780rp.h index ddd67b6..c18f648 100644 --- a/include/asm-sh/r7780rp.h +++ b/include/asm-sh/r7780rp.h @@ -81,7 +81,6 @@ #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 */ @@ -153,7 +152,6 @@ #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 */ -- cgit v0.10.2 From 206daaf77f68ce0f103164e6406336068c87a4a5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 19 Oct 2006 23:58:23 -0700 Subject: [NETPOLL]: initialize skb for UDP Need to fully initialize skb to keep lower layers and queueing happy. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ead5920..9308af0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -335,13 +335,13 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) memcpy(skb->data, msg, len); skb->len += len; - udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); + skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph)); udph->source = htons(np->local_port); udph->dest = htons(np->remote_port); udph->len = htons(udp_len); udph->check = 0; - iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); + skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); /* iph->version = 4; iph->ihl = 5; */ put_unaligned(0x45, (unsigned char *)iph); @@ -357,8 +357,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); - - eth->h_proto = htons(ETH_P_IP); + skb->mac.raw = skb->data; + skb->protocol = eth->h_proto = htons(ETH_P_IP); memcpy(eth->h_source, np->local_mac, 6); memcpy(eth->h_dest, np->remote_mac, 6); -- cgit v0.10.2 From 82fac0542e11c0d3316cc8fdafd2a990d2aab692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 20 Oct 2006 00:21:10 -0700 Subject: [NETFILTER]: Missing check for CAP_NET_ADMIN in iptables compat layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 32bit compatibility layer has no CAP_NET_ADMIN check in compat_do_ipt_get_ctl, which for example allows to list the current iptables rules even without having that capability (the non-compat version requires it). Other capabilities might be required to exploit the bug (eg. CAP_NET_RAW to get the nfnetlink socket?), so a plain user can't exploit it, but a setup actually using the posix capability system might very well hit such a constellation of granted capabilities. Signed-off-by: Björn Steinbrink Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 78a44b0..4b90927 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1932,6 +1932,9 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { int ret; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + switch (cmd) { case IPT_SO_GET_INFO: ret = get_info(user, len, 1); -- cgit v0.10.2 From 06ca719faddaf5ea46c6356b12847663c3ed8806 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Oct 2006 00:22:25 -0700 Subject: [TCP]: One NET_INC_STATS() could be NET_INC_STATS_BH in tcp_v4_err() I believe this NET_INC_STATS() call can be replaced by NET_INC_STATS_BH(), a little bit cheaper. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6bbd985..22ef8bd 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -373,7 +373,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) seq = ntohl(th->seq); if (sk->sk_state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) { - NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS); + NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); goto out; } -- cgit v0.10.2 From 78d79423179c0efc7ec34b55d287e7be4ca07da6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Oct 2006 00:28:35 -0700 Subject: [IPV4] inet_peer: Group together avl_left, avl_right, v4daddr to speedup lookups on some CPUS Lot of routers/embedded devices still use CPUS with 16/32 bytes cache lines. (486, Pentium, ... PIII) It makes sense to group together fields used at lookup time so they fit in one cache line. This reduce cache footprint and speedup lookups. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index f13cc0c..aa10a81 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -17,14 +17,15 @@ struct inet_peer { + /* group together avl_left,avl_right,v4daddr to speedup lookups */ struct inet_peer *avl_left, *avl_right; + __be32 v4daddr; /* peer's address */ + __u16 avl_height; + __u16 ip_id_count; /* IP ID for the next packet */ struct inet_peer *unused_next, **unused_prevp; __u32 dtime; /* the time of last use of not * referenced entries */ atomic_t refcnt; - __be32 v4daddr; /* peer's address */ - __u16 avl_height; - __u16 ip_id_count; /* IP ID for the next packet */ atomic_t rid; /* Frag reception counter */ __u32 tcp_ts; unsigned long tcp_ts_stamp; -- cgit v0.10.2 From 6cf431d77c3e917399a847e3a7ec239d5163056b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 20 Oct 2006 00:29:33 -0700 Subject: [SPARC]: Clean up asm-sparc/elf.h pollution in userspace. We don't need to export sparc_elf_hwcap() to userspace, and it doesn't build there. Remove it by moving it inside #ifdef __KERNEL__, along with some other things which don't need to be exported. Signed-off-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h index 83a3dd1..aaf6ef4 100644 --- a/include/asm-sparc/elf.h +++ b/include/asm-sparc/elf.h @@ -8,11 +8,6 @@ #include -#ifdef __KERNEL__ -#include -#include -#endif - /* * Sparc section types */ @@ -77,6 +72,23 @@ typedef unsigned long elf_greg_t; #define ELF_NGREG 38 typedef elf_greg_t elf_gregset_t[ELF_NGREG]; +typedef struct { + union { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; +} elf_fpregset_t; + +#ifdef __KERNEL__ +#include +#include + /* Format is: * G0 --> G7 * O0 --> O7 @@ -99,20 +111,7 @@ do { unsigned long *dest = &(__elf_regs[0]); \ dest[34] = src->npc; \ dest[35] = src->y; \ dest[36] = dest[37] = 0; /* XXX */ \ -} while(0); /* Janitors: Don't touch this colon. */ - -typedef struct { - union { - unsigned long pr_regs[32]; - double pr_dregs[16]; - } pr_fr; - unsigned long __unused; - unsigned long pr_fsr; - unsigned char pr_qcnt; - unsigned char pr_q_entrysize; - unsigned char pr_en; - unsigned int pr_q[64]; -} elf_fpregset_t; +} while(0); /* Janitors: Don't touch this semicolon. */ #define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; }) @@ -165,8 +164,8 @@ typedef struct { #define ELF_PLATFORM (NULL) -#ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif + +#endif /* __KERNEL__ */ #endif /* !(__ASMSPARC_ELF_H) */ -- cgit v0.10.2 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 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 93fbea1..82c10de 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 v0.10.2 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 diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index e7c800f..07eafbc 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 v0.10.2 From 7b19ffc40b0247fcfe083644fdb621fdb3c05ef6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 20 Oct 2006 08:55:48 +0200 Subject: [Bluetooth] Fix HID disconnect NULL pointer dereference The latest HID disconnect sequence change introduced a NULL pointer dereference. For the quirk to handle buggy remote HID implementations, it is enough to wait for a potential control channel disconnect from the remote side and it is also enough to wait only 500 msecs. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 9a562cf..6678201 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -507,12 +507,10 @@ static int hidp_session(void *arg) hidp_del_timer(session); - if (intr_sk->sk_state != BT_CONNECTED) - wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ); - fput(session->intr_sock->file); - wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ); + wait_event_timeout(*(ctrl_sk->sk_sleep), + (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); fput(session->ctrl_sock->file); -- cgit v0.10.2 From 42fb00838a644d03f9a2a5fbbe0b668a5ff5df4d Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Fri, 13 Oct 2006 17:12:05 +0100 Subject: [DLM] fix iovec length in recvmsg I didn't spot that the msg_iovlen was set to 2 if there were two elements in the iovec but left at zero if not :( I think this might be why bob was still seeing trouble. Signed-Off-By: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 867f93d..6da6b14 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -519,6 +519,7 @@ static int receive_from_sock(void) msg.msg_flags = 0; msg.msg_control = incmsg; msg.msg_controllen = sizeof(incmsg); + msg.msg_iovlen = 1; /* I don't see why this circular buffer stuff is necessary for SCTP * which is a packet-based protocol, but the whole thing breaks under -- cgit v0.10.2 From 23591256d61354e20f12e98d7a496ad5c23de74c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 13 Oct 2006 17:25:45 -0400 Subject: [GFS2] Fix bmap to map extents properly This fix means that bmap will map extents of the length requested by the VFS rather than guessing at it, or just mapping one block at a time. The other callers of gfs2_block_map are audited to ensure they send the correct max extent lengths (i.e. set bh->b_size correctly). Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index cc57f2e..06e9a8c 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -434,8 +434,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, */ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, - struct buffer_head *bh_map, struct metapath *mp, - unsigned int maxlen) + struct buffer_head *bh_map, struct metapath *mp) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); @@ -448,6 +447,7 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, int new = 0; u64 dblock = 0; int boundary; + unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; BUG_ON(maxlen == 0); @@ -541,13 +541,13 @@ static inline void bmap_unlock(struct inode *inode, int create) } int gfs2_block_map(struct inode *inode, u64 lblock, int create, - struct buffer_head *bh, unsigned int maxlen) + struct buffer_head *bh) { struct metapath mp; int ret; bmap_lock(inode, create); - ret = gfs2_block_pointers(inode, lblock, create, bh, &mp, maxlen); + ret = gfs2_block_pointers(inode, lblock, create, bh, &mp); bmap_unlock(inode, create); return ret; } @@ -555,7 +555,7 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create, int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) { struct metapath mp; - struct buffer_head bh = { .b_state = 0, .b_blocknr = 0, .b_size = 0 }; + struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; int ret; int create = *new; @@ -563,8 +563,9 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi BUG_ON(!dblock); BUG_ON(!new); + bh.b_size = 1 << (inode->i_blkbits + 5); bmap_lock(inode, create); - ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, 32); + ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp); bmap_unlock(inode, create); *extlen = bh.b_size >> inode->i_blkbits; *dblock = bh.b_blocknr; diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index 0fd379b..ac2fd04 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h @@ -15,7 +15,7 @@ struct gfs2_inode; struct page; int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); -int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh, unsigned int maxlen); +int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh); int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); int gfs2_truncatei(struct gfs2_inode *ip, u64 size); diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 72eec65..0cace3d 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -312,10 +312,12 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) { + struct inode *inode = sdp->sd_jdesc->jd_inode; int error; - struct buffer_head bh_map; + struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; - error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, 0, &bh_map, 1); + bh_map.b_size = 1 << inode->i_blkbits; + error = gfs2_block_map(inode, lbn, 0, &bh_map); if (error || !bh_map.b_blocknr) printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn); gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index e0599fe..8d5963c 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -65,7 +65,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, int gfs2_get_block(struct inode *inode, sector_t lblock, struct buffer_head *bh_result, int create) { - return gfs2_block_map(inode, lblock, create, bh_result, 32); + return gfs2_block_map(inode, lblock, create, bh_result); } /** @@ -83,7 +83,7 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock, { int error; - error = gfs2_block_map(inode, lblock, 0, bh_result, 1); + error = gfs2_block_map(inode, lblock, 0, bh_result); if (error) return error; if (bh_result->b_blocknr == 0) @@ -94,7 +94,7 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock, static int gfs2_get_block_direct(struct inode *inode, sector_t lblock, struct buffer_head *bh_result, int create) { - return gfs2_block_map(inode, lblock, 0, bh_result, 32); + return gfs2_block_map(inode, lblock, 0, bh_result); } /** diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index c69b94a..a3deae7 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -251,7 +251,7 @@ static int bh_get(struct gfs2_quota_data *qd) unsigned int block, offset; struct buffer_head *bh; int error; - struct buffer_head bh_map; + struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; mutex_lock(&sdp->sd_quota_mutex); @@ -263,7 +263,8 @@ static int bh_get(struct gfs2_quota_data *qd) block = qd->qd_slot / sdp->sd_qc_per_block; offset = qd->qd_slot % sdp->sd_qc_per_block;; - error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1); + bh_map.b_size = 1 << ip->i_inode.i_blkbits; + error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map); if (error) goto fail; error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh); diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 0a8a4b8..62cd223 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -372,11 +372,12 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head) u32 hash; struct buffer_head *bh; int error; - struct buffer_head bh_map; + struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; lblock = head->lh_blkno; gfs2_replay_incr_blk(sdp, &lblock); - error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map, 1); + bh_map.b_size = 1 << ip->i_inode.i_blkbits; + error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map); if (error) return error; if (!bh_map.b_blocknr) { -- cgit v0.10.2 From a2d7d021d78dbc00d24d9c809c64a7f3e61fa773 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Oct 2006 16:49:30 +0100 Subject: [GFS2] gfs2 endianness bug: be16 assigned to be32 field Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 459498c..d43caf0 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -815,7 +815,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, leaf = (struct gfs2_leaf *)bh->b_data; leaf->lf_depth = cpu_to_be16(depth); leaf->lf_entries = 0; - leaf->lf_dirent_format = cpu_to_be16(GFS2_FORMAT_DE); + leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE); leaf->lf_next = 0; memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved)); dent = (struct gfs2_dirent *)(leaf+1); -- cgit v0.10.2 From abbdbd2065e74411dc2c401501c2c85a82f60e06 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 15:12:24 +0200 Subject: [GFS2] fs/gfs2/dir.c:gfs2_dir_write_data(): remove dead code The Coverity checker spotted this obviously dead code. Signed-off-by: Adrian Bunk Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index d43caf0..ce52bd9 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -212,8 +212,6 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, gfs2_trans_add_bh(ip->i_gl, bh, 1); memcpy(bh->b_data + o, buf, amount); brelse(bh); - if (error) - goto fail; buf += amount; copied += amount; -- cgit v0.10.2 From b0cb66955f4bf7a72b544096ceef48a829361a3c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 15:13:26 +0200 Subject: [GFS2] fs/gfs2/ops_fstype.c:gfs2_get_sb_meta(): remove unused variable The Coverity checker spotted this unused variable. Signed-off-by: Adrian Bunk Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 178b339..e99444d 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -854,7 +854,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, int error = 0; struct super_block *sb = NULL, *new; struct gfs2_sbd *sdp; - char *gfs2mnt = NULL; sb = get_gfs2_sb(dev_name); if (!sb) { @@ -892,8 +891,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, atomic_inc(&sdp->sd_gfs2mnt->mnt_count); return simple_set_mnt(mnt, new); error: - if (gfs2mnt) - kfree(gfs2mnt); return error; } -- cgit v0.10.2 From 348acd48f050f5ba7fa917b1421ae34443be97dd Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 15:20:04 +0200 Subject: [GFS2] fs/gfs2/dir.c:gfs2_dir_write_data(): don't use an uninitialized variable In the "if (extlen)" case, "new" might be used uninitialized. Looking at the code, it should be initialized to 0. Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index ce52bd9..ead7df0 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -184,7 +184,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, while (copied < size) { unsigned int amount; struct buffer_head *bh; - int new; + int new = 0; amount = size - copied; if (amount > sdp->sd_sb.sb_bsize - o) -- cgit v0.10.2 From bbbe4512735eb0f15f09ffd14876091a8e91bc69 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 15:27:00 +0200 Subject: [GFS2] fs/gfs2/ops_fstype.c:fill_super_meta(): fix NULL dereference Don't dereference new->s_root when we do know it's NULL. Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index e99444d..882873a 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -794,8 +794,8 @@ static int fill_super_meta(struct super_block *sb, struct super_block *new, fs_err(sdp, "can't get root dentry\n"); error = -ENOMEM; iput(inode); - } - new->s_root->d_op = &gfs2_dops; + } else + new->s_root->d_op = &gfs2_dops; return error; } -- cgit v0.10.2 From b7d8ac3e1779c30ddef0a8f38042076c5007a23d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 16:02:07 +0200 Subject: [GFS2] gfs2_dir_read_data(): fix uninitialized variable usage In the "if (extlen)" case, "bh" was used uninitialized. This patch changes the code to what seems to have been intended. Spotted by the Coverity checker. This patch also removes a pointless "bh = NULL" asignment (the variable is never accessed again after this point). Signed-off-by: Adrian Bunk Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index ead7df0..e24af28b1 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -315,8 +315,7 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset, if (!ra) extlen = 1; bh = gfs2_meta_ra(ip->i_gl, dblock, extlen); - } - if (!bh) { + } else { error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh); if (error) goto fail; @@ -330,7 +329,6 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset, extlen--; memcpy(buf, bh->b_data + o, amount); brelse(bh); - bh = NULL; buf += amount; copied += amount; lblock++; -- cgit v0.10.2 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 diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 27d5d2f..a3a08a5d 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 v0.10.2 From fb5527e68d495650a7658fec9a7246bf922db212 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 19 Oct 2006 23:28:13 -0700 Subject: [PATCH] direct-io: sync and invalidate file region when falling back to buffered write When direct-io falls back to buffered write, it will just leave the dirty data floating about in pagecache, pending regular writeback. But normal direct-io semantics are that IO is synchronous, and that it leaves no pagecache behind. So change the fallback-to-buffered-write code to sync the file region and to then strip away the pagecache, just as a regular direct-io write would do. Acked-by: Jeff Moyer Cc: Zach Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/filemap.c b/mm/filemap.c index 3464b68..57faa8d 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2222,7 +2222,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { struct file *file = iocb->ki_filp; - const struct address_space * mapping = file->f_mapping; + struct address_space * mapping = file->f_mapping; size_t ocount; /* original count */ size_t count; /* after file limit checks */ struct inode *inode = mapping->host; @@ -2275,8 +2275,11 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ if (unlikely(file->f_flags & O_DIRECT)) { - written = generic_file_direct_write(iocb, iov, - &nr_segs, pos, ppos, count, ocount); + loff_t endbyte; + ssize_t written_buffered; + + written = generic_file_direct_write(iocb, iov, &nr_segs, pos, + ppos, count, ocount); if (written < 0 || written == count) goto out; /* @@ -2285,10 +2288,46 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, */ pos += written; count -= written; - } + written_buffered = generic_file_buffered_write(iocb, iov, + nr_segs, pos, ppos, count, + written); + /* + * If generic_file_buffered_write() retuned a synchronous error + * then we want to return the number of bytes which were + * direct-written, or the error code if that was zero. Note + * that this differs from normal direct-io semantics, which + * will return -EFOO even if some bytes were written. + */ + if (written_buffered < 0) { + err = written_buffered; + goto out; + } - written = generic_file_buffered_write(iocb, iov, nr_segs, - pos, ppos, count, written); + /* + * We need to ensure that the page cache pages are written to + * disk and invalidated to preserve the expected O_DIRECT + * semantics. + */ + endbyte = pos + written_buffered - written - 1; + err = do_sync_file_range(file, pos, endbyte, + SYNC_FILE_RANGE_WAIT_BEFORE| + SYNC_FILE_RANGE_WRITE| + SYNC_FILE_RANGE_WAIT_AFTER); + if (err == 0) { + written = written_buffered; + invalidate_mapping_pages(mapping, + pos >> PAGE_CACHE_SHIFT, + endbyte >> PAGE_CACHE_SHIFT); + } else { + /* + * We don't know how much we wrote, so just return + * the number of bytes which were direct-written + */ + } + } else { + written = generic_file_buffered_write(iocb, iov, nr_segs, + pos, ppos, count, written); + } out: current->backing_dev_info = NULL; return written ? written : err; -- cgit v0.10.2 From 26da82058e62ea173559a26881b16d10089645ba Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 19 Oct 2006 23:28:14 -0700 Subject: [PATCH] ecryptfs: use special_file() Use the special_file() macro to check whether an inode is special instead of open-coding it. Acked-by: Mike Halcrow Cc: Phillip Hellewell Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 7a11b8a..5938a23 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -104,10 +104,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, inode->i_op = &ecryptfs_dir_iops; if (S_ISDIR(lower_inode->i_mode)) inode->i_fop = &ecryptfs_dir_fops; - /* TODO: Is there a better way to identify if the inode is - * special? */ - if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || - S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) + if (special_file(lower_inode->i_mode)) init_special_inode(inode, lower_inode->i_mode, lower_inode->i_rdev); dentry->d_op = &ecryptfs_dops; -- cgit v0.10.2 From 79e2de4bc53d7ca2a8eedee49e4a92479b4b530e Mon Sep 17 00:00:00 2001 From: Thomas Maier Date: Thu, 19 Oct 2006 23:28:15 -0700 Subject: [PATCH] export clear_queue_congested and set_queue_congested Export the clear_queue_congested() and set_queue_congested() functions located in ll_rw_blk.c The functions are renamed to blk_clear_queue_congested() and blk_set_queue_congested(). (needed in the pktcdvd driver's bio write congestion control) Signed-off-by: Thomas Maier Cc: Peter Osterlund Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index c847e17..132a858 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -117,7 +117,7 @@ static void blk_queue_congestion_threshold(struct request_queue *q) * congested queues, and wake up anyone who was waiting for requests to be * put back. */ -static void clear_queue_congested(request_queue_t *q, int rw) +void blk_clear_queue_congested(request_queue_t *q, int rw) { enum bdi_state bit; wait_queue_head_t *wqh = &congestion_wqh[rw]; @@ -128,18 +128,20 @@ static void clear_queue_congested(request_queue_t *q, int rw) 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. */ -static void set_queue_congested(request_queue_t *q, int rw) +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 @@ -159,7 +161,6 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev) ret = &q->backing_dev_info; return ret; } - EXPORT_SYMBOL(blk_get_backing_dev_info); void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) @@ -167,7 +168,6 @@ void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) q->activity_fn = fn; q->activity_data = data; } - EXPORT_SYMBOL(blk_queue_activity_fn); /** @@ -2067,7 +2067,7 @@ static void __freed_request(request_queue_t *q, int rw) struct request_list *rl = &q->rq; if (rl->count[rw] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, rw); + blk_clear_queue_congested(q, rw); if (rl->count[rw] + 1 <= q->nr_requests) { if (waitqueue_active(&rl->wait[rw])) @@ -2137,7 +2137,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, } } } - set_queue_congested(q, rw); + blk_set_queue_congested(q, rw); } /* @@ -3765,14 +3765,14 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count) blk_queue_congestion_threshold(q); if (rl->count[READ] >= queue_congestion_on_threshold(q)) - set_queue_congested(q, READ); + blk_set_queue_congested(q, READ); else if (rl->count[READ] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, READ); + blk_clear_queue_congested(q, READ); if (rl->count[WRITE] >= queue_congestion_on_threshold(q)) - set_queue_congested(q, WRITE); + blk_set_queue_congested(q, WRITE); else if (rl->count[WRITE] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, WRITE); + blk_clear_queue_congested(q, WRITE); if (rl->count[READ] >= q->nr_requests) { blk_set_queue_full(q, READ); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d370d2c..9575e3a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -651,6 +651,8 @@ 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); 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); -- cgit v0.10.2 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 diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 258df6b..d22cfc9 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 132a858..1360665 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 655d816..a625576 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 f4b8f8b..8337451 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 f6675d2..ca92ac3 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 ad8cbc4..85ce232 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 d597375..004baf6 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 9bbadaf..db5f5a3 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 f7a1390..7011d625 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 9575e3a..7bfcde2 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 a341c80..fc35e6b 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 12b3a4e..f3c077e 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 0000000..f50a281 --- /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 a0f3390..8d9b19f 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 */ } @@ -956,15 +956,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 40db96a..afee38f 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 b378f66..4959535 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 af73c14..f05527b 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 v0.10.2 From 34e856e6a522a8fc0feba7497f5b05aeaa13d473 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 19 Oct 2006 23:28:17 -0700 Subject: [PATCH] Make userspace proof contains the constants for personality(2) but also some defintions that are useless or even harmful in userspace such as the personality() macro. Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/personality.h b/include/linux/personality.h index 80d780e..bf4cf20 100644 --- a/include/linux/personality.h +++ b/include/linux/personality.h @@ -1,6 +1,8 @@ #ifndef _LINUX_PERSONALITY_H #define _LINUX_PERSONALITY_H +#ifdef __KERNEL__ + /* * Handling of different ABIs (personalities). */ @@ -12,6 +14,8 @@ extern int register_exec_domain(struct exec_domain *); extern int unregister_exec_domain(struct exec_domain *); extern int __set_personality(unsigned long); +#endif /* __KERNEL__ */ + /* * Flags for bug emulation. * @@ -71,6 +75,7 @@ enum { PER_MASK = 0x00ff, }; +#ifdef __KERNEL__ /* * Description of an execution domain. @@ -111,4 +116,6 @@ struct exec_domain { #define set_personality(pers) \ ((current->personality == pers) ? 0 : __set_personality(pers)) +#endif /* __KERNEL__ */ + #endif /* _LINUX_PERSONALITY_H */ -- cgit v0.10.2 From 1a3e9ad163b77a3c7504f58f2780b5a62238c0ac Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 19 Oct 2006 23:28:18 -0700 Subject: [PATCH] uml: MODE_TT is bust arch/um/sys-x86_64/ptrace.c:20:1: warning: "SC_SS" redefined In file included from arch/um/include/sysdep/ptrace.h:18, from include/asm/ptrace-generic.h:12, from include/asm/ptrace.h:15, from arch/um/sys-x86_64/ptrace.c:8: arch/um/include/sysdep/sc.h:38:1: warning: this is the location of the previous definition arch/um/sys-x86_64/ptrace.c: In function 'putreg': arch/um/sys-x86_64/ptrace.c:63: warning: implicit declaration of function 'SC_FS_BASE' arch/um/sys-x86_64/ptrace.c:63: error: invalid lvalue in unary '&' arch/um/sys-x86_64/ptrace.c:63: warning: implicit declaration of function 'SC_GS_BASE' arch/um/sys-x86_64/ptrace.c:63: error: invalid lvalue in unary '&' arch/um/sys-x86_64/ptrace.c: In function 'getreg': arch/um/sys-x86_64/ptrace.c:101: error: invalid lvalue in unary '&' arch/um/sys-x86_64/ptrace.c:101: error: invalid lvalue in unary '&' I'd have to say that the fix for this, for now, is this: Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 78fb619..50fb89e 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -52,6 +52,7 @@ menu "UML-specific options" config MODE_TT bool "Tracing thread support (DEPRECATED)" default n + depends on BROKEN help This option controls whether tracing thread support is compiled into UML. This option is largely obsolete, given that skas0 provides -- cgit v0.10.2 From 3fda982c501c6a8baa3fa79aaea1bfa7bb2a5def Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:19 -0700 Subject: [PATCH] fix typo in memory barrier docs Fix cut'n'paste typo - &a and &b are used in other examples, in this one the doc uses &u and &v. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 994355b..7f790f6 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -1898,7 +1898,7 @@ queue before processing any further requests: smp_wmb(); - p = &b; q = p; + p = &v; q = p; -- cgit v0.10.2 From 02a5323d8060d7259277e9e2936fd02129dc0984 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:20 -0700 Subject: [PATCH] uml: remove some leftover PPC code I happened to notice that this code is a leftover and it should be removed - since there are sporadical efforts to revive the PPC port doing such cleanups is not useless. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-um/archparam-ppc.h b/include/asm-um/archparam-ppc.h index 172cd6f..4269d8a 100644 --- a/include/asm-um/archparam-ppc.h +++ b/include/asm-um/archparam-ppc.h @@ -1,15 +1,6 @@ #ifndef __UM_ARCHPARAM_PPC_H #define __UM_ARCHPARAM_PPC_H -/********* Bits for asm-um/hw_irq.h **********/ - -struct hw_interrupt_type; - -/********* Bits for asm-um/hardirq.h **********/ - -#define irq_enter(cpu, irq) hardirq_enter(cpu) -#define irq_exit(cpu, irq) hardirq_exit(cpu) - /********* Bits for asm-um/string.h **********/ #define __HAVE_ARCH_STRRCHR -- cgit v0.10.2 From c13e569073b89eb75216a2551e89ae93ad1f9951 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:20 -0700 Subject: [PATCH] uml: split memory allocation prototypes out of user.h user.h is too generic a header name. I've split out allocation routines from it. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index 7a5b4af..c6a3084 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h @@ -5,6 +5,7 @@ #include "user_util.h" #include "os.h" #include "user.h" +#include "um_malloc.h" static inline void *cow_malloc(int size) { diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 77954ea..310af0f 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -17,6 +17,7 @@ #include "user_util.h" #include "user.h" #include "os.h" +#include "um_malloc.h" #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 108b7da..218aa0e 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -12,6 +12,7 @@ #include "user_util.h" #include "chan_user.h" #include "os.h" +#include "um_malloc.h" struct fd_chan { int fd; diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 4d2bd39..8138f5e 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -23,6 +23,7 @@ #include "user_util.h" #include "user.h" #include "os.h" +#include "um_malloc.h" #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index f3a3f8a..0ffd7ac 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -18,6 +18,7 @@ #include "kern_util.h" #include "net_user.h" #include "os.h" +#include "um_malloc.h" int tap_open_common(void *dev, char *gate_addr) { diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 2ef641d..11921a7 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c @@ -12,6 +12,7 @@ #include "net_user.h" #include "pcap_user.h" #include "user.h" +#include "um_malloc.h" #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index f2e8fc4..bc6afaf 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -19,6 +19,7 @@ #include "chan_user.h" #include "port.h" #include "os.h" +#include "um_malloc.h" struct port_chan { int raw; diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index abec620..829a5ec 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -13,6 +13,7 @@ #include "user_util.h" #include "kern_util.h" #include "os.h" +#include "um_malloc.h" struct pty_chan { void (*announce)(char *dev_name, int dev); diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 8460285..7eddacc 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -15,6 +15,7 @@ #include "slip.h" #include "slip_common.h" #include "os.h" +#include "um_malloc.h" void slip_user_init(void *data, void *dev) { diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 11de3ac..d95d643 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -11,6 +11,7 @@ #include "user_util.h" #include "user.h" #include "os.h" +#include "um_malloc.h" struct tty_chan { char *dev; diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h new file mode 100644 index 0000000..0363a9b --- /dev/null +++ b/arch/um/include/um_malloc.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso + * Licensed under the GPL + */ + +#ifndef __UM_MALLOC_H__ +#define __UM_MALLOC_H__ + +extern void *um_kmalloc(int size); +extern void *um_kmalloc_atomic(int size); +extern void kfree(const void *ptr); + +extern void *um_vmalloc(int size); +extern void *um_vmalloc_atomic(int size); +extern void vfree(void *ptr); + +#endif /* __UM_MALLOC_H__ */ diff --git a/arch/um/include/user.h b/arch/um/include/user.h index 39f8c88..acadce3 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -11,17 +11,11 @@ extern void panic(const char *fmt, ...) extern int printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); extern void schedule(void); -extern void *um_kmalloc(int size); -extern void *um_kmalloc_atomic(int size); -extern void kfree(void *ptr); extern int in_aton(char *str); extern int open_gdb_chan(void); /* These use size_t, however unsigned long is correct on both i386 and x86_64. */ extern unsigned long strlcpy(char *, const char *, unsigned long); extern unsigned long strlcat(char *, const char *, unsigned long); -extern void *um_vmalloc(int size); -extern void *um_vmalloc_atomic(int size); -extern void vfree(void *ptr); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index 802d784..06625fe 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -52,7 +52,6 @@ extern int linux_main(int argc, char **argv); extern void set_cmdline(char *cmd); extern void input_cb(void (*proc)(void *), void *arg, int arg_len); extern int get_pty(void); -extern void *um_kmalloc(int size); extern int switcheroo(int fd, int prot, void *from, void *to, int size); extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...) diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index ef25956..5c1e611 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -31,6 +31,7 @@ #include "irq_kern.h" #include "os.h" #include "sigio.h" +#include "um_malloc.h" #include "misc_constants.h" /* diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index fe6c64a..348b272 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -46,6 +46,7 @@ #include "mode.h" #include "mode_kern.h" #include "choose-mode.h" +#include "um_malloc.h" /* This is a per-cpu array. A processor only modifies its entry and it only * cares about its entry, so it's OK if another processor is modifying its diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index f559bdf7..863981b 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -20,6 +20,7 @@ #include "net_user.h" #include "etap.h" #include "os.h" +#include "um_malloc.h" #define MAX_PACKET ETH_MAX_PACKET diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index a97206d..d46b818 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -18,6 +18,7 @@ #include "sigio.h" #include "irq_user.h" #include "os.h" +#include "um_malloc.h" static struct pollfd *pollfds = NULL; static int pollfds_num = 0; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index d1c5670..685feaa 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -23,6 +23,7 @@ #include "choose-mode.h" #include "uml-config.h" #include "os.h" +#include "um_malloc.h" /* Set in set_stklim, which is called from main and __wrap_malloc. * __wrap_malloc only calls it if main hasn't started. diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index f645776..925a652 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -19,6 +19,7 @@ #include "user_util.h" #include "sigio.h" #include "os.h" +#include "um_malloc.h" /* Protected by sigio_lock(), also used by sigio_cleanup, which is an * exitcall. -- cgit v0.10.2 From 8b028bcd0e746ae0f2f218b911032232a32dedd5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:21 -0700 Subject: [PATCH] uml: code convention cleanup of a file Fix coding conventions violations is arch/um/os-Linux/helper.c. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index cd15b9d..8a78bf0 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -35,18 +35,18 @@ static int helper_child(void *arg) char **argv = data->argv; int errval; - if(helper_pause){ + if (helper_pause){ signal(SIGHUP, helper_hup); pause(); } - if(data->pre_exec != NULL) + if (data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); execvp(argv[0], argv); errval = -errno; printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); os_write_file(data->fd, &errval, sizeof(errval)); kill(os_getpid(), SIGKILL); - return(0); + return 0; } /* Returns either the pid of the child process we run or -E* on failure. @@ -58,20 +58,21 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, unsigned long stack, sp; int pid, fds[2], ret, n; - if((stack_out != NULL) && (*stack_out != 0)) + if ((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; - else stack = alloc_stack(0, __cant_sleep()); - if(stack == 0) + else + stack = alloc_stack(0, __cant_sleep()); + if (stack == 0) return -ENOMEM; ret = os_pipe(fds, 1, 0); - if(ret < 0){ + if (ret < 0) { printk("run_helper : pipe failed, ret = %d\n", -ret); goto out_free; } ret = os_set_exec_close(fds[1], 1); - if(ret < 0){ + if (ret < 0) { printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", -ret); goto out_close; @@ -83,7 +84,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, data.argv = argv; data.fd = fds[1]; pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); - if(pid < 0){ + if (pid < 0) { ret = -errno; printk("run_helper : clone failed, errno = %d\n", errno); goto out_close; @@ -95,10 +96,10 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, /* Read the errno value from the child, if the exec failed, or get 0 if * the exec succeeded because the pipe fd was set as close-on-exec. */ n = os_read_file(fds[0], &ret, sizeof(ret)); - if(n == 0) + if (n == 0) { ret = pid; - else { - if(n < 0){ + } else { + if (n < 0) { printk("run_helper : read on pipe failed, ret = %d\n", -n); ret = n; @@ -112,10 +113,11 @@ out_close: close(fds[1]); close(fds[0]); out_free: - if(stack_out == NULL) + if (stack_out == NULL) free_stack(stack, 0); - else *stack_out = stack; - return(ret); + else + *stack_out = stack; + return ret; } int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, @@ -125,31 +127,32 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, int pid, status, err; stack = alloc_stack(stack_order, __cant_sleep()); - if(stack == 0) return(-ENOMEM); + if (stack == 0) + return -ENOMEM; sp = stack + (page_size() << stack_order) - sizeof(void *); pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); - if(pid < 0){ + if (pid < 0) { err = -errno; printk("run_helper_thread : clone failed, errno = %d\n", errno); return err; } - if(stack_out == NULL){ + if (stack_out == NULL) { CATCH_EINTR(pid = waitpid(pid, &status, 0)); - if(pid < 0){ + if (pid < 0) { err = -errno; printk("run_helper_thread - wait failed, errno = %d\n", errno); pid = err; } - if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) + if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " "0x%x\n", status); free_stack(stack, stack_order); - } - else *stack_out = stack; - return(pid); + } else + *stack_out = stack; + return pid; } int helper_wait(int pid) @@ -157,9 +160,9 @@ int helper_wait(int pid) int ret; CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); - if(ret < 0){ + if (ret < 0) { ret = -errno; printk("helper_wait : waitpid failed, errno = %d\n", errno); } - return(ret); + return ret; } -- cgit v0.10.2 From 493e3758be1d5628b4d799fe21d68969edbe32aa Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:22 -0700 Subject: [PATCH] uml: reenable compilation of enable_timer, disabled by mistake CONFIG_MODE_TT does not work there, the UML_ prefixed version must be used - this causes a link-time failure when CONFIG_MODE_TT is enabled (i.e. always here, never by Jeff). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 38be096..2115b8b 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -16,6 +16,7 @@ #include "process.h" #include "kern_constants.h" #include "os.h" +#include "uml-config.h" int set_interval(int is_virtual) { @@ -30,7 +31,7 @@ int set_interval(int is_virtual) return 0; } -#ifdef CONFIG_MODE_TT +#ifdef UML_CONFIG_MODE_TT void enable_timer(void) { set_interval(1); -- cgit v0.10.2 From b2670eacfb013169b8bf151a5078a9ef8ef86466 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:23 -0700 Subject: [PATCH] uml: use DEFCONFIG_LIST to avoid reading host's config This should make sure that, for UML, host's configuration files are not considered, which avoids various pains to the user. Our dependency are such that the obtained Kconfig will be valid and will lead to successful compilation - however they cannot prevent an user from disabling any boot device, and if an option is not set in the read .config (say /boot/config-XXX), with make menuconfig ARCH=um, it is not set. This always disables UBD and all console I/O channels, which leads to non-working UML kernels, so this bothers users - especially now, since it will happen on almost every machine (/boot/config-`uname -r` exists almost on every machine). It can be workarounded with make defconfig ARCH=um, but it is non-obvious and can be avoided, so please _do_ merge this patch. Given the existence of options, it could be interesting to implement (additionally) "option required" - with it, Kconfig will refuse reading a .config file (from wherever it comes) if the given option is not set. With this, one could mark with it the option characteristic of the given architecture (it was an old proposal of Roman Zippel, when I pointed out our problem): config UML option required default y However this should be further discussed: *) for x86, it must support constructs like: ==arch/i386/Kconfig== config 64BIT option required default n where Kconfig must require that CONFIG_64BIT is disabled or not present in the read .config. *) do we want to do such checks only for the starting defconfig or also for .config? Which leads to: *) I may want to port a x86_64 .config to x86 and viceversa, or even among more different archs. Should that be allowed, and in which measure (the user may force skipping the check for a .config or it is only given a warning by default)? Cc: Roman Zippel Cc: Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 50fb89e..5ac1f29 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -1,3 +1,8 @@ +config DEFCONFIG_LIST + string + option defconfig_list + default "arch/$ARCH/defconfig" + # UML uses the generic IRQ sugsystem config GENERIC_HARDIRQS bool diff --git a/init/Kconfig b/init/Kconfig index 1038293..c8b2624 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1,5 +1,6 @@ config DEFCONFIG_LIST string + depends on !UML option defconfig_list default "/lib/modules/$UNAME_RELEASE/.config" default "/etc/kernel-config" -- cgit v0.10.2 From d9d645f06a8f50659bbae2be64ed8367ba068fc0 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:24 -0700 Subject: [PATCH] uml: cleanup run_helper() API to fix a leak Freeing the stack is left uselessly to the caller of run_helper in some cases - this is taken from run_helper_thread, but here it is useless, so no caller needs it and the only place where this happens has a potential leak - in case of error neither run_helper() nor xterm_open() call free_stack(). At this point passing a pointer is not needed - the stack pointer should be passed directly, but this change is not done here. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 386f8b9..850221d 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -136,8 +136,6 @@ int xterm_open(int input, int output, int primary, void *d, return(pid); } - if(data->stack == 0) free_stack(stack, 0); - if (data->direct_rcv) { new = os_rcv_fd(fd, &data->helper_pid); } else { diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 8a78bf0..d13299c 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -50,7 +50,8 @@ static int helper_child(void *arg) } /* Returns either the pid of the child process we run or -E* on failure. - * XXX The alloc_stack here breaks if this is called in the tracing thread */ + * XXX The alloc_stack here breaks if this is called in the tracing thread, so + * we need to receive a preallocated stack (a local buffer is ok). */ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, unsigned long *stack_out) { @@ -113,10 +114,8 @@ out_close: close(fds[1]); close(fds[0]); out_free: - if (stack_out == NULL) + if ((stack_out == NULL) || (*stack_out == 0)) free_stack(stack, 0); - else - *stack_out = stack; return ret; } -- cgit v0.10.2 From f43e6a5a72566675da3581dc0d7076042e6701f7 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:25 -0700 Subject: [PATCH] uml: kconfig - silence warning Silence useless warning about undefined symbol in Kconfig. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 62d87b7..e03e40c 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -190,6 +190,11 @@ config HOSTAUDIO tristate default UML_SOUND +#It is selected elsewhere, so kconfig would warn without this. +config HW_RANDOM + tristate + default n + config UML_RANDOM tristate "Hardware random number generator" help -- cgit v0.10.2 From 1ba0ce6f9c19a8573832e14b418dc835dc6f3bbd Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 19 Oct 2006 23:28:26 -0700 Subject: [PATCH] uml: mmapper - remove just added but wrong "const" attribute When enabling the mmapper driver I got warnings because this "const" miscdevice structure is passed to function as non-const pointer; unlike struct tty_operations, however, I verified that misc_{de,}register _do_ modify their parameter, so this const attribute must be removed. Since the purpose of the change was to guarantee that no lock was needed, add a comment to prove this differently. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 9a3b5da..df3516e 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -95,7 +95,8 @@ static const struct file_operations mmapper_fops = { .release = mmapper_release, }; -static const struct miscdevice mmapper_dev = { +/* No locking needed - only used (and modified) by below initcall and exitcall. */ +static struct miscdevice mmapper_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "mmapper", .fops = &mmapper_fops -- cgit v0.10.2 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 diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b0d5026..0b71e7d 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 v0.10.2 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 diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e67144c..65b3f05 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 v0.10.2 From 145fc655a1ceabda76cf2ad74f7cf96863c65b65 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 19 Oct 2006 23:28:28 -0700 Subject: [PATCH] genirq: clean up irq-flow-type naming, fix Re-add the set_irq_chip_and_handler() prototype, it's still widely used. Signed-off-by: Ingo Molnar Cc: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/irq.h b/include/linux/irq.h index 775f5a7..52fc405 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -322,6 +322,9 @@ extern struct irq_chip no_irq_chip; extern struct irq_chip dummy_irq_chip; extern void +set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, + irq_flow_handler_t handle); +extern void set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, irq_flow_handler_t handle, const char *name); -- cgit v0.10.2 From 91fcdd4e0314145d7d4fa52dba2f9c2da25346fd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 19 Oct 2006 23:28:29 -0700 Subject: [PATCH] readjust comments of task_timeslice for kernel doc Signed-off-by: Borislav Petkov Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/sched.c b/kernel/sched.c index 094b568..3399701 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -160,15 +160,6 @@ #define TASK_PREEMPTS_CURR(p, rq) \ ((p)->prio < (rq)->curr->prio) -/* - * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ] - * to time slice values: [800ms ... 100ms ... 5ms] - * - * The higher a thread's priority, the bigger timeslices - * it gets during one round of execution. But even the lowest - * priority thread gets MIN_TIMESLICE worth of execution time. - */ - #define SCALE_PRIO(x, prio) \ max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE) @@ -180,6 +171,15 @@ static unsigned int static_prio_timeslice(int static_prio) return SCALE_PRIO(DEF_TIMESLICE, static_prio); } +/* + * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ] + * to time slice values: [800ms ... 100ms ... 5ms] + * + * The higher a thread's priority, the bigger timeslices + * it gets during one round of execution. But even the lowest + * priority thread gets MIN_TIMESLICE worth of execution time. + */ + static inline unsigned int task_timeslice(struct task_struct *p) { return static_prio_timeslice(p->static_prio); -- cgit v0.10.2 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 diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 98099de..9090b5a 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 v0.10.2 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 diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 9090b5a..6bcd9e8 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 v0.10.2 From 8ac773b4f73afa6fd66695131103944b975d5d5c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 19 Oct 2006 23:28:32 -0700 Subject: [PATCH] OOM killer meets userspace headers Despite mm.h is not being exported header, it does contain one thing which is part of userspace ABI -- value disabling OOM killer for given process. So, a) create and export include/linux/oom.h b) move OOM_DISABLE define there. c) turn bounding values of /proc/$PID/oom_adj into defines and export them too. Note: mass __KERNEL__ removal will be done later. Signed-off-by: Alexey Dobriyan Cc: Nick Piggin Cc: David Woodhouse Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 26a8f841..8df27401 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -72,6 +72,7 @@ #include #include #include +#include #include "internal.h" /* NOTE: @@ -689,7 +690,8 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, if (copy_from_user(buffer, buf, count)) return -EFAULT; oom_adjust = simple_strtol(buffer, &end, 0); - if ((oom_adjust < -16 || oom_adjust > 15) && oom_adjust != OOM_DISABLE) + if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && + oom_adjust != OOM_DISABLE) return -EINVAL; if (*end == '\n') end++; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5114ff1..a1155a2 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -120,6 +120,7 @@ header-y += netrom.h header-y += nfs2.h header-y += nfs4_mount.h header-y += nfs_mount.h +header-y += oom.h header-y += param.h header-y += pci_ids.h header-y += pci_regs.h diff --git a/include/linux/mm.h b/include/linux/mm.h index 5a6068f..d538de9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1115,9 +1115,6 @@ int in_gate_area_no_task(unsigned long addr); #define in_gate_area(task, addr) ({(void)task; in_gate_area_no_task(addr);}) #endif /* __HAVE_ARCH_GATE_AREA */ -/* /proc//oom_adj set to -17 protects from the oom-killer */ -#define OOM_DISABLE -17 - int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, diff --git a/include/linux/oom.h b/include/linux/oom.h new file mode 100644 index 0000000..ad76463 --- /dev/null +++ b/include/linux/oom.h @@ -0,0 +1,10 @@ +#ifndef __INCLUDE_LINUX_OOM_H +#define __INCLUDE_LINUX_OOM_H + +/* /proc//oom_adj set to -17 protects from the oom-killer */ +#define OOM_DISABLE (-17) +/* inclusive */ +#define OOM_ADJUST_MIN (-16) +#define OOM_ADJUST_MAX 15 + +#endif diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 20f41b0..2e3ce3a 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -15,6 +15,7 @@ * kernel subsystems and hints as to where to find out what things do. */ +#include #include #include #include -- cgit v0.10.2 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 diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 811d884..2dbb66d 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 v0.10.2 From 8c7c7c9bf39470c9689ad43cae3142cf948f4cfb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 19 Oct 2006 23:28:34 -0700 Subject: [PATCH] Fix warnings for WARN_ON if CONFIG_BUG is disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In most cases the return value of WARN_ON() is ignored. If the generic definition for the !CONFIG_BUG case is used this will result in a warning: CC kernel/sched.o In file included from include/linux/bio.h:25, from include/linux/blkdev.h:14, from kernel/sched.c:39: include/linux/ioprio.h: In function â€Âtask_ioprio’: include/linux/ioprio.h:50: warning: statement with no effect kernel/sched.c: In function â€Âcontext_switch’: kernel/sched.c:1834: warning: statement with no effect Signed-off-by: Ralf Baechle Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 1d9573c..c92ae0f 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -37,7 +37,10 @@ #endif #ifndef HAVE_ARCH_WARN_ON -#define WARN_ON(condition) unlikely((condition)) +#define WARN_ON(condition) ({ \ + typeof(condition) __ret_warn_on = (condition); \ + unlikely(__ret_warn_on); \ +}) #endif #endif -- cgit v0.10.2 From d6f8ff7381501887233666b508b9eac70143303d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 19 Oct 2006 23:28:34 -0700 Subject: [PATCH] cad_pid sysctl with PROC_FS=n If CONFIG_PROC_FS=n: kernel/sysctl.c:148: warning: 'proc_do_cad_pid' used but never defined kernel/built-in.o:(.data+0x1228): undefined reference to `proc_do_cad_pid' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8020fb2..8bff2c1 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -136,8 +136,10 @@ static int parse_table(int __user *, int, void __user *, size_t __user *, static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos); +#ifdef CONFIG_PROC_SYSCTL static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos); +#endif static ctl_table root_table[]; static struct ctl_table_header root_table_header = @@ -542,6 +544,7 @@ static ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif +#ifdef CONFIG_PROC_SYSCTL { .ctl_name = KERN_CADPID, .procname = "cad_pid", @@ -550,6 +553,7 @@ static ctl_table kern_table[] = { .mode = 0600, .proc_handler = &proc_do_cad_pid, }, +#endif { .ctl_name = KERN_MAX_THREADS, .procname = "threads-max", -- cgit v0.10.2 From f2fbc6c2dad7bbcbf226c094749534f1e84d3be2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 19 Oct 2006 23:28:35 -0700 Subject: [PATCH] fs/Kconfig: move GENERIC_ACL, fix acl() call errors GENERIC_ACL shouldn't be under Network File Systems (which made it depend on NET) as far as I can tell. Having it there and having many (FS) config symbols disabled gives this (which the patch fixes): mm/built-in.o: In function `shmem_check_acl': shmem_acl.c:(.text.shmem_check_acl+0x33): undefined reference to `posix_acl_permission' fs/built-in.o: In function `generic_acl_get': (.text.generic_acl_get+0x30): undefined reference to `posix_acl_to_xattr' fs/built-in.o: In function `generic_acl_set': (.text.generic_acl_set+0x75): undefined reference to `posix_acl_from_xattr' fs/built-in.o: In function `generic_acl_set': (.text.generic_acl_set+0x94): undefined reference to `posix_acl_valid' fs/built-in.o: In function `generic_acl_set': (.text.generic_acl_set+0xc1): undefined reference to `posix_acl_equiv_mode' fs/built-in.o: In function `generic_acl_init': (.text.generic_acl_init+0x7a): undefined reference to `posix_acl_clone' fs/built-in.o: In function `generic_acl_init': (.text.generic_acl_init+0xb4): undefined reference to `posix_acl_clone' fs/built-in.o: In function `generic_acl_init': (.text.generic_acl_init+0xc8): undefined reference to `posix_acl_create_masq' fs/built-in.o: In function `generic_acl_chmod': (.text.generic_acl_chmod+0x49): undefined reference to `posix_acl_clone' fs/built-in.o: In function `generic_acl_chmod': (.text.generic_acl_chmod+0x76): undefined reference to `posix_acl_chmod_masq' Signed-off-by: Randy Dunlap Acked-by: Andreas Gruenbacher Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/Kconfig b/fs/Kconfig index 6a3df05..fee318e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -634,6 +634,10 @@ config FUSE_FS If you want to develop a userspace FS, or if you want to use a filesystem based on FUSE, answer Y or M. +config GENERIC_ACL + bool + select FS_POSIX_ACL + if BLOCK menu "CD-ROM/DVD Filesystems" @@ -2080,10 +2084,6 @@ config 9P_FS If unsure, say N. -config GENERIC_ACL - bool - select FS_POSIX_ACL - endmenu if BLOCK -- cgit v0.10.2 From 0e7d73824e6b0024100701da246fec769dd8f087 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 19 Oct 2006 23:28:36 -0700 Subject: [PATCH] autofs3: Make sure all dentries refs are released before calling kill_anon_super() Make sure all dentries refs are released before calling kill_anon_super() so that the assumption that generic_shutdown_super() can completely destroy the dentry tree for there will be no external references holds true. What was being done in the put_super() superblock op, is now done in the kill_sb() filesystem op instead, prior to calling kill_anon_super(). The call to shrink_dcache_sb() is removed as it is redundant since shrink_dcache_for_umount() will now be called after the cleanup routine. Signed-off-by: David Howells Acked-by: Ian Kent Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index c7700d9..906ba5c 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -149,6 +149,7 @@ extern const struct file_operations autofs_root_operations; /* Initializing function */ int autofs_fill_super(struct super_block *, void *, int); +void autofs_kill_sb(struct super_block *sb); /* Queue management functions */ diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index 3fded38..bf8c8af 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c @@ -246,5 +246,4 @@ void autofs_hash_nuke(struct autofs_sb_info *sbi) kfree(ent); } } - shrink_dcache_sb(sbi->sb); } diff --git a/fs/autofs/init.c b/fs/autofs/init.c index aca1237..cea5219 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -24,7 +24,7 @@ static struct file_system_type autofs_fs_type = { .owner = THIS_MODULE, .name = "autofs", .get_sb = autofs_get_sb, - .kill_sb = kill_anon_super, + .kill_sb = autofs_kill_sb, }; static int __init init_autofs_fs(void) diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 2c9759ba..54c518c 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -20,7 +20,7 @@ #include "autofs_i.h" #include -static void autofs_put_super(struct super_block *sb) +void autofs_kill_sb(struct super_block *sb) { struct autofs_sb_info *sbi = autofs_sbi(sb); unsigned int n; @@ -37,13 +37,13 @@ static void autofs_put_super(struct super_block *sb) kfree(sb->s_fs_info); DPRINTK(("autofs: shutting down\n")); + kill_anon_super(sb); } static void autofs_read_inode(struct inode *inode); static struct super_operations autofs_sops = { .read_inode = autofs_read_inode, - .put_super = autofs_put_super, .statfs = simple_statfs, }; -- cgit v0.10.2 From 575b5c7870c940326a11614e0279b74356c1d44f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2006 23:28:37 -0700 Subject: [PATCH] NFSv4: Fix thinko in fs/nfs/super.c Duh. addr.sin_port should be in network byte order. Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 28659a9..28108c8 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -834,7 +834,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type, } /* RFC3530: The default port for NFS is 2049 */ if (addr.sin_port == 0) - addr.sin_port = NFS_PORT; + addr.sin_port = htons(NFS_PORT); /* Grab the authentication type */ authflavour = RPC_AUTH_UNIX; -- cgit v0.10.2 From b6dff26a08189932eeb0fa4261e09e733b0fc540 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2006 23:28:38 -0700 Subject: [PATCH] NFS: Fix oops in nfs_cancel_commit_list Fix two bugs: - nfs_inode_remove_request will call nfs_clear_request, so we cannot reference req->wb_page after it. Move the call to dec_zone_page_state so that it occurs while req->wb_page is still valid. - Calling nfs_clear_page_writeback is unnecessary since the radix tree tags will have been cleared by the call to nfs_inode_remove_request. Replace with a simple call to nfs_unlock_request. Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ca92ac3..883dd4a 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -590,10 +590,10 @@ static void nfs_cancel_commit_list(struct list_head *head) while(!list_empty(head)) { req = nfs_list_entry(head->next); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); nfs_list_remove_request(req); nfs_inode_remove_request(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } } -- cgit v0.10.2 From eda3cef8dd2b83875affe82595db9d0c278879b2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2006 23:28:38 -0700 Subject: [PATCH] NFS: Fix error handling in nfs_direct_write_result() If the RPC call tanked, we should not be checking the return value of data->res.verf->committed, since it is unlikely to even be initialised. Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 9f7f8b9..1e873fc 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -532,10 +532,12 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) spin_lock(&dreq->lock); - if (likely(status >= 0)) - dreq->count += data->res.count; - else - dreq->error = task->tk_status; + if (unlikely(status < 0)) { + dreq->error = status; + goto out_unlock; + } + + dreq->count += data->res.count; if (data->res.verf->committed != NFS_FILE_SYNC) { switch (dreq->flags) { @@ -550,7 +552,7 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata) } } } - +out_unlock: spin_unlock(&dreq->lock); } -- cgit v0.10.2 From 7d9ac06f26fe8d477c813405f1a8c7c90eecef2d Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 19 Oct 2006 23:28:39 -0700 Subject: [PATCH] nfs4: initialize cl_ipaddr David forgot to do this. I'm not sure if this is the right place to put it.... Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 34c3996..8b123f6 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -849,6 +849,7 @@ error: */ static int nfs4_init_client(struct nfs_client *clp, int proto, int timeo, int retrans, + const char *ip_addr, rpc_authflavor_t authflavour) { int error; @@ -865,6 +866,7 @@ static int nfs4_init_client(struct nfs_client *clp, error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); if (error < 0) goto error; + memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); error = nfs_idmap_new(clp); if (error < 0) { @@ -888,6 +890,7 @@ error: */ static int nfs4_set_client(struct nfs_server *server, const char *hostname, const struct sockaddr_in *addr, + const char *ip_addr, rpc_authflavor_t authflavour, int proto, int timeo, int retrans) { @@ -902,7 +905,7 @@ static int nfs4_set_client(struct nfs_server *server, error = PTR_ERR(clp); goto error; } - error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); + error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); if (error < 0) goto error_put; @@ -971,7 +974,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, return ERR_PTR(-ENOMEM); /* Get a client record */ - error = nfs4_set_client(server, hostname, addr, authflavour, + error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour, data->proto, data->timeo, data->retrans); if (error < 0) goto error; @@ -1041,6 +1044,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, /* Get a client representation. * Note: NFSv4 always uses TCP, */ error = nfs4_set_client(server, data->hostname, data->addr, + parent_client->cl_ipaddr, data->authflavor, parent_server->client->cl_xprt->prot, parent_client->retrans_timeo, -- cgit v0.10.2 From 13bbc06af8a5f65df0f888b442e557c617cadba7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2006 23:28:40 -0700 Subject: [PATCH] NFS: Fix NFSv4 callback regression The change in semantics for nfs_find_client() introduced by David breaks the NFSv4 callback channel. Also, replace another completely broken BUG_ON() in nfs_find_client(). In initialised clients, clp->cl_cons_state == 0, and callers of that function should in any case never want to see clients that are uninitialised. Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 8b123f6..5fea638 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -232,11 +232,15 @@ void nfs_put_client(struct nfs_client *clp) * Find a client by address * - caller must hold nfs_client_lock */ -static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) +static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion, int match_port) { struct nfs_client *clp; list_for_each_entry(clp, &nfs_client_list, cl_share_link) { + /* Don't match clients that failed to initialise properly */ + if (clp->cl_cons_state < 0) + continue; + /* Different NFS versions cannot share the same nfs_client */ if (clp->cl_nfsversion != nfsversion) continue; @@ -245,7 +249,7 @@ static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int sizeof(clp->cl_addr.sin_addr)) != 0) continue; - if (clp->cl_addr.sin_port == addr->sin_port) + if (!match_port || clp->cl_addr.sin_port == addr->sin_port) goto found; } @@ -265,11 +269,12 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio struct nfs_client *clp; spin_lock(&nfs_client_lock); - clp = __nfs_find_client(addr, nfsversion); + clp = __nfs_find_client(addr, nfsversion, 0); spin_unlock(&nfs_client_lock); - - BUG_ON(clp && clp->cl_cons_state == 0); - + if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) { + nfs_put_client(clp); + clp = NULL; + } return clp; } @@ -292,7 +297,7 @@ static struct nfs_client *nfs_get_client(const char *hostname, do { spin_lock(&nfs_client_lock); - clp = __nfs_find_client(addr, nfsversion); + clp = __nfs_find_client(addr, nfsversion, 1); if (clp) goto found_client; if (new) -- cgit v0.10.2 From cd9ae2b6a75bb1fa0d370929c2d7a7da1ed719d9 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2006 23:28:40 -0700 Subject: [PATCH] NFS: Deal with failure of invalidate_inode_pages2() If invalidate_inode_pages2() fails, then it should in principle just be because the current process was signalled. In that case, we just want to ensure that the inode's page cache remains marked as invalid. Also add a helper to allow the O_DIRECT code to simply mark the page cache as invalid once it is finished writing, instead of calling invalidate_inode_pages2() itself. Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 481f889..58d4405 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -203,8 +203,10 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) * Note: assumes we have exclusive access to this mapping either * through inode->i_mutex or some other mechanism. */ - if (page->index == 0) - invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1); + if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) { + /* Should never happen */ + nfs_zap_mapping(inode, inode->i_mapping); + } unlock_page(page); return 0; error: diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 1e873fc..bdfabf8 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -497,6 +497,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode if (dreq->commit_data != NULL) nfs_commit_free(dreq->commit_data); nfs_direct_free_writedata(dreq); + nfs_zap_mapping(inode, inode->i_mapping); nfs_direct_complete(dreq); } } @@ -517,6 +518,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode { nfs_end_data_update(inode); nfs_direct_free_writedata(dreq); + nfs_zap_mapping(inode, inode->i_mapping); nfs_direct_complete(dreq); } #endif @@ -830,17 +832,6 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); - /* - * XXX: nfs_end_data_update() already ensures this file's - * cached data is subsequently invalidated. Do we really - * need to call invalidate_inode_pages2() again here? - * - * For aio writes, this invalidation will almost certainly - * occur before the writes complete. Kind of racey. - */ - if (mapping->nrpages) - invalidate_inode_pages2(mapping); - if (retval > 0) iocb->ki_pos = pos + retval; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index bc9376c..9979ad1 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -131,6 +131,15 @@ void nfs_zap_caches(struct inode *inode) spin_unlock(&inode->i_lock); } +void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) +{ + if (mapping->nrpages != 0) { + spin_lock(&inode->i_lock); + NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; + spin_unlock(&inode->i_lock); + } +} + static void nfs_zap_acl_cache(struct inode *inode) { void (*clear_acl_cache)(struct inode *); @@ -671,13 +680,20 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); + if (ret < 0) + goto out; if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { - nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); - if (S_ISREG(inode->i_mode)) - nfs_sync_mapping(mapping); - invalidate_inode_pages2(mapping); - + if (mapping->nrpages != 0) { + if (S_ISREG(inode->i_mode)) { + ret = nfs_sync_mapping(mapping); + if (ret < 0) + goto out; + } + ret = invalidate_inode_pages2(mapping); + if (ret < 0) + goto out; + } spin_lock(&inode->i_lock); nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; if (S_ISDIR(inode->i_mode)) { @@ -687,10 +703,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) } spin_unlock(&inode->i_lock); + nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", inode->i_sb->s_id, (long long)NFS_FILEID(inode)); } +out: return ret; } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 76ff548..6b2de1b 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -290,6 +290,7 @@ static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long * linux/fs/nfs/inode.c */ extern int nfs_sync_mapping(struct address_space *mapping); +extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); extern void nfs_zap_caches(struct inode *); extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *); -- cgit v0.10.2 From 39cf8a1374dc51fea169190674d5e4996a7d7ea2 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 19 Oct 2006 23:28:41 -0700 Subject: [PATCH] NFS: fix minor bug in new NFS symlink code The original code confused a zero return code from pagevec_add() as success. Test plan: None. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 58d4405..c86a1ea 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1519,8 +1519,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym pagevec_init(&lru_pvec, 0); if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0, GFP_KERNEL)) { - if (!pagevec_add(&lru_pvec, page)) - __pagevec_lru_add(&lru_pvec); + pagevec_add(&lru_pvec, page); + pagevec_lru_add(&lru_pvec); SetPageUptodate(page); unlock_page(page); } else -- cgit v0.10.2 From 85233a7a436a48a0b98e7976a66797e5da79c9d6 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 19 Oct 2006 23:28:42 -0700 Subject: [PATCH] NFS: __nfs_revalidate_inode() can use "inode" before checking it is non-NULL The "!inode" check in __nfs_revalidate_inode() occurs well after the first time it is dereferenced, so get rid of it. Coverity: #cid 1372, 1373 Test plan: Code review; recheck with Coverity. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 9979ad1..08cc4c5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -583,7 +583,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); lock_kernel(); - if (!inode || is_bad_inode(inode)) + if (is_bad_inode(inode)) goto out_nowait; if (NFS_STALE(inode)) goto out_nowait; -- cgit v0.10.2 From b87c0adfeaaf8d8310c4f790d76072a5961b3518 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 19 Oct 2006 23:28:42 -0700 Subject: [PATCH] NFS: remove unused check in nfs4_open_revalidate Coverity spotted a superfluous error check in nfs4_open_revalidate(). Remove it. Coverity: #cid 847 Test plan: Code inspection; another pass through Coverity. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 47c7e6e..7421bcb 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1314,11 +1314,9 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st case -EROFS: lookup_instantiate_filp(nd, (struct dentry *)state, NULL); return 1; - case -ENOENT: - if (dentry->d_inode == NULL) - return 1; + default: + goto out_drop; } - goto out_drop; } if (state->inode == dentry->d_inode) { nfs4_intent_set_file(nd, dentry, state); -- cgit v0.10.2 From 71bdcf8056f910dc57ea3d0def80a9329e7dc52d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 19 Oct 2006 23:28:43 -0700 Subject: [PATCH] SUNRPC: fix race in in-kernel RPC portmapper client When submitting a request to a fast portmapper (such as the local rpcbind daemon), the request can complete before the parent task is even queued up on xprt->binding. Fix this by queuing before submitting the rpcbind request. Test plan: Connectathon locking test with UDP. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c index 919d5ba..e52afab 100644 --- a/net/sunrpc/pmap_clnt.c +++ b/net/sunrpc/pmap_clnt.c @@ -101,11 +101,13 @@ void rpc_getport(struct rpc_task *task) /* Autobind on cloned rpc clients is discouraged */ BUG_ON(clnt->cl_parent != clnt); - if (xprt_test_and_set_binding(xprt)) { - task->tk_status = -EACCES; /* tell caller to check again */ - rpc_sleep_on(&xprt->binding, task, NULL, NULL); - return; - } + /* Put self on queue before sending rpcbind request, in case + * pmap_getport_done completes before we return from rpc_run_task */ + rpc_sleep_on(&xprt->binding, task, NULL, NULL); + + status = -EACCES; /* tell caller to check again */ + if (xprt_test_and_set_binding(xprt)) + goto bailout_nofree; /* Someone else may have bound if we slept */ status = 0; @@ -134,8 +136,6 @@ void rpc_getport(struct rpc_task *task) goto bailout; rpc_release_task(child); - rpc_sleep_on(&xprt->binding, task, NULL, NULL); - task->tk_xprt->stat.bind_count++; return; -- cgit v0.10.2 From b7766da7f7395b74dec9e52005b7dac0d09391a4 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 19 Oct 2006 23:28:44 -0700 Subject: [PATCH] SUNRPC: fix a typo Yes, this actually passed tests the way it was. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 28100e0..757fc91 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1366,7 +1366,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) if (xprt->slot == NULL) return -ENOMEM; - if (ntohs(addr->sin_port != 0)) + if (ntohs(addr->sin_port) != 0) xprt_set_bound(xprt); xprt->port = xs_get_random_port(); -- cgit v0.10.2 From cc45f0175088e000ac7493e5e3f05579b6f7d240 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:44 -0700 Subject: [PATCH] bug: nfsd/nfs4xdr.c misuse of ERR_PTR() a) ERR_PTR(nfserr_something) is a bad idea; IS_ERR() will be false for it. b) mixing nfserr_.... with -EOPNOTSUPP is even worse idea. nfsd4_path() does both; caller expects to get NFS protocol error out it if anything goes wrong, but if it does we either do not notice (see (a)) or get host-endian negative (see (b)). IOW, that's a case when we can't use ERR_PTR() to return error, even though we return a pointer in case of success. Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 41fc241..77be0c4 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1292,16 +1292,15 @@ static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, * Returned string is safe to use as long as the caller holds a reference * to @exp. */ -static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp) +static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, u32 *stat) { struct svc_fh tmp_fh; char *path, *rootpath; - int stat; fh_init(&tmp_fh, NFS4_FHSIZE); - stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); - if (stat) - return ERR_PTR(stat); + *stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); + if (*stat) + return NULL; rootpath = tmp_fh.fh_export->ex_path; path = exp->ex_path; @@ -1309,7 +1308,8 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp) if (strncmp(path, rootpath, strlen(rootpath))) { printk("nfsd: fs_locations failed;" "%s is not contained in %s\n", path, rootpath); - return ERR_PTR(-EOPNOTSUPP); + *stat = nfserr_notsupp; + return NULL; } return path + strlen(rootpath); @@ -1322,13 +1322,14 @@ static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp, struct svc_export *exp, u32 **pp, int *buflen) { - int status, i; + u32 status; + int i; u32 *p = *pp; struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; - char *root = nfsd4_path(rqstp, exp); + char *root = nfsd4_path(rqstp, exp, &status); - if (IS_ERR(root)) - return PTR_ERR(root); + if (status) + return status; status = nfsd4_encode_components('/', root, &p, buflen); if (status) return status; -- cgit v0.10.2 From 7111c66e4e70588c9602035a4996c9cdc2087d2d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:45 -0700 Subject: [PATCH] fix svc_procfunc declaration svc_procfunc instances return __be32, not int Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 399ad11..4e71986 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -68,7 +68,7 @@ no_locks: /* * NULL: Test for presence of service */ -static int +static __be32 nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { dprintk("lockd: NULL called\n"); @@ -78,7 +78,7 @@ nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * TEST: Check for conflicting lock */ -static int +static __be32 nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -107,7 +107,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -150,7 +150,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -183,7 +183,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNLOCK: release a lock */ -static int +static __be32 nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -217,7 +217,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, * GRANTED: A server calls us to tell that a process' lock request * was granted */ -static int +static __be32 nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -253,12 +253,12 @@ static const struct rpc_call_ops nlm4svc_callback_ops = { * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, - int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) +static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { struct nlm_host *host; struct nlm_rqst *call; - int stat; + __be32 stat; host = nlmsvc_lookup_host(rqstp, argp->lock.caller, @@ -282,35 +282,35 @@ static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *a return rpc_success; } -static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: TEST_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test); } -static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: LOCK_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock); } -static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: CANCEL_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel); } -static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: UNLOCK_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock); } -static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: GRANTED_MSG called\n"); @@ -320,7 +320,7 @@ static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *arg /* * SHARE: create a DOS share or alter existing share. */ -static int +static __be32 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -353,7 +353,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNSHARE: Release a DOS share. */ -static int +static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -386,7 +386,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* * NM_LOCK: Create an unmonitored lock */ -static int +static __be32 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -399,7 +399,7 @@ nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* * FREE_ALL: Release all locks and shares held by client */ -static int +static __be32 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -417,7 +417,7 @@ nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SM_NOTIFY: private callback from statd (not part of official NLM proto) */ -static int +static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { @@ -446,7 +446,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, /* * client sent a GRANTED_RES, let's remove the associated block */ -static int +static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, void *resp) { diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 6a931f4..db8d85c 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -96,7 +96,7 @@ no_locks: /* * NULL: Test for presence of service */ -static int +static __be32 nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { dprintk("lockd: NULL called\n"); @@ -106,7 +106,7 @@ nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * TEST: Check for conflicting lock */ -static int +static __be32 nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -136,7 +136,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -179,7 +179,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -212,7 +212,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNLOCK: release a lock */ -static int +static __be32 nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -246,7 +246,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, * GRANTED: A server calls us to tell that a process' lock request * was granted */ -static int +static __be32 nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -282,12 +282,12 @@ static const struct rpc_call_ops nlmsvc_callback_ops = { * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, - int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) +static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { struct nlm_host *host; struct nlm_rqst *call; - int stat; + __be32 stat; host = nlmsvc_lookup_host(rqstp, argp->lock.caller, @@ -311,28 +311,28 @@ static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *ar return rpc_success; } -static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: TEST_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test); } -static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: LOCK_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock); } -static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: CANCEL_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel); } -static int +static __be32 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -340,7 +340,7 @@ nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock); } -static int +static __be32 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -351,7 +351,7 @@ nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SHARE: create a DOS share or alter existing share. */ -static int +static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -384,7 +384,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNSHARE: Release a DOS share. */ -static int +static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -417,7 +417,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* * NM_LOCK: Create an unmonitored lock */ -static int +static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -430,7 +430,7 @@ nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* * FREE_ALL: Release all locks and shares held by client */ -static int +static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -448,7 +448,7 @@ nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SM_NOTIFY: private callback from statd (not part of official NLM proto) */ -static int +static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { @@ -477,7 +477,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, /* * client sent a GRANTED_RES, let's remove the associated block */ -static int +static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, void *resp) { diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 29f9321..5998d0c 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -36,7 +36,7 @@ struct callback_op { static struct callback_op callback_ops[]; -static int nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp) +static __be32 nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp) { return htonl(NFS4_OK); } @@ -399,7 +399,7 @@ static unsigned process_op(struct svc_rqst *rqstp, /* * Decode, process and encode a COMPOUND */ -static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp) +static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp) { struct cb_compound_hdr_arg hdr_arg; struct cb_compound_hdr_res hdr_res; diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 9187755..8d48616 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -21,7 +21,7 @@ /* * NULL call. */ -static int +static __be32 nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { return nfs_ok; @@ -30,7 +30,7 @@ nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * Get the Access and/or Default ACL of a file. */ -static int nfsacld_proc_getacl(struct svc_rqst * rqstp, +static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) { svc_fh *fh; @@ -97,7 +97,7 @@ fail: /* * Set the Access and/or Default ACL of a file. */ -static int nfsacld_proc_setacl(struct svc_rqst * rqstp, +static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp, struct nfsd3_setaclargs *argp, struct nfsd_attrstat *resp) { @@ -128,7 +128,7 @@ static int nfsacld_proc_setacl(struct svc_rqst * rqstp, /* * Check file attributes */ -static int nfsacld_proc_getattr(struct svc_rqst * rqstp, +static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) { dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); @@ -140,7 +140,7 @@ static int nfsacld_proc_getattr(struct svc_rqst * rqstp, /* * Check file access */ -static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, +static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, struct nfsd3_accessres *resp) { int nfserr; diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index d4bdc00..ed6e2c2 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -19,7 +19,7 @@ /* * NULL call. */ -static int +static __be32 nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { return nfs_ok; @@ -28,7 +28,7 @@ nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * Get the Access and/or Default ACL of a file. */ -static int nfsd3_proc_getacl(struct svc_rqst * rqstp, +static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) { svc_fh *fh; @@ -93,7 +93,7 @@ fail: /* * Set the Access and/or Default ACL of a file. */ -static int nfsd3_proc_setacl(struct svc_rqst * rqstp, +static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, struct nfsd3_setaclargs *argp, struct nfsd3_attrstat *resp) { diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index a5ebc7d..a12663f 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -43,7 +43,7 @@ static int nfs3_ftypes[] = { /* * NULL call. */ -static int +static __be32 nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { return nfs_ok; @@ -52,7 +52,7 @@ nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * Get a file's attributes */ -static int +static __be32 nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd3_attrstat *resp) { @@ -76,7 +76,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, /* * Set a file's attributes */ -static int +static __be32 nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp, struct nfsd3_attrstat *resp) { @@ -94,7 +94,7 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp, /* * Look up a path name component */ -static int +static __be32 nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_diropres *resp) { @@ -118,7 +118,7 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, /* * Check file access */ -static int +static __be32 nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, struct nfsd3_accessres *resp) { @@ -137,7 +137,7 @@ nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, /* * Read a symlink. */ -static int +static __be32 nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp, struct nfsd3_readlinkres *resp) { @@ -155,7 +155,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp, /* * Read a portion of a file. */ -static int +static __be32 nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, struct nfsd3_readres *resp) { @@ -195,7 +195,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, /* * Write data to a file */ -static int +static __be32 nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, struct nfsd3_writeres *resp) { @@ -223,7 +223,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, * At least in theory; we'll see how it fares in practice when the * first reports about SunOS compatibility problems start to pour in... */ -static int +static __be32 nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, struct nfsd3_diropres *resp) { @@ -265,7 +265,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, /* * Make directory. This operation is not idempotent. */ -static int +static __be32 nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, struct nfsd3_diropres *resp) { @@ -285,7 +285,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, RETURN_STATUS(nfserr); } -static int +static __be32 nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, struct nfsd3_diropres *resp) { @@ -307,7 +307,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, /* * Make socket/fifo/device. */ -static int +static __be32 nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, struct nfsd3_diropres *resp) { @@ -343,7 +343,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, /* * Remove file/fifo/socket etc. */ -static int +static __be32 nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_attrstat *resp) { @@ -363,7 +363,7 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, /* * Remove a directory */ -static int +static __be32 nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_attrstat *resp) { @@ -379,7 +379,7 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, RETURN_STATUS(nfserr); } -static int +static __be32 nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp, struct nfsd3_renameres *resp) { @@ -401,7 +401,7 @@ nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp, RETURN_STATUS(nfserr); } -static int +static __be32 nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp, struct nfsd3_linkres *resp) { @@ -424,7 +424,7 @@ nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp, /* * Read a portion of a directory. */ -static int +static __be32 nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, struct nfsd3_readdirres *resp) { @@ -459,7 +459,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, * Read a portion of a directory, including file handles and attrs. * For now, we choose to ignore the dircount parameter. */ -static int +static __be32 nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, struct nfsd3_readdirres *resp) { @@ -517,7 +517,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, /* * Get file system stats */ -static int +static __be32 nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_fsstatres *resp) { @@ -534,7 +534,7 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, /* * Get file system info */ -static int +static __be32 nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_fsinfores *resp) { @@ -576,7 +576,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, /* * Get pathconf info for the specified file */ -static int +static __be32 nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_pathconfres *resp) { @@ -619,7 +619,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, /* * Commit a file (range) to stable storage. */ -static int +static __be32 nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp, struct nfsd3_commitres *resp) { diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index d1fac68..795ad6c5 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -715,7 +715,7 @@ out_kfree: /* * NULL call. */ -static int +static __be32 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { return nfs_ok; @@ -731,7 +731,7 @@ static inline void nfsd4_increment_op_stats(u32 opnum) /* * COMPOUND call. */ -static int +static __be32 nfsd4_proc_compound(struct svc_rqst *rqstp, struct nfsd4_compoundargs *args, struct nfsd4_compoundres *resp) diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 9ee1dab..09030af 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -30,7 +30,7 @@ typedef struct svc_buf svc_buf; #define NFSDDBG_FACILITY NFSDDBG_PROC -static int +static __be32 nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { return nfs_ok; @@ -56,7 +56,7 @@ nfsd_return_dirop(int err, struct nfsd_diropres *resp) * Get a file's attributes * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) { @@ -72,7 +72,7 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, * Set a file's attributes * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, struct nfsd_attrstat *resp) { @@ -92,7 +92,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, * doesn't exist yet. * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, struct nfsd_diropres *resp) { @@ -112,7 +112,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, /* * Read a symlink. */ -static int +static __be32 nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_readlinkargs *argp, struct nfsd_readlinkres *resp) { @@ -132,7 +132,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_readlinkargs *argp, * Read a portion of a file. * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, struct nfsd_readres *resp) { @@ -172,7 +172,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, * Write data to a file * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp, struct nfsd_attrstat *resp) { @@ -197,7 +197,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp, * and the actual create() call in compliance with VFS protocols. * N.B. After this call _both_ argp->fh and resp->fh need an fh_put */ -static int +static __be32 nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, struct nfsd_diropres *resp) { @@ -348,7 +348,7 @@ done: return nfsd_return_dirop(nfserr, resp); } -static int +static __be32 nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, void *resp) { @@ -363,7 +363,7 @@ nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, return nfserr; } -static int +static __be32 nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp, void *resp) { @@ -381,7 +381,7 @@ nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp, return nfserr; } -static int +static __be32 nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp, void *resp) { @@ -401,7 +401,7 @@ nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp, return nfserr; } -static int +static __be32 nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp, void *resp) { @@ -430,7 +430,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp, * Make directory. This operation is not idempotent. * N.B. After this call resp->fh needs an fh_put */ -static int +static __be32 nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, struct nfsd_diropres *resp) { @@ -454,7 +454,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, /* * Remove a directory */ -static int +static __be32 nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, void *resp) { @@ -470,7 +470,7 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, /* * Read a portion of a directory. */ -static int +static __be32 nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp, struct nfsd_readdirres *resp) { @@ -509,7 +509,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp, /* * Get file system info */ -static int +static __be32 nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd_statfsres *resp) { diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 9c9a8ad..965d6c2 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -335,7 +335,7 @@ struct svc_version { /* * RPC procedure info */ -typedef int (*svc_procfunc)(struct svc_rqst *, void *argp, void *resp); +typedef __be32 (*svc_procfunc)(struct svc_rqst *, void *argp, void *resp); struct svc_procedure { svc_procfunc pc_func; /* process the request */ kxdrproc_t pc_decode; /* XDR decode args */ -- cgit v0.10.2 From 52921e02a4f4163a7b1f4b5dde71e1debc71de4a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:46 -0700 Subject: [PATCH] lockd endianness annotations Signed-off-by: Alexey Dobriyan Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index e8c7765..b85a0ad 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -100,12 +100,12 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) /* * The server lockd has called us back to tell us the lock was granted */ -u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) +__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) { const struct file_lock *fl = &lock->fl; const struct nfs_fh *fh = &lock->fh; struct nlm_wait *block; - u32 res = nlm_lck_denied; + __be32 res = nlm_lck_denied; /* * Look up blocked request based on arguments. diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e0179f8..eb243ed 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -148,8 +148,8 @@ nsm_create(void) * XDR functions for NSM. */ -static u32 * -xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +static __be32 * +xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { char buffer[20], *name; @@ -176,7 +176,7 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) } static int -xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { p = xdr_encode_common(rqstp, p, argp); if (IS_ERR(p)) @@ -192,7 +192,7 @@ xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) } static int -xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { p = xdr_encode_common(rqstp, p, argp); if (IS_ERR(p)) @@ -202,7 +202,7 @@ xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) } static int -xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) +xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) { resp->status = ntohl(*p++); resp->state = ntohl(*p++); @@ -212,7 +212,7 @@ xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) } static int -xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) +xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) { resp->state = ntohl(*p++); return 0; diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 4e71986..0ce5c81 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -24,14 +24,14 @@ /* * Obtain client and file from arguments */ -static u32 +static __be32 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; - u32 error = 0; + __be32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 814c606..7e219b9 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -334,13 +334,13 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call) * Attempt to establish a lock, and if it can't be granted, block it * if required. */ -u32 +__be32 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) { struct nlm_block *block, *newblock = NULL; int error; - u32 ret; + __be32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", file->f_file->f_dentry->d_inode->i_sb->s_id, @@ -415,7 +415,7 @@ out: /* * Test for presence of a conflicting lock. */ -u32 +__be32 nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, struct nlm_lock *conflock) { @@ -448,7 +448,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, * afterwards. In this case the block will still be there, and hence * must be removed. */ -u32 +__be32 nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) { int error; @@ -476,7 +476,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) * be in progress. * The calling procedure must check whether the file can be closed. */ -u32 +__be32 nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) { struct nlm_block *block; diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index db8d85c..32e99a6 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -22,8 +22,8 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #ifdef CONFIG_LOCKD_V4 -static u32 -cast_to_nlm(u32 status, u32 vers) +static __be32 +cast_to_nlm(__be32 status, u32 vers) { /* Note: status is assumed to be in network byte order !!! */ if (vers != 4){ @@ -52,14 +52,14 @@ cast_to_nlm(u32 status, u32 vers) /* * Obtain client and file from arguments */ -static u32 +static __be32 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; - u32 error = 0; + __be32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c index b9926ce..6220dc2a 100644 --- a/fs/lockd/svcshare.c +++ b/fs/lockd/svcshare.c @@ -23,7 +23,7 @@ nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh) && !memcmp(share->s_owner.data, oh->data, oh->len); } -u32 +__be32 nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file, struct nlm_args *argp) { @@ -64,7 +64,7 @@ update: /* * Delete a share. */ -u32 +__be32 nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, struct nlm_args *argp) { diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 7dac96e..e83024e 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -78,14 +78,14 @@ static inline unsigned int file_hash(struct nfs_fh *f) * This is not quite right, but for now, we assume the client performs * the proper R/W checking. */ -u32 +__be32 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, struct nfs_fh *f) { struct hlist_node *pos; struct nlm_file *file; unsigned int hash; - u32 nfserr; + __be32 nfserr; nlm_debug_print_fh("nlm_file_lookup", f); diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 61c46fa..b7c9492 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -43,7 +43,7 @@ loff_t_to_s32(loff_t offset) /* * XDR functions for basic NLM types */ -static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c) { unsigned int len; @@ -69,8 +69,8 @@ static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static inline u32 * -nlm_encode_cookie(u32 *p, struct nlm_cookie *c) +static inline __be32 * +nlm_encode_cookie(__be32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); @@ -78,8 +78,8 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm_decode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm_decode_fh(__be32 *p, struct nfs_fh *f) { unsigned int len; @@ -95,8 +95,8 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f) return p + XDR_QUADLEN(NFS2_FHSIZE); } -static inline u32 * -nlm_encode_fh(u32 *p, struct nfs_fh *f) +static inline __be32 * +nlm_encode_fh(__be32 *p, struct nfs_fh *f) { *p++ = htonl(NFS2_FHSIZE); memcpy(p, f->data, NFS2_FHSIZE); @@ -106,20 +106,20 @@ nlm_encode_fh(u32 *p, struct nfs_fh *f) /* * Encode and decode owner handle */ -static inline u32 * -nlm_decode_oh(u32 *p, struct xdr_netobj *oh) +static inline __be32 * +nlm_decode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_decode_netobj(p, oh); } -static inline u32 * -nlm_encode_oh(u32 *p, struct xdr_netobj *oh) +static inline __be32 * +nlm_encode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_encode_netobj(p, oh); } -static u32 * -nlm_decode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm_decode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; s32 start, len, end; @@ -153,8 +153,8 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock) /* * Encode a lock as part of an NLM call */ -static u32 * -nlm_encode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm_encode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s32 start, len; @@ -184,8 +184,8 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock) /* * Encode result of a TEST/TEST_MSG call */ -static u32 * -nlm_encode_testres(u32 *p, struct nlm_res *resp) +static __be32 * +nlm_encode_testres(__be32 *p, struct nlm_res *resp) { s32 start, len; @@ -221,7 +221,7 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp) * First, the server side XDR functions */ int -nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -238,7 +238,7 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_testres(p, resp))) return 0; @@ -246,7 +246,7 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -266,7 +266,7 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -282,7 +282,7 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { if (!(p = nlm_decode_cookie(p, &argp->cookie)) || !(p = nlm_decode_lock(p, &argp->lock))) @@ -292,7 +292,7 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -313,7 +313,7 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; @@ -323,7 +323,7 @@ nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; @@ -332,7 +332,7 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) +nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -344,7 +344,7 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) } int -nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) +nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) { if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; @@ -357,7 +357,7 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) } int -nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return 0; @@ -366,13 +366,13 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } int -nlmsvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } @@ -389,7 +389,7 @@ nlmclt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) #endif static int -nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -403,7 +403,7 @@ nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return -EIO; @@ -438,7 +438,7 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) static int -nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -455,7 +455,7 @@ nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -470,7 +470,7 @@ nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -483,7 +483,7 @@ nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return -EIO; @@ -493,7 +493,7 @@ nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_testres(p, resp))) return -EIO; @@ -502,7 +502,7 @@ nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return -EIO; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 36eb175..f4c0b2b 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -44,8 +44,8 @@ loff_t_to_s64(loff_t offset) /* * XDR functions for basic NLM types */ -static u32 * -nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 * +nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) { unsigned int len; @@ -71,8 +71,8 @@ nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 * +nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); @@ -80,8 +80,8 @@ nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm4_decode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm4_decode_fh(__be32 *p, struct nfs_fh *f) { memset(f->data, 0, sizeof(f->data)); f->size = ntohl(*p++); @@ -95,8 +95,8 @@ nlm4_decode_fh(u32 *p, struct nfs_fh *f) return p + XDR_QUADLEN(f->size); } -static u32 * -nlm4_encode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm4_encode_fh(__be32 *p, struct nfs_fh *f) { *p++ = htonl(f->size); if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */ @@ -107,20 +107,20 @@ nlm4_encode_fh(u32 *p, struct nfs_fh *f) /* * Encode and decode owner handle */ -static u32 * -nlm4_decode_oh(u32 *p, struct xdr_netobj *oh) +static __be32 * +nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_decode_netobj(p, oh); } -static u32 * -nlm4_encode_oh(u32 *p, struct xdr_netobj *oh) +static __be32 * +nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_encode_netobj(p, oh); } -static u32 * -nlm4_decode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s64 len, start, end; @@ -153,8 +153,8 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock) /* * Encode a lock as part of an NLM call */ -static u32 * -nlm4_encode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm4_encode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s64 start, len; @@ -185,8 +185,8 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock) /* * Encode result of a TEST/TEST_MSG call */ -static u32 * -nlm4_encode_testres(u32 *p, struct nlm_res *resp) +static __be32 * +nlm4_encode_testres(__be32 *p, struct nlm_res *resp) { s64 start, len; @@ -227,7 +227,7 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp) * First, the server side XDR functions */ int -nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -244,7 +244,7 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_testres(p, resp))) return 0; @@ -252,7 +252,7 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -272,7 +272,7 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -288,7 +288,7 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { if (!(p = nlm4_decode_cookie(p, &argp->cookie)) || !(p = nlm4_decode_lock(p, &argp->lock))) @@ -298,7 +298,7 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -319,7 +319,7 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return 0; @@ -329,7 +329,7 @@ nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return 0; @@ -338,7 +338,7 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) +nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -350,7 +350,7 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) } int -nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) +nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) { if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; @@ -363,7 +363,7 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) } int -nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return 0; @@ -372,13 +372,13 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } int -nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } @@ -388,14 +388,14 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) */ #ifdef NLMCLNT_SUPPORT_SHARES static int -nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) +nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr) { return 0; } #endif static int -nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -409,7 +409,7 @@ nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return -EIO; @@ -444,7 +444,7 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) static int -nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -461,7 +461,7 @@ nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -476,7 +476,7 @@ nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -489,7 +489,7 @@ nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return -EIO; @@ -499,7 +499,7 @@ nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_testres(p, resp))) return -EIO; @@ -508,7 +508,7 @@ nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return -EIO; diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 2909619..862d973 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -154,7 +154,7 @@ int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *); struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); void nlmclnt_finish_block(struct nlm_wait *block); int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); -u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); +__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *); void nlmclnt_recovery(struct nlm_host *); int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); void nlmclnt_next_cookie(struct nlm_cookie *); @@ -184,12 +184,12 @@ typedef int (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref) /* * Server-side lock handling */ -u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, +__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, struct nlm_lock *, int, struct nlm_cookie *); -u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); -u32 nlmsvc_testlock(struct nlm_file *, struct nlm_lock *, +__be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); +__be32 nlmsvc_testlock(struct nlm_file *, struct nlm_lock *, struct nlm_lock *); -u32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); +__be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); unsigned long nlmsvc_retry_blocked(void); void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, nlm_host_match_fn_t match); @@ -198,7 +198,7 @@ void nlmsvc_grant_reply(struct nlm_cookie *, u32); /* * File handling for the server personality */ -u32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, +__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, struct nfs_fh *); void nlm_release_file(struct nlm_file *); void nlmsvc_mark_resources(void); diff --git a/include/linux/lockd/share.h b/include/linux/lockd/share.h index cd7816e..630c5bf 100644 --- a/include/linux/lockd/share.h +++ b/include/linux/lockd/share.h @@ -21,9 +21,9 @@ struct nlm_share { u32 s_mode; /* deny mode */ }; -u32 nlmsvc_share_file(struct nlm_host *, struct nlm_file *, +__be32 nlmsvc_share_file(struct nlm_host *, struct nlm_file *, struct nlm_args *); -u32 nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *, +__be32 nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *, struct nlm_args *); void nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *, nlm_host_match_fn_t); diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h index 66fdae3..29e7d9f 100644 --- a/include/linux/lockd/xdr.h +++ b/include/linux/lockd/xdr.h @@ -90,19 +90,19 @@ struct nlm_reboot { */ #define NLMSVC_XDRSIZE sizeof(struct nlm_args) -int nlmsvc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *); -int nlmsvc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *); -int nlmsvc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *); -int nlmsvc_encode_void(struct svc_rqst *, u32 *, void *); -int nlmsvc_decode_void(struct svc_rqst *, u32 *, void *); -int nlmsvc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *); -int nlmsvc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *); -int nlmsvc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *); +int nlmsvc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlmsvc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlmsvc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlmsvc_encode_void(struct svc_rqst *, __be32 *, void *); +int nlmsvc_decode_void(struct svc_rqst *, __be32 *, void *); +int nlmsvc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlmsvc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlmsvc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *); /* int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h index 3cc1ae2..dd12b4c 100644 --- a/include/linux/lockd/xdr4.h +++ b/include/linux/lockd/xdr4.h @@ -23,19 +23,19 @@ -int nlm4svc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *); -int nlm4svc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *); -int nlm4svc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *); -int nlm4svc_encode_void(struct svc_rqst *, u32 *, void *); -int nlm4svc_decode_void(struct svc_rqst *, u32 *, void *); -int nlm4svc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *); -int nlm4svc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *); -int nlm4svc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *); +int nlm4svc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlm4svc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlm4svc_encode_void(struct svc_rqst *, __be32 *, void *); +int nlm4svc_decode_void(struct svc_rqst *, __be32 *, void *); +int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *); +int nlm4svc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *); +int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *); /* int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); -- cgit v0.10.2 From 9d787a75a00679c3ebcb88236a7af7b38a0b5932 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:47 -0700 Subject: [PATCH] xdr annotations: NFSv2 on-the-wire data is big-endian [in large part pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index b49501f..1d801e3 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -66,15 +66,15 @@ /* * Common NFS XDR functions as inlines */ -static inline u32 * -xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle) +static inline __be32 * +xdr_encode_fhandle(__be32 *p, struct nfs_fh *fhandle) { memcpy(p, fhandle->data, NFS2_FHSIZE); return p + XDR_QUADLEN(NFS2_FHSIZE); } -static inline u32 * -xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle) +static inline __be32 * +xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle) { /* NFSv2 handles have a fixed length */ fhandle->size = NFS2_FHSIZE; @@ -82,8 +82,8 @@ xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle) return p + XDR_QUADLEN(NFS2_FHSIZE); } -static inline u32* -xdr_encode_time(u32 *p, struct timespec *timep) +static inline __be32* +xdr_encode_time(__be32 *p, struct timespec *timep) { *p++ = htonl(timep->tv_sec); /* Convert nanoseconds into microseconds */ @@ -91,8 +91,8 @@ xdr_encode_time(u32 *p, struct timespec *timep) return p; } -static inline u32* -xdr_encode_current_server_time(u32 *p, struct timespec *timep) +static inline __be32* +xdr_encode_current_server_time(__be32 *p, struct timespec *timep) { /* * Passing the invalid value useconds=1000000 is a @@ -108,8 +108,8 @@ xdr_encode_current_server_time(u32 *p, struct timespec *timep) return p; } -static inline u32* -xdr_decode_time(u32 *p, struct timespec *timep) +static inline __be32* +xdr_decode_time(__be32 *p, struct timespec *timep) { timep->tv_sec = ntohl(*p++); /* Convert microseconds into nanoseconds */ @@ -117,8 +117,8 @@ xdr_decode_time(u32 *p, struct timespec *timep) return p; } -static u32 * -xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) +static __be32 * +xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) { u32 rdev; fattr->type = (enum nfs_ftype) ntohl(*p++); @@ -146,10 +146,10 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) return p; } -static inline u32 * -xdr_encode_sattr(u32 *p, struct iattr *attr) +static inline __be32 * +xdr_encode_sattr(__be32 *p, struct iattr *attr) { - const u32 not_set = __constant_htonl(0xFFFFFFFF); + const __be32 not_set = __constant_htonl(0xFFFFFFFF); *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set; *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set; @@ -184,7 +184,7 @@ xdr_encode_sattr(u32 *p, struct iattr *attr) * GETATTR, READLINK, STATFS */ static int -nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh) +nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) { p = xdr_encode_fhandle(p, fh); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); @@ -195,7 +195,7 @@ nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh) * Encode SETATTR arguments */ static int -nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args) +nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_sattr(p, args->sattr); @@ -208,7 +208,7 @@ nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args) * LOOKUP, REMOVE, RMDIR */ static int -nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) +nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -222,7 +222,7 @@ nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) * exactly to the page we want to fetch. */ static int -nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) +nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; @@ -246,7 +246,7 @@ nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) * Decode READ reply */ static int -nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) +nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) { struct kvec *iov = req->rq_rcv_buf.head; int status, count, recvd, hdrlen; @@ -286,7 +286,7 @@ nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) * Write arguments. Splice the buffer to be written into the iovec. */ static int -nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) +nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { struct xdr_buf *sndbuf = &req->rq_snd_buf; u32 offset = (u32)args->offset; @@ -309,7 +309,7 @@ nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) * CREATE, MKDIR */ static int -nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args) +nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -322,7 +322,7 @@ nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args) * Encode RENAME arguments */ static int -nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args) +nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); @@ -336,7 +336,7 @@ nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args) * Encode LINK arguments */ static int -nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) +nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_fhandle(p, args->tofh); @@ -349,7 +349,7 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) * Encode SYMLINK arguments */ static int -nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) +nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args) { struct xdr_buf *sndbuf = &req->rq_snd_buf; size_t pad; @@ -378,7 +378,7 @@ nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) * Encode arguments to readdir call */ static int -nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args) +nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) { struct rpc_task *task = req->rq_task; struct rpc_auth *auth = task->tk_auth; @@ -404,7 +404,7 @@ nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args) * from nfs_readdir for each entry. */ static int -nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy) +nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; @@ -412,7 +412,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy) int hdrlen, recvd; int status, nr; unsigned int len, pglen; - u32 *end, *entry, *kaddr; + __be32 *end, *entry, *kaddr; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); @@ -432,8 +432,8 @@ nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy) if (pglen > recvd) pglen = recvd; page = rcvbuf->pages; - kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0); - end = (u32 *)((char *)p + pglen); + kaddr = p = kmap_atomic(*page, KM_USER0); + end = (__be32 *)((char *)p + pglen); entry = p; for (nr = 0; *p++; nr++) { if (p + 2 > end) @@ -496,7 +496,7 @@ nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) * Decode simple status reply */ static int -nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy) +nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy) { int status; @@ -510,7 +510,7 @@ nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy) * GETATTR, SETATTR, WRITE */ static int -nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) { int status; @@ -525,7 +525,7 @@ nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) * LOOKUP, CREATE, MKDIR */ static int -nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) +nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res) { int status; @@ -540,7 +540,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) * Encode READLINK args */ static int -nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args) +nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; @@ -558,7 +558,7 @@ nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args * Decode READLINK reply */ static int -nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy) +nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; @@ -601,7 +601,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy) * Decode WRITE reply */ static int -nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) +nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) { res->verf->committed = NFS_FILE_SYNC; return nfs_xdr_attrstat(req, p, res->fattr); @@ -611,7 +611,7 @@ nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) * Decode STATFS reply */ static int -nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs2_fsstat *res) +nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res) { int status; -- cgit v0.10.2 From d61005a6855160091dca44b718db93fe7aa9876f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:48 -0700 Subject: [PATCH] xdr annotations: NFSv3 on-the-wire data is big-endian [in large part pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 16556fa..b4e740e 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -105,14 +105,14 @@ static struct { /* * Common NFS XDR functions as inlines */ -static inline u32 * -xdr_encode_fhandle(u32 *p, struct nfs_fh *fh) +static inline __be32 * +xdr_encode_fhandle(__be32 *p, struct nfs_fh *fh) { return xdr_encode_array(p, fh->data, fh->size); } -static inline u32 * -xdr_decode_fhandle(u32 *p, struct nfs_fh *fh) +static inline __be32 * +xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh) { if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { memcpy(fh->data, p, fh->size); @@ -124,24 +124,24 @@ xdr_decode_fhandle(u32 *p, struct nfs_fh *fh) /* * Encode/decode time. */ -static inline u32 * -xdr_encode_time3(u32 *p, struct timespec *timep) +static inline __be32 * +xdr_encode_time3(__be32 *p, struct timespec *timep) { *p++ = htonl(timep->tv_sec); *p++ = htonl(timep->tv_nsec); return p; } -static inline u32 * -xdr_decode_time3(u32 *p, struct timespec *timep) +static inline __be32 * +xdr_decode_time3(__be32 *p, struct timespec *timep) { timep->tv_sec = ntohl(*p++); timep->tv_nsec = ntohl(*p++); return p; } -static u32 * -xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) +static __be32 * +xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) { unsigned int type, major, minor; int fmode; @@ -177,8 +177,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) return p; } -static inline u32 * -xdr_encode_sattr(u32 *p, struct iattr *attr) +static inline __be32 * +xdr_encode_sattr(__be32 *p, struct iattr *attr) { if (attr->ia_valid & ATTR_MODE) { *p++ = xdr_one; @@ -223,8 +223,8 @@ xdr_encode_sattr(u32 *p, struct iattr *attr) return p; } -static inline u32 * -xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr) +static inline __be32 * +xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr) { p = xdr_decode_hyper(p, &fattr->pre_size); p = xdr_decode_time3(p, &fattr->pre_mtime); @@ -233,16 +233,16 @@ xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr) return p; } -static inline u32 * -xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr) +static inline __be32 * +xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr) { if (*p++) p = xdr_decode_fattr(p, fattr); return p; } -static inline u32 * -xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr) +static inline __be32 * +xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr) { if (*p++) return xdr_decode_wcc_attr(p, fattr); @@ -250,8 +250,8 @@ xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr) } -static inline u32 * -xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr) +static inline __be32 * +xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr) { p = xdr_decode_pre_op_attr(p, fattr); return xdr_decode_post_op_attr(p, fattr); @@ -265,7 +265,7 @@ xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr) * Encode file handle argument */ static int -nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh) +nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) { p = xdr_encode_fhandle(p, fh); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); @@ -276,7 +276,7 @@ nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh) * Encode SETATTR arguments */ static int -nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args) +nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_sattr(p, args->sattr); @@ -291,7 +291,7 @@ nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args) * Encode directory ops argument */ static int -nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args) +nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -303,7 +303,7 @@ nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args) * Encode access() argument */ static int -nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args) +nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args) { p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(args->access); @@ -317,7 +317,7 @@ nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args) * exactly to the page we want to fetch. */ static int -nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) +nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; @@ -339,7 +339,7 @@ nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) * Write arguments. Splice the buffer to be written into the iovec. */ static int -nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) +nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { struct xdr_buf *sndbuf = &req->rq_snd_buf; u32 count = args->count; @@ -360,7 +360,7 @@ nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) * Encode CREATE arguments */ static int -nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args) +nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -380,7 +380,7 @@ nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args) * Encode MKDIR arguments */ static int -nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args) +nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -393,7 +393,7 @@ nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args) * Encode SYMLINK arguments */ static int -nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args) +nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); @@ -410,7 +410,7 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args * Encode MKNOD arguments */ static int -nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args) +nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); @@ -429,7 +429,7 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args) * Encode RENAME arguments */ static int -nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args) +nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); @@ -443,7 +443,7 @@ nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args) * Encode LINK arguments */ static int -nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args) +nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_fhandle(p, args->tofh); @@ -456,7 +456,7 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args) * Encode arguments to readdir call */ static int -nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args) +nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; @@ -485,7 +485,7 @@ nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args * We just check for syntactical correctness. */ static int -nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res) +nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; @@ -493,7 +493,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res) int hdrlen, recvd; int status, nr; unsigned int len, pglen; - u32 *entry, *end, *kaddr; + __be32 *entry, *end, *kaddr; status = ntohl(*p++); /* Decode post_op_attrs */ @@ -523,8 +523,8 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res) if (pglen > recvd) pglen = recvd; page = rcvbuf->pages; - kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0); - end = (u32 *)((char *)p + pglen); + kaddr = p = kmap_atomic(*page, KM_USER0); + end = (__be32 *)((char *)p + pglen); entry = p; for (nr = 0; *p++; nr++) { if (p + 3 > end) @@ -626,7 +626,7 @@ nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) * Encode COMMIT arguments */ static int -nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) +nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_hyper(p, args->offset); @@ -640,7 +640,7 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) * Encode GETACL arguments */ static int -nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p, +nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, struct nfs3_getaclargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; @@ -664,7 +664,7 @@ nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p, * Encode SETACL arguments */ static int -nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p, +nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, struct nfs3_setaclargs *args) { struct xdr_buf *buf = &req->rq_snd_buf; @@ -711,7 +711,7 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p, * Decode attrstat reply. */ static int -nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) { int status; @@ -726,7 +726,7 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) * SATTR, REMOVE, RMDIR */ static int -nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) { int status; @@ -740,7 +740,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) * Decode LOOKUP reply */ static int -nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) +nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) { int status; @@ -759,7 +759,7 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) * Decode ACCESS reply */ static int -nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res) +nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) { int status = ntohl(*p++); @@ -771,7 +771,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res) } static int -nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args) +nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; @@ -789,7 +789,7 @@ nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *ar * Decode READLINK reply */ static int -nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; @@ -837,7 +837,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) * Decode READ reply */ static int -nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) +nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) { struct kvec *iov = req->rq_rcv_buf.head; int status, count, ocount, recvd, hdrlen; @@ -888,7 +888,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) * Decode WRITE response */ static int -nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) +nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) { int status; @@ -910,7 +910,7 @@ nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) * Decode a CREATE response */ static int -nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) +nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) { int status; @@ -937,7 +937,7 @@ nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) * Decode RENAME reply */ static int -nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res) +nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res) { int status; @@ -952,7 +952,7 @@ nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res) * Decode LINK reply */ static int -nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res) +nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res) { int status; @@ -967,7 +967,7 @@ nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res) * Decode FSSTAT reply */ static int -nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res) +nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) { int status; @@ -992,7 +992,7 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res) * Decode FSINFO reply */ static int -nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) +nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) { int status; @@ -1020,7 +1020,7 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) * Decode PATHCONF reply */ static int -nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res) +nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) { int status; @@ -1040,7 +1040,7 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res) * Decode COMMIT reply */ static int -nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) +nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) { int status; @@ -1059,7 +1059,7 @@ nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) * Decode GETACL reply */ static int -nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p, +nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p, struct nfs3_getaclres *res) { struct xdr_buf *buf = &req->rq_rcv_buf; @@ -1091,7 +1091,7 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p, * Decode setacl reply. */ static int -nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) { int status = ntohl(*p++); -- cgit v0.10.2 From 8687b63afbe42103730bff4d3f7bfff3463c303e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:48 -0700 Subject: [PATCH] xdr annotations: NFSv4 on-the-wire data is big-endian [in large part pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 3dd413f..e284123 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -471,7 +471,7 @@ struct compound_hdr { static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) { - uint32_t *p; + __be32 *p; p = xdr_reserve_space(xdr, 4 + len); BUG_ON(p == NULL); @@ -480,7 +480,7 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char * static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) { - uint32_t *p; + __be32 *p; dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); @@ -494,7 +494,7 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf) { - uint32_t *p; + __be32 *p; p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); BUG_ON(p == NULL); @@ -507,8 +507,8 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s char owner_group[IDMAP_NAMESZ]; int owner_namelen = 0; int owner_grouplen = 0; - uint32_t *p; - uint32_t *q; + __be32 *p; + __be32 *q; int len; uint32_t bmval0 = 0; uint32_t bmval1 = 0; @@ -630,7 +630,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s static int encode_access(struct xdr_stream *xdr, u32 access) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8); WRITE32(OP_ACCESS); @@ -641,7 +641,7 @@ static int encode_access(struct xdr_stream *xdr, u32 access) static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8+sizeof(arg->stateid->data)); WRITE32(OP_CLOSE); @@ -653,7 +653,7 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(16); WRITE32(OP_COMMIT); @@ -665,7 +665,7 @@ static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *arg static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8); WRITE32(OP_CREATE); @@ -697,7 +697,7 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(12); WRITE32(OP_GETATTR); @@ -708,7 +708,7 @@ static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap) static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(16); WRITE32(OP_GETATTR); @@ -740,7 +740,7 @@ static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask) static int encode_getfh(struct xdr_stream *xdr) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_GETFH); @@ -750,7 +750,7 @@ static int encode_getfh(struct xdr_stream *xdr) static int encode_link(struct xdr_stream *xdr, const struct qstr *name) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8 + name->len); WRITE32(OP_LINK); @@ -780,7 +780,7 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl) */ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(32); WRITE32(OP_LOCK); @@ -809,7 +809,7 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args) static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(40); WRITE32(OP_LOCKT); @@ -825,7 +825,7 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *arg static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(44); WRITE32(OP_LOCKU); @@ -841,7 +841,7 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *arg static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name) { int len = name->len; - uint32_t *p; + __be32 *p; RESERVE_SPACE(8 + len); WRITE32(OP_LOOKUP); @@ -853,7 +853,7 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name) static void encode_share_access(struct xdr_stream *xdr, int open_flags) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8); switch (open_flags & (FMODE_READ|FMODE_WRITE)) { @@ -874,7 +874,7 @@ static void encode_share_access(struct xdr_stream *xdr, int open_flags) static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg) { - uint32_t *p; + __be32 *p; /* * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, * owner 4 = 32 @@ -891,7 +891,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); switch(arg->open_flags & O_EXCL) { @@ -907,7 +907,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); switch (arg->open_flags & O_CREAT) { @@ -923,7 +923,7 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation_type) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); switch (delegation_type) { @@ -943,7 +943,7 @@ static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(NFS4_OPEN_CLAIM_NULL); @@ -952,7 +952,7 @@ static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr * static inline void encode_claim_previous(struct xdr_stream *xdr, int type) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(NFS4_OPEN_CLAIM_PREVIOUS); @@ -961,7 +961,7 @@ static inline void encode_claim_previous(struct xdr_stream *xdr, int type) static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4+sizeof(stateid->data)); WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR); @@ -991,7 +991,7 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg) static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8+sizeof(arg->stateid->data)); WRITE32(OP_OPEN_CONFIRM); @@ -1003,7 +1003,7 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8+sizeof(arg->stateid->data)); WRITE32(OP_OPEN_DOWNGRADE); @@ -1017,7 +1017,7 @@ static int encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh) { int len = fh->size; - uint32_t *p; + __be32 *p; RESERVE_SPACE(8 + len); WRITE32(OP_PUTFH); @@ -1029,7 +1029,7 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh) static int encode_putrootfh(struct xdr_stream *xdr) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_PUTROOTFH); @@ -1040,7 +1040,7 @@ static int encode_putrootfh(struct xdr_stream *xdr) static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) { nfs4_stateid stateid; - uint32_t *p; + __be32 *p; RESERVE_SPACE(16); if (ctx->state != NULL) { @@ -1052,7 +1052,7 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_READ); @@ -1074,7 +1074,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg FATTR4_WORD1_MOUNTED_ON_FILEID, }; int replen; - uint32_t *p; + __be32 *p; RESERVE_SPACE(32+sizeof(nfs4_verifier)); WRITE32(OP_READDIR); @@ -1116,7 +1116,7 @@ static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *r { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_READLINK); @@ -1134,7 +1134,7 @@ static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *r static int encode_remove(struct xdr_stream *xdr, const struct qstr *name) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8 + name->len); WRITE32(OP_REMOVE); @@ -1146,7 +1146,7 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name) static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(8 + oldname->len); WRITE32(OP_RENAME); @@ -1162,7 +1162,7 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(12); WRITE32(OP_RENEW); @@ -1174,7 +1174,7 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_ static int encode_restorefh(struct xdr_stream *xdr) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_RESTOREFH); @@ -1185,7 +1185,7 @@ encode_restorefh(struct xdr_stream *xdr) static int encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4+sizeof(zero_stateid.data)); WRITE32(OP_SETATTR); @@ -1204,7 +1204,7 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) static int encode_savefh(struct xdr_stream *xdr) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_SAVEFH); @@ -1215,7 +1215,7 @@ encode_savefh(struct xdr_stream *xdr) static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server) { int status; - uint32_t *p; + __be32 *p; RESERVE_SPACE(4+sizeof(arg->stateid.data)); WRITE32(OP_SETATTR); @@ -1229,7 +1229,7 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs * static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data)); WRITE32(OP_SETCLIENTID); @@ -1248,7 +1248,7 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(12 + sizeof(client_state->cl_confirm.data)); WRITE32(OP_SETCLIENTID_CONFIRM); @@ -1260,7 +1260,7 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_c static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(4); WRITE32(OP_WRITE); @@ -1279,7 +1279,7 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid) { - uint32_t *p; + __be32 *p; RESERVE_SPACE(20); @@ -1295,7 +1295,7 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *statei /* * Encode an ACCESS request */ -static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct nfs4_accessargs *args) +static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1313,7 +1313,7 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct n /* * Encode LOOKUP request */ -static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_arg *args) +static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1337,7 +1337,7 @@ out: /* * Encode LOOKUP_ROOT request */ -static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_root_arg *args) +static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1358,7 +1358,7 @@ out: /* * Encode REMOVE request */ -static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct nfs4_remove_arg *args) +static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs4_remove_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1380,7 +1380,7 @@ out: /* * Encode RENAME request */ -static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct nfs4_rename_arg *args) +static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1410,7 +1410,7 @@ out: /* * Encode LINK request */ -static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs4_link_arg *args) +static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1440,7 +1440,7 @@ out: /* * Encode CREATE request */ -static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args) +static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1470,7 +1470,7 @@ out: /* * Encode SYMLINK request */ -static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args) +static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args) { return nfs4_xdr_enc_create(req, p, args); } @@ -1478,7 +1478,7 @@ static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct /* * Encode GETATTR request */ -static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct nfs4_getattr_arg *args) +static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1496,7 +1496,7 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct /* * Encode a CLOSE request */ -static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args) +static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1520,7 +1520,7 @@ out: /* * Encode an OPEN request */ -static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args) +static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1556,7 +1556,7 @@ out: /* * Encode an OPEN_CONFIRM request */ -static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_open_confirmargs *args) +static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_open_confirmargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1577,7 +1577,7 @@ out: /* * Encode an OPEN request with no attributes. */ -static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args) +static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1601,7 +1601,7 @@ out: /* * Encode an OPEN_DOWNGRADE request */ -static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args) +static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1625,7 +1625,7 @@ out: /* * Encode a LOCK request */ -static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_args *args) +static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1646,7 +1646,7 @@ out: /* * Encode a LOCKT request */ -static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockt_args *args) +static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1667,7 +1667,7 @@ out: /* * Encode a LOCKU request */ -static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_locku_args *args) +static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1688,7 +1688,7 @@ out: /* * Encode a READLINK request */ -static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readlink *args) +static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1709,7 +1709,7 @@ out: /* * Encode a READDIR request */ -static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readdir_arg *args) +static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1730,7 +1730,7 @@ out: /* * Encode a READ request */ -static int nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args) +static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; struct xdr_stream xdr; @@ -1762,7 +1762,7 @@ out: /* * Encode an SETATTR request */ -static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, uint32_t *p, struct nfs_setattrargs *args) +static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args) { struct xdr_stream xdr; @@ -1788,7 +1788,7 @@ out: * Encode a GETACL request */ static int -nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p, +nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p, struct nfs_getaclargs *args) { struct xdr_stream xdr; @@ -1815,7 +1815,7 @@ out: /* * Encode a WRITE request */ -static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args) +static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1839,7 +1839,7 @@ out: /* * a COMMIT request */ -static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args) +static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1863,7 +1863,7 @@ out: /* * FSINFO request */ -static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fsinfo_arg *args) +static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1882,7 +1882,7 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs /* * a PATHCONF request */ -static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args) +static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1902,7 +1902,7 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct /* * a STATFS request */ -static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) +static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1923,7 +1923,7 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct n /* * GETATTR_BITMAP request */ -static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const struct nfs_fh *fhandle) +static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1945,7 +1945,7 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const str /* * a RENEW request */ -static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) +static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1960,7 +1960,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_clie /* * a SETCLIENTID request */ -static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nfs4_setclientid *sc) +static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid *sc) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1975,7 +1975,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nf /* * a SETCLIENTID_CONFIRM request */ -static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) +static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1997,7 +1997,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s /* * DELEGRETURN request */ -static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const struct nfs4_delegreturnargs *args) +static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -2021,7 +2021,7 @@ out: /* * Encode FS_LOCATIONS request */ -static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations_arg *args) +static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -2086,7 +2086,7 @@ out: static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) { - uint32_t *p; + __be32 *p; READ_BUF(4); READ32(*len); @@ -2097,7 +2097,7 @@ static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) { - uint32_t *p; + __be32 *p; READ_BUF(8); READ32(hdr->status); @@ -2112,7 +2112,7 @@ static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) { - uint32_t *p; + __be32 *p; uint32_t opnum; int32_t nfserr; @@ -2134,7 +2134,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) /* Dummy routine */ static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) { - uint32_t *p; + __be32 *p; unsigned int strlen; char *str; @@ -2144,7 +2144,8 @@ static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) { - uint32_t bmlen, *p; + uint32_t bmlen; + __be32 *p; READ_BUF(4); READ32(bmlen); @@ -2159,9 +2160,9 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) return 0; } -static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, uint32_t **savep) +static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) { - uint32_t *p; + __be32 *p; READ_BUF(4); READ32(*attrlen); @@ -2182,7 +2183,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3 static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type) { - uint32_t *p; + __be32 *p; *type = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U))) @@ -2202,7 +2203,7 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t * static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change) { - uint32_t *p; + __be32 *p; *change = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U))) @@ -2219,7 +2220,7 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size) { - uint32_t *p; + __be32 *p; *size = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U))) @@ -2235,7 +2236,7 @@ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t * static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; *res = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U))) @@ -2251,7 +2252,7 @@ static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, ui static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; *res = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U))) @@ -2267,7 +2268,7 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid) { - uint32_t *p; + __be32 *p; fsid->major = 0; fsid->minor = 0; @@ -2287,7 +2288,7 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; *res = 60; if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U))) @@ -2303,7 +2304,7 @@ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) @@ -2319,7 +2320,7 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) { - uint32_t *p; + __be32 *p; *fileid = 0; if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U))) @@ -2335,7 +2336,7 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) { - uint32_t *p; + __be32 *p; *fileid = 0; if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U))) @@ -2351,7 +2352,7 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2368,7 +2369,7 @@ static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2385,7 +2386,7 @@ static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2403,7 +2404,7 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) { int n; - uint32_t *p; + __be32 *p; int status = 0; READ_BUF(4); @@ -2448,7 +2449,7 @@ out_eio: static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) { int n; - uint32_t *p; + __be32 *p; int status = -EIO; if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U))) @@ -2512,7 +2513,7 @@ out_eio: static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2529,7 +2530,7 @@ static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uin static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink) { - uint32_t *p; + __be32 *p; int status = 0; *maxlink = 1; @@ -2546,7 +2547,7 @@ static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname) { - uint32_t *p; + __be32 *p; int status = 0; *maxname = 1024; @@ -2563,7 +2564,7 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 1024; @@ -2584,7 +2585,7 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 1024; @@ -2605,7 +2606,7 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32 static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode) { - uint32_t *p; + __be32 *p; *mode = 0; if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U))) @@ -2622,7 +2623,7 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t * static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink) { - uint32_t *p; + __be32 *p; *nlink = 1; if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U))) @@ -2638,7 +2639,8 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid) { - uint32_t len, *p; + uint32_t len; + __be32 *p; *uid = -2; if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U))) @@ -2662,7 +2664,8 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid) { - uint32_t len, *p; + uint32_t len; + __be32 *p; *gid = -2; if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U))) @@ -2686,7 +2689,8 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nf static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev) { - uint32_t major = 0, minor = 0, *p; + uint32_t major = 0, minor = 0; + __be32 *p; *rdev = MKDEV(0,0); if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U))) @@ -2708,7 +2712,7 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2725,7 +2729,7 @@ static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2742,7 +2746,7 @@ static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res) { - uint32_t *p; + __be32 *p; int status = 0; *res = 0; @@ -2759,7 +2763,7 @@ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uin static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used) { - uint32_t *p; + __be32 *p; *used = 0; if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U))) @@ -2776,7 +2780,7 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time) { - uint32_t *p; + __be32 *p; uint64_t sec; uint32_t nsec; @@ -2836,7 +2840,7 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str return status; } -static int verify_attr_len(struct xdr_stream *xdr, uint32_t *savep, uint32_t attrlen) +static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) { unsigned int attrwords = XDR_QUADLEN(attrlen); unsigned int nwords = xdr->p - savep; @@ -2854,7 +2858,7 @@ static int verify_attr_len(struct xdr_stream *xdr, uint32_t *savep, uint32_t att static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) { - uint32_t *p; + __be32 *p; READ_BUF(20); READ32(cinfo->atomic); @@ -2865,7 +2869,7 @@ static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *c static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) { - uint32_t *p; + __be32 *p; uint32_t supp, acc; int status; @@ -2882,7 +2886,7 @@ static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_CLOSE); @@ -2895,7 +2899,7 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_COMMIT); @@ -2908,7 +2912,7 @@ static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) { - uint32_t *p; + __be32 *p; uint32_t bmlen; int status; @@ -2925,7 +2929,7 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2] = {0}; int status; @@ -2952,7 +2956,7 @@ xdr_error: static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2] = {0}; int status; @@ -2985,7 +2989,7 @@ xdr_error: static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2] = {0}; int status; @@ -3010,7 +3014,7 @@ xdr_error: static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, const struct nfs_server *server) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2] = {0}, type; @@ -3079,7 +3083,7 @@ xdr_error: static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2]; int status; @@ -3111,7 +3115,7 @@ xdr_error: static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) { - uint32_t *p; + __be32 *p; uint32_t len; int status; @@ -3147,7 +3151,7 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) { uint64_t offset, length, clientid; - uint32_t *p; + __be32 *p; uint32_t namelen, type; READ_BUF(32); @@ -3172,7 +3176,7 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_LOCK); @@ -3195,7 +3199,7 @@ static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_LOCKU); @@ -3214,7 +3218,7 @@ static int decode_lookup(struct xdr_stream *xdr) /* This is too sick! */ static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) { - uint32_t *p; + __be32 *p; uint32_t limit_type, nblocks, blocksize; READ_BUF(12); @@ -3233,7 +3237,7 @@ static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize) static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) { - uint32_t *p; + __be32 *p; uint32_t delegation_type; READ_BUF(4); @@ -3259,7 +3263,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) { - uint32_t *p; + __be32 *p; uint32_t bmlen; int status; @@ -3287,7 +3291,7 @@ xdr_error: static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); @@ -3300,7 +3304,7 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); @@ -3324,7 +3328,7 @@ static int decode_putrootfh(struct xdr_stream *xdr) static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) { struct kvec *iov = req->rq_rcv_buf.head; - uint32_t *p; + __be32 *p; uint32_t count, eof, recvd, hdrlen; int status; @@ -3354,7 +3358,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n struct page *page = *rcvbuf->pages; struct kvec *iov = rcvbuf->head; unsigned int nr, pglen = rcvbuf->page_len; - uint32_t *end, *entry, *p, *kaddr; + __be32 *end, *entry, *p, *kaddr; uint32_t len, attrlen, xlen; int hdrlen, recvd, status; @@ -3376,7 +3380,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n xdr_read_pages(xdr, pglen); BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); - kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); + kaddr = p = kmap_atomic(page, KM_USER0); end = p + ((pglen + readdir->pgbase) >> 2); entry = p; for (nr = 0; *p++; nr++) { @@ -3428,7 +3432,7 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; int hdrlen, len, recvd; - uint32_t *p; + __be32 *p; char *kaddr; int status; @@ -3505,7 +3509,7 @@ decode_restorefh(struct xdr_stream *xdr) static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, size_t *acl_len) { - uint32_t *savep; + __be32 *savep; uint32_t attrlen, bitmap[2] = {0}; struct kvec *iov = req->rq_rcv_buf.head; @@ -3551,7 +3555,7 @@ decode_savefh(struct xdr_stream *xdr) static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) { - uint32_t *p; + __be32 *p; uint32_t bmlen; int status; @@ -3567,7 +3571,7 @@ static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) { - uint32_t *p; + __be32 *p; uint32_t opnum; int32_t nfserr; @@ -3610,7 +3614,7 @@ static int decode_setclientid_confirm(struct xdr_stream *xdr) static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) { - uint32_t *p; + __be32 *p; int status; status = decode_op_hdr(xdr, OP_WRITE); @@ -3632,7 +3636,7 @@ static int decode_delegreturn(struct xdr_stream *xdr) /* * Decode OPEN_DOWNGRADE response */ -static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res) +static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3660,7 +3664,7 @@ out: /* * Decode ACCESS response */ -static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_accessres *res) +static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3678,7 +3682,7 @@ out: /* * Decode LOOKUP response */ -static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res) +static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3701,7 +3705,7 @@ out: /* * Decode LOOKUP_ROOT response */ -static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res) +static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3721,7 +3725,7 @@ out: /* * Decode REMOVE response */ -static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res) +static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_remove_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3742,7 +3746,7 @@ out: /* * Decode RENAME response */ -static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_rename_res *res) +static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3772,7 +3776,7 @@ out: /* * Decode LINK response */ -static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res) +static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3805,7 +3809,7 @@ out: /* * Decode CREATE response */ -static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res) +static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3834,7 +3838,7 @@ out: /* * Decode SYMLINK response */ -static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res) +static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res) { return nfs4_xdr_dec_create(rqstp, p, res); } @@ -3842,7 +3846,7 @@ static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4 /* * Decode GETATTR response */ -static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_getattr_res *res) +static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3865,7 +3869,7 @@ out: * Encode an SETACL request */ static int -nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args) +nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -3886,7 +3890,7 @@ out: * Decode SETACL response */ static int -nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res) +nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3908,7 +3912,7 @@ out: * Decode GETACL response */ static int -nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len) +nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3930,7 +3934,7 @@ out: /* * Decode CLOSE response */ -static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res) +static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3960,7 +3964,7 @@ out: /* * Decode OPEN response */ -static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) +static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3994,7 +3998,7 @@ out: /* * Decode OPEN_CONFIRM response */ -static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_open_confirmres *res) +static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4015,7 +4019,7 @@ out: /* * Decode OPEN response */ -static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) +static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4039,7 +4043,7 @@ out: /* * Decode SETATTR response */ -static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_setattrres *res) +static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4065,7 +4069,7 @@ out: /* * Decode LOCK response */ -static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lock_res *res) +static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4086,7 +4090,7 @@ out: /* * Decode LOCKT response */ -static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockt_res *res) +static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4107,7 +4111,7 @@ out: /* * Decode LOCKU response */ -static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_locku_res *res) +static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4128,7 +4132,7 @@ out: /* * Decode READLINK response */ -static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, uint32_t *p, void *res) +static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4149,7 +4153,7 @@ out: /* * Decode READDIR response */ -static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_readdir_res *res) +static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4170,7 +4174,7 @@ out: /* * Decode Read response */ -static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res) +static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4193,7 +4197,7 @@ out: /* * Decode WRITE response */ -static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res) +static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4219,7 +4223,7 @@ out: /* * Decode COMMIT response */ -static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res) +static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4243,7 +4247,7 @@ out: /* * FSINFO request */ -static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo) +static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4263,7 +4267,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsi /* * PATHCONF request */ -static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, uint32_t *p, struct nfs_pathconf *pathconf) +static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4281,7 +4285,7 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, uint32_t *p, struct nfs_p /* * STATFS request */ -static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, uint32_t *p, struct nfs_fsstat *fsstat) +static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4299,7 +4303,7 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, uint32_t *p, struct nfs_fss /* * GETATTR_BITMAP request */ -static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, uint32_t *p, struct nfs4_server_caps_res *res) +static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4318,7 +4322,7 @@ out: /* * Decode RENEW response */ -static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) +static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4334,7 +4338,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) /* * a SETCLIENTID request */ -static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, +static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp) { struct xdr_stream xdr; @@ -4353,7 +4357,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, /* * a SETCLIENTID_CONFIRM request */ -static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo) +static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4375,7 +4379,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s /* * DELEGRETURN request */ -static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_delegreturnres *res) +static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4397,7 +4401,7 @@ out: /* * FS_LOCATIONS request */ -static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res) +static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res) { struct xdr_stream xdr; struct compound_hdr hdr; -- cgit v0.10.2 From 0dbb4c6799cf8fa8c5ba1926153a30960117477d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:49 -0700 Subject: [PATCH] xdr annotations: NFS readdir entries on-the-wire data is big-endian [in large part pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c86a1ea..4133ef5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -142,12 +142,12 @@ nfs_opendir(struct inode *inode, struct file *filp) return res; } -typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int); +typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int); typedef struct { struct file *file; struct page *page; unsigned long page_index; - u32 *ptr; + __be32 *ptr; u64 *dir_cookie; loff_t current_index; struct nfs_entry *entry; @@ -220,7 +220,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) static inline int dir_decode(nfs_readdir_descriptor_t *desc) { - u32 *p = desc->ptr; + __be32 *p = desc->ptr; p = desc->decode(p, desc->entry, desc->plus); if (IS_ERR(p)) return PTR_ERR(p); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index bea0b01..d205466 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -93,15 +93,15 @@ extern void nfs_destroy_directcache(void); /* nfs2xdr.c */ extern int nfs_stat_to_errno(int); extern struct rpc_procinfo nfs_procedures[]; -extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); +extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int); /* nfs3xdr.c */ extern struct rpc_procinfo nfs3_procedures[]; -extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); +extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); /* nfs4xdr.c */ #ifdef CONFIG_NFS_V4 -extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); +extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); #endif /* nfs4proc.c */ diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 1d801e3..3be4e72 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -468,8 +468,8 @@ err_unmap: goto out; } -u32 * -nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) +__be32 * +nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) { if (!*p++) { if (!*p) diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index b4e740e..0ace092 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -583,8 +583,8 @@ err_unmap: goto out; } -u32 * -nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) +__be32 * +nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) { struct nfs_entry old = *entry; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 61095fe..6f34667 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -212,7 +212,7 @@ extern void nfs_free_seqid(struct nfs_seqid *seqid); extern const nfs4_stateid zero_stateid; /* nfs4xdr.c */ -extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus); +extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); extern struct rpc_procinfo nfs4_procedures[]; struct nfs4_mount_data; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7421bcb..8d09b47 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -141,7 +141,7 @@ const u32 nfs4_fs_locations_bitmap[2] = { static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, struct nfs4_readdir_arg *readdir) { - u32 *start, *p; + __be32 *start, *p; BUG_ON(readdir->count < 80); if (cookie > 2) { @@ -162,7 +162,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, * when talking to the server, we always send cookie 0 * instead of 1 or 2. */ - start = p = (u32 *)kmap_atomic(*readdir->pages, KM_USER0); + start = p = kmap_atomic(*readdir->pages, KM_USER0); if (cookie == 0) { *p++ = xdr_one; /* next */ diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index e284123..0cf3fa3 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -4421,7 +4421,7 @@ out: return status; } -uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) +__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) { uint32_t bitmap[2] = {0}; uint32_t len; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index dc5397d..ac8058b 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -811,7 +811,7 @@ struct nfs_rpc_ops { int (*pathconf) (struct nfs_server *, struct nfs_fh *, struct nfs_pathconf *); int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); - u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); + __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus); void (*read_setup) (struct nfs_read_data *); int (*read_done) (struct rpc_task *, struct nfs_read_data *); void (*write_setup) (struct nfs_write_data *, int how); -- cgit v0.10.2 From e6f684f6443dd37384c63d2f27571350e0b5c8aa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:50 -0700 Subject: [PATCH] fs/nfs/callback* passes error values big-endian [pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 5676163d..6921d82 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -44,7 +44,7 @@ struct cb_getattrargs { }; struct cb_getattrres { - uint32_t status; + __be32 status; uint32_t bitmap[2]; uint64_t size; uint64_t change_attr; @@ -59,8 +59,8 @@ struct cb_recallargs { uint32_t truncate; }; -extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); -extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy); +extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); +extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); #ifdef CONFIG_NFS_V4 extern int nfs_callback_up(void); diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 97cf8f7..72e55d8 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -14,7 +14,7 @@ #define NFSDBG_FACILITY NFSDBG_CALLBACK -unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) +__be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) { struct nfs_client *clp; struct nfs_delegation *delegation; @@ -55,11 +55,11 @@ out: return res->status; } -unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy) +__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { struct nfs_client *clp; struct inode *inode; - unsigned res; + __be32 res; res = htonl(NFS4ERR_BADHANDLE); clp = nfs_find_client(args->addr, 4); diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 5998d0c..909a140 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -22,9 +22,9 @@ #define NFSDBG_FACILITY NFSDBG_CALLBACK -typedef unsigned (*callback_process_op_t)(void *, void *); -typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *); -typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *); +typedef __be32 (*callback_process_op_t)(void *, void *); +typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *); +typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *); struct callback_op { @@ -61,7 +61,7 @@ static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes) return p; } -static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str) +static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str) { uint32_t *p; @@ -81,7 +81,7 @@ static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const c return 0; } -static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) +static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) { uint32_t *p; @@ -99,7 +99,7 @@ static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) return 0; } -static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) +static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) { uint32_t *p; unsigned int attrlen; @@ -118,7 +118,7 @@ static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) return 0; } -static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) +static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) { uint32_t *p; @@ -129,11 +129,11 @@ static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) return 0; } -static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr) +static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr) { uint32_t *p; unsigned int minor_version; - unsigned status; + __be32 status; status = decode_string(xdr, &hdr->taglen, &hdr->tag); if (unlikely(status != 0)) @@ -159,7 +159,7 @@ static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compou return 0; } -static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) +static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) { uint32_t *p; p = read_buf(xdr, 4); @@ -169,9 +169,9 @@ static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) return 0; } -static unsigned decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args) +static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args) { - unsigned status; + __be32 status; status = decode_fh(xdr, &args->fh); if (unlikely(status != 0)) @@ -183,10 +183,10 @@ out: return status; } -static unsigned decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args) +static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args) { uint32_t *p; - unsigned status; + __be32 status; args->addr = &rqstp->rq_addr; status = decode_stateid(xdr, &args->stateid); @@ -204,7 +204,7 @@ out: return status; } -static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) +static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) { uint32_t *p; @@ -217,7 +217,7 @@ static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const ch #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) -static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep) +static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep) { uint32_t bm[2]; uint32_t *p; @@ -247,7 +247,7 @@ static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitma return 0; } -static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change) +static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change) { uint32_t *p; @@ -260,7 +260,7 @@ static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitma return 0; } -static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size) +static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size) { uint32_t *p; @@ -273,7 +273,7 @@ static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, return 0; } -static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec *time) +static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec *time) { uint32_t *p; @@ -285,23 +285,23 @@ static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec * return 0; } -static unsigned encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) +static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) { if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) return 0; return encode_attr_time(xdr,time); } -static unsigned encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) +static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time) { if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) return 0; return encode_attr_time(xdr,time); } -static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr) +static __be32 encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr) { - unsigned status; + __be32 status; hdr->status = xdr_reserve_space(xdr, 4); if (unlikely(hdr->status == NULL)) @@ -315,7 +315,7 @@ static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compou return 0; } -static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res) +static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res) { uint32_t *p; @@ -327,10 +327,10 @@ static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res) return 0; } -static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res) +static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res) { uint32_t *savep = NULL; - unsigned status = res->status; + __be32 status = res->status; if (unlikely(status != 0)) goto out; @@ -353,15 +353,15 @@ out: return status; } -static unsigned process_op(struct svc_rqst *rqstp, +static __be32 process_op(struct svc_rqst *rqstp, struct xdr_stream *xdr_in, void *argp, struct xdr_stream *xdr_out, void *resp) { struct callback_op *op = &callback_ops[0]; unsigned int op_nr = OP_CB_ILLEGAL; - unsigned int status = 0; + __be32 status = 0; long maxlen; - unsigned res; + __be32 res; dprintk("%s: start\n", __FUNCTION__); status = decode_op_hdr(xdr_in, &op_nr); @@ -405,7 +405,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r struct cb_compound_hdr_res hdr_res; struct xdr_stream xdr_in, xdr_out; uint32_t *p; - unsigned int status; + __be32 status; unsigned int nops = 1; dprintk("%s: start\n", __FUNCTION__); -- cgit v0.10.2 From 5704fdeb41c9fb282ae576516f221ea0b8f64b2b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:51 -0700 Subject: [PATCH] xdr annotations: fs/nfs/callback* on-the-wire data is big-endian [mostly pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 6921d82..db3d791 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -31,10 +31,10 @@ struct cb_compound_hdr_arg { }; struct cb_compound_hdr_res { - uint32_t *status; + __be32 *status; int taglen; const char *tag; - uint32_t *nops; + __be32 *nops; }; struct cb_getattrargs { diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 909a140..f8ea1f5 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -41,19 +41,19 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp) return htonl(NFS4_OK); } -static int nfs4_decode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy) +static int nfs4_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } -static int nfs4_encode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy) +static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } -static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes) +static __be32 *read_buf(struct xdr_stream *xdr, int nbytes) { - uint32_t *p; + __be32 *p; p = xdr_inline_decode(xdr, nbytes); if (unlikely(p == NULL)) @@ -63,7 +63,7 @@ static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes) static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str) { - uint32_t *p; + __be32 *p; p = read_buf(xdr, 4); if (unlikely(p == NULL)) @@ -83,7 +83,7 @@ static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, const cha static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) { - uint32_t *p; + __be32 *p; p = read_buf(xdr, 4); if (unlikely(p == NULL)) @@ -101,7 +101,7 @@ static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh) static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) { - uint32_t *p; + __be32 *p; unsigned int attrlen; p = read_buf(xdr, 4); @@ -120,7 +120,7 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap) static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) { - uint32_t *p; + __be32 *p; p = read_buf(xdr, 16); if (unlikely(p == NULL)) @@ -131,7 +131,7 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr) { - uint32_t *p; + __be32 *p; unsigned int minor_version; __be32 status; @@ -161,7 +161,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op) { - uint32_t *p; + __be32 *p; p = read_buf(xdr, 4); if (unlikely(p == NULL)) return htonl(NFS4ERR_RESOURCE); @@ -185,7 +185,7 @@ out: static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args) { - uint32_t *p; + __be32 *p; __be32 status; args->addr = &rqstp->rq_addr; @@ -206,7 +206,7 @@ out: static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) { - uint32_t *p; + __be32 *p; p = xdr_reserve_space(xdr, 4 + len); if (unlikely(p == NULL)) @@ -217,10 +217,10 @@ static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) -static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep) +static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, __be32 **savep) { - uint32_t bm[2]; - uint32_t *p; + __be32 bm[2]; + __be32 *p; bm[0] = htonl(bitmap[0] & CB_SUPPORTED_ATTR0); bm[1] = htonl(bitmap[1] & CB_SUPPORTED_ATTR1); @@ -249,7 +249,7 @@ static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change) { - uint32_t *p; + __be32 *p; if (!(bitmap[0] & FATTR4_WORD0_CHANGE)) return 0; @@ -262,7 +262,7 @@ static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size) { - uint32_t *p; + __be32 *p; if (!(bitmap[0] & FATTR4_WORD0_SIZE)) return 0; @@ -275,7 +275,7 @@ static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, u static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec *time) { - uint32_t *p; + __be32 *p; p = xdr_reserve_space(xdr, 12); if (unlikely(p == 0)) @@ -317,7 +317,7 @@ static __be32 encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res) { - uint32_t *p; + __be32 *p; p = xdr_reserve_space(xdr, 8); if (unlikely(p == NULL)) @@ -329,7 +329,7 @@ static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res) static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res) { - uint32_t *savep = NULL; + __be32 *savep = NULL; __be32 status = res->status; if (unlikely(status != 0)) @@ -404,7 +404,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r struct cb_compound_hdr_arg hdr_arg; struct cb_compound_hdr_res hdr_res; struct xdr_stream xdr_in, xdr_out; - uint32_t *p; + __be32 *p; __be32 status; unsigned int nops = 1; @@ -412,7 +412,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); - p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); + p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); xdr_init_encode(&xdr_out, &rqstp->rq_res, p); decode_compound_hdr_arg(&xdr_in, &hdr_arg); -- cgit v0.10.2 From bc4785cd475a11ba125df7af674e16c6ea1cfc30 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:51 -0700 Subject: [PATCH] nfs: verifier is network-endian Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 3b234d4..e5f128f 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -668,7 +668,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, { struct inode *dir = dentry->d_inode; struct nfs_fattr dir_attr; - u32 *verf = NFS_COOKIEVERF(dir); + __be32 *verf = NFS_COOKIEVERF(dir); struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8d09b47..8118036 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -138,7 +138,7 @@ const u32 nfs4_fs_locations_bitmap[2] = { | FATTR4_WORD1_MOUNTED_ON_FILEID }; -static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, +static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, struct nfs4_readdir_arg *readdir) { __be32 *start, *p; @@ -2915,11 +2915,11 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po .rpc_resp = clp, .rpc_cred = cred, }; - u32 *p; + __be32 *p; int loop = 0; int status; - p = (u32*)sc_verifier.data; + p = (__be32*)sc_verifier.data; *p++ = htonl((u32)clp->cl_boot_time.tv_sec); *p = htonl((u32)clp->cl_boot_time.tv_nsec); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 6b2de1b..45228c1 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -157,7 +157,7 @@ struct nfs_inode { * This is the cookie verifier used for NFSv3 readdir * operations */ - __u32 cookieverf[2]; + __be32 cookieverf[2]; /* * This is the list of dirty unwritten pages. diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ac8058b..768c1ad 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -266,7 +266,7 @@ struct nfs_writeargs { struct nfs_writeverf { enum nfs3_stable_how committed; - __u32 verifier[2]; + __be32 verifier[2]; }; struct nfs_writeres { @@ -420,7 +420,7 @@ struct nfs3_createargs { unsigned int len; struct iattr * sattr; enum nfs3_createmode createmode; - __u32 verifier[2]; + __be32 verifier[2]; }; struct nfs3_mkdirargs { @@ -467,7 +467,7 @@ struct nfs3_linkargs { struct nfs3_readdirargs { struct nfs_fh * fh; __u64 cookie; - __u32 verf[2]; + __be32 verf[2]; int plus; unsigned int count; struct page ** pages; @@ -503,7 +503,7 @@ struct nfs3_linkres { struct nfs3_readdirres { struct nfs_fattr * dir_attr; - __u32 * verf; + __be32 * verf; int plus; }; -- cgit v0.10.2 From d21ec0c33d0a9eb7a6f6c716008863a97797709e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:52 -0700 Subject: [PATCH] xdr annotations: mount_clnt [pulled from Alexey's patch] Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index d507b02..f75fe72 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -95,7 +95,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, * XDR encode/decode functions for MOUNT */ static int -xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path) +xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path) { p = xdr_encode_string(p, path); @@ -104,7 +104,7 @@ xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path) } static int -xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) +xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res) { struct nfs_fh *fh = res->fh; @@ -116,7 +116,7 @@ xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) } static int -xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) +xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res) { struct nfs_fh *fh = res->fh; -- cgit v0.10.2 From 83bbe2ef63ec4f6a22aaaa0c03bd918b38300127 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:53 -0700 Subject: [PATCH] nfs_common endianness annotations Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 0c2be8c..c11f537 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -46,7 +46,7 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) { struct nfsacl_encode_desc *nfsacl_desc = (struct nfsacl_encode_desc *) desc; - u32 *p = (u32 *) elem; + __be32 *p = elem; struct posix_acl_entry *entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; @@ -127,7 +127,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) { struct nfsacl_decode_desc *nfsacl_desc = (struct nfsacl_decode_desc *) desc; - u32 *p = (u32 *) elem; + __be32 *p = elem; struct posix_acl_entry *entry; if (!nfsacl_desc->acl) { -- cgit v0.10.2 From 63f103111fdfc3cba00e4c94921d32362f375d93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:54 -0700 Subject: [PATCH] nfsd: nfserrno() endianness annotations Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 09030af..03ab682 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -579,11 +579,11 @@ struct svc_version nfsd_version2 = { /* * Map errnos to NFS errnos. */ -int +__be32 nfserrno (int errno) { static struct { - int nfserr; + __be32 nfserr; int syserr; } nfs_errtbl[] = { { nfs_ok, 0 }, @@ -615,11 +615,10 @@ nfserrno (int errno) { nfserr_badname, -ESRCH }, { nfserr_io, -ETXTBSY }, { nfserr_notsupp, -EOPNOTSUPP }, - { -1, -EIO } }; int i; - for (i = 0; nfs_errtbl[i].nfserr != -1; i++) { + for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) { if (nfs_errtbl[i].syserr == errno) return nfs_errtbl[i].nfserr; } diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 6e78ea9..27666f5b 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -118,7 +118,7 @@ struct svc_export * exp_parent(struct auth_domain *clp, int exp_rootfh(struct auth_domain *, char *path, struct knfsd_fh *, int maxsize); int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); -int nfserrno(int errno); +__be32 nfserrno(int errno); extern struct cache_detail svc_export_cache; -- cgit v0.10.2 From 83b11340d683a67a77e35a5ffb5ad4afbf0be4e5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:55 -0700 Subject: [PATCH] nfsfh simple endianness annotations Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 501d838..727ab3b 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -76,7 +76,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry) * comment in the NFSv3 spec says this is incorrect (implementation notes for * the write call). */ -static inline int +static inline __be32 nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type) { /* Type can be negative when creating hardlinks - not to a dir */ @@ -110,13 +110,13 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type) * This is only called at the start of an nfsproc call, so fhp points to * a svc_fh which is all 0 except for the over-the-wire file handle. */ -u32 +__be32 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) { struct knfsd_fh *fh = &fhp->fh_handle; struct svc_export *exp = NULL; struct dentry *dentry; - u32 error = 0; + __be32 error = 0; dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); @@ -315,7 +315,7 @@ static inline void _fh_update_old(struct dentry *dentry, fh->ofh_dirino = 0; } -int +__be32 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. @@ -451,7 +451,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st * Update file handle information after changing a dentry. * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create */ -int +__be32 fh_update(struct svc_fh *fhp) { struct dentry *dentry; diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index 069257e..749bad1 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -209,9 +209,9 @@ extern char * SVCFH_fmt(struct svc_fh *fhp); /* * Function prototypes */ -u32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int); -int fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); -int fh_update(struct svc_fh *); +__be32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int); +__be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); +__be32 fh_update(struct svc_fh *); void fh_put(struct svc_fh *); static __inline__ struct svc_fh * -- cgit v0.10.2 From ad451d389f46f699832da3e9ad95f610cb8c0fd2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:55 -0700 Subject: [PATCH] xdr annotations: nfsd_dispatch() Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 013b389..8067118 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -495,8 +495,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) { struct svc_procedure *proc; kxdrproc_t xdr; - u32 nfserr; - u32 *nfserrp; + __be32 nfserr; + __be32 *nfserrp; dprintk("nfsd_dispatch: vers %d proc %d\n", rqstp->rq_vers, rqstp->rq_proc); @@ -515,7 +515,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) /* Decode arguments */ xdr = proc->pc_decode; - if (xdr && !xdr(rqstp, (u32*)rqstp->rq_arg.head[0].iov_base, + if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base, rqstp->rq_argp)) { dprintk("nfsd: failed to decode arguments!\n"); nfsd_cache_update(rqstp, RC_NOCACHE, NULL); @@ -528,7 +528,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) */ nfserrp = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; - rqstp->rq_res.head[0].iov_len += sizeof(u32); + rqstp->rq_res.head[0].iov_len += sizeof(__be32); /* Now call the procedure handler, and encode NFS status. */ nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); -- cgit v0.10.2 From 131a21c2177c267ab259fcd06947c6f593a7de8e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:56 -0700 Subject: [PATCH] xdr annotations: NFSv2 server Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 8d48616..fd5397d 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -158,7 +158,7 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessarg /* * XDR decode functions */ -static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclargs *argp) { if (!(p = nfs2svc_decode_fh(p, &argp->fh))) @@ -169,7 +169,7 @@ static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, } -static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_setaclargs *argp) { struct kvec *head = rqstp->rq_arg.head; @@ -194,7 +194,7 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, return (n > 0); } -static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *argp) { if (!(p = nfs2svc_decode_fh(p, &argp->fh))) @@ -202,7 +202,7 @@ static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p, return xdr_argsize_check(rqstp, p); } -static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_accessargs *argp) { if (!(p = nfs2svc_decode_fh(p, &argp->fh))) @@ -217,7 +217,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p, */ /* GETACL */ -static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclres *resp) { struct dentry *dentry = resp->fh.fh_dentry; @@ -259,7 +259,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, return 1; } -static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_attrstat *resp) { p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); @@ -267,7 +267,7 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p, } /* ACCESS */ -static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_accessres *resp) { p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); @@ -278,7 +278,7 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p, /* * XDR release functions */ -static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclres *resp) { fh_put(&resp->fh); @@ -287,7 +287,7 @@ static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p, return 1; } -static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p, +static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *resp) { fh_put(&resp->fh); diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 1135c0d..56ebb14 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -37,8 +37,8 @@ static u32 nfs_ftypes[] = { /* * XDR functions for basic NFS types */ -static u32 * -decode_fh(u32 *p, struct svc_fh *fhp) +static __be32 * +decode_fh(__be32 *p, struct svc_fh *fhp) { fh_init(fhp, NFS_FHSIZE); memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); @@ -50,13 +50,13 @@ decode_fh(u32 *p, struct svc_fh *fhp) } /* Helper function for NFSv2 ACL code */ -u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp) +__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp) { return decode_fh(p, fhp); } -static inline u32 * -encode_fh(u32 *p, struct svc_fh *fhp) +static inline __be32 * +encode_fh(__be32 *p, struct svc_fh *fhp) { memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE); return p + (NFS_FHSIZE>> 2); @@ -66,8 +66,8 @@ encode_fh(u32 *p, struct svc_fh *fhp) * Decode a file name and make sure that the path contains * no slashes or null bytes. */ -static inline u32 * -decode_filename(u32 *p, char **namp, int *lenp) +static inline __be32 * +decode_filename(__be32 *p, char **namp, int *lenp) { char *name; int i; @@ -82,8 +82,8 @@ decode_filename(u32 *p, char **namp, int *lenp) return p; } -static inline u32 * -decode_pathname(u32 *p, char **namp, int *lenp) +static inline __be32 * +decode_pathname(__be32 *p, char **namp, int *lenp) { char *name; int i; @@ -98,8 +98,8 @@ decode_pathname(u32 *p, char **namp, int *lenp) return p; } -static inline u32 * -decode_sattr(u32 *p, struct iattr *iap) +static inline __be32 * +decode_sattr(__be32 *p, struct iattr *iap) { u32 tmp, tmp1; @@ -151,8 +151,8 @@ decode_sattr(u32 *p, struct iattr *iap) return p; } -static u32 * -encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, +static __be32 * +encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat) { struct dentry *dentry = fhp->fh_dentry; @@ -195,7 +195,7 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, } /* Helper function for NFSv2 ACL code */ -u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) +__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct kstat stat; vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat); @@ -206,13 +206,13 @@ u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) * XDR decode functions */ int -nfssvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } int -nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args) +nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) { if (!(p = decode_fh(p, &args->fh))) return 0; @@ -220,7 +220,7 @@ nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args) } int -nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_sattrargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -231,7 +231,7 @@ nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_diropargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -242,7 +242,7 @@ nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readargs *args) { unsigned int len; @@ -273,7 +273,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_writeargs *args) { unsigned int len; @@ -303,7 +303,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_createargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -315,7 +315,7 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_renameargs *args) { if (!(p = decode_fh(p, &args->ffh)) @@ -328,7 +328,7 @@ nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinkargs *args) +nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkargs *args) { if (!(p = decode_fh(p, &args->fh))) return 0; @@ -338,7 +338,7 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinka } int -nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_linkargs *args) { if (!(p = decode_fh(p, &args->ffh)) @@ -350,7 +350,7 @@ nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_symlinkargs *args) { if (!(p = decode_fh(p, &args->ffh)) @@ -363,7 +363,7 @@ nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, +nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readdirargs *args) { if (!(p = decode_fh(p, &args->fh))) @@ -382,13 +382,13 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, * XDR encode functions */ int -nfssvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } int -nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, struct nfsd_attrstat *resp) { p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); @@ -396,7 +396,7 @@ nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_diropres *resp) { p = encode_fh(p, &resp->fh); @@ -405,7 +405,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkres *resp) { *p++ = htonl(resp->len); @@ -421,7 +421,7 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readres *resp) { p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); @@ -440,7 +440,7 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readdirres *resp) { xdr_ressize_check(rqstp, p); @@ -453,7 +453,7 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, } int -nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p, +nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p, struct nfsd_statfsres *resp) { struct kstatfs *stat = &resp->stats; @@ -471,7 +471,7 @@ nfssvc_encode_entry(struct readdir_cd *ccd, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); - u32 *p = cd->buffer; + __be32 *p = cd->buffer; int buflen, slen; /* @@ -497,7 +497,7 @@ nfssvc_encode_entry(struct readdir_cd *ccd, const char *name, *p++ = htonl((u32) ino); /* file id */ p = xdr_encode_array(p, name, namlen);/* name length & name */ cd->offset = p; /* remember pointer */ - *p++ = ~(u32) 0; /* offset of next entry */ + *p++ = htonl(~0U); /* offset of next entry */ cd->buflen = buflen; cd->buffer = p; @@ -509,7 +509,7 @@ nfssvc_encode_entry(struct readdir_cd *ccd, const char *name, * XDR release functions */ int -nfssvc_release_fhandle(struct svc_rqst *rqstp, u32 *p, +nfssvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *resp) { fh_put(&resp->fh); diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index d0d4aae..2f75160 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -50,7 +50,7 @@ * Callback function for readdir */ struct readdir_cd { - int err; /* 0, nfserr, or nfserr_eof */ + __be32 err; /* 0, nfserr, or nfserr_eof */ }; typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, int, loff_t, ino_t, unsigned int); diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h index 0e53de8..877192d 100644 --- a/include/linux/nfsd/xdr.h +++ b/include/linux/nfsd/xdr.h @@ -81,7 +81,7 @@ struct nfsd_readdirargs { struct svc_fh fh; __u32 cookie; __u32 count; - u32 * buffer; + __be32 * buffer; }; struct nfsd_attrstat { @@ -108,9 +108,9 @@ struct nfsd_readdirres { int count; struct readdir_cd common; - u32 * buffer; + __be32 * buffer; int buflen; - u32 * offset; + __be32 * offset; }; struct nfsd_statfsres { @@ -135,43 +135,43 @@ union nfsd_xdrstore { #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) -int nfssvc_decode_void(struct svc_rqst *, u32 *, void *); -int nfssvc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); -int nfssvc_decode_sattrargs(struct svc_rqst *, u32 *, +int nfssvc_decode_void(struct svc_rqst *, __be32 *, void *); +int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); +int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *, struct nfsd_sattrargs *); -int nfssvc_decode_diropargs(struct svc_rqst *, u32 *, +int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *, struct nfsd_diropargs *); -int nfssvc_decode_readargs(struct svc_rqst *, u32 *, +int nfssvc_decode_readargs(struct svc_rqst *, __be32 *, struct nfsd_readargs *); -int nfssvc_decode_writeargs(struct svc_rqst *, u32 *, +int nfssvc_decode_writeargs(struct svc_rqst *, __be32 *, struct nfsd_writeargs *); -int nfssvc_decode_createargs(struct svc_rqst *, u32 *, +int nfssvc_decode_createargs(struct svc_rqst *, __be32 *, struct nfsd_createargs *); -int nfssvc_decode_renameargs(struct svc_rqst *, u32 *, +int nfssvc_decode_renameargs(struct svc_rqst *, __be32 *, struct nfsd_renameargs *); -int nfssvc_decode_readlinkargs(struct svc_rqst *, u32 *, +int nfssvc_decode_readlinkargs(struct svc_rqst *, __be32 *, struct nfsd_readlinkargs *); -int nfssvc_decode_linkargs(struct svc_rqst *, u32 *, +int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *, struct nfsd_linkargs *); -int nfssvc_decode_symlinkargs(struct svc_rqst *, u32 *, +int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *, struct nfsd_symlinkargs *); -int nfssvc_decode_readdirargs(struct svc_rqst *, u32 *, +int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *, struct nfsd_readdirargs *); -int nfssvc_encode_void(struct svc_rqst *, u32 *, void *); -int nfssvc_encode_attrstat(struct svc_rqst *, u32 *, struct nfsd_attrstat *); -int nfssvc_encode_diropres(struct svc_rqst *, u32 *, struct nfsd_diropres *); -int nfssvc_encode_readlinkres(struct svc_rqst *, u32 *, struct nfsd_readlinkres *); -int nfssvc_encode_readres(struct svc_rqst *, u32 *, struct nfsd_readres *); -int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *); -int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *); +int nfssvc_encode_void(struct svc_rqst *, __be32 *, void *); +int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *, struct nfsd_attrstat *); +int nfssvc_encode_diropres(struct svc_rqst *, __be32 *, struct nfsd_diropres *); +int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *, struct nfsd_readlinkres *); +int nfssvc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd_readres *); +int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *, struct nfsd_statfsres *); +int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd_readdirres *); int nfssvc_encode_entry(struct readdir_cd *, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int); -int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); +int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); /* Helper functions for NFSv2 ACL code */ -u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp); -u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp); +__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp); +__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp); #endif /* LINUX_NFSD_H */ -- cgit v0.10.2 From 91f07168cef8e99dd16f608fbc703e7a5af0237f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:57 -0700 Subject: [PATCH] xdr annotations: NFSv3 server Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index ed6e2c2..78b2c83 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -122,7 +122,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, /* * XDR decode functions */ -static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, +static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclargs *args) { if (!(p = nfs3svc_decode_fh(p, &args->fh))) @@ -133,7 +133,7 @@ static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, } -static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, +static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_setaclargs *args) { struct kvec *head = rqstp->rq_arg.head; @@ -163,7 +163,7 @@ static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, */ /* GETACL */ -static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, +static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclres *resp) { struct dentry *dentry = resp->fh.fh_dentry; @@ -208,7 +208,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, } /* SETACL */ -static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p, +static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); @@ -219,7 +219,7 @@ static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p, /* * XDR release functions */ -static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p, +static int nfs3svc_release_getacl(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_getaclres *resp) { fh_put(&resp->fh); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 247d518..b4baca3 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -42,23 +42,23 @@ static u32 nfs3_ftypes[] = { /* * XDR functions for basic NFS types */ -static inline u32 * -encode_time3(u32 *p, struct timespec *time) +static inline __be32 * +encode_time3(__be32 *p, struct timespec *time) { *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); return p; } -static inline u32 * -decode_time3(u32 *p, struct timespec *time) +static inline __be32 * +decode_time3(__be32 *p, struct timespec *time) { time->tv_sec = ntohl(*p++); time->tv_nsec = ntohl(*p++); return p; } -static inline u32 * -decode_fh(u32 *p, struct svc_fh *fhp) +static inline __be32 * +decode_fh(__be32 *p, struct svc_fh *fhp) { unsigned int size; fh_init(fhp, NFS3_FHSIZE); @@ -72,13 +72,13 @@ decode_fh(u32 *p, struct svc_fh *fhp) } /* Helper function for NFSv3 ACL code */ -u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp) +__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp) { return decode_fh(p, fhp); } -static inline u32 * -encode_fh(u32 *p, struct svc_fh *fhp) +static inline __be32 * +encode_fh(__be32 *p, struct svc_fh *fhp) { unsigned int size = fhp->fh_handle.fh_size; *p++ = htonl(size); @@ -91,8 +91,8 @@ encode_fh(u32 *p, struct svc_fh *fhp) * Decode a file name and make sure that the path contains * no slashes or null bytes. */ -static inline u32 * -decode_filename(u32 *p, char **namp, int *lenp) +static inline __be32 * +decode_filename(__be32 *p, char **namp, int *lenp) { char *name; int i; @@ -107,8 +107,8 @@ decode_filename(u32 *p, char **namp, int *lenp) return p; } -static inline u32 * -decode_sattr3(u32 *p, struct iattr *iap) +static inline __be32 * +decode_sattr3(__be32 *p, struct iattr *iap) { u32 tmp; @@ -153,8 +153,8 @@ decode_sattr3(u32 *p, struct iattr *iap) return p; } -static inline u32 * -encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, +static inline __be32 * +encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat) { struct dentry *dentry = fhp->fh_dentry; @@ -186,8 +186,8 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, return p; } -static inline u32 * -encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) +static inline __be32 * +encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct inode *inode = fhp->fh_dentry->d_inode; @@ -224,8 +224,8 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) * The inode may be NULL if the call failed because of a stale file * handle. In this case, no attributes are returned. */ -static u32 * -encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) +static __be32 * +encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct dentry *dentry = fhp->fh_dentry; if (dentry && dentry->d_inode != NULL) { @@ -243,8 +243,8 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) } /* Helper for NFSv3 ACLs */ -u32 * -nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) +__be32 * +nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { return encode_post_op_attr(rqstp, p, fhp); } @@ -252,8 +252,8 @@ nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) /* * Enocde weak cache consistency data */ -static u32 * -encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) +static __be32 * +encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct dentry *dentry = fhp->fh_dentry; @@ -278,7 +278,7 @@ encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) * XDR decode functions */ int -nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args) +nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) { if (!(p = decode_fh(p, &args->fh))) return 0; @@ -286,7 +286,7 @@ nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args } int -nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_sattrargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -303,7 +303,7 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_diropargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -314,7 +314,7 @@ nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_accessargs *args) { if (!(p = decode_fh(p, &args->fh))) @@ -325,7 +325,7 @@ nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readargs *args) { unsigned int len; @@ -355,7 +355,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_writeargs *args) { unsigned int len, v, hdr; @@ -393,7 +393,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_createargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -417,7 +417,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p, return xdr_argsize_check(rqstp, p); } int -nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_createargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -429,7 +429,7 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_symlinkargs *args) { unsigned int len; @@ -481,7 +481,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_mknodargs *args) { if (!(p = decode_fh(p, &args->fh)) @@ -505,7 +505,7 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_renameargs *args) { if (!(p = decode_fh(p, &args->ffh)) @@ -518,7 +518,7 @@ nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readlinkargs *args) { if (!(p = decode_fh(p, &args->fh))) @@ -530,7 +530,7 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_linkargs *args) { if (!(p = decode_fh(p, &args->ffh)) @@ -542,7 +542,7 @@ nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readdirargs *args) { if (!(p = decode_fh(p, &args->fh))) @@ -562,7 +562,7 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readdirargs *args) { int len, pn; @@ -590,7 +590,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p, +nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_commitargs *args) { if (!(p = decode_fh(p, &args->fh))) @@ -609,14 +609,14 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p, * will work properly. */ int -nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy) +nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } /* GETATTR */ int -nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { if (resp->status == 0) @@ -626,7 +626,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, /* SETATTR, REMOVE, RMDIR */ int -nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { p = encode_wcc_data(rqstp, p, &resp->fh); @@ -635,7 +635,7 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p, /* LOOKUP */ int -nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_diropres *resp) { if (resp->status == 0) { @@ -648,7 +648,7 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p, /* ACCESS */ int -nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_accessres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -659,7 +659,7 @@ nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p, /* READLINK */ int -nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readlinkres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -680,7 +680,7 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, /* READ */ int -nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -704,7 +704,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p, /* WRITE */ int -nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_writeres *resp) { p = encode_wcc_data(rqstp, p, &resp->fh); @@ -719,7 +719,7 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p, /* CREATE, MKDIR, SYMLINK, MKNOD */ int -nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_diropres *resp) { if (resp->status == 0) { @@ -733,7 +733,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p, /* RENAME */ int -nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_renameres *resp) { p = encode_wcc_data(rqstp, p, &resp->ffh); @@ -743,7 +743,7 @@ nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p, /* LINK */ int -nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_linkres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -753,7 +753,7 @@ nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p, /* READDIR */ int -nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_readdirres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -776,8 +776,8 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, return xdr_ressize_check(rqstp, p); } -static inline u32 * -encode_entry_baggage(struct nfsd3_readdirres *cd, u32 *p, const char *name, +static inline __be32 * +encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, ino_t ino) { *p++ = xdr_one; /* mark entry present */ @@ -790,8 +790,8 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, u32 *p, const char *name, return p; } -static inline u32 * -encode_entryplus_baggage(struct nfsd3_readdirres *cd, u32 *p, +static inline __be32 * +encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, struct svc_fh *fhp) { p = encode_post_op_attr(cd->rqstp, p, fhp); @@ -853,7 +853,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, { struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, common); - u32 *p = cd->buffer; + __be32 *p = cd->buffer; caddr_t curr_page_addr = NULL; int pn; /* current page number */ int slen; /* string (name) length */ @@ -919,7 +919,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, } else if (cd->rqstp->rq_respages[pn+1] != NULL) { /* temporarily encode entry into next page, then move back to * current and next page in rq_respages[] */ - u32 *p1, *tmp; + __be32 *p1, *tmp; int len1, len2; /* grab next page for temporary storage of entry */ @@ -1009,7 +1009,7 @@ nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name, /* FSSTAT */ int -nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_fsstatres *resp) { struct kstatfs *s = &resp->stats; @@ -1031,7 +1031,7 @@ nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p, /* FSINFO */ int -nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_fsinfores *resp) { *p++ = xdr_zero; /* no post_op_attr */ @@ -1055,7 +1055,7 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p, /* PATHCONF */ int -nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_pathconfres *resp) { *p++ = xdr_zero; /* no post_op_attr */ @@ -1074,7 +1074,7 @@ nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p, /* COMMIT */ int -nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p, +nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_commitres *resp) { p = encode_wcc_data(rqstp, p, &resp->fh); @@ -1090,7 +1090,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p, * XDR release functions */ int -nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p, +nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { fh_put(&resp->fh); @@ -1098,7 +1098,7 @@ nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p, } int -nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p, +nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_fhandle_pair *resp) { fh_put(&resp->fh1); diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h index 474d882..7996386 100644 --- a/include/linux/nfsd/xdr3.h +++ b/include/linux/nfsd/xdr3.h @@ -51,7 +51,7 @@ struct nfsd3_createargs { int len; int createmode; struct iattr attrs; - __u32 * verf; + __be32 * verf; }; struct nfsd3_mknodargs { @@ -98,8 +98,8 @@ struct nfsd3_readdirargs { __u64 cookie; __u32 dircount; __u32 count; - __u32 * verf; - u32 * buffer; + __be32 * verf; + __be32 * buffer; }; struct nfsd3_commitargs { @@ -122,79 +122,79 @@ struct nfsd3_setaclargs { }; struct nfsd3_attrstat { - __u32 status; + __be32 status; struct svc_fh fh; struct kstat stat; }; /* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */ struct nfsd3_diropres { - __u32 status; + __be32 status; struct svc_fh dirfh; struct svc_fh fh; }; struct nfsd3_accessres { - __u32 status; + __be32 status; struct svc_fh fh; __u32 access; }; struct nfsd3_readlinkres { - __u32 status; + __be32 status; struct svc_fh fh; __u32 len; }; struct nfsd3_readres { - __u32 status; + __be32 status; struct svc_fh fh; unsigned long count; int eof; }; struct nfsd3_writeres { - __u32 status; + __be32 status; struct svc_fh fh; unsigned long count; int committed; }; struct nfsd3_renameres { - __u32 status; + __be32 status; struct svc_fh ffh; struct svc_fh tfh; }; struct nfsd3_linkres { - __u32 status; + __be32 status; struct svc_fh tfh; struct svc_fh fh; }; struct nfsd3_readdirres { - __u32 status; + __be32 status; struct svc_fh fh; int count; - __u32 verf[2]; + __be32 verf[2]; struct readdir_cd common; - u32 * buffer; + __be32 * buffer; int buflen; - u32 * offset; - u32 * offset1; + __be32 * offset; + __be32 * offset1; struct svc_rqst * rqstp; }; struct nfsd3_fsstatres { - __u32 status; + __be32 status; struct kstatfs stats; __u32 invarsec; }; struct nfsd3_fsinfores { - __u32 status; + __be32 status; __u32 f_rtmax; __u32 f_rtpref; __u32 f_rtmult; @@ -207,7 +207,7 @@ struct nfsd3_fsinfores { }; struct nfsd3_pathconfres { - __u32 status; + __be32 status; __u32 p_link_max; __u32 p_name_max; __u32 p_no_trunc; @@ -217,12 +217,12 @@ struct nfsd3_pathconfres { }; struct nfsd3_commitres { - __u32 status; + __be32 status; struct svc_fh fh; }; struct nfsd3_getaclres { - __u32 status; + __be32 status; struct svc_fh fh; int mask; struct posix_acl *acl_access; @@ -266,70 +266,70 @@ union nfsd3_xdrstore { #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) -int nfs3svc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); -int nfs3svc_decode_sattrargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); +int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *, struct nfsd3_sattrargs *); -int nfs3svc_decode_diropargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *, struct nfsd3_diropargs *); -int nfs3svc_decode_accessargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_accessargs(struct svc_rqst *, __be32 *, struct nfsd3_accessargs *); -int nfs3svc_decode_readargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_readargs(struct svc_rqst *, __be32 *, struct nfsd3_readargs *); -int nfs3svc_decode_writeargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_writeargs(struct svc_rqst *, __be32 *, struct nfsd3_writeargs *); -int nfs3svc_decode_createargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_createargs(struct svc_rqst *, __be32 *, struct nfsd3_createargs *); -int nfs3svc_decode_mkdirargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_mkdirargs(struct svc_rqst *, __be32 *, struct nfsd3_createargs *); -int nfs3svc_decode_mknodargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_mknodargs(struct svc_rqst *, __be32 *, struct nfsd3_mknodargs *); -int nfs3svc_decode_renameargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_renameargs(struct svc_rqst *, __be32 *, struct nfsd3_renameargs *); -int nfs3svc_decode_readlinkargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_readlinkargs(struct svc_rqst *, __be32 *, struct nfsd3_readlinkargs *); -int nfs3svc_decode_linkargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_linkargs(struct svc_rqst *, __be32 *, struct nfsd3_linkargs *); -int nfs3svc_decode_symlinkargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *, struct nfsd3_symlinkargs *); -int nfs3svc_decode_readdirargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *, struct nfsd3_readdirargs *); -int nfs3svc_decode_readdirplusargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __be32 *, struct nfsd3_readdirargs *); -int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *, +int nfs3svc_decode_commitargs(struct svc_rqst *, __be32 *, struct nfsd3_commitargs *); -int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *); -int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *, +int nfs3svc_encode_voidres(struct svc_rqst *, __be32 *, void *); +int nfs3svc_encode_attrstat(struct svc_rqst *, __be32 *, struct nfsd3_attrstat *); -int nfs3svc_encode_wccstat(struct svc_rqst *, u32 *, +int nfs3svc_encode_wccstat(struct svc_rqst *, __be32 *, struct nfsd3_attrstat *); -int nfs3svc_encode_diropres(struct svc_rqst *, u32 *, +int nfs3svc_encode_diropres(struct svc_rqst *, __be32 *, struct nfsd3_diropres *); -int nfs3svc_encode_accessres(struct svc_rqst *, u32 *, +int nfs3svc_encode_accessres(struct svc_rqst *, __be32 *, struct nfsd3_accessres *); -int nfs3svc_encode_readlinkres(struct svc_rqst *, u32 *, +int nfs3svc_encode_readlinkres(struct svc_rqst *, __be32 *, struct nfsd3_readlinkres *); -int nfs3svc_encode_readres(struct svc_rqst *, u32 *, struct nfsd3_readres *); -int nfs3svc_encode_writeres(struct svc_rqst *, u32 *, struct nfsd3_writeres *); -int nfs3svc_encode_createres(struct svc_rqst *, u32 *, +int nfs3svc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd3_readres *); +int nfs3svc_encode_writeres(struct svc_rqst *, __be32 *, struct nfsd3_writeres *); +int nfs3svc_encode_createres(struct svc_rqst *, __be32 *, struct nfsd3_diropres *); -int nfs3svc_encode_renameres(struct svc_rqst *, u32 *, +int nfs3svc_encode_renameres(struct svc_rqst *, __be32 *, struct nfsd3_renameres *); -int nfs3svc_encode_linkres(struct svc_rqst *, u32 *, +int nfs3svc_encode_linkres(struct svc_rqst *, __be32 *, struct nfsd3_linkres *); -int nfs3svc_encode_readdirres(struct svc_rqst *, u32 *, +int nfs3svc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd3_readdirres *); -int nfs3svc_encode_fsstatres(struct svc_rqst *, u32 *, +int nfs3svc_encode_fsstatres(struct svc_rqst *, __be32 *, struct nfsd3_fsstatres *); -int nfs3svc_encode_fsinfores(struct svc_rqst *, u32 *, +int nfs3svc_encode_fsinfores(struct svc_rqst *, __be32 *, struct nfsd3_fsinfores *); -int nfs3svc_encode_pathconfres(struct svc_rqst *, u32 *, +int nfs3svc_encode_pathconfres(struct svc_rqst *, __be32 *, struct nfsd3_pathconfres *); -int nfs3svc_encode_commitres(struct svc_rqst *, u32 *, +int nfs3svc_encode_commitres(struct svc_rqst *, __be32 *, struct nfsd3_commitres *); -int nfs3svc_release_fhandle(struct svc_rqst *, u32 *, +int nfs3svc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd3_attrstat *); -int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *, +int nfs3svc_release_fhandle2(struct svc_rqst *, __be32 *, struct nfsd3_fhandle_pair *); int nfs3svc_encode_entry(struct readdir_cd *, const char *name, int namlen, loff_t offset, ino_t ino, @@ -338,9 +338,9 @@ int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int); /* Helper functions for NFSv3 ACL code */ -u32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, +__be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp); -u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp); +__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp); #endif /* _LINUX_NFSD_XDR3_H */ -- cgit v0.10.2 From 2ebbc012a9433a252be7ab4ce54e94bf7b21e506 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:58 -0700 Subject: [PATCH] xdr annotations: NFSv4 server Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 795ad6c5..ca64142 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -664,7 +664,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ static int nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) { - u32 *buf, *p; + __be32 *buf, *p; int count; int status; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 77be0c4..3419d99 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -94,7 +94,7 @@ check_filename(char *str, int len, int err) * consistent with the style used in NFSv2/v3... */ #define DECODE_HEAD \ - u32 *p; \ + __be32 *p; \ int status #define DECODE_TAIL \ status = 0; \ @@ -144,13 +144,13 @@ xdr_error: \ } \ } while (0) -static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) +static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) { /* We want more bytes than seem to be available. * Maybe we need a new page, maybe we have just run out */ int avail = (char*)argp->end - (char*)argp->p; - u32 *p; + __be32 *p; if (avail + argp->pagelen < nbytes) return NULL; if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ @@ -197,7 +197,7 @@ defer_free(struct nfsd4_compoundargs *argp, return 0; } -static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) +static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) { void *new = NULL; if (p == argp->tmp) { @@ -951,8 +951,8 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) argp->pagelen -= len; } } - argp->end = (u32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); - argp->p = (u32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); + argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); + argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); argp->rqstp->rq_vec[v].iov_len = len; write->wr_vlen = v+1; @@ -1179,7 +1179,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) * task to translate them into Linux-specific versions which are more * consistent with the style used in NFSv2/v3... */ -#define ENCODE_HEAD u32 *p +#define ENCODE_HEAD __be32 *p #define WRITE32(n) *p++ = htonl(n) #define WRITE64(n) do { \ @@ -1209,8 +1209,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) * Header routine to setup seqid operation replay cache */ #define ENCODE_SEQID_OP_HEAD \ - u32 *p; \ - u32 *save; \ + __be32 *p; \ + __be32 *save; \ \ save = resp->p; @@ -1235,10 +1235,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) * seperated @sep. */ static int nfsd4_encode_components(char sep, char *components, - u32 **pp, int *buflen) + __be32 **pp, int *buflen) { - u32 *p = *pp; - u32 *countp = p; + __be32 *p = *pp; + __be32 *countp = p; int strlen, count=0; char *str, *end; @@ -1272,10 +1272,10 @@ static int nfsd4_encode_components(char sep, char *components, * encode a location element of a fs_locations structure */ static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, - u32 **pp, int *buflen) + __be32 **pp, int *buflen) { int status; - u32 *p = *pp; + __be32 *p = *pp; status = nfsd4_encode_components(':', location->hosts, &p, buflen); if (status) @@ -1320,11 +1320,11 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, u32 *sta */ static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp, struct svc_export *exp, - u32 **pp, int *buflen) + __be32 **pp, int *buflen) { u32 status; int i; - u32 *p = *pp; + __be32 *p = *pp; struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; char *root = nfsd4_path(rqstp, exp, &status); @@ -1355,7 +1355,7 @@ static u32 nfs4_ftypes[16] = { static int nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, - u32 **p, int *buflen) + __be32 **p, int *buflen) { int status; @@ -1376,20 +1376,20 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, } static inline int -nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen) +nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen) { return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen); } static inline int -nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen) +nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen) { return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen); } static inline int nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, - u32 **p, int *buflen) + __be32 **p, int *buflen) { return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); } @@ -1423,7 +1423,7 @@ static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) */ int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, - struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval, + struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, struct svc_rqst *rqstp) { u32 bmval0 = bmval[0]; @@ -1432,11 +1432,11 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, struct svc_fh tempfh; struct kstatfs statfs; int buflen = *countp << 2; - u32 *attrlenp; + __be32 *attrlenp; u32 dummy; u64 dummy64; u32 rdattr_err = 0; - u32 *p = buffer; + __be32 *p = buffer; int status; int aclsupport = 0; struct nfs4_acl *acl = NULL; @@ -1831,7 +1831,7 @@ out_serverfault: static int nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, - const char *name, int namlen, u32 *p, int *buflen) + const char *name, int namlen, __be32 *p, int *buflen) { struct svc_export *exp = cd->rd_fhp->fh_export; struct dentry *dentry; @@ -1864,10 +1864,10 @@ out_put: return nfserr; } -static u32 * -nfsd4_encode_rdattr_error(u32 *p, int buflen, int nfserr) +static __be32 * +nfsd4_encode_rdattr_error(__be32 *p, int buflen, int nfserr) { - u32 *attrlenp; + __be32 *attrlenp; if (buflen < 6) return NULL; @@ -1887,7 +1887,7 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen, { struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); int buflen; - u32 *p = cd->buffer; + __be32 *p = cd->buffer; int nfserr = nfserr_toosmall; /* In nfsv4, "." and ".." never make it onto the wire.. */ @@ -2321,7 +2321,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re { int maxcount; loff_t offset; - u32 *page, *savep, *tailbase; + __be32 *page, *savep, *tailbase; ENCODE_HEAD; if (nfserr) @@ -2479,7 +2479,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_writ void nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) { - u32 *statp; + __be32 *statp; ENCODE_HEAD; RESERVE_SPACE(8); @@ -2617,7 +2617,7 @@ nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) */ int -nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy) +nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } @@ -2639,7 +2639,7 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) } int -nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args) +nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) { int status; @@ -2660,7 +2660,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoun } int -nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp) +nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp) { /* * All that remains is to write the tag and operation count... diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 66e6427..003193f 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -258,9 +258,9 @@ struct nfsd4_readdir { struct svc_fh * rd_fhp; /* response */ struct readdir_cd common; - u32 * buffer; + __be32 * buffer; int buflen; - u32 * offset; + __be32 * offset; }; struct nfsd4_release_lockowner { @@ -371,12 +371,12 @@ struct nfsd4_op { struct nfsd4_compoundargs { /* scratch variables for XDR decode */ - u32 * p; - u32 * end; + __be32 * p; + __be32 * end; struct page ** pagelist; int pagelen; - u32 tmp[8]; - u32 * tmpp; + __be32 tmp[8]; + __be32 * tmpp; struct tmpbuf { struct tmpbuf *next; void (*release)(const void *); @@ -395,15 +395,15 @@ struct nfsd4_compoundargs { struct nfsd4_compoundres { /* scratch variables for XDR encode */ - u32 * p; - u32 * end; + __be32 * p; + __be32 * end; struct xdr_buf * xbuf; struct svc_rqst * rqstp; u32 taglen; char * tag; u32 opcnt; - u32 * tagp; /* where to encode tag and opcount */ + __be32 * tagp; /* where to encode tag and opcount */ }; #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) @@ -419,10 +419,10 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; } -int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *); -int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *, +int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); +int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *, struct nfsd4_compoundargs *); -int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *, +int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *, struct nfsd4_compoundres *); void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); -- cgit v0.10.2 From 6264d69d7df654ca64f625e9409189a0e50734e9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:58 -0700 Subject: [PATCH] nfsd: vfs.c endianness annotations don't use the same variable to store NFS and host error values Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1141bd2..f21e917 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -110,7 +110,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, struct dentry *dentry = *dpp; struct vfsmount *mnt = mntget(exp->ex_mnt); struct dentry *mounts = dget(dentry); - int err = nfs_ok; + int err = 0; while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)); @@ -148,14 +148,15 @@ out: * clients and is explicitly disallowed for NFSv3 * NeilBrown */ -int +__be32 nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, int len, struct svc_fh *resfh) { struct svc_export *exp; struct dentry *dparent; struct dentry *dentry; - int err; + __be32 err; + int host_err; dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); @@ -193,7 +194,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, exp2 = exp_parent(exp->ex_client, mnt, dentry, &rqstp->rq_chandle); if (IS_ERR(exp2)) { - err = PTR_ERR(exp2); + host_err = PTR_ERR(exp2); dput(dentry); mntput(mnt); goto out_nfserr; @@ -210,14 +211,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, } else { fh_lock(fhp); dentry = lookup_one_len(name, dparent, len); - err = PTR_ERR(dentry); + host_err = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_nfserr; /* * check if we have crossed a mount point ... */ if (d_mountpoint(dentry)) { - if ((err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { + if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { dput(dentry); goto out_nfserr; } @@ -236,7 +237,7 @@ out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } @@ -244,7 +245,7 @@ out_nfserr: * Set various file attributes. * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, int check_guard, time_t guardtime) { @@ -253,7 +254,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, int accmode = MAY_SATTR; int ftype = 0; int imode; - int err; + __be32 err; + int host_err; int size_change = 0; if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) @@ -319,19 +321,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, * If we are changing the size of the file, then * we need to break all leases. */ - err = break_lease(inode, FMODE_WRITE | O_NONBLOCK); - if (err == -EWOULDBLOCK) - err = -ETIMEDOUT; - if (err) /* ENOMEM or EWOULDBLOCK */ + host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK); + if (host_err == -EWOULDBLOCK) + host_err = -ETIMEDOUT; + if (host_err) /* ENOMEM or EWOULDBLOCK */ goto out_nfserr; - err = get_write_access(inode); - if (err) + host_err = get_write_access(inode); + if (host_err) goto out_nfserr; size_change = 1; - err = locks_verify_truncate(inode, NULL, iap->ia_size); - if (err) { + host_err = locks_verify_truncate(inode, NULL, iap->ia_size); + if (host_err) { put_write_access(inode); goto out_nfserr; } @@ -357,8 +359,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime.tv_sec) { fh_lock(fhp); - err = notify_change(dentry, iap); - err = nfserrno(err); + host_err = notify_change(dentry, iap); + err = nfserrno(host_err); fh_unlock(fhp); } if (size_change) @@ -370,7 +372,7 @@ out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } @@ -420,11 +422,12 @@ out: return error; } -int +__be32 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfs4_acl *acl) { - int error; + __be32 error; + int host_error; struct dentry *dentry; struct inode *inode; struct posix_acl *pacl = NULL, *dpacl = NULL; @@ -440,20 +443,20 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, if (S_ISDIR(inode->i_mode)) flags = NFS4_ACL_DIR; - error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); - if (error == -EINVAL) { + host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); + if (host_error == -EINVAL) { error = nfserr_attrnotsupp; goto out; - } else if (error < 0) + } else if (host_error < 0) goto out_nfserr; - error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); - if (error < 0) + host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); + if (host_error < 0) goto out_nfserr; if (S_ISDIR(inode->i_mode)) { - error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); - if (error < 0) + host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); + if (host_error < 0) goto out_nfserr; } @@ -464,7 +467,7 @@ out: posix_acl_release(dpacl); return (error); out_nfserr: - error = nfserrno(error); + error = nfserrno(host_error); goto out; } @@ -571,14 +574,14 @@ static struct accessmap nfs3_anyaccess[] = { { 0, 0 } }; -int +__be32 nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported) { struct accessmap *map; struct svc_export *export; struct dentry *dentry; u32 query, result = 0, sresult = 0; - unsigned int error; + __be32 error; error = fh_verify(rqstp, fhp, 0, MAY_NOP); if (error) @@ -598,7 +601,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor query = *access; for (; map->access; map++) { if (map->access & query) { - unsigned int err2; + __be32 err2; sresult |= map->access; @@ -637,13 +640,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor * The access argument indicates the type of open (read/write/lock) * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access, struct file **filp) { struct dentry *dentry; struct inode *inode; - int flags = O_RDONLY|O_LARGEFILE, err; + int flags = O_RDONLY|O_LARGEFILE; + __be32 err; + int host_err; /* * If we get here, then the client has already done an "open", @@ -673,10 +678,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, * Check to see if there are any leases on this file. * This may block while leases are broken. */ - err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0)); - if (err == -EWOULDBLOCK) - err = -ETIMEDOUT; - if (err) /* NOMEM or WOULDBLOCK */ + host_err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0)); + if (host_err == -EWOULDBLOCK) + host_err = -ETIMEDOUT; + if (host_err) /* NOMEM or WOULDBLOCK */ goto out_nfserr; if (access & MAY_WRITE) { @@ -689,10 +694,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, } *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags); if (IS_ERR(*filp)) - err = PTR_ERR(*filp); + host_err = PTR_ERR(*filp); out_nfserr: - if (err) - err = nfserrno(err); + err = nfserrno(host_err); out: return err; } @@ -830,14 +834,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset return size; } -static int +static __be32 nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long *count) { struct inode *inode; struct raparms *ra; mm_segment_t oldfs; - int err; + __be32 err; + int host_err; err = nfserr_perm; inode = file->f_dentry->d_inode; @@ -855,12 +860,12 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { rqstp->rq_resused = 1; - err = file->f_op->sendfile(file, &offset, *count, + host_err = file->f_op->sendfile(file, &offset, *count, nfsd_read_actor, rqstp); } else { oldfs = get_fs(); set_fs(KERNEL_DS); - err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); + host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); set_fs(oldfs); } @@ -874,13 +879,13 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, spin_unlock(&rab->pb_lock); } - if (err >= 0) { - nfsdstats.io_read += err; - *count = err; + if (host_err >= 0) { + nfsdstats.io_read += host_err; + *count = host_err; err = 0; fsnotify_access(file->f_dentry); } else - err = nfserrno(err); + err = nfserrno(host_err); out: return err; } @@ -895,7 +900,7 @@ static void kill_suid(struct dentry *dentry) mutex_unlock(&dentry->d_inode->i_mutex); } -static int +static __be32 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long cnt, int *stablep) @@ -904,7 +909,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, struct dentry *dentry; struct inode *inode; mm_segment_t oldfs; - int err = 0; + __be32 err = 0; + int host_err; int stable = *stablep; #ifdef MSNFS @@ -940,18 +946,18 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); - err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset); + host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset); set_fs(oldfs); - if (err >= 0) { + if (host_err >= 0) { nfsdstats.io_write += cnt; fsnotify_modify(file->f_dentry); } /* clear setuid/setgid flag after write */ - if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) + if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) kill_suid(dentry); - if (err >= 0 && stable) { + if (host_err >= 0 && stable) { static ino_t last_ino; static dev_t last_dev; @@ -977,7 +983,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (inode->i_state & I_DIRTY) { dprintk("nfsd: write sync %d\n", current->pid); - err=nfsd_sync(file); + host_err=nfsd_sync(file); } #if 0 wake_up(&inode->i_wait); @@ -987,11 +993,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, last_dev = inode->i_sb->s_dev; } - dprintk("nfsd: write complete err=%d\n", err); - if (err >= 0) + dprintk("nfsd: write complete host_err=%d\n", host_err); + if (host_err >= 0) err = 0; else - err = nfserrno(err); + err = nfserrno(host_err); out: return err; } @@ -1001,12 +1007,12 @@ out: * on entry. On return, *count contains the number of bytes actually read. * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long *count) { - int err; + __be32 err; if (file) { err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, @@ -1030,12 +1036,12 @@ out: * The stable flag requests synchronous writes. * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long cnt, int *stablep) { - int err = 0; + __be32 err = 0; if (file) { err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, @@ -1067,12 +1073,12 @@ out: * Unfortunately we cannot lock the file to make sure we return full WCC * data to the client, as locking happens lower down in the filesystem. */ -int +__be32 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, unsigned long count) { struct file *file; - int err; + __be32 err; if ((u64)count > ~(u64)offset) return nfserr_inval; @@ -1100,14 +1106,15 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, * * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp */ -int +__be32 nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, char *fname, int flen, struct iattr *iap, int type, dev_t rdev, struct svc_fh *resfhp) { struct dentry *dentry, *dchild = NULL; struct inode *dirp; - int err; + __be32 err; + int host_err; err = nfserr_perm; if (!flen) @@ -1134,7 +1141,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ fh_lock_nested(fhp, I_MUTEX_PARENT); dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); + host_err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); @@ -1173,22 +1180,22 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, err = nfserr_perm; switch (type) { case S_IFREG: - err = vfs_create(dirp, dchild, iap->ia_mode, NULL); + host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); break; case S_IFDIR: - err = vfs_mkdir(dirp, dchild, iap->ia_mode); + host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); break; case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); + host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: printk("nfsd: bad file type %o in nfsd_create\n", type); - err = -EINVAL; + host_err = -EINVAL; } - if (err < 0) + if (host_err < 0) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) { @@ -1203,7 +1210,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, * directories via NFS. */ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { - int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); if (err2) err = err2; } @@ -1218,7 +1225,7 @@ out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } @@ -1226,7 +1233,7 @@ out_nfserr: /* * NFSv3 version of nfsd_create */ -int +__be32 nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, char *fname, int flen, struct iattr *iap, struct svc_fh *resfhp, int createmode, u32 *verifier, @@ -1234,7 +1241,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, { struct dentry *dentry, *dchild = NULL; struct inode *dirp; - int err; + __be32 err; + int host_err; __u32 v_mtime=0, v_atime=0; int v_mode=0; @@ -1264,7 +1272,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, * Compose the response file handle. */ dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); + host_err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; @@ -1320,8 +1328,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; } - err = vfs_create(dirp, dchild, iap->ia_mode, NULL); - if (err < 0) + host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); + if (host_err < 0) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) { @@ -1350,7 +1358,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, */ set_attr: if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { - int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); if (err2) err = err2; } @@ -1368,7 +1376,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } #endif /* CONFIG_NFSD_V3 */ @@ -1378,13 +1386,14 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, * fits into the buffer. On return, it contains the true length. * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) { struct dentry *dentry; struct inode *inode; mm_segment_t oldfs; - int err; + __be32 err; + int host_err; err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP); if (err) @@ -1403,18 +1412,18 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) */ oldfs = get_fs(); set_fs(KERNEL_DS); - err = inode->i_op->readlink(dentry, buf, *lenp); + host_err = inode->i_op->readlink(dentry, buf, *lenp); set_fs(oldfs); - if (err < 0) + if (host_err < 0) goto out_nfserr; - *lenp = err; + *lenp = host_err; err = 0; out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } @@ -1422,7 +1431,7 @@ out_nfserr: * Create a symlink and look up its inode * N.B. After this call _both_ fhp and resfhp need an fh_put */ -int +__be32 nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *fname, int flen, char *path, int plen, @@ -1430,7 +1439,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap) { struct dentry *dentry, *dnew; - int err, cerr; + __be32 err, cerr; + int host_err; umode_t mode; err = nfserr_noent; @@ -1446,7 +1456,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, fh_lock(fhp); dentry = fhp->fh_dentry; dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); + host_err = PTR_ERR(dnew); if (IS_ERR(dnew)) goto out_nfserr; @@ -1458,21 +1468,21 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, if (unlikely(path[plen] != 0)) { char *path_alloced = kmalloc(plen+1, GFP_KERNEL); if (path_alloced == NULL) - err = -ENOMEM; + host_err = -ENOMEM; else { strncpy(path_alloced, path, plen); path_alloced[plen] = 0; - err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode); + host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode); kfree(path_alloced); } } else - err = vfs_symlink(dentry->d_inode, dnew, path, mode); + host_err = vfs_symlink(dentry->d_inode, dnew, path, mode); - if (!err) + if (!host_err) { if (EX_ISSYNC(fhp->fh_export)) - err = nfsd_sync_dir(dentry); - if (err) - err = nfserrno(err); + host_err = nfsd_sync_dir(dentry); + } + err = nfserrno(host_err); fh_unlock(fhp); cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); @@ -1482,7 +1492,7 @@ out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out; } @@ -1490,13 +1500,14 @@ out_nfserr: * Create a hardlink * N.B. After this call _both_ ffhp and tfhp need an fh_put */ -int +__be32 nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *name, int len, struct svc_fh *tfhp) { struct dentry *ddir, *dnew, *dold; struct inode *dirp, *dest; - int err; + __be32 err; + int host_err; err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE); if (err) @@ -1517,24 +1528,25 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, dirp = ddir->d_inode; dnew = lookup_one_len(name, ddir, len); - err = PTR_ERR(dnew); + host_err = PTR_ERR(dnew); if (IS_ERR(dnew)) goto out_nfserr; dold = tfhp->fh_dentry; dest = dold->d_inode; - err = vfs_link(dold, dirp, dnew); - if (!err) { + host_err = vfs_link(dold, dirp, dnew); + if (!host_err) { if (EX_ISSYNC(ffhp->fh_export)) { err = nfserrno(nfsd_sync_dir(ddir)); write_inode_now(dest, 1); } + err = 0; } else { - if (err == -EXDEV && rqstp->rq_vers == 2) + if (host_err == -EXDEV && rqstp->rq_vers == 2) err = nfserr_acces; else - err = nfserrno(err); + err = nfserrno(host_err); } dput(dnew); @@ -1544,7 +1556,7 @@ out: return err; out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); goto out_unlock; } @@ -1552,13 +1564,14 @@ out_nfserr: * Rename a file * N.B. After this call _both_ ffhp and tfhp need an fh_put */ -int +__be32 nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, struct svc_fh *tfhp, char *tname, int tlen) { struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap; struct inode *fdir, *tdir; - int err; + __be32 err; + int host_err; err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE); if (err) @@ -1589,22 +1602,22 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, fill_pre_wcc(tfhp); odentry = lookup_one_len(fname, fdentry, flen); - err = PTR_ERR(odentry); + host_err = PTR_ERR(odentry); if (IS_ERR(odentry)) goto out_nfserr; - err = -ENOENT; + host_err = -ENOENT; if (!odentry->d_inode) goto out_dput_old; - err = -EINVAL; + host_err = -EINVAL; if (odentry == trap) goto out_dput_old; ndentry = lookup_one_len(tname, tdentry, tlen); - err = PTR_ERR(ndentry); + host_err = PTR_ERR(ndentry); if (IS_ERR(ndentry)) goto out_dput_old; - err = -ENOTEMPTY; + host_err = -ENOTEMPTY; if (ndentry == trap) goto out_dput_new; @@ -1612,14 +1625,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && ((atomic_read(&odentry->d_count) > 1) || (atomic_read(&ndentry->d_count) > 1))) { - err = -EPERM; + host_err = -EPERM; } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - err = nfsd_sync_dir(tdentry); - if (!err) - err = nfsd_sync_dir(fdentry); + host_err = vfs_rename(fdir, odentry, tdir, ndentry); + if (!host_err && EX_ISSYNC(tfhp->fh_export)) { + host_err = nfsd_sync_dir(tdentry); + if (!host_err) + host_err = nfsd_sync_dir(fdentry); } out_dput_new: @@ -1627,8 +1640,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, out_dput_old: dput(odentry); out_nfserr: - if (err) - err = nfserrno(err); + err = nfserrno(host_err); /* we cannot reply on fh_unlock on the two filehandles, * as that would do the wrong thing if the two directories @@ -1647,13 +1659,14 @@ out: * Unlink a file or directory * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, char *fname, int flen) { struct dentry *dentry, *rdentry; struct inode *dirp; - int err; + __be32 err; + int host_err; err = nfserr_acces; if (!flen || isdotent(fname, flen)) @@ -1667,7 +1680,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, dirp = dentry->d_inode; rdentry = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(rdentry); + host_err = PTR_ERR(rdentry); if (IS_ERR(rdentry)) goto out_nfserr; @@ -1684,22 +1697,23 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, #ifdef MSNFS if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && (atomic_read(&rdentry->d_count) > 1)) { - err = -EPERM; + host_err = -EPERM; } else #endif - err = vfs_unlink(dirp, rdentry); + host_err = vfs_unlink(dirp, rdentry); } else { /* It's RMDIR */ - err = vfs_rmdir(dirp, rdentry); + host_err = vfs_rmdir(dirp, rdentry); } dput(rdentry); - if (err == 0 && - EX_ISSYNC(fhp->fh_export)) - err = nfsd_sync_dir(dentry); + if (host_err) + goto out_nfserr; + if (EX_ISSYNC(fhp->fh_export)) + host_err = nfsd_sync_dir(dentry); out_nfserr: - err = nfserrno(err); + err = nfserrno(host_err); out: return err; } @@ -1708,11 +1722,12 @@ out: * Read entries from a directory. * The NFSv3/4 verifier we ignore for now. */ -int +__be32 nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, struct readdir_cd *cdp, encode_dent_fn func) { - int err; + __be32 err; + int host_err; struct file *file; loff_t offset = *offsetp; @@ -1734,10 +1749,10 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, do { cdp->err = nfserr_eof; /* will be cleared on successful read */ - err = vfs_readdir(file, (filldir_t) func, cdp); - } while (err >=0 && cdp->err == nfs_ok); - if (err) - err = nfserrno(err); + host_err = vfs_readdir(file, (filldir_t) func, cdp); + } while (host_err >=0 && cdp->err == nfs_ok); + if (host_err) + err = nfserrno(host_err); else err = cdp->err; *offsetp = vfs_llseek(file, 0, 1); @@ -1754,10 +1769,10 @@ out: * Get file system stats * N.B. After this call fhp needs an fh_put */ -int +__be32 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) { - int err = fh_verify(rqstp, fhp, 0, MAY_NOP); + __be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP); if (!err && vfs_statfs(fhp->fh_dentry,stat)) err = nfserr_io; return err; @@ -1766,7 +1781,7 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) /* * Check for a user's access permissions to this inode. */ -int +__be32 nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) { struct inode *inode = dentry->d_inode; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 2f75160..19a3c83 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -72,57 +72,57 @@ int nfsd_racache_init(int); void nfsd_racache_shutdown(void); int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, struct svc_export **expp); -int nfsd_lookup(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, const char *, int, struct svc_fh *); -int nfsd_setattr(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, struct iattr *, int, time_t); #ifdef CONFIG_NFSD_V4 -int nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, +__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, struct nfs4_acl *); int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); #endif /* CONFIG_NFSD_V4 */ -int nfsd_create(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_create(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, int type, dev_t rdev, struct svc_fh *res); #ifdef CONFIG_NFSD_V3 -int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); -int nfsd_create_v3(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); +__be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, struct svc_fh *res, int createmode, u32 *verifier, int *truncp); -int nfsd_commit(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, loff_t, unsigned long); #endif /* CONFIG_NFSD_V3 */ -int nfsd_open(struct svc_rqst *, struct svc_fh *, int, +__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int, int, struct file **); void nfsd_close(struct file *); -int nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, +__be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, loff_t, struct kvec *, int, unsigned long *); -int nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, +__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, loff_t, struct kvec *,int, unsigned long, int *); -int nfsd_readlink(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *, char *, int *); -int nfsd_symlink(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *, char *name, int len, char *path, int plen, struct svc_fh *res, struct iattr *); -int nfsd_link(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_link(struct svc_rqst *, struct svc_fh *, char *, int, struct svc_fh *); -int nfsd_rename(struct svc_rqst *, +__be32 nfsd_rename(struct svc_rqst *, struct svc_fh *, char *, int, struct svc_fh *, char *, int); -int nfsd_remove(struct svc_rqst *, +__be32 nfsd_remove(struct svc_rqst *, struct svc_fh *, char *, int); -int nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, +__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, char *name, int len); int nfsd_truncate(struct svc_rqst *, struct svc_fh *, unsigned long size); -int nfsd_readdir(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, loff_t *, struct readdir_cd *, encode_dent_fn); -int nfsd_statfs(struct svc_rqst *, struct svc_fh *, +__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, struct kstatfs *); int nfsd_notify_change(struct inode *, struct iattr *); -int nfsd_permission(struct svc_export *, struct dentry *, int); +__be32 nfsd_permission(struct svc_export *, struct dentry *, int); int nfsd_sync_dir(struct dentry *dp); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -- cgit v0.10.2 From b37ad28bcaa7c486a4ff0fb6c3bdaaacd67b86ce Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:28:59 -0700 Subject: [PATCH] nfsd: nfs4 code returns error values in net-endian Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index ca64142..6382394 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -67,10 +67,10 @@ fh_dup2(struct svc_fh *dst, struct svc_fh *src) *dst = *src; } -static int +static __be32 do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode) { - int status; + __be32 status; if (open->op_truncate && !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) @@ -88,11 +88,11 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs return status; } -static int +static __be32 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { struct svc_fh resfh; - int status; + __be32 status; fh_init(&resfh, NFS4_FHSIZE); open->op_truncate = 0; @@ -131,10 +131,10 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o return status; } -static int +static __be32 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { - int status; + __be32 status; /* Only reclaims from previously confirmed clients are valid */ if ((status = nfs4_check_open_reclaim(&open->op_clientid))) @@ -161,10 +161,10 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ } -static inline int +static inline __be32 nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) { - int status; + __be32 status; dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", (int)open->op_fname.len, open->op_fname.data, open->op_stateowner); @@ -261,7 +261,7 @@ out: /* * filehandle-manipulating ops. */ -static inline int +static inline __be32 nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) { if (!current_fh->fh_dentry) @@ -271,7 +271,7 @@ nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) return nfs_ok; } -static inline int +static inline __be32 nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) { fh_put(current_fh); @@ -280,10 +280,10 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putf return fh_verify(rqstp, current_fh, 0, MAY_NOP); } -static inline int +static inline __be32 nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) { - int status; + __be32 status; fh_put(current_fh); status = exp_pseudoroot(rqstp->rq_client, current_fh, @@ -291,7 +291,7 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) return status; } -static inline int +static inline __be32 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) { if (!save_fh->fh_dentry) @@ -301,7 +301,7 @@ nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) return nfs_ok; } -static inline int +static inline __be32 nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) { if (!current_fh->fh_dentry) @@ -314,7 +314,7 @@ nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) /* * misc nfsv4 ops */ -static inline int +static inline __be32 nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) { if (access->ac_req_access & ~NFS3_ACCESS_FULL) @@ -324,10 +324,10 @@ nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_acc return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported); } -static inline int +static inline __be32 nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) { - int status; + __be32 status; u32 *p = (u32 *)commit->co_verf.data; *p++ = nfssvc_boot.tv_sec; @@ -339,11 +339,11 @@ nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_com return status; } -static int +static __be32 nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) { struct svc_fh resfh; - int status; + __be32 status; dev_t rdev; fh_init(&resfh, NFS4_FHSIZE); @@ -423,10 +423,10 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre return status; } -static inline int +static inline __be32 nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) { - int status; + __be32 status; status = fh_verify(rqstp, current_fh, 0, MAY_NOP); if (status) @@ -442,11 +442,11 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ge return nfs_ok; } -static inline int +static inline __be32 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct svc_fh *save_fh, struct nfsd4_link *link) { - int status = nfserr_nofilehandle; + __be32 status = nfserr_nofilehandle; if (!save_fh->fh_dentry) return status; @@ -456,11 +456,11 @@ nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, return status; } -static int +static __be32 nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) { struct svc_fh tmp_fh; - int ret; + __be32 ret; fh_init(&tmp_fh, NFS4_FHSIZE); if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh, @@ -474,16 +474,16 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh); } -static inline int +static inline __be32 nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) { return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh); } -static inline int +static inline __be32 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) { - int status; + __be32 status; /* no need to check permission - this will be done in nfsd_read() */ @@ -508,7 +508,7 @@ out: return status; } -static inline int +static inline __be32 nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) { u64 cookie = readdir->rd_cookie; @@ -531,7 +531,7 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_re return nfs_ok; } -static inline int +static inline __be32 nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) { readlink->rl_rqstp = rqstp; @@ -539,10 +539,10 @@ nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_r return nfs_ok; } -static inline int +static inline __be32 nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) { - int status; + __be32 status; if (nfs4_in_grace()) return nfserr_grace; @@ -556,11 +556,11 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem return status; } -static inline int +static inline __be32 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct svc_fh *save_fh, struct nfsd4_rename *rename) { - int status = nfserr_nofilehandle; + __be32 status = nfserr_nofilehandle; if (!save_fh->fh_dentry) return status; @@ -589,10 +589,10 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, return status; } -static inline int +static inline __be32 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) { - int status = nfs_ok; + __be32 status = nfs_ok; if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { nfs4_lock_state(); @@ -614,13 +614,13 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se return status; } -static inline int +static inline __be32 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) { stateid_t *stateid = &write->wr_stateid; struct file *filp = NULL; u32 *p; - int status = nfs_ok; + __be32 status = nfs_ok; /* no need to check permission - this will be done in nfsd_write() */ @@ -661,12 +661,12 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ * attributes matched. VERIFY is implemented by mapping NFSERR_SAME * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. */ -static int +static __be32 nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) { __be32 *buf, *p; int count; - int status; + __be32 status; status = fh_verify(rqstp, current_fh, 0, MAY_NOP); if (status) @@ -741,7 +741,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, struct svc_fh *save_fh = NULL; struct nfs4_stateowner *replay_owner = NULL; int slack_space; /* in words, not bytes! */ - int status; + __be32 status; status = nfserr_resource; current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL); diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 1cbd2e4..e9d0770 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -83,13 +83,13 @@ md5_to_hex(char *out, char *md5) *out = '\0'; } -int +__be32 nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) { struct xdr_netobj cksum; struct hash_desc desc; struct scatterlist sg[1]; - int status = nfserr_resource; + __be32 status = nfserr_resource; dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", clname->len, clname->data); @@ -193,7 +193,7 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen, struct dentry_list *child; if (name && isdotent(name, namlen)) - return nfs_ok; + return 0; dentry = lookup_one_len(name, parent, namlen); if (IS_ERR(dentry)) return PTR_ERR(dentry); @@ -333,14 +333,14 @@ purge_old(struct dentry *parent, struct dentry *child) int status; if (nfs4_has_reclaimed_state(child->d_name.name)) - return nfs_ok; + return 0; status = nfsd4_clear_clid_dir(parent, child); if (status) printk("failed to remove client recovery directory %s\n", child->d_name.name); /* Keep trying, success or failure: */ - return nfs_ok; + return 0; } void @@ -365,10 +365,10 @@ load_recdir(struct dentry *parent, struct dentry *child) printk("nfsd4: illegal name %s in recovery directory\n", child->d_name.name); /* Keep trying; maybe the others are OK: */ - return nfs_ok; + return 0; } nfs4_client_to_reclaim(child->d_name.name); - return nfs_ok; + return 0; } int diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index ebcf226..e5ca6d7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -710,7 +710,7 @@ out_err: * as described above. * */ -int +__be32 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) { u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; @@ -721,7 +721,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) nfs4_verifier clverifier = setclid->se_verf; unsigned int strhashval; struct nfs4_client *conf, *unconf, *new; - int status; + __be32 status; char dname[HEXDIR_LEN]; if (!check_name(clname)) @@ -875,14 +875,14 @@ out: * * NOTE: callback information will be processed here in a future patch */ -int +__be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) { u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; struct nfs4_client *conf, *unconf; nfs4_verifier confirm = setclientid_confirm->sc_confirm; clientid_t * clid = &setclientid_confirm->sc_clientid; - int status; + __be32 status; if (STALE_CLIENTID(clid)) return nfserr_stale_clientid; @@ -1280,13 +1280,13 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) { * Called to check deny when READ with all zero stateid or * WRITE with all zero or all one stateid */ -static int +static __be32 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) { struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_file *fp; struct nfs4_stateid *stp; - int ret; + __be32 ret; dprintk("NFSD: nfs4_share_conflict\n"); @@ -1444,7 +1444,7 @@ static struct lock_manager_operations nfsd_lease_mng_ops = { }; -int +__be32 nfsd4_process_open1(struct nfsd4_open *open) { clientid_t *clientid = &open->op_clientid; @@ -1501,7 +1501,7 @@ renew: return nfs_ok; } -static inline int +static inline __be32 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) { if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ)) @@ -1522,12 +1522,12 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid) return NULL; } -static int +static __be32 nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_delegation **dp) { int flags; - int status = nfserr_bad_stateid; + __be32 status = nfserr_bad_stateid; *dp = find_delegation_file(fp, &open->op_delegate_stateid); if (*dp == NULL) @@ -1546,11 +1546,11 @@ out: return nfs_ok; } -static int +static __be32 nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) { struct nfs4_stateid *local; - int status = nfserr_share_denied; + __be32 status = nfserr_share_denied; struct nfs4_stateowner *sop = open->op_stateowner; list_for_each_entry(local, &fp->fi_stateids, st_perfile) { @@ -1575,7 +1575,7 @@ nfs4_alloc_stateid(void) return kmem_cache_alloc(stateid_slab, GFP_KERNEL); } -static int +static __be32 nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, struct nfs4_delegation *dp, struct svc_fh *cur_fh, int flags) @@ -1590,7 +1590,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, get_file(dp->dl_vfs_file); stp->st_vfs_file = dp->dl_vfs_file; } else { - int status; + __be32 status; status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file); if (status) { @@ -1604,7 +1604,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, return 0; } -static inline int +static inline __be32 nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, struct nfsd4_open *open) { @@ -1619,22 +1619,22 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); } -static int +static __be32 nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) { struct file *filp = stp->st_vfs_file; struct inode *inode = filp->f_dentry->d_inode; unsigned int share_access, new_writer; - int status; + __be32 status; set_access(&share_access, stp->st_access_bmap); new_writer = (~share_access) & open->op_share_access & NFS4_SHARE_ACCESS_WRITE; if (new_writer) { - status = get_write_access(inode); - if (status) - return nfserrno(status); + int err = get_write_access(inode); + if (err) + return nfserrno(err); } status = nfsd4_truncate(rqstp, cur_fh, open); if (status) { @@ -1738,14 +1738,14 @@ out: /* * called with nfs4_lock_state() held. */ -int +__be32 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { struct nfs4_file *fp = NULL; struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_stateid *stp = NULL; struct nfs4_delegation *dp = NULL; - int status; + __be32 status; status = nfserr_inval; if (!access_valid(open->op_share_access) @@ -1833,11 +1833,11 @@ static struct work_struct laundromat_work; static void laundromat_main(void *); static DECLARE_WORK(laundromat_work, laundromat_main, NULL); -int +__be32 nfsd4_renew(clientid_t *clid) { struct nfs4_client *clp; - int status; + __be32 status; nfs4_lock_state(); dprintk("process_renew(%08x/%08x): starting\n", @@ -1996,9 +1996,9 @@ access_permit_write(unsigned long access_bmap) } static -int nfs4_check_openmode(struct nfs4_stateid *stp, int flags) +__be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags) { - int status = nfserr_openmode; + __be32 status = nfserr_openmode; if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap))) goto out; @@ -2009,7 +2009,7 @@ out: return status; } -static inline int +static inline __be32 check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) { /* Trying to call delegreturn with a special stateid? Yuch: */ @@ -2043,14 +2043,14 @@ io_during_grace_disallowed(struct inode *inode, int flags) /* * Checks for stateid operations */ -int +__be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp) { struct nfs4_stateid *stp = NULL; struct nfs4_delegation *dp = NULL; stateid_t *stidp; struct inode *ino = current_fh->fh_dentry->d_inode; - int status; + __be32 status; dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n", stateid->si_boot, stateid->si_stateownerid, @@ -2125,7 +2125,7 @@ setlkflg (int type) /* * Checks for sequence id mutating operations. */ -static int +static __be32 nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock) { struct nfs4_stateid *stp; @@ -2169,7 +2169,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei clientid_t *lockclid = &lock->v.new.clientid; struct nfs4_client *clp = sop->so_client; int lkflg = 0; - int status; + __be32 status; lkflg = setlkflg(lock->lk_type); @@ -2241,10 +2241,10 @@ check_replay: return nfserr_bad_seqid; } -int +__be32 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) { - int status; + __be32 status; struct nfs4_stateowner *sop; struct nfs4_stateid *stp; @@ -2310,10 +2310,10 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap) } } -int +__be32 nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) { - int status; + __be32 status; struct nfs4_stateid *stp; unsigned int share_access; @@ -2365,10 +2365,10 @@ out: /* * nfs4_unlock_state() called after encode */ -int +__be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) { - int status; + __be32 status; struct nfs4_stateid *stp; dprintk("NFSD: nfsd4_close on file %.*s\n", @@ -2404,10 +2404,10 @@ out: return status; } -int +__be32 nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr) { - int status; + __be32 status; if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) goto out; @@ -2635,7 +2635,7 @@ check_lock_length(u64 offset, u64 length) /* * LOCK operation */ -int +__be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) { struct nfs4_stateowner *open_sop = NULL; @@ -2644,7 +2644,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock struct file *filp; struct file_lock file_lock; struct file_lock conflock; - int status = 0; + __be32 status = 0; unsigned int strhashval; dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", @@ -2793,14 +2793,14 @@ out: /* * LOCKT operation */ -int +__be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) { struct inode *inode; struct file file; struct file_lock file_lock; struct file_lock conflock; - int status; + __be32 status; if (nfs4_in_grace()) return nfserr_grace; @@ -2873,13 +2873,13 @@ out: return status; } -int +__be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) { struct nfs4_stateid *stp; struct file *filp = NULL; struct file_lock file_lock; - int status; + __be32 status; dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n", (long long) locku->lu_offset, @@ -2965,7 +2965,7 @@ out: return status; } -int +__be32 nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) { clientid_t *clid = &rlockowner->rl_clientid; @@ -2974,7 +2974,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * struct xdr_netobj *owner = &rlockowner->rl_owner; struct list_head matches; int i; - int status; + __be32 status; dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", clid->cl_boot, clid->cl_id); @@ -3111,7 +3111,7 @@ nfs4_find_reclaim_client(clientid_t *clid) /* * Called from OPEN. Look for clientid in reclaim list. */ -int +__be32 nfs4_check_open_reclaim(clientid_t *clid) { return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 3419d99..d7b630f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -68,8 +68,8 @@ #define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL #define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL -static int -check_filename(char *str, int len, int err) +static __be32 +check_filename(char *str, int len, __be32 err) { int i; @@ -95,7 +95,7 @@ check_filename(char *str, int len, int err) */ #define DECODE_HEAD \ __be32 *p; \ - int status + __be32 status #define DECODE_TAIL \ status = 0; \ out: \ @@ -217,7 +217,7 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) } -static int +static __be32 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) { u32 bmlen; @@ -240,7 +240,7 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr, struct nfs4_acl **acl) { @@ -418,7 +418,7 @@ out_nfserr: goto out; } -static int +static __be32 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access) { DECODE_HEAD; @@ -429,7 +429,7 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access DECODE_TAIL; } -static int +static __be32 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) { DECODE_HEAD; @@ -444,7 +444,7 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) } -static int +static __be32 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit) { DECODE_HEAD; @@ -456,7 +456,7 @@ nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit DECODE_TAIL; } -static int +static __be32 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create) { DECODE_HEAD; @@ -496,7 +496,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create DECODE_TAIL; } -static inline int +static inline __be32 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr) { DECODE_HEAD; @@ -508,13 +508,13 @@ nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegretu DECODE_TAIL; } -static inline int +static inline __be32 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr) { return nfsd4_decode_bitmap(argp, getattr->ga_bmval); } -static int +static __be32 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link) { DECODE_HEAD; @@ -529,7 +529,7 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) { DECODE_HEAD; @@ -568,7 +568,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) { DECODE_HEAD; @@ -587,7 +587,7 @@ nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku) { DECODE_HEAD; @@ -606,7 +606,7 @@ nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup) { DECODE_HEAD; @@ -621,7 +621,7 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup DECODE_TAIL; } -static int +static __be32 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) { DECODE_HEAD; @@ -699,7 +699,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf) { DECODE_HEAD; @@ -713,7 +713,7 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con DECODE_TAIL; } -static int +static __be32 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down) { DECODE_HEAD; @@ -729,7 +729,7 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d DECODE_TAIL; } -static int +static __be32 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) { DECODE_HEAD; @@ -744,7 +744,7 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read) { DECODE_HEAD; @@ -758,7 +758,7 @@ nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir) { DECODE_HEAD; @@ -774,7 +774,7 @@ nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *read DECODE_TAIL; } -static int +static __be32 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove) { DECODE_HEAD; @@ -789,7 +789,7 @@ nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove DECODE_TAIL; } -static int +static __be32 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename) { DECODE_HEAD; @@ -809,7 +809,7 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename DECODE_TAIL; } -static int +static __be32 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) { DECODE_HEAD; @@ -820,7 +820,7 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) { DECODE_HEAD; @@ -834,7 +834,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta DECODE_TAIL; } -static int +static __be32 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid) { DECODE_HEAD; @@ -859,7 +859,7 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient DECODE_TAIL; } -static int +static __be32 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c) { DECODE_HEAD; @@ -872,7 +872,7 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s } /* Also used for NVERIFY */ -static int +static __be32 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify) { #if 0 @@ -908,7 +908,7 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify DECODE_TAIL; } -static int +static __be32 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) { int avail; @@ -959,7 +959,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) DECODE_TAIL; } -static int +static __be32 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner) { DECODE_HEAD; @@ -973,7 +973,7 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel DECODE_TAIL; } -static int +static __be32 nfsd4_decode_compound(struct nfsd4_compoundargs *argp) { DECODE_HEAD; @@ -1234,7 +1234,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) /* Encode as an array of strings the string given with components * seperated @sep. */ -static int nfsd4_encode_components(char sep, char *components, +static __be32 nfsd4_encode_components(char sep, char *components, __be32 **pp, int *buflen) { __be32 *p = *pp; @@ -1271,10 +1271,10 @@ static int nfsd4_encode_components(char sep, char *components, /* * encode a location element of a fs_locations structure */ -static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, +static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, __be32 **pp, int *buflen) { - int status; + __be32 status; __be32 *p = *pp; status = nfsd4_encode_components(':', location->hosts, &p, buflen); @@ -1292,7 +1292,7 @@ static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, * Returned string is safe to use as long as the caller holds a reference * to @exp. */ -static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, u32 *stat) +static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) { struct svc_fh tmp_fh; char *path, *rootpath; @@ -1318,11 +1318,11 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, u32 *sta /* * encode a fs_locations structure */ -static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp, +static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, struct svc_export *exp, __be32 **pp, int *buflen) { - u32 status; + __be32 status; int i; __be32 *p = *pp; struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; @@ -1353,7 +1353,7 @@ static u32 nfs4_ftypes[16] = { NF4SOCK, NF4BAD, NF4LNK, NF4BAD, }; -static int +static __be32 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, __be32 **p, int *buflen) { @@ -1375,19 +1375,19 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, return 0; } -static inline int +static inline __be32 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen) { return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen); } -static inline int +static inline __be32 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen) { return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen); } -static inline int +static inline __be32 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, __be32 **p, int *buflen) { @@ -1398,7 +1398,7 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, FATTR4_WORD0_RDATTR_ERROR) #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID -static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) +static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) { /* As per referral draft: */ if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS || @@ -1421,7 +1421,7 @@ static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) * @countp is the buffer size in _words_; upon successful return this becomes * replaced with the number of words written. */ -int +__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, struct svc_rqst *rqstp) @@ -1437,7 +1437,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, u64 dummy64; u32 rdattr_err = 0; __be32 *p = buffer; - int status; + __be32 status; int aclsupport = 0; struct nfs4_acl *acl = NULL; @@ -1829,13 +1829,13 @@ out_serverfault: goto out; } -static int +static __be32 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, const char *name, int namlen, __be32 *p, int *buflen) { struct svc_export *exp = cd->rd_fhp->fh_export; struct dentry *dentry; - int nfserr; + __be32 nfserr; dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); if (IS_ERR(dentry)) @@ -1865,7 +1865,7 @@ out_put: } static __be32 * -nfsd4_encode_rdattr_error(__be32 *p, int buflen, int nfserr) +nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) { __be32 *attrlenp; @@ -1888,7 +1888,7 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen, struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); int buflen; __be32 *p = cd->buffer; - int nfserr = nfserr_toosmall; + __be32 nfserr = nfserr_toosmall; /* In nfsv4, "." and ".." never make it onto the wire.. */ if (name && isdotent(name, namlen)) { @@ -1944,7 +1944,7 @@ fail: } static void -nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_access *access) +nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) { ENCODE_HEAD; @@ -1957,7 +1957,7 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_acc } static void -nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_close *close) +nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) { ENCODE_SEQID_OP_HEAD; @@ -1972,7 +1972,7 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_clos static void -nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_commit *commit) +nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) { ENCODE_HEAD; @@ -1984,7 +1984,7 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_com } static void -nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_create *create) +nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) { ENCODE_HEAD; @@ -1998,8 +1998,8 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_cre } } -static int -nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_getattr *getattr) +static __be32 +nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr) { struct svc_fh *fhp = getattr->ga_fhp; int buflen; @@ -2017,7 +2017,7 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ge } static void -nfsd4_encode_getfh(struct nfsd4_compoundres *resp, int nfserr, struct svc_fh *fhp) +nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp) { unsigned int len; ENCODE_HEAD; @@ -2057,7 +2057,7 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie } static void -nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock) +nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) { ENCODE_SEQID_OP_HEAD; @@ -2073,14 +2073,14 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock } static void -nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt) +nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) { if (nfserr == nfserr_denied) nfsd4_encode_lock_denied(resp, &lockt->lt_denied); } static void -nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku) +nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) { ENCODE_SEQID_OP_HEAD; @@ -2096,7 +2096,7 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock static void -nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link) +nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) { ENCODE_HEAD; @@ -2109,7 +2109,7 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link static void -nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open) +nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) { ENCODE_SEQID_OP_HEAD; @@ -2174,7 +2174,7 @@ out: } static void -nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc) +nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) { ENCODE_SEQID_OP_HEAD; @@ -2189,7 +2189,7 @@ nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfs } static void -nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od) +nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) { ENCODE_SEQID_OP_HEAD; @@ -2203,8 +2203,8 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct n ENCODE_SEQID_OP_TAIL(od->od_stateowner); } -static int -nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, +static __be32 +nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read) { u32 eof; @@ -2268,8 +2268,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, return 0; } -static int -nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink) +static __be32 +nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) { int maxcount; char *page; @@ -2316,8 +2316,8 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r return 0; } -static int -nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir) +static __be32 +nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir) { int maxcount; loff_t offset; @@ -2396,7 +2396,7 @@ err_no_verf: } static void -nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove) +nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) { ENCODE_HEAD; @@ -2408,7 +2408,7 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rem } static void -nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename) +nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) { ENCODE_HEAD; @@ -2425,7 +2425,7 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ren * regardless of the error status. */ static void -nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr) +nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) { ENCODE_HEAD; @@ -2444,7 +2444,7 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_se } static void -nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd) +nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) { ENCODE_HEAD; @@ -2463,7 +2463,7 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd } static void -nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write) +nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) { ENCODE_HEAD; @@ -2641,7 +2641,7 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) int nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) { - int status; + __be32 status; args->p = p; args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index 8bf23cf..a597e2e 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -164,7 +164,7 @@ update_stateid(stateid_t *stateid) * is cached. */ struct nfs4_replay { - u32 rp_status; + __be32 rp_status; unsigned int rp_buflen; char *rp_buf; unsigned intrp_allocated; @@ -273,19 +273,19 @@ struct nfs4_stateid { ((err) != nfserr_stale_stateid) && \ ((err) != nfserr_bad_stateid)) -extern int nfsd4_renew(clientid_t *clid); -extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, +extern __be32 nfsd4_renew(clientid_t *clid); +extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filp); extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); -extern int nfs4_check_open_reclaim(clientid_t *clid); +extern __be32 nfs4_check_open_reclaim(clientid_t *clid); extern void put_nfs4_client(struct nfs4_client *clp); extern void nfs4_free_stateowner(struct kref *kref); extern void nfsd4_probe_callback(struct nfs4_client *clp); extern void nfsd4_cb_recall(struct nfs4_delegation *dp); extern void nfs4_put_delegation(struct nfs4_delegation *dp); -extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); +extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern void nfsd4_init_recdir(char *recdir_name); extern int nfsd4_recdir_load(void); extern void nfsd4_shutdown_recdir(void); diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 003193f..45ca01b 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -334,7 +334,7 @@ struct nfsd4_write { struct nfsd4_op { int opnum; - int status; + __be32 status; union { struct nfsd4_access access; struct nfsd4_close close; @@ -426,38 +426,38 @@ int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *, struct nfsd4_compoundres *); void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); -int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, - struct dentry *dentry, u32 *buffer, int *countp, +__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, + struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, struct svc_rqst *); -extern int nfsd4_setclientid(struct svc_rqst *rqstp, +extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid); -extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, +extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm); -extern int nfsd4_process_open1(struct nfsd4_open *open); -extern int nfsd4_process_open2(struct svc_rqst *rqstp, +extern __be32 nfsd4_process_open1(struct nfsd4_open *open); +extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open); -extern int nfsd4_open_confirm(struct svc_rqst *rqstp, +extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **); -extern int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, +extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner); -extern int nfsd4_open_downgrade(struct svc_rqst *rqstp, +extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner); -extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, +extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner); -extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, +extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt); -extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, +extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner); -extern int +extern __be32 nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner); extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *); -extern int nfsd4_delegreturn(struct svc_rqst *rqstp, +extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr); #endif -- cgit v0.10.2 From c4d987ba841dff4b2fc768e52d1d95af83f9f157 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:29:00 -0700 Subject: [PATCH] nfsd: NFSv{2,3} trivial endianness annotations for error values Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index fd5397d..e3eca08 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -35,7 +35,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, { svc_fh *fh; struct posix_acl *acl; - int nfserr = 0; + __be32 nfserr = 0; dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); @@ -102,7 +102,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp, struct nfsd_attrstat *resp) { svc_fh *fh; - int nfserr = 0; + __be32 nfserr = 0; dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); @@ -143,7 +143,7 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp, static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, struct nfsd3_accessres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: ACCESS(2acl) %s 0x%x\n", SVCFH_fmt(&argp->fh), diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 78b2c83..fcad289 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -33,7 +33,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, { svc_fh *fh; struct posix_acl *acl; - int nfserr = 0; + __be32 nfserr = 0; fh = fh_copy(&resp->fh, &argp->fh); if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) @@ -98,7 +98,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, struct nfsd3_attrstat *resp) { svc_fh *fh; - int nfserr = 0; + __be32 nfserr = 0; fh = fh_copy(&resp->fh, &argp->fh); nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR); diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index a12663f..64db601 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -56,7 +56,8 @@ static __be32 nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd3_attrstat *resp) { - int err, nfserr; + int err; + __be32 nfserr; dprintk("nfsd: GETATTR(3) %s\n", SVCFH_fmt(&argp->fh)); @@ -80,7 +81,7 @@ static __be32 nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp, struct nfsd3_attrstat *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: SETATTR(3) %s\n", SVCFH_fmt(&argp->fh)); @@ -98,7 +99,7 @@ static __be32 nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_diropres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: LOOKUP(3) %s %.*s\n", SVCFH_fmt(&argp->fh), @@ -122,7 +123,7 @@ static __be32 nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, struct nfsd3_accessres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: ACCESS(3) %s 0x%x\n", SVCFH_fmt(&argp->fh), @@ -141,7 +142,7 @@ static __be32 nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp, struct nfsd3_readlinkres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh)); @@ -159,7 +160,7 @@ static __be32 nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, struct nfsd3_readres *resp) { - int nfserr; + __be32 nfserr; u32 max_blocksize = svc_max_payload(rqstp); dprintk("nfsd: READ(3) %s %lu bytes at %lu\n", @@ -199,7 +200,7 @@ static __be32 nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, struct nfsd3_writeres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n", SVCFH_fmt(&argp->fh), @@ -229,7 +230,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, { svc_fh *dirfhp, *newfhp = NULL; struct iattr *attr; - u32 nfserr; + __be32 nfserr; dprintk("nfsd: CREATE(3) %s %.*s\n", SVCFH_fmt(&argp->fh), @@ -269,7 +270,7 @@ static __be32 nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, struct nfsd3_diropres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: MKDIR(3) %s %.*s\n", SVCFH_fmt(&argp->fh), @@ -289,7 +290,7 @@ static __be32 nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, struct nfsd3_diropres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n", SVCFH_fmt(&argp->ffh), @@ -311,7 +312,8 @@ static __be32 nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, struct nfsd3_diropres *resp) { - int nfserr, type; + __be32 nfserr; + int type; dev_t rdev = 0; dprintk("nfsd: MKNOD(3) %s %.*s\n", @@ -347,7 +349,7 @@ static __be32 nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_attrstat *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: REMOVE(3) %s %.*s\n", SVCFH_fmt(&argp->fh), @@ -367,7 +369,7 @@ static __be32 nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_attrstat *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: RMDIR(3) %s %.*s\n", SVCFH_fmt(&argp->fh), @@ -383,7 +385,7 @@ static __be32 nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp, struct nfsd3_renameres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: RENAME(3) %s %.*s ->\n", SVCFH_fmt(&argp->ffh), @@ -405,7 +407,7 @@ static __be32 nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp, struct nfsd3_linkres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: LINK(3) %s ->\n", SVCFH_fmt(&argp->ffh)); @@ -428,7 +430,8 @@ static __be32 nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, struct nfsd3_readdirres *resp) { - int nfserr, count; + __be32 nfserr; + int count; dprintk("nfsd: READDIR(3) %s %d bytes at %d\n", SVCFH_fmt(&argp->fh), @@ -463,7 +466,8 @@ static __be32 nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, struct nfsd3_readdirres *resp) { - int nfserr, count = 0; + __be32 nfserr; + int count = 0; loff_t offset; int i; caddr_t page_addr = NULL; @@ -521,7 +525,7 @@ static __be32 nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_fsstatres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: FSSTAT(3) %s\n", SVCFH_fmt(&argp->fh)); @@ -538,7 +542,7 @@ static __be32 nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_fsinfores *resp) { - int nfserr; + __be32 nfserr; u32 max_blocksize = svc_max_payload(rqstp); dprintk("nfsd: FSINFO(3) %s\n", @@ -580,7 +584,7 @@ static __be32 nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_pathconfres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: PATHCONF(3) %s\n", SVCFH_fmt(&argp->fh)); @@ -623,7 +627,7 @@ static __be32 nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp, struct nfsd3_commitres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: COMMIT(3) %s %u@%Lu\n", SVCFH_fmt(&argp->fh), diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 03ab682..ec983b7 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -36,16 +36,16 @@ nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) return nfs_ok; } -static int -nfsd_return_attrs(int err, struct nfsd_attrstat *resp) +static __be32 +nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp) { if (err) return err; return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, resp->fh.fh_dentry, &resp->stat)); } -static int -nfsd_return_dirop(int err, struct nfsd_diropres *resp) +static __be32 +nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp) { if (err) return err; return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, @@ -60,7 +60,7 @@ static __be32 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); @@ -76,7 +76,7 @@ static __be32 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, struct nfsd_attrstat *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", SVCFH_fmt(&argp->fh), argp->attrs.ia_valid, (long) argp->attrs.ia_size); @@ -96,7 +96,7 @@ static __be32 nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, struct nfsd_diropres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: LOOKUP %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); @@ -116,7 +116,7 @@ static __be32 nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_readlinkargs *argp, struct nfsd_readlinkres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh)); @@ -136,7 +136,7 @@ static __be32 nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, struct nfsd_readres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: READ %s %d bytes at %d\n", SVCFH_fmt(&argp->fh), @@ -176,7 +176,7 @@ static __be32 nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp, struct nfsd_attrstat *resp) { - int nfserr; + __be32 nfserr; int stable = 1; dprintk("nfsd: WRITE %s %d bytes at %d\n", @@ -206,7 +206,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, struct iattr *attr = &argp->attrs; struct inode *inode; struct dentry *dchild; - int nfserr, type, mode; + int type, mode; + __be32 nfserr; dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); dprintk("nfsd: CREATE %s %.*s\n", @@ -352,7 +353,7 @@ static __be32 nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, void *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); @@ -367,7 +368,7 @@ static __be32 nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp, void *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: RENAME %s %.*s -> \n", SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); @@ -385,7 +386,7 @@ static __be32 nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp, void *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: LINK %s ->\n", SVCFH_fmt(&argp->ffh)); @@ -406,7 +407,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp, void *resp) { struct svc_fh newfh; - int nfserr; + __be32 nfserr; dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n", SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, @@ -434,7 +435,7 @@ static __be32 nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, struct nfsd_diropres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); @@ -458,7 +459,7 @@ static __be32 nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, void *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); @@ -474,7 +475,8 @@ static __be32 nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp, struct nfsd_readdirres *resp) { - int nfserr, count; + int count; + __be32 nfserr; loff_t offset; dprintk("nfsd: READDIR %s %d bytes at %d\n", @@ -513,7 +515,7 @@ static __be32 nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd_statfsres *resp) { - int nfserr; + __be32 nfserr; dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh)); -- cgit v0.10.2 From b8dd7b9ab194d9ab322881f49fde42954757efae Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:29:01 -0700 Subject: [PATCH] nfsd: NFSv4 errno endianness annotations don't use the same variable to store NFS and host error values Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e5ca6d7..ae1d477 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2646,6 +2646,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock struct file_lock conflock; __be32 status = 0; unsigned int strhashval; + int err; dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", (long long) lock->lk_offset, @@ -2758,13 +2759,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock * locks_copy_lock: */ conflock.fl_ops = NULL; conflock.fl_lmops = NULL; - status = posix_lock_file_conf(filp, &file_lock, &conflock); + err = posix_lock_file_conf(filp, &file_lock, &conflock); dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status); - switch (-status) { + switch (-err) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, sizeof(stateid_t)); + status = 0; break; case (EAGAIN): /* conflock holds conflicting lock */ status = nfserr_denied; @@ -2775,7 +2777,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock status = nfserr_deadlock; break; default: - dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status); + dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",err); status = nfserr_resource; break; } @@ -2880,6 +2882,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock struct file *filp = NULL; struct file_lock file_lock; __be32 status; + int err; dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n", (long long) locku->lu_offset, @@ -2917,8 +2920,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock /* * Try to unlock the file in the VFS. */ - status = posix_lock_file(filp, &file_lock); - if (status) { + err = posix_lock_file(filp, &file_lock); + if (err) { dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); goto out_nfserr; } @@ -2937,7 +2940,7 @@ out: return status; out_nfserr: - status = nfserrno(status); + status = nfserrno(err); goto out; } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index d7b630f..f3f239d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -247,6 +247,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia int expected_len, len = 0; u32 dummy32; char *buf; + int host_err; DECODE_HEAD; iattr->ia_valid = 0; @@ -280,7 +281,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia *acl = nfs4_acl_new(); if (*acl == NULL) { - status = -ENOMEM; + host_err = -ENOMEM; goto out_nfserr; } defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl); @@ -295,20 +296,20 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia len += XDR_QUADLEN(dummy32) << 2; READMEM(buf, dummy32); ace.whotype = nfs4_acl_get_whotype(buf, dummy32); - status = 0; + host_err = 0; if (ace.whotype != NFS4_ACL_WHO_NAMED) ace.who = 0; else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP) - status = nfsd_map_name_to_gid(argp->rqstp, + host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &ace.who); else - status = nfsd_map_name_to_uid(argp->rqstp, + host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &ace.who); - if (status) + if (host_err) goto out_nfserr; - status = nfs4_acl_add_ace(*acl, ace.type, ace.flag, + host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag, ace.access_mask, ace.whotype, ace.who); - if (status) + if (host_err) goto out_nfserr; } } else @@ -327,7 +328,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia READ_BUF(dummy32); len += (XDR_QUADLEN(dummy32) << 2); READMEM(buf, dummy32); - if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) + if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) goto out_nfserr; iattr->ia_valid |= ATTR_UID; } @@ -338,7 +339,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia READ_BUF(dummy32); len += (XDR_QUADLEN(dummy32) << 2); READMEM(buf, dummy32); - if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) + if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) goto out_nfserr; iattr->ia_valid |= ATTR_GID; } @@ -414,7 +415,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia DECODE_TAIL; out_nfserr: - status = nfserrno(status); + status = nfserrno(host_err); goto out; } @@ -1438,6 +1439,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, u32 rdattr_err = 0; __be32 *p = buffer; __be32 status; + int err; int aclsupport = 0; struct nfs4_acl *acl = NULL; @@ -1451,14 +1453,14 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, goto out; } - status = vfs_getattr(exp->ex_mnt, dentry, &stat); - if (status) + err = vfs_getattr(exp->ex_mnt, dentry, &stat); + if (err) goto out_nfserr; if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { - status = vfs_statfs(dentry, &statfs); - if (status) + err = vfs_statfs(dentry, &statfs); + if (err) goto out_nfserr; } if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { @@ -1470,15 +1472,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, } if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_SUPPORTED_ATTRS)) { - status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); - aclsupport = (status == 0); + err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); + aclsupport = (err == 0); if (bmval0 & FATTR4_WORD0_ACL) { - if (status == -EOPNOTSUPP) + if (err == -EOPNOTSUPP) bmval0 &= ~FATTR4_WORD0_ACL; - else if (status == -EINVAL) { + else if (err == -EINVAL) { status = nfserr_attrnotsupp; goto out; - } else if (status != 0) + } else if (err != 0) goto out_nfserr; } } @@ -1818,7 +1820,7 @@ out: fh_put(&tempfh); return status; out_nfserr: - status = nfserrno(status); + status = nfserrno(err); goto out; out_resource: *countp = 0; -- cgit v0.10.2 From f00f328fda1eeec575cd0f360da81b66bf4133a1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:29:01 -0700 Subject: [PATCH] xdr annotations: nfsd callback* Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 324a278..8497ed4 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -85,8 +85,8 @@ enum nfs_cb_opnum4 { /* * Generic encode routines from fs/nfs/nfs4xdr.c */ -static inline u32 * -xdr_writemem(u32 *p, const void *ptr, int nbytes) +static inline __be32 * +xdr_writemem(__be32 *p, const void *ptr, int nbytes) { int tmp = XDR_QUADLEN(nbytes); if (!tmp) @@ -205,7 +205,7 @@ nfs_cb_stat_to_errno(int stat) static int encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) { - u32 * p; + __be32 * p; RESERVE_SPACE(16); WRITE32(0); /* tag length is always 0 */ @@ -218,7 +218,7 @@ encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) static int encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec) { - u32 *p; + __be32 *p; int len = cb_rec->cbr_fhlen; RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len); @@ -231,7 +231,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec) } static int -nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p) +nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p) { struct xdr_stream xdrs, *xdr = &xdrs; @@ -241,7 +241,7 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p) } static int -nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p, struct nfs4_cb_recall *args) +nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_cb_recall *args) { struct xdr_stream xdr; struct nfs4_cb_compound_hdr hdr = { @@ -257,7 +257,7 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p, struct nfs4_cb_recall *args static int decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ - u32 *p; + __be32 *p; READ_BUF(8); READ32(hdr->status); @@ -272,7 +272,7 @@ decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) static int decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) { - u32 *p; + __be32 *p; u32 op; int32_t nfserr; @@ -291,13 +291,13 @@ decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) } static int -nfs4_xdr_dec_cb_null(struct rpc_rqst *req, u32 *p) +nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p) { return 0; } static int -nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p) +nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p) { struct xdr_stream xdr; struct nfs4_cb_compound_hdr hdr; -- cgit v0.10.2 From c7afef1f963bec198b186cc34b9e8c9b9ce2e266 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:29:02 -0700 Subject: [PATCH] nfsd: misc endianness annotations Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index e13fa23..f37df46 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1148,12 +1148,12 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, * for a given NFSv4 client. The root is defined to be the * export point with fsid==0 */ -int +__be32 exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, struct cache_req *creq) { struct svc_export *exp; - int rv; + __be32 rv; u32 fsidv[2]; mk_fsid_v1(fsidv, 0); diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 9b9e7e1..11fdaf7 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -25,7 +25,7 @@ static u32 nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) { - u32 nfserr; + __be32 nfserr; struct svc_fh fh; /* must initialize before using! but maxsize doesn't matter */ diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 8497ed4..f57655a 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -461,7 +461,7 @@ nfs4_cb_null(struct rpc_task *task, void *dummy) { struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; struct nfs4_callback *cb = &clp->cl_callback; - u32 addr = htonl(cb->cb_addr); + __be32 addr = htonl(cb->cb_addr); dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index ae1d477..2e468c9 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -713,7 +713,7 @@ out_err: __be32 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) { - u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; + __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; struct xdr_netobj clname = { .len = setclid->se_namelen, .data = setclid->se_name, @@ -878,7 +878,7 @@ out: __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) { - u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; + __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; struct nfs4_client *conf, *unconf; nfs4_verifier confirm = setclientid_confirm->sc_confirm; clientid_t * clid = &setclientid_confirm->sc_clientid; diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index fdf7cf3..6100bbe 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -29,7 +29,7 @@ */ #define CACHESIZE 1024 #define HASHSIZE 64 -#define REQHASH(xid) ((((xid) >> 24) ^ (xid)) & (HASHSIZE-1)) +#define REQHASH(xid) (((((__force __u32)xid) >> 24) ^ ((__force __u32)xid)) & (HASHSIZE-1)) static struct hlist_head * hash_list; static struct list_head lru_head; @@ -127,8 +127,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type) struct hlist_node *hn; struct hlist_head *rh; struct svc_cacherep *rp; - u32 xid = rqstp->rq_xid, - proto = rqstp->rq_prot, + __be32 xid = rqstp->rq_xid; + u32 proto = rqstp->rq_prot, vers = rqstp->rq_vers, proc = rqstp->rq_proc; unsigned long age; @@ -258,7 +258,7 @@ found_entry: * In this case, nfsd_cache_update is called with statp == NULL. */ void -nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, u32 *statp) +nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp) { struct svc_cacherep *rp; struct kvec *resv = &rqstp->rq_res.head[0], *cachv; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 8067118..0aaccb0 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -491,7 +491,7 @@ out: } int -nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) +nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) { struct svc_procedure *proc; kxdrproc_t xdr; diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h index c3a3557..007480c 100644 --- a/include/linux/nfsd/cache.h +++ b/include/linux/nfsd/cache.h @@ -26,14 +26,14 @@ struct svc_cacherep { c_type, /* status, buffer */ c_secure : 1; /* req came from port < 1024 */ struct sockaddr_in c_addr; - u32 c_xid; + __be32 c_xid; u32 c_prot; u32 c_proc; u32 c_vers; unsigned long c_timestamp; union { struct kvec u_vec; - u32 u_status; + __be32 u_status; } c_u; }; @@ -75,7 +75,7 @@ enum { void nfsd_cache_init(void); void nfsd_cache_shutdown(void); int nfsd_cache_lookup(struct svc_rqst *, int); -void nfsd_cache_update(struct svc_rqst *, int, u32 *); +void nfsd_cache_update(struct svc_rqst *, int, __be32 *); #endif /* __KERNEL__ */ #endif /* NFSCACHE_H */ diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 27666f5b..045e38c 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -117,7 +117,7 @@ struct svc_export * exp_parent(struct auth_domain *clp, struct cache_req *reqp); int exp_rootfh(struct auth_domain *, char *path, struct knfsd_fh *, int maxsize); -int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); +__be32 exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); __be32 nfserrno(int errno); extern struct cache_detail svc_export_cache; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 19a3c83..68d29b6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -64,7 +64,7 @@ extern struct svc_serv *nfsd_serv; * Function prototypes. */ int nfsd_svc(unsigned short port, int nrservs); -int nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp); +int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); /* nfsd/vfs.c */ int fh_lock_parent(struct svc_fh *, struct dentry *); diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index 749bad1..f3b51d6 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -157,7 +157,7 @@ typedef struct svc_fh { __u64 fh_post_size; /* i_size */ unsigned long fh_post_blocks; /* i_blocks */ unsigned long fh_post_blksize;/* i_blksize */ - __u32 fh_post_rdev[2];/* i_rdev */ + __be32 fh_post_rdev[2];/* i_rdev */ struct timespec fh_post_atime; /* i_atime */ struct timespec fh_post_mtime; /* i_mtime */ struct timespec fh_post_ctime; /* i_ctime */ diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index a597e2e..c3673f4 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -125,7 +125,7 @@ struct nfs4_client { char cl_recdir[HEXDIR_LEN]; /* recovery dir */ nfs4_verifier cl_verifier; /* generated by client */ time_t cl_time; /* time of last lease renewal */ - u32 cl_addr; /* client ipaddress */ + __be32 cl_addr; /* client ipaddress */ struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ -- cgit v0.10.2 From a90b061c0bf712961cea40d9c916b300073d12e5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Oct 2006 23:29:03 -0700 Subject: [PATCH] nfsd: nfs_replay_me We are using NFS_REPLAY_ME as a special error value that is never leaked to clients. That works fine; the only problem is mixing host- and network- endian values in the same objects. Network-endian equivalent would work just as fine; switch to it. Signed-off-by: Al Viro Acked-by: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 6382394..0a7bbdc 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -177,7 +177,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open /* check seqid for replay. set nfs4_owner */ status = nfsd4_process_open1(open); - if (status == NFSERR_REPLAY_ME) { + if (status == nfserr_replay_me) { struct nfs4_replay *rp = &open->op_stateowner->so_replay; fh_put(current_fh); current_fh->fh_handle.fh_size = rp->rp_openfh_len; @@ -188,7 +188,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open dprintk("nfsd4_open: replay failed" " restoring previous filehandle\n"); else - status = NFSERR_REPLAY_ME; + status = nfserr_replay_me; } if (status) goto out; @@ -937,7 +937,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, } encode_op: - if (op->status == NFSERR_REPLAY_ME) { + if (op->status == nfserr_replay_me) { op->replay = &replay_owner->so_replay; nfsd4_encode_replay(resp, op); status = op->status = op->replay->rp_status; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2e468c9..293b649 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1477,7 +1477,7 @@ nfsd4_process_open1(struct nfsd4_open *open) } if (open->op_seqid == sop->so_seqid - 1) { if (sop->so_replay.rp_buflen) - return NFSERR_REPLAY_ME; + return nfserr_replay_me; /* The original OPEN failed so spectacularly * that we don't even have replay data saved! * Therefore, we have no choice but to continue @@ -2233,7 +2233,7 @@ check_replay: if (seqid == sop->so_seqid - 1) { dprintk("NFSD: preprocess_seqid_op: retransmission?\n"); /* indicate replay to calling function */ - return NFSERR_REPLAY_ME; + return nfserr_replay_me; } printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", sop->so_seqid, seqid); diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 68d29b6..eb23114 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -238,6 +238,7 @@ void nfsd_lockd_shutdown(void); #define nfserr_badname __constant_htonl(NFSERR_BADNAME) #define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) #define nfserr_locked __constant_htonl(NFSERR_LOCKED) +#define nfserr_replay_me __constant_htonl(NFSERR_REPLAY_ME) /* error codes for internal use */ /* if a request fails due to kmalloc failure, it gets dropped. -- cgit v0.10.2 From e51959faa61278c762389802faf8ba1a40676628 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Thu, 19 Oct 2006 23:29:04 -0700 Subject: [PATCH] Fix potential interrupts during alternative patching Interrupts must be disabled during alternative instruction patching. On systems with high timer IRQ rates, or when running in an emulator, timing differences can result in random kernel panics because of running partially patched instructions. This doesn't yet fix NMIs, which requires extricating the patch code from the late bug checking and is logically separate (and also less likely to cause problems). Signed-off-by: Zachary Amsden Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 28ab806..583c238 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -344,6 +344,7 @@ void alternatives_smp_switch(int smp) void __init alternative_instructions(void) { + unsigned long flags; if (no_replacement) { printk(KERN_INFO "(SMP-)alternatives turned off\n"); free_init_pages("SMP alternatives", @@ -351,6 +352,8 @@ void __init alternative_instructions(void) (unsigned long)__smp_alt_end); return; } + + local_irq_save(flags); apply_alternatives(__alt_instructions, __alt_instructions_end); /* switch to patch-once-at-boottime-only mode and free the @@ -386,4 +389,5 @@ void __init alternative_instructions(void) alternatives_smp_switch(0); } #endif + local_irq_restore(flags); } -- cgit v0.10.2 From 6220ec7844fda2686496013a66b5b9169976b991 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 19 Oct 2006 23:29:05 -0700 Subject: [PATCH] highest_possible_node_id() linkage fix Qooting Adrian: - net/sunrpc/svc.c uses highest_possible_node_id() - include/linux/nodemask.h says highest_possible_node_id() is out-of-line #if MAX_NUMNODES > 1 - the out-of-line highest_possible_node_id() is in lib/cpumask.c - lib/Makefile: lib-$(CONFIG_SMP) += cpumask.o CONFIG_ARCH_DISCONTIGMEM_ENABLE=y, CONFIG_SMP=n, CONFIG_SUNRPC=y -> highest_possible_node_id() is used in net/sunrpc/svc.c CONFIG_NODES_SHIFT defined and > 0 -> include/linux/numa.h: MAX_NUMNODES > 1 -> compile error The bug is not present on architectures where ARCH_DISCONTIGMEM_ENABLE depends on NUMA (but m32r isn't the only affected architecture). So move the function into page_alloc.c Cc: Adrian Bunk Cc: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/cpumask.c b/lib/cpumask.c index 7a2a73f..3a67dc5 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -43,19 +43,3 @@ int __any_online_cpu(const cpumask_t *mask) return cpu; } EXPORT_SYMBOL(__any_online_cpu); - -#if MAX_NUMNODES > 1 -/* - * Find the highest possible node id. - */ -int highest_possible_node_id(void) -{ - unsigned int node; - unsigned int highest = 0; - - for_each_node_mask(node, node_possible_map) - highest = node; - return highest; -} -EXPORT_SYMBOL(highest_possible_node_id); -#endif diff --git a/mm/page_alloc.c b/mm/page_alloc.c index afee38f..ebd425c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3120,3 +3120,19 @@ unsigned long page_to_pfn(struct page *page) EXPORT_SYMBOL(pfn_to_page); EXPORT_SYMBOL(page_to_pfn); #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */ + +#if MAX_NUMNODES > 1 +/* + * Find the highest possible node id. + */ +int highest_possible_node_id(void) +{ + unsigned int node; + unsigned int highest = 0; + + for_each_node_mask(node, node_possible_map) + highest = node; + return highest; +} +EXPORT_SYMBOL(highest_possible_node_id); +#endif -- cgit v0.10.2 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 diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 7e95f04..3dacfff 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); @@ -734,6 +736,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) { if (cs->subtyp == DIVA_IPAC_ISA) { @@ -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 8bbe33a..82e42a8 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 v0.10.2 From ca926e80dcfd18adaf7c4304935da4cc8ded8364 Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Thu, 19 Oct 2006 23:29:06 -0700 Subject: [PATCH] doc: fixing cpu-hotplug documentation Fixing cpu-hotplug documentation as follows: - moving confusing asterisk on additional_cpus descrition - fixing some typos - unifying indentation for source code and command line example Signed-off-by: Satoru Takeuchi Cc: Ashok Raj Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index bc107cb..4868c34 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -46,7 +46,7 @@ maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using maxcpus=2 will only boot 2. You can choose to bring the other cpus later online, read FAQ's for more info. -additional_cpus*=n Use this to limit hotpluggable cpus. This option sets +additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets cpu_possible_map = cpu_present_map + additional_cpus (*) Option valid only for following architectures @@ -101,15 +101,15 @@ cpu_possible_map/for_each_possible_cpu() to iterate. Never use anything other than cpumask_t to represent bitmap of CPUs. -#include + #include -for_each_possible_cpu - Iterate over cpu_possible_map -for_each_online_cpu - Iterate over cpu_online_map -for_each_present_cpu - Iterate over cpu_present_map -for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. + for_each_possible_cpu - Iterate over cpu_possible_map + for_each_online_cpu - Iterate over cpu_online_map + for_each_present_cpu - Iterate over cpu_present_map + for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. -#include -lock_cpu_hotplug() and unlock_cpu_hotplug(): + #include + lock_cpu_hotplug() and unlock_cpu_hotplug(): The above calls are used to inhibit cpu hotplug operations. While holding the cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid @@ -120,7 +120,7 @@ will work as long as stop_machine_run() is used to take a cpu down. CPU Hotplug - Frequently Asked Questions. -Q: How to i enable my kernel to support CPU hotplug? +Q: How to enable my kernel to support CPU hotplug? A: When doing make defconfig, Enable CPU hotplug support "Processor type and Features" -> Support for Hotpluggable CPUs @@ -141,39 +141,39 @@ A: You should now notice an entry in sysfs. Check if sysfs is mounted, using the "mount" command. You should notice an entry as shown below in the output. -.... -none on /sys type sysfs (rw) -.... + .... + none on /sys type sysfs (rw) + .... -if this is not mounted, do the following. +If this is not mounted, do the following. -#mkdir /sysfs -#mount -t sysfs sys /sys + #mkdir /sysfs + #mount -t sysfs sys /sys -now you should see entries for all present cpu, the following is an example +Now you should see entries for all present cpu, the following is an example in a 8-way system. -#pwd -#/sys/devices/system/cpu -#ls -l -total 0 -drwxr-xr-x 10 root root 0 Sep 19 07:44 . -drwxr-xr-x 13 root root 0 Sep 19 07:45 .. -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu0 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu1 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu2 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu3 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu4 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu5 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu6 -drwxr-xr-x 3 root root 0 Sep 19 07:48 cpu7 + #pwd + #/sys/devices/system/cpu + #ls -l + total 0 + drwxr-xr-x 10 root root 0 Sep 19 07:44 . + drwxr-xr-x 13 root root 0 Sep 19 07:45 .. + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu0 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu1 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu2 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu3 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu4 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu5 + drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu6 + drwxr-xr-x 3 root root 0 Sep 19 07:48 cpu7 Under each directory you would find an "online" file which is the control file to logically online/offline a processor. Q: Does hot-add/hot-remove refer to physical add/remove of cpus? A: The usage of hot-add/remove may not be very consistently used in the code. -CONFIG_CPU_HOTPLUG enables logical online/offline capability in the kernel. +CONFIG_HOTPLUG_CPU enables logical online/offline capability in the kernel. To support physical addition/removal, one would need some BIOS hooks and the platform should have something like an attention button in PCI hotplug. CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs. @@ -181,17 +181,17 @@ CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs. Q: How do i logically offline a CPU? A: Do the following. -#echo 0 > /sys/devices/system/cpu/cpuX/online + #echo 0 > /sys/devices/system/cpu/cpuX/online -once the logical offline is successful, check +Once the logical offline is successful, check -#cat /proc/interrupts + #cat /proc/interrupts -you should now not see the CPU that you removed. Also online file will report +You should now not see the CPU that you removed. Also online file will report the state as 0 when a cpu if offline and 1 when its online. -#To display the current cpu state. -#cat /sys/devices/system/cpu/cpuX/online + #To display the current cpu state. + #cat /sys/devices/system/cpu/cpuX/online Q: Why cant i remove CPU0 on some systems? A: Some architectures may have some special dependency on a certain CPU. @@ -234,8 +234,8 @@ Q: If i have some kernel code that needs to be aware of CPU arrival and departure, how to i arrange for proper notification? A: This is what you would need in your kernel code to receive notifications. - #include - static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb, + #include + static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -279,10 +279,10 @@ Q: I don't see my action being called for all CPUs already up and running? A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined. If you need to perform some action for each cpu already in the system, then - for_each_online_cpu(i) { + for_each_online_cpu(i) { foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); - foobar_cpu_callback(&foobar-cpu_notifier, CPU_ONLINE, i); - } + foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i); + } Q: If i would like to develop cpu hotplug support for a new architecture, what do i need at a minimum? @@ -307,38 +307,38 @@ Q: I need to ensure that a particular cpu is not removed when there is some work specific to this cpu is in progress. A: First switch the current thread context to preferred cpu - int my_func_on_cpu(int cpu) - { - cpumask_t saved_mask, new_mask = CPU_MASK_NONE; - int curr_cpu, err = 0; - - saved_mask = current->cpus_allowed; - cpu_set(cpu, new_mask); - err = set_cpus_allowed(current, new_mask); - - if (err) - return err; - - /* - * If we got scheduled out just after the return from - * set_cpus_allowed() before running the work, this ensures - * we stay locked. - */ - curr_cpu = get_cpu(); - - if (curr_cpu != cpu) { - err = -EAGAIN; - goto ret; - } else { - /* - * Do work : But cant sleep, since get_cpu() disables preempt - */ - } - ret: - put_cpu(); - set_cpus_allowed(current, saved_mask); - return err; - } + int my_func_on_cpu(int cpu) + { + cpumask_t saved_mask, new_mask = CPU_MASK_NONE; + int curr_cpu, err = 0; + + saved_mask = current->cpus_allowed; + cpu_set(cpu, new_mask); + err = set_cpus_allowed(current, new_mask); + + if (err) + return err; + + /* + * If we got scheduled out just after the return from + * set_cpus_allowed() before running the work, this ensures + * we stay locked. + */ + curr_cpu = get_cpu(); + + if (curr_cpu != cpu) { + err = -EAGAIN; + goto ret; + } else { + /* + * Do work : But cant sleep, since get_cpu() disables preempt + */ + } + ret: + put_cpu(); + set_cpus_allowed(current, saved_mask); + return err; + } Q: How do we determine how many CPUs are available for hotplug. -- cgit v0.10.2 From c4ec7b0de4bc18ccb4380de638550984d9a65c25 Mon Sep 17 00:00:00 2001 From: Dmitriy Monakhov Date: Thu, 19 Oct 2006 23:29:08 -0700 Subject: [PATCH] mm: D-cache aliasing issue in cow_user_page --=-=-= from mm/memory.c: 1434 static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va) 1435 { 1436 /* 1437 * If the source page was a PFN mapping, we don't have 1438 * a "struct page" for it. We do a best-effort copy by 1439 * just copying from the original user address. If that 1440 * fails, we just zero-fill it. Live with it. 1441 */ 1442 if (unlikely(!src)) { 1443 void *kaddr = kmap_atomic(dst, KM_USER0); 1444 void __user *uaddr = (void __user *)(va & PAGE_MASK); 1445 1446 /* 1447 * This really shouldn't fail, because the page is there 1448 * in the page tables. But it might just be unreadable, 1449 * in which case we just give up and fill the result with 1450 * zeroes. 1451 */ 1452 if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) 1453 memset(kaddr, 0, PAGE_SIZE); 1454 kunmap_atomic(kaddr, KM_USER0); #### D-cache have to be flushed here. #### It seems it is just forgotten. 1455 return; 1456 1457 } 1458 copy_user_highpage(dst, src, va); #### Ok here. flush_dcache_page() called from this func if arch need it 1459 } Following is the patch fix this issue: Signed-off-by: Dmitriy Monakhov Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memory.c b/mm/memory.c index b5a4aad..156861f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1452,6 +1452,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) memset(kaddr, 0, PAGE_SIZE); kunmap_atomic(kaddr, KM_USER0); + flush_dcache_page(dst); return; } -- cgit v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 24825bd..e5cfb1f 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 v0.10.2 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 diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 8bcb58c..1865b56 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 v0.10.2 From 82591e6ea234762eeaa8b2337fe060ed438c18dc Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 19 Oct 2006 23:29:10 -0700 Subject: [PATCH] mm: more commenting on lock ordering Clarify lockorder comments now that sys_msync dropps mmap_sem before calling do_fsync. Signed-off-by: Nick Piggin Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/filemap.c b/mm/filemap.c index 57faa8d..8558732 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -75,8 +75,8 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, * ->mmap_sem * ->lock_page (access_process_vm) * - * ->mmap_sem - * ->i_mutex (msync) + * ->i_mutex (generic_file_buffered_write) + * ->mmap_sem (fault_in_pages_readable->do_page_fault) * * ->i_mutex * ->i_alloc_sem (various) diff --git a/mm/rmap.c b/mm/rmap.c index a9136d8..d8a842a 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -21,27 +21,21 @@ * Lock ordering in mm: * * inode->i_mutex (while writing or truncating, not reading or faulting) - * inode->i_alloc_sem - * - * When a page fault occurs in writing from user to file, down_read - * of mmap_sem nests within i_mutex; in sys_msync, i_mutex nests within - * down_read of mmap_sem; i_mutex and down_write of mmap_sem are never - * taken together; in truncation, i_mutex is taken outermost. - * - * mm->mmap_sem - * page->flags PG_locked (lock_page) - * mapping->i_mmap_lock - * anon_vma->lock - * mm->page_table_lock or pte_lock - * zone->lru_lock (in mark_page_accessed, isolate_lru_page) - * swap_lock (in swap_duplicate, swap_info_get) - * mmlist_lock (in mmput, drain_mmlist and others) - * mapping->private_lock (in __set_page_dirty_buffers) - * inode_lock (in set_page_dirty's __mark_inode_dirty) - * sb_lock (within inode_lock in fs/fs-writeback.c) - * mapping->tree_lock (widely used, in set_page_dirty, - * in arch-dependent flush_dcache_mmap_lock, - * within inode_lock in __sync_single_inode) + * inode->i_alloc_sem (vmtruncate_range) + * mm->mmap_sem + * page->flags PG_locked (lock_page) + * mapping->i_mmap_lock + * anon_vma->lock + * mm->page_table_lock or pte_lock + * zone->lru_lock (in mark_page_accessed, isolate_lru_page) + * swap_lock (in swap_duplicate, swap_info_get) + * mmlist_lock (in mmput, drain_mmlist and others) + * mapping->private_lock (in __set_page_dirty_buffers) + * inode_lock (in set_page_dirty's __mark_inode_dirty) + * sb_lock (within inode_lock in fs/fs-writeback.c) + * mapping->tree_lock (widely used, in set_page_dirty, + * in arch-dependent flush_dcache_mmap_lock, + * within inode_lock in __sync_single_inode) */ #include -- cgit v0.10.2 From 3e2a532b26b491706bd8b5c7cfc8d767b43b8f36 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 19 Oct 2006 23:29:11 -0700 Subject: [PATCH] ext3/4: fix J_ASSERT(transaction->t_updates > 0) in journal_stop() A disk generated some I/O error, after it, I hitted J_ASSERT(transaction->t_updates > 0) in journal_stop(). It seems to happened on ext3_truncate() path from stack trace. Then, maybe the following case may trigger J_ASSERT(transaction->t_updates > 0). ext3_truncate() -> ext3_free_branches() -> ext3_journal_test_restart() -> ext3_journal_restart() -> journal_restart() transaction->t_updates--; /* another process aborted journal */ -> start_this_handle() returns -EROFS without transaction->t_updates++; -> ext3_journal_stop() -> journal_stop() J_ASSERT(transaction->t_updates > 0) If journal was aborted in middle of journal_restart(), ext3_truncate() may trigger J_ASSERT(). Signed-off-by: OGAWA Hirofumi Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index e1b3c8a..d5c6304 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1314,13 +1314,14 @@ int journal_stop(handle_t *handle) int old_handle_count, err; pid_t pid; - J_ASSERT(transaction->t_updates > 0); J_ASSERT(journal_current_handle() == handle); if (is_handle_aborted(handle)) err = -EIO; - else + else { + J_ASSERT(transaction->t_updates > 0); err = 0; + } if (--handle->h_ref > 0) { jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 149957b..b6cf2be 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1314,13 +1314,14 @@ int jbd2_journal_stop(handle_t *handle) int old_handle_count, err; pid_t pid; - J_ASSERT(transaction->t_updates > 0); J_ASSERT(journal_current_handle() == handle); if (is_handle_aborted(handle)) err = -EIO; - else + else { + J_ASSERT(transaction->t_updates > 0); err = 0; + } if (--handle->h_ref > 0) { jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, -- cgit v0.10.2 From e05d722e4555cd54677b4c8431d9e81fd047ef7a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 19 Oct 2006 23:29:12 -0700 Subject: [PATCH] kernel/nsproxy.c: use kmemdup() Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 6ebdb82..674aceb 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -44,11 +44,9 @@ static inline struct nsproxy *clone_namespaces(struct nsproxy *orig) { struct nsproxy *ns; - ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL); - if (ns) { - memcpy(ns, orig, sizeof(struct nsproxy)); + ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL); + if (ns) atomic_set(&ns->count, 1); - } return ns; } -- cgit v0.10.2 From 1a047060a99f274a7c52cfea8159e4142a14b8a7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 19 Oct 2006 23:29:13 -0700 Subject: [PATCH] knfsd: fix race that can disable NFS server This patch is suitable for just about any 2.6 kernel. It should go in 2.6.19 and 2.6.18.2 and possible even the .17 and .16 stable series. This is a long standing bug that seems to have only recently become apparent, presumably due to increasing use of NFS over TCP - many distros seem to be making it the default. The SK_CONN bit gets set when a listening socket may be ready for an accept, just as SK_DATA is set when data may be available. It is entirely possible for svc_tcp_accept to be called with neither of these set. It doesn't happen often but there is a small race in svc_sock_enqueue as SK_CONN and SK_DATA are tested outside the spin_lock. They could be cleared immediately after the test and before the lock is gained. This normally shouldn't be a problem. The sockets are non-blocking so trying to read() or accept() when ther is nothing to do is not a problem. However: svc_tcp_recvfrom makes the decision "Should I accept() or should I read()" based on whether SK_CONN is set or not. This usually works but is not safe. The decision should be based on whether it is a TCP_LISTEN socket or a TCP_CONNECTED socket. Signed-off-by: Neil Brown Cc: Adrian Bunk Cc: Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 61e307c..96521f1 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -973,7 +973,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) return 0; } - if (test_bit(SK_CONN, &svsk->sk_flags)) { + if (svsk->sk_sk->sk_state == TCP_LISTEN) { svc_tcp_accept(svsk); svc_sock_received(svsk); return 0; -- cgit v0.10.2 From ac4e0aba7daf0a7c6ac20974070428481dc940f5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Oct 2006 23:29:14 -0700 Subject: [PATCH] one more ARM IRQ fix Fix one more compile breakage caused by the post -rc1 IRQ changes. Signed-off-by: Adrian Bunk Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h index 18e8bb4..0ca20c6 100644 --- a/arch/arm/mach-lh7a40x/common.h +++ b/arch/arm/mach-lh7a40x/common.h @@ -15,4 +15,4 @@ extern void lh7a404_init_irq (void); extern void lh7a40x_clcd_init (void); extern void lh7a40x_init_board_irq (void); -#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs) +#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq)) -- cgit v0.10.2 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 diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a4f861b..9997081 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 v0.10.2 From 79cd22d3ac921b9209bf813c7e75e6b69e74896c Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 12 Oct 2006 14:29:33 +0900 Subject: ocfs2: delete redundant memcmp() This patch deletes redundant memcmp() while looking up in rb tree. Signed-off-by: Akinbou Mita Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index e1fceb8..d11753c 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c @@ -152,14 +152,16 @@ static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, struct o2nm_node *node, *ret = NULL; while (*p) { + int cmp; + parent = *p; node = rb_entry(parent, struct o2nm_node, nd_ip_node); - if (memcmp(&ip_needle, &node->nd_ipv4_address, - sizeof(ip_needle)) < 0) + cmp = memcmp(&ip_needle, &node->nd_ipv4_address, + sizeof(ip_needle)); + if (cmp < 0) p = &(*p)->rb_left; - else if (memcmp(&ip_needle, &node->nd_ipv4_address, - sizeof(ip_needle)) > 0) + else if (cmp > 0) p = &(*p)->rb_right; else { ret = node; -- cgit v0.10.2 From 711a40fcaa83bfad87736544b69f6fdd6527482d Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Wed, 11 Oct 2006 12:23:02 -0700 Subject: ocfs2: remove spurious d_count check in ocfs2_rename() This was causing some folks to incorrectly get -EBUSY during rename. Signed-off-by: Sunil Mushran Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 259155f..a57b751 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -1085,14 +1085,6 @@ static int ocfs2_rename(struct inode *old_dir, BUG(); } - if (atomic_read(&old_dentry->d_count) > 2) { - shrink_dcache_parent(old_dentry); - if (atomic_read(&old_dentry->d_count) > 2) { - status = -EBUSY; - goto bail; - } - } - /* Assume a directory heirarchy thusly: * a/b/c * a/d -- cgit v0.10.2 From 0effef776ff95b7a6d6e48a2ef407ecaa8c21f96 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 3 Oct 2006 17:44:42 -0700 Subject: ocfs2: fix page zeroing during simple extends The page zeroing code was missing the region between old i_size and new i_size for those extends that didn't actually require a change in space allocation. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d9ba0a9..b499c32 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -728,31 +728,36 @@ static int ocfs2_extend_file(struct inode *inode, clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - OCFS2_I(inode)->ip_clusters; - if (clusters_to_add) { - /* - * protect the pages that ocfs2_zero_extend is going to - * be pulling into the page cache.. we do this before the - * metadata extend so that we don't get into the situation - * where we've extended the metadata but can't get the data - * lock to zero. - */ - ret = ocfs2_data_lock(inode, 1); - if (ret < 0) { - mlog_errno(ret); - goto out; - } + /* + * protect the pages that ocfs2_zero_extend is going to be + * pulling into the page cache.. we do this before the + * metadata extend so that we don't get into the situation + * where we've extended the metadata but can't get the data + * lock to zero. + */ + ret = ocfs2_data_lock(inode, 1); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + if (clusters_to_add) { ret = ocfs2_extend_allocation(inode, clusters_to_add); if (ret < 0) { mlog_errno(ret); goto out_unlock; } + } - ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); - if (ret < 0) { - mlog_errno(ret); - goto out_unlock; - } + /* + * Call this even if we don't add any clusters to the tree. We + * still need to zero the area between the old i_size and the + * new i_size. + */ + ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); + if (ret < 0) { + mlog_errno(ret); + goto out_unlock; } if (!tail_to_skip) { @@ -764,8 +769,7 @@ static int ocfs2_extend_file(struct inode *inode, } out_unlock: - if (clusters_to_add) /* this is the only case in which we lock */ - ocfs2_data_unlock(inode, 1); + ocfs2_data_unlock(inode, 1); out: return ret; -- cgit v0.10.2 From e2057c5a63821e17c8a54dab6db680c77ce7ee6c Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 3 Oct 2006 17:53:05 -0700 Subject: ocfs2: cond_resched() in ocfs2_zero_extend() The loop within ocfs2_zero_extend() can execute for a long time, causing spurious soft lockup warnings. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b499c32..1be74c4 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -30,6 +30,7 @@ #include #include #include +#include #define MLOG_MASK_PREFIX ML_INODE #include @@ -691,6 +692,12 @@ static int ocfs2_zero_extend(struct inode *inode, } start_off += sb->s_blocksize; + + /* + * Very large extends have the potential to lock up + * the cpu for extended periods of time. + */ + cond_resched(); } out: -- cgit v0.10.2 From 559c9ac391c046710bdeee5581dc5d9dda794881 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Tue, 10 Oct 2006 15:15:55 -0700 Subject: configfs: handle kzalloc() failure in check_perm() check_perm() does not drop the reference to the module when kzalloc() failure occurs. Signed-Off-By: Chandra Seetharaman Signed-off-by: Joel Becker Signed-off-by: Mark Fasheh diff --git a/fs/configfs/file.c b/fs/configfs/file.c index e6d5754..cf33fac 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -275,13 +275,14 @@ static int check_perm(struct inode * inode, struct file * file) * it in file->private_data for easy access. */ buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL); - if (buffer) { - init_MUTEX(&buffer->sem); - buffer->needs_read_fill = 1; - buffer->ops = ops; - file->private_data = buffer; - } else + if (!buffer) { error = -ENOMEM; + goto Enomem; + } + init_MUTEX(&buffer->sem); + buffer->needs_read_fill = 1; + buffer->ops = ops; + file->private_data = buffer; goto Done; Einval: @@ -289,6 +290,7 @@ static int check_perm(struct inode * inode, struct file * file) goto Done; Eaccess: error = -EACCES; + Enomem: module_put(attr->ca_owner); Done: if (error && item) -- cgit v0.10.2 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 diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 310b618..2e7accf 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 v0.10.2 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 diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index f42c00e..671c24b 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 v0.10.2 From f248b6a34fdd726dd12b549fceba907b6df2771c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:00 +0200 Subject: [PATCH] x86-64: Update defconfig Signed-off-by: Andi Kleen diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 47bfba6e..0f5d44e 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc1 -# Thu Oct 5 13:04:43 2006 +# Linux kernel version: 2.6.19-rc2-git4 +# Sat Oct 21 03:38:52 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -335,8 +335,8 @@ CONFIG_IPV6=y # CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -438,6 +438,13 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_IBM_ASM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -1008,6 +1015,7 @@ CONFIG_I2C_ISA=m # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -1059,12 +1067,6 @@ CONFIG_SENSORS_SMSC47B397=m # CONFIG_HWMON_DEBUG_CHIP is not set # -# Misc devices -# -# CONFIG_IBM_ASM is not set -# CONFIG_TIFM_CORE is not set - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -1196,7 +1198,6 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -1242,6 +1243,7 @@ CONFIG_USB_MON=y # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1318,6 +1320,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1341,6 +1344,7 @@ CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y # # CD-ROM/DVD Filesystems @@ -1418,7 +1422,6 @@ CONFIG_SUNRPC=y # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # CONFIG_9P_FS is not set -CONFIG_GENERIC_ACL=y # # Partition Types @@ -1471,10 +1474,6 @@ CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y # -# Distributed Lock Manager -# - -# # Instrumentation Support # CONFIG_PROFILING=y @@ -1512,6 +1511,7 @@ CONFIG_DEBUG_FS=y CONFIG_UNWIND_INFO=y CONFIG_STACK_UNWIND=y # CONFIG_FORCED_INLINING is not set +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_LKDTM is not set # CONFIG_DEBUG_RODATA is not set -- cgit v0.10.2 From 13892de19eb9007ea47430c701bdbf69df71d883 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] i386: Update defconfig Signed-off-by: Andi Kleen diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 60c0c02..97aacd6 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc1 -# Thu Oct 5 13:04:53 2006 +# Linux kernel version: 2.6.19-rc2-git4 +# Sat Oct 21 03:38:56 2006 # CONFIG_X86_32=y CONFIG_GENERIC_TIME=y @@ -380,8 +380,8 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y # CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -483,6 +483,13 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_IBM_ASM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -1024,6 +1031,7 @@ CONFIG_HANGCHECK_TIMER=y # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -1032,12 +1040,6 @@ CONFIG_HANGCHECK_TIMER=y # CONFIG_HWMON_VID is not set # -# Misc devices -# -# CONFIG_IBM_ASM is not set -# CONFIG_TIFM_CORE is not set - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -1169,7 +1171,6 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -1215,6 +1216,7 @@ CONFIG_USB_MON=y # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1284,6 +1286,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1307,6 +1310,7 @@ CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y # # CD-ROM/DVD Filesystems @@ -1384,7 +1388,6 @@ CONFIG_SUNRPC=y # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # CONFIG_9P_FS is not set -CONFIG_GENERIC_ACL=y # # Partition Types @@ -1437,10 +1440,6 @@ CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y # -# Distributed Lock Manager -# - -# # Instrumentation Support # CONFIG_PROFILING=y @@ -1480,6 +1479,7 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_UNWIND_INFO=y CONFIG_STACK_UNWIND=y # CONFIG_FORCED_INLINING is not set +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_LKDTM is not set CONFIG_EARLY_PRINTK=y -- cgit v0.10.2 From 926fafebc48a3218fac675f12974f9a46473bd40 Mon Sep 17 00:00:00 2001 From: keith mannthey Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86-64: x86_64 hot-add memory srat.c fix This patch corrects the logic used in srat.c to figure out what parsing what action to take when registering hot-add areas. Hot-add areas should only be added to the node information for the MEMORY_HOTPLUG_RESERVE case. When booting MEMORY_HOTPLUG_SPARSE hot-add areas on everything but the last node are getting include in the node data and during kernel boot the pages are setup then the kernel dies when the pages are used. This patch fixes this issue. Signed-off-by: Keith Mannthey Signed-off-by: Andi Kleen diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 3cc0544..1087e15 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -207,7 +207,7 @@ static inline int save_add_info(void) return hotadd_percent > 0; } #else -int update_end_of_memory(unsigned long end) {return 0;} +int update_end_of_memory(unsigned long end) {return -1;} static int hotadd_enough_memory(struct bootnode *nd) {return 1;} #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE static inline int save_add_info(void) {return 1;} @@ -337,7 +337,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) push_node_boundaries(node, nd->start >> PAGE_SHIFT, nd->end >> PAGE_SHIFT); - if (ma->flags.hot_pluggable && !reserve_hotadd(node, start, end) < 0) { + if (ma->flags.hot_pluggable && (reserve_hotadd(node, start, end) < 0)) { /* Ignore hotadd region. Undo damage */ printk(KERN_NOTICE "SRAT: Hotplug region ignored\n"); *nd = oldnode; -- cgit v0.10.2 From 45edfd1db02f818b3dc7e4743ee8585af6b78f78 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86-64: typo in __assign_irq_vector when updating pos for vector and offset typo with cpu instead of new_cpu Signed-off-by: Yinghai Lu Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 49e94f7..b848f48 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -651,12 +651,12 @@ next: if (vector == IA32_SYSCALL_VECTOR) goto next; for_each_cpu_mask(new_cpu, domain) - if (per_cpu(vector_irq, cpu)[vector] != -1) + if (per_cpu(vector_irq, new_cpu)[vector] != -1) goto next; /* Found one! */ for_each_cpu_mask(new_cpu, domain) { - pos[cpu].vector = vector; - pos[cpu].offset = offset; + pos[new_cpu].vector = vector; + pos[new_cpu].offset = offset; } if (old_vector >= 0) { int old_cpu; -- cgit v0.10.2 From da8604cc2d6cd4cbde873c7ba308365e402ac7bf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] i386: fix .cfi_signal_frame copy-n-paste error This was copied, pasted but not edited. Cc: Andi Kleen Cc: Jan Beulich Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 7cc0b18..2d9d756 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -51,8 +51,8 @@ cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? -cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) CFLAGS += $(cflags-y) -- cgit v0.10.2 From 469b1d8741a5970ad49f2b5a837811579ba0b6f2 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86-64: Fix for arch/x86_64/pci/Makefile CFLAGS The arch/x86_64/pci directory was giving problems in a wierd cross-compile environment. The exact cause is unknown, but the Makefile used CFLAGS instead of EXTRA_CFLAGS. From what I can tell from Documentation/kbuild/makefiles.txt, CFLAGS should not be used for this, it should be EXTRA_CFLAGS. And it solves the cross-compile problem. Signed-off-by: Corey Minyard Signed-off-by: Andi Kleen Cc: Andi Kleen Cc: Vojtech Pavlik Cc: Sam Ravnborg Signed-off-by: Andrew Morton diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index 1eb18f4..149aba0 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile @@ -3,7 +3,7 @@ # # Reuse the i386 PCI subsystem # -CFLAGS += -Iarch/i386/pci +EXTRA_CFLAGS += -Iarch/i386/pci obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o -- cgit v0.10.2 From 73bb8919b33d42cf75a0ed89bc9ca6a7128665be Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86-64: fix page align in e820 allocator Currently some code pieces assume that address returned by find_e820_area() are page aligned. But looks like find_e820_area() had no such intention and hence one might end up stomping over some of the data. One such case is bootmem allocator initialization code stomped over bss. This patch modified find_e820_area() to return page aligned address. This might be little wasteful of memory but at the same time probably it is easier to handle page aligned memory. Signed-off-by: Vivek Goyal Signed-off-by: Andi Kleen Cc: Andi Kleen Signed-off-by: Andrew Morton diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index b3f0908..a75c829 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -54,13 +54,13 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) /* various gunk below that needed for SMP startup */ if (addr < 0x8000) { - *addrp = 0x8000; + *addrp = PAGE_ALIGN(0x8000); return 1; } /* direct mapping tables of the kernel */ if (last >= table_start<= INITRD_START && addr < INITRD_START+INITRD_SIZE) { - *addrp = INITRD_START + INITRD_SIZE; + *addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE); return 1; } #endif /* kernel code */ - if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { - *addrp = __pa_symbol(&_end); + if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) { + *addrp = PAGE_ALIGN(__pa_symbol(&_end)); return 1; } if (last >= ebda_addr && addr < ebda_addr + ebda_size) { - *addrp = ebda_addr + ebda_size; + *addrp = PAGE_ALIGN(ebda_addr + ebda_size); return 1; } @@ -152,7 +152,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi continue; while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size) ; - last = addr + size; + last = PAGE_ALIGN(addr) + size; if (last > ei->addr + ei->size) continue; if (last > end) -- cgit v0.10.2 From cdfce1f5714fec7b24715f569b2fee1607350a6d Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86: Use -maccumulate-outgoing-args This avoids some problems with gcc 4.x and earlier generating invalid unwind information. In 4.1 the option is default when unwind information is enabled. And it seems to generate smaller code too, so it's probably a good thing on its own. With gcc 4.0: i386: 4683198 902112 480868 6066178 5c9002 vmlinux (before) 4449895 902112 480868 5832875 5900ab vmlinux (after) x86-64: 4939761 1449584 648216 7037561 6b6279 vmlinux (before) 4854193 1449584 648216 6951993 6a1439 vmlinux (after) On 4.1 it shouldn't make much difference because it is default when unwind is enabled anyways. Suggested by Michael Matz and Jan Beulich Cc: jbeulich@novell.com Signed-off-by: Andi Kleen diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 2d9d756..0677908 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -42,6 +42,10 @@ cflags-$(CONFIG_REGPARM) += -mregparm=3 # temporary until string.h is fixed cflags-y += -ffreestanding +# this works around some issues with generating unwind tables in older gccs +# newer gccs do it by default +cflags-y += -maccumulate-outgoing-args + # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots: CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 1c0f18d..1397214 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -54,6 +54,10 @@ endif cflags-y += $(call cc-option,-funit-at-a-time) # prevent gcc from generating any FP code by mistake cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) +# this works around some issues with generating unwind tables in older gccs +# newer gccs do it by default +cflags-y += -maccumulate-outgoing-args + # do binutils support CFI? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -- cgit v0.10.2 From 690a973f48b6ba2954465992c08e65059c8374fe Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Sat, 21 Oct 2006 18:37:01 +0200 Subject: [PATCH] x86-64: Speed up dwarf2 unwinder This changes the dwarf2 unwinder to do a binary search for CIEs instead of a linear work. The linker is unfortunately not able to build a proper lookup table at link time, instead it creates one at runtime as soon as the bootmem allocator is usable (so you'll continue using the linear lookup for the first [hopefully] few calls). The code should be ready to utilize a build-time created table once a fixed linker becomes available. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen diff --git a/Makefile b/Makefile index 62a1343..389ff0c 100644 --- a/Makefile +++ b/Makefile @@ -499,6 +499,7 @@ endif ifdef CONFIG_UNWIND_INFO CFLAGS += -fasynchronous-unwind-tables +LDFLAGS_vmlinux += --eh-frame-hdr endif ifdef CONFIG_DEBUG_INFO diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 69240b5..9d0d11c 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -125,6 +125,10 @@ *(__param) \ VMLINUX_SYMBOL(__stop___param) = .; \ } \ + \ + /* Unwind data binary search table */ \ + EH_FRAME_HDR \ + \ __end_rodata = .; \ . = ALIGN(4096); @@ -157,6 +161,18 @@ *(.kprobes.text) \ VMLINUX_SYMBOL(__kprobes_text_end) = .; +#ifdef CONFIG_STACK_UNWIND + /* Unwind data binary search table */ +#define EH_FRAME_HDR \ + .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_unwind_hdr) = .; \ + *(.eh_frame_hdr) \ + VMLINUX_SYMBOL(__end_unwind_hdr) = .; \ + } +#else +#define EH_FRAME_HDR +#endif + /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ diff --git a/include/linux/unwind.h b/include/linux/unwind.h index 73e1751..749928c 100644 --- a/include/linux/unwind.h +++ b/include/linux/unwind.h @@ -26,6 +26,7 @@ struct module; * Initialize unwind support. */ extern void unwind_init(void); +extern void unwind_setup(void); #ifdef CONFIG_MODULES @@ -73,6 +74,7 @@ extern int unwind_to_user(struct unwind_frame_info *); struct unwind_frame_info {}; static inline void unwind_init(void) {} +static inline void unwind_setup(void) {} #ifdef CONFIG_MODULES diff --git a/init/main.c b/init/main.c index ee12324..36f608a 100644 --- a/init/main.c +++ b/init/main.c @@ -503,6 +503,7 @@ asmlinkage void __init start_kernel(void) printk(KERN_NOTICE); printk(linux_banner); setup_arch(&command_line); + unwind_setup(); setup_per_cpu_areas(); smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ diff --git a/kernel/unwind.c b/kernel/unwind.c index 2e23686..f7e50d1 100644 --- a/kernel/unwind.c +++ b/kernel/unwind.c @@ -11,13 +11,15 @@ #include #include -#include +#include +#include #include #include #include #include extern char __start_unwind[], __end_unwind[]; +extern const u8 __start_unwind_hdr[], __end_unwind_hdr[]; #define MAX_STACK_DEPTH 8 @@ -100,6 +102,8 @@ static struct unwind_table { } core, init; const void *address; unsigned long size; + const unsigned char *header; + unsigned long hdrsz; struct unwind_table *link; const char *name; } root_table; @@ -145,6 +149,10 @@ static struct unwind_table *find_table(unsigned long pc) return table; } +static unsigned long read_pointer(const u8 **pLoc, + const void *end, + signed ptrType); + static void init_unwind_table(struct unwind_table *table, const char *name, const void *core_start, @@ -152,14 +160,30 @@ static void init_unwind_table(struct unwind_table *table, const void *init_start, unsigned long init_size, const void *table_start, - unsigned long table_size) + unsigned long table_size, + const u8 *header_start, + unsigned long header_size) { + const u8 *ptr = header_start + 4; + const u8 *end = header_start + header_size; + table->core.pc = (unsigned long)core_start; table->core.range = core_size; table->init.pc = (unsigned long)init_start; table->init.range = init_size; table->address = table_start; table->size = table_size; + /* See if the linker provided table looks valid. */ + if (header_size <= 4 + || header_start[0] != 1 + || (void *)read_pointer(&ptr, end, header_start[1]) != table_start + || header_start[2] == DW_EH_PE_omit + || read_pointer(&ptr, end, header_start[2]) <= 0 + || header_start[3] == DW_EH_PE_omit) + header_start = NULL; + table->hdrsz = header_size; + smp_wmb(); + table->header = header_start; table->link = NULL; table->name = name; } @@ -169,7 +193,143 @@ void __init unwind_init(void) init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0, - __start_unwind, __end_unwind - __start_unwind); + __start_unwind, __end_unwind - __start_unwind, + __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr); +} + +static const u32 bad_cie, not_fde; +static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *); +static signed fde_pointer_type(const u32 *cie); + +struct eh_frame_hdr_table_entry { + unsigned long start, fde; +}; + +static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2) +{ + const struct eh_frame_hdr_table_entry *e1 = p1; + const struct eh_frame_hdr_table_entry *e2 = p2; + + return (e1->start > e2->start) - (e1->start < e2->start); +} + +static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size) +{ + struct eh_frame_hdr_table_entry *e1 = p1; + struct eh_frame_hdr_table_entry *e2 = p2; + unsigned long v; + + v = e1->start; + e1->start = e2->start; + e2->start = v; + v = e1->fde; + e1->fde = e2->fde; + e2->fde = v; +} + +static void __init setup_unwind_table(struct unwind_table *table, + void *(*alloc)(unsigned long)) +{ + const u8 *ptr; + unsigned long tableSize = table->size, hdrSize; + unsigned n; + const u32 *fde; + struct { + u8 version; + u8 eh_frame_ptr_enc; + u8 fde_count_enc; + u8 table_enc; + unsigned long eh_frame_ptr; + unsigned int fde_count; + struct eh_frame_hdr_table_entry table[]; + } __attribute__((__packed__)) *header; + + if (table->header) + return; + + if (table->hdrsz) + printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n", + table->name); + + if (tableSize & (sizeof(*fde) - 1)) + return; + + for (fde = table->address, n = 0; + tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + const u32 *cie = cie_for_fde(fde, table); + signed ptrType; + + if (cie == ¬_fde) + continue; + if (cie == NULL + || cie == &bad_cie + || (ptrType = fde_pointer_type(cie)) < 0) + return; + ptr = (const u8 *)(fde + 2); + if (!read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType)) + return; + ++n; + } + + if (tableSize || !n) + return; + + hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int) + + 2 * n * sizeof(unsigned long); + header = alloc(hdrSize); + if (!header) + return; + header->version = 1; + header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native; + header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4; + header->table_enc = DW_EH_PE_abs|DW_EH_PE_native; + put_unaligned((unsigned long)table->address, &header->eh_frame_ptr); + BUILD_BUG_ON(offsetof(typeof(*header), fde_count) + % __alignof(typeof(header->fde_count))); + header->fde_count = n; + + BUILD_BUG_ON(offsetof(typeof(*header), table) + % __alignof(typeof(*header->table))); + for (fde = table->address, tableSize = table->size, n = 0; + tableSize; + tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); + + if (!fde[1]) + continue; /* this is a CIE */ + ptr = (const u8 *)(fde + 2); + header->table[n].start = read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + fde_pointer_type(cie)); + header->table[n].fde = (unsigned long)fde; + ++n; + } + WARN_ON(n != header->fde_count); + + sort(header->table, + n, + sizeof(*header->table), + cmp_eh_frame_hdr_table_entries, + swap_eh_frame_hdr_table_entries); + + table->hdrsz = hdrSize; + smp_wmb(); + table->header = (const void *)header; +} + +static void *__init balloc(unsigned long sz) +{ + return __alloc_bootmem_nopanic(sz, + sizeof(unsigned int), + __pa(MAX_DMA_ADDRESS)); +} + +void __init unwind_setup(void) +{ + setup_unwind_table(&root_table, balloc); } #ifdef CONFIG_MODULES @@ -193,7 +353,8 @@ void *unwind_add_table(struct module *module, init_unwind_table(table, module->name, module->module_core, module->core_size, module->module_init, module->init_size, - table_start, table_size); + table_start, table_size, + NULL, 0); if (last_table) last_table->link = table; @@ -303,6 +464,26 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) return value; } +static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table) +{ + const u32 *cie; + + if (!*fde || (*fde & (sizeof(*fde) - 1))) + return &bad_cie; + if (!fde[1]) + return ¬_fde; /* this is a CIE */ + if ((fde[1] & (sizeof(*fde) - 1)) + || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) + return NULL; /* this is not a valid FDE */ + cie = fde + 1 - fde[1] / sizeof(*fde); + if (*cie <= sizeof(*cie) + 4 + || *cie >= fde[1] - sizeof(*fde) + || (*cie & (sizeof(*cie) - 1)) + || cie[1]) + return NULL; /* this is not a (valid) CIE */ + return cie; +} + static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrType) @@ -610,49 +791,108 @@ int unwind(struct unwind_frame_info *frame) unsigned i; signed ptrType = -1; uleb128_t retAddrReg = 0; - struct unwind_table *table; + const struct unwind_table *table; struct unwind_state state; if (UNW_PC(frame) == 0) return -EINVAL; if ((table = find_table(pc)) != NULL && !(table->size & (sizeof(*fde) - 1))) { - unsigned long tableSize = table->size; - - for (fde = table->address; - tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; - tableSize -= sizeof(*fde) + *fde, - fde += 1 + *fde / sizeof(*fde)) { - if (!*fde || (*fde & (sizeof(*fde) - 1))) - break; - if (!fde[1]) - continue; /* this is a CIE */ - if ((fde[1] & (sizeof(*fde) - 1)) - || fde[1] > (unsigned long)(fde + 1) - - (unsigned long)table->address) - continue; /* this is not a valid FDE */ - cie = fde + 1 - fde[1] / sizeof(*fde); - if (*cie <= sizeof(*cie) + 4 - || *cie >= fde[1] - sizeof(*fde) - || (*cie & (sizeof(*cie) - 1)) - || cie[1] - || (ptrType = fde_pointer_type(cie)) < 0) { - cie = NULL; /* this is not a (valid) CIE */ - continue; + const u8 *hdr = table->header; + unsigned long tableSize; + + smp_rmb(); + if (hdr && hdr[0] == 1) { + switch(hdr[3] & DW_EH_PE_FORM) { + case DW_EH_PE_native: tableSize = sizeof(unsigned long); break; + case DW_EH_PE_data2: tableSize = 2; break; + case DW_EH_PE_data4: tableSize = 4; break; + case DW_EH_PE_data8: tableSize = 8; break; + default: tableSize = 0; break; + } + ptr = hdr + 4; + end = hdr + table->hdrsz; + if (tableSize + && read_pointer(&ptr, end, hdr[1]) + == (unsigned long)table->address + && (i = read_pointer(&ptr, end, hdr[2])) > 0 + && i == (end - ptr) / (2 * tableSize) + && !((end - ptr) % (2 * tableSize))) { + do { + const u8 *cur = ptr + (i / 2) * (2 * tableSize); + + startLoc = read_pointer(&cur, + cur + tableSize, + hdr[3]); + if (pc < startLoc) + i /= 2; + else { + ptr = cur - tableSize; + i = (i + 1) / 2; + } + } while (startLoc && i > 1); + if (i == 1 + && (startLoc = read_pointer(&ptr, + ptr + tableSize, + hdr[3])) != 0 + && pc >= startLoc) + fde = (void *)read_pointer(&ptr, + ptr + tableSize, + hdr[3]); } + } + + if (fde != NULL) { + cie = cie_for_fde(fde, table); ptr = (const u8 *)(fde + 2); - startLoc = read_pointer(&ptr, - (const u8 *)(fde + 1) + *fde, - ptrType); - endLoc = startLoc - + read_pointer(&ptr, - (const u8 *)(fde + 1) + *fde, - ptrType & DW_EH_PE_indirect - ? ptrType - : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); - if (pc >= startLoc && pc < endLoc) - break; - cie = NULL; + if(cie != NULL + && cie != &bad_cie + && cie != ¬_fde + && (ptrType = fde_pointer_type(cie)) >= 0 + && read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType) == startLoc) { + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed; + endLoc = startLoc + + read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType); + if(pc >= endLoc) + fde = NULL; + } else + fde = NULL; + } + if (fde == NULL) { + for (fde = table->address, tableSize = table->size; + cie = NULL, tableSize > sizeof(*fde) + && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, + fde += 1 + *fde / sizeof(*fde)) { + cie = cie_for_fde(fde, table); + if (cie == &bad_cie) { + cie = NULL; + break; + } + if (cie == NULL + || cie == ¬_fde + || (ptrType = fde_pointer_type(cie)) < 0) + continue; + ptr = (const u8 *)(fde + 2); + startLoc = read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType); + if (!startLoc) + continue; + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed; + endLoc = startLoc + + read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType); + if (pc >= startLoc && pc < endLoc) + break; + } } } if (cie != NULL) { -- cgit v0.10.2 From 7a71cef780404e8c90d23b1131142e158d94354b Mon Sep 17 00:00:00 2001 From: "bibo,mao" Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86-64: x86_64 add NX mask for PTE entry If function change_page_attr_addr calls revert_page to revert to original pte value, mk_pte_phys does not mask NX bit. If NX bit is set on no NX hardware supported x86_64 machine, there is will be RSVD type page fault and system will crash. This patch adds NX mask bit for PTE entry. Signed-off-by: bibo,mao Signed-off-by: Andi Kleen diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 6899e77..0555c1c 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -366,6 +366,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) { pte_t pte; pte_val(pte) = physpage | pgprot_val(pgprot); + pte_val(pte) &= __supported_pte_mask; return pte; } -- cgit v0.10.2 From 26fd5e084e470dbe8edc6f726fc918e89b9f988c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] i386: Fix fake return address The fake return address was being set to __KERNEL_PDA, rather than 0. Push it earlier while %eax still equals 0. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Andi Kleen Cc: Andi Kleen Cc: Andrew Morton diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index be9d883..ca31f18 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -317,7 +317,7 @@ is386: movl $2,%ecx # set MP movl %eax,%gs lldt %ax cld # gcc2 wants the direction flag cleared at all times - pushl %eax # fake return address + pushl $0 # fake return address for unwinder #ifdef CONFIG_SMP movb ready, %cl movb $1, ready -- cgit v0.10.2 From cc7d479fe56133e79840beffe9cb4fd193af93aa Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86-64: Fix ENOSYS in system call tracing This patch: - out of range system calls failing to return -ENOSYS under system call tracing [AK: split out from another patch by Jan as separate bugfix] Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 38a7b2d..038dcf7 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -315,6 +315,8 @@ tracesys: LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST cmpq $__NR_syscall_max,%rax + movq $-ENOSYS,%rcx + cmova %rcx,%rax ja 1f movq %r10,%rcx /* fixup for C */ call *sys_call_table(,%rax,8) -- cgit v0.10.2 From 581910e2eb952e541b8ca9b5f551d6c124903b61 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86-64: Revert interrupt backlink changes They break more than they fix Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 038dcf7..e3eddde 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -537,8 +537,6 @@ END(stub_rt_sigreturn) 1: incl %gs:pda_irqcount cmoveq %gs:pda_irqstackptr,%rsp push %rbp # backlink for old unwinder - CFI_ADJUST_CFA_OFFSET 8 - CFI_REL_OFFSET rbp,0 /* * We entered an interrupt context - irqs are off: */ @@ -1178,7 +1176,6 @@ ENTRY(call_softirq) incl %gs:pda_irqcount cmove %gs:pda_irqstackptr,%rsp push %rbp # backlink for old unwinder - CFI_ADJUST_CFA_OFFSET 8 call __do_softirq leaveq CFI_DEF_CFA_REGISTER rsp -- cgit v0.10.2 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 diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 3e8e3ad..eaafe23 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 b8b596d..37deee6 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 38dc403..904bf3d 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 v0.10.2 From 6bf2dafad18c119beb534cbb3d882fe7a6c3f529 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86-64: Use irq_domain in ioapic_retrigger_irq Thanks to YH Lu for spotting this. It appears I missed this function when I refactored allocate_irq_vector and introduced irq_domain, with the result that all retriggered irqs would go to cpu 0 even if we were not prepared to receive them there. While reviewing YH's patch I also noticed that this function was missing locking, and since I am now reading two values from two diffrent arrays that looks like a race we might be able to hit in the real world. Cc: Yinghai Lu Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index b848f48..8a9a357 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1255,12 +1255,15 @@ static int ioapic_retrigger_irq(unsigned int irq) { cpumask_t mask; unsigned vector; + unsigned long flags; + spin_lock_irqsave(&vector_lock, flags); vector = irq_vector[irq]; cpus_clear(mask); - cpu_set(vector >> 8, mask); + cpu_set(first_cpu(irq_domain[irq]), mask); - send_IPI_mask(mask, vector & 0xff); + send_IPI_mask(mask, vector); + spin_unlock_irqrestore(&vector_lock, flags); return 1; } -- cgit v0.10.2 From 8cf2c51927bbeefafc25193d01b91f9ed3806e96 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86: Revert new unwind kernel stack termination Jan convinced me that it was unnecessary because the assembly stubs do this already on the stack. Cc: jbeulich@novell.com Signed-off-by: Andi Kleen diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 57d3759..1e1fa3e 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -336,7 +336,6 @@ extern void kernel_thread_helper(void); int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; - int err; memset(®s, 0, sizeof(regs)); @@ -351,10 +350,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; /* Ok, create the new process.. */ - err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); - if (err == 0) /* terminate kernel stack */ - task_pt_regs(current)->eip = 0; - return err; + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index e3eddde..7d401b0 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -980,11 +980,6 @@ ENTRY(kernel_thread) call do_fork movq %rax,RAX(%rsp) xorl %edi,%edi - test %rax,%rax - jnz 1f - /* terminate stack in child */ - movq %rdi,RIP(%rsp) -1: /* * It isn't worth to check for reschedule here, -- cgit v0.10.2 From 84f404f695b16bd142c8dd9910d5a398f54fb044 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] x86-64: Put more than one cpu in TARGET_CPUS TARGET_CPUS is the default irq routing poicy. It specifies which cpus the kernel should aim an irq at. In physflat delivery mode we can route an irq to a single cpu. But that doesn't mean our default policy should only be a single cpu is allowed. By allowing the irq routing code to select from multiple cpus this enables systems with more irqs then we can service on a single processor to actually work. I just audited and tested the code and irqbalance doesn't care, and the io_apic.c doesn't care if we have extra cpus in the mask. Everything will use or assume we are using the lowest numbered cpu in the mask if we can't use them all. So this should result in no behavior changes except on systems that need it. Thanks for YH Lu for spotting this problem in his testing. Cc: Yinghai Lu Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c index 0dfc223..7c01db8 100644 --- a/arch/x86_64/kernel/genapic_flat.c +++ b/arch/x86_64/kernel/genapic_flat.c @@ -153,7 +153,7 @@ struct genapic apic_flat = { static cpumask_t physflat_target_cpus(void) { - return cpumask_of_cpu(0); + return cpu_online_map; } static cpumask_t physflat_vector_allocation_domain(int cpu) -- cgit v0.10.2 From dbaab49f92ff6ae6255762a948375e4036cbdbd2 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Sat, 21 Oct 2006 18:37:03 +0200 Subject: [PATCH] x86-64: Overlapping program headers in physical addr space fix o A recent change to vmlinux.ld.S file broke kexec as now resulting vmlinux program headers are overlapping in physical address space. o Now all the vsyscall related sections are placed after data and after that mostly init data sections are placed. To avoid physical overlap among phdrs, there are three possible solutions. - Place vsyscall sections also in data phdrs instead of user - move vsyscal sections after init data in bss. - create another phdrs say data.init and move all the sections after vsyscall into this new phdr. o This patch implements the third solution. Signed-off-by: Vivek Goyal Signed-off-by: Andi Kleen Cc: Magnus Damm Cc: Andi Kleen Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index b9df2ab..1283614 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -17,6 +17,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* R_E */ data PT_LOAD FLAGS(7); /* RWE */ user PT_LOAD FLAGS(7); /* RWE */ + data.init PT_LOAD FLAGS(7); /* RWE */ note PT_NOTE FLAGS(4); /* R__ */ } SECTIONS @@ -131,7 +132,7 @@ SECTIONS . = ALIGN(8192); /* init_task */ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { *(.data.init_task) - } :data + }:data.init . = ALIGN(4096); .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { -- cgit v0.10.2 From e70ea8c09db0e25ab58f84ba7f393e5c9125a8ee Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:03 +0200 Subject: [PATCH] x86-64: Revert timer routing behaviour back to 2.6.16 state By default route the 8254 over the 8259 and only disable it on ATI boards where this causes double timer interrupts. This should unbreak some Nvidia boards where the timer doesn't seem to tick of it isn't enabled in the 8259. At least one VIA board also seemed to have a little trouble with the disabled 8259. For 2.6.20 we'll try both dynamically without black listing, but I think for .19 this is the safer approach because it has been already well tested in earlier kernels. This also makes the x86-64 behaviour the same as i386. Command line options can change all this of course. Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c index 208e38a..2b1245d 100644 --- a/arch/x86_64/kernel/early-quirks.c +++ b/arch/x86_64/kernel/early-quirks.c @@ -61,10 +61,11 @@ static void nvidia_bugs(void) static void ati_bugs(void) { -#if 1 /* for testing */ - printk("ATI board detected\n"); -#endif - /* No bugs right now */ + if (timer_over_8254 == 1) { + timer_over_8254 = 0; + printk(KERN_INFO + "ATI board detected. Disabling timer routing over 8254.\n"); + } } struct chipset { diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 8a9a357..b000017 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -57,7 +57,7 @@ static int no_timer_check; static int disable_timer_pin_1 __initdata; -int timer_over_8254 __initdata = 0; +int timer_over_8254 __initdata = 1; /* Where if anywhere is the i8259 connect in external int mode */ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index c181fef..e72cfcd 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -122,6 +122,8 @@ extern int fix_aperture; extern int reboot_force; extern int notsc_setup(char *); +extern int timer_over_8254; + extern int gsi_irq_sharing(int gsi); extern void smp_local_timer_interrupt(void); -- cgit v0.10.2 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 diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 0c9f1e7..a864016 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 v0.10.2 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 diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 5823e3b..36d1c3f 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ce0d35f..fa84983 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67ecd66..95efdb5 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 v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ab92cc7..e2ed249 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 12cd7b5..b378880 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 005965f..a665612 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 67260eb..5360ec0 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 2f98b8f..f574078 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 v0.10.2 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 diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index db23249..1eae16b 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 v0.10.2 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 diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index e963dbf..f56b00e 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 v0.10.2 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 diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2802db2..44c9f99 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 v0.10.2 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 diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 5719704..5250187 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 v0.10.2 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 diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 3f4aa0c..03f6338 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 v0.10.2 From 3343571d9f88a0de542d33aea9ab881f00ff866d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 19 Oct 2006 14:44:53 +0900 Subject: [PATCH] libata: typo fix Typo fix in commment. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/include/linux/libata.h b/include/linux/libata.h index d0a7ad5..b03d5a3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -143,7 +143,7 @@ enum { ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ - ATA_DFLAG_NCQ_OFF = (1 << 9), /* devied limited to non-NCQ mode */ + ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */ ATA_DFLAG_SUSPENDED = (1 << 10), /* device suspended */ ATA_DFLAG_INIT_MASK = (1 << 16) - 1, -- cgit v0.10.2 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 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2592912..cef2e70 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 v0.10.2 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 diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 06daaa3..7645f2b 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 v0.10.2 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 diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index b401383..96cb1f0 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 ee2ddea..23d0681 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 c382df0..7ac68cb 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 v0.10.2 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 diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 5b77a5b..ad418ce 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 v0.10.2 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 diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 171ff41..a6260f0 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 1250f0e..74f17a9 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 v0.10.2 From da3ed32fe568148ede256975d40825ffcdac767b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 21 Oct 2006 10:24:08 -0700 Subject: [PATCH] md: add another COMPAT_IOCTL for md .. so that you can use bitmaps with 32bit userspace on a 64 bit kernel. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index cfdb4f6a..c26c3ad 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -131,6 +131,7 @@ COMPATIBLE_IOCTL(RUN_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY_RO) COMPATIBLE_IOCTL(RESTART_ARRAY_RW) +COMPATIBLE_IOCTL(GET_BITMAP_FILE) ULONG_IOCTL(SET_BITMAP_FILE) /* DM */ COMPATIBLE_IOCTL(DM_VERSION_32) -- cgit v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index f7f1908..7daa7b1 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 b6ebc69..3f2cd98 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 v0.10.2 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 diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index d47d38a..d6f6147 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 84d8877..ebd42a3 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 v0.10.2 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 diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 7ad3be8..7fcb77a 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 v0.10.2 From d42552c3ace1fa1f16ae02ce642f4c733cec40ca Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 21 Oct 2006 10:24:12 -0700 Subject: [PATCH] pci: declare pci_get_device_reverse() We seem to have lost the declaration of pci_get_device_reverse(), if we ever had one. Add a CONFIG_PCI=0 stub too. Acked-by: Alan Cox Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/pci.h b/include/linux/pci.h index 4689e2a..09be0f8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -455,7 +455,11 @@ 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_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from); +struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, + struct pci_dev *from); +struct pci_dev *pci_get_device_reverse(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); @@ -660,7 +664,12 @@ static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn) { return NULL; } -static inline struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from) +static inline struct pci_dev *pci_get_device(unsigned int vendor, + unsigned int device, struct pci_dev *from) +{ return NULL; } + +static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor, + unsigned int device, struct pci_dev *from) { return NULL; } static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, -- cgit v0.10.2 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 diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2802db2..44c9f99 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 v0.10.2 From 7516795739bd53175629b90fab0ad488d7a6a9f7 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Sat, 21 Oct 2006 10:24:14 -0700 Subject: [PATCH] Reintroduce NODES_SPAN_OTHER_NODES for powerpc Reintroduce NODES_SPAN_OTHER_NODES for powerpc Revert "[PATCH] Remove SPAN_OTHER_NODES config definition" This reverts commit f62859bb6871c5e4a8e591c60befc8caaf54db8c. Revert "[PATCH] mm: remove arch independent NODES_SPAN_OTHER_NODES" This reverts commit a94b3ab7eab4edcc9b2cb474b188f774c331adf7. Also update the comments to indicate that this is still required and where its used. Signed-off-by: Andy Whitcroft Cc: Paul Mackerras Cc: Mike Kravetz Cc: Benjamin Herrenschmidt Acked-by: Mel Gorman Acked-by: Will Schmidt Cc: Christoph Lameter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8b69104..2bd9b7f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -751,6 +751,15 @@ config ARCH_MEMORY_PROBE def_bool y depends on MEMORY_HOTPLUG +# Some NUMA nodes have memory ranges that span +# other nodes. Even though a pfn is valid and +# between a node's start and end pfns, it may not +# reside on that node. See memmap_init_zone() +# for details. +config NODES_SPAN_OTHER_NODES + def_bool y + depends on NEED_MULTIPLE_NODES + config PPC_64K_PAGES bool "64k page size" depends on PPC64 diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 9828663..d2833c1 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -184,6 +184,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_NODES_SPAN_OTHER_NODES=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 59855b8..ed0762b 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -674,6 +674,12 @@ void sparse_init(void); #define sparse_index_init(_sec, _nid) do {} while (0) #endif /* CONFIG_SPARSEMEM */ +#ifdef CONFIG_NODES_SPAN_OTHER_NODES +#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid)) +#else +#define early_pfn_in_nid(pfn, nid) (1) +#endif + #ifndef early_pfn_valid #define early_pfn_valid(pfn) (1) #endif diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ebd425c..f5fc454 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1689,6 +1689,8 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, for (pfn = start_pfn; pfn < end_pfn; pfn++) { if (!early_pfn_valid(pfn)) continue; + if (!early_pfn_in_nid(pfn, nid)) + continue; page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); init_page_count(page); -- cgit v0.10.2 From aedb0eb107961a234f7c38e53da65a8f7ea992a9 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Sat, 21 Oct 2006 10:24:16 -0700 Subject: [PATCH] Slab: Do not fallback to nodes that have not been bootstrapped yet The zonelist may contain zones of nodes that have not been bootstrapped and we will oops if we try to allocate from those zones. So check if the node information for the slab and the node have been setup before attempting an allocation. If it has not been setup then skip that zone. Usually we will not encounter this situation since the slab bootstrap code avoids falling back before we have setup the respective nodes but we seem to have a special needs for pppc. Signed-off-by: Christoph Lameter Acked-by: Andy Whitcroft Cc: Paul Mackerras Cc: Mike Kravetz Cc: Benjamin Herrenschmidt Acked-by: Mel Gorman Acked-by: Will Schmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index 266449d..84c631f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3152,12 +3152,15 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) struct zone **z; void *obj = NULL; - for (z = zonelist->zones; *z && !obj; z++) + for (z = zonelist->zones; *z && !obj; z++) { + int nid = zone_to_nid(*z); + if (zone_idx(*z) <= ZONE_NORMAL && - cpuset_zone_allowed(*z, flags)) + cpuset_zone_allowed(*z, flags) && + cache->nodelists[nid]) obj = __cache_alloc_node(cache, - flags | __GFP_THISNODE, - zone_to_nid(*z)); + flags | __GFP_THISNODE, nid); + } return obj; } -- cgit v0.10.2 From faf6bbcf94caee10ba34adb86db4ecca96bfd3bf Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sat, 21 Oct 2006 10:24:17 -0700 Subject: [PATCH] cpuset: mempolicy migration typo fix Mistyped an ifdef CONFIG_CPUSETS - fixed. I doubt that anyone ever noticed. The impact of this typo was that if someone: 1) was using MPOL_BIND to force off node allocations 2) while using cpusets to constrain memory placement 3) when that cpuset was migrating that jobs memory 4) while the tasks in that job were actively forking then there was a rare chance that future allocations using that MPOL_BIND policy would be node local, not off node. Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 09f0f57..daabb3a 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -150,7 +150,7 @@ extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new); extern void mpol_fix_fork_child_flag(struct task_struct *p); #define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x)) -#ifdef CONFIG_CPUSET +#ifdef CONFIG_CPUSETS #define current_cpuset_is_being_rebound() \ (cpuset_being_rebound == current->cpuset) #else -- cgit v0.10.2 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 diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 91f95d1..01a5a70 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 v0.10.2 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 diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index dcccaf2..bc66026 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 v0.10.2 From 9eaef27b36a6b716384948da94b8fc5bfba7b712 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 21 Oct 2006 10:24:20 -0700 Subject: [PATCH] VFS: Make d_materialise_unique() enforce directory uniqueness If the caller tries to instantiate a directory using an inode that already has a dentry alias, then we attempt to rename the existing dentry instead of instantiating a new one. Fail with an ELOOP error if the rename would affect one of our parent directories. This behaviour is needed in order to avoid issues such as http://bugzilla.kernel.org/show_bug.cgi?id=7178 Signed-off-by: Trond Myklebust Cc: Miklos Szeredi Cc: Maneesh Soni Cc: Dipankar Sarma Cc: Neil Brown Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/dcache.c b/fs/dcache.c index 2bac4ba..a1ff91e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1469,23 +1469,21 @@ static void switch_names(struct dentry *dentry, struct dentry *target) * deleted it. */ -/** - * d_move - move a dentry +/* + * d_move_locked - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. */ - -void d_move(struct dentry * dentry, struct dentry * target) +static void d_move_locked(struct dentry * dentry, struct dentry * target) { struct hlist_head *list; if (!dentry->d_inode) printk(KERN_WARNING "VFS: moving negative dcache entry\n"); - spin_lock(&dcache_lock); write_seqlock(&rename_lock); /* * XXXX: do we really need to take target->d_lock? @@ -1536,10 +1534,84 @@ already_unhashed: fsnotify_d_move(dentry); spin_unlock(&dentry->d_lock); write_sequnlock(&rename_lock); +} + +/** + * d_move - move a dentry + * @dentry: entry to move + * @target: new dentry + * + * Update the dcache to reflect the move of a file name. Negative + * dcache entries should not be moved in this way. + */ + +void d_move(struct dentry * dentry, struct dentry * target) +{ + spin_lock(&dcache_lock); + d_move_locked(dentry, target); spin_unlock(&dcache_lock); } /* + * Helper that returns 1 if p1 is a parent of p2, else 0 + */ +static int d_isparent(struct dentry *p1, struct dentry *p2) +{ + struct dentry *p; + + for (p = p2; p->d_parent != p; p = p->d_parent) { + if (p->d_parent == p1) + return 1; + } + return 0; +} + +/* + * This helper attempts to cope with remotely renamed directories + * + * It assumes that the caller is already holding + * dentry->d_parent->d_inode->i_mutex and the dcache_lock + * + * Note: If ever the locking in lock_rename() changes, then please + * remember to update this too... + * + * On return, dcache_lock will have been unlocked. + */ +static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) +{ + struct mutex *m1 = NULL, *m2 = NULL; + struct dentry *ret; + + /* If alias and dentry share a parent, then no extra locks required */ + if (alias->d_parent == dentry->d_parent) + goto out_unalias; + + /* Check for loops */ + ret = ERR_PTR(-ELOOP); + if (d_isparent(alias, dentry)) + goto out_err; + + /* See lock_rename() */ + ret = ERR_PTR(-EBUSY); + if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) + goto out_err; + m1 = &dentry->d_sb->s_vfs_rename_mutex; + if (!mutex_trylock(&alias->d_parent->d_inode->i_mutex)) + goto out_err; + m2 = &alias->d_parent->d_inode->i_mutex; +out_unalias: + d_move_locked(alias, dentry); + ret = alias; +out_err: + spin_unlock(&dcache_lock); + if (m2) + mutex_unlock(m2); + if (m1) + mutex_unlock(m1); + return ret; +} + +/* * Prepare an anonymous dentry for life in the superblock's dentry tree as a * named dentry in place of the dentry to be replaced. */ @@ -1581,7 +1653,7 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) */ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) { - struct dentry *alias, *actual; + struct dentry *actual; BUG_ON(!d_unhashed(dentry)); @@ -1593,26 +1665,27 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) goto found_lock; } - /* See if a disconnected directory already exists as an anonymous root - * that we should splice into the tree instead */ - if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) { - spin_lock(&alias->d_lock); - - /* Is this a mountpoint that we could splice into our tree? */ - if (IS_ROOT(alias)) - goto connect_mountpoint; - - if (alias->d_name.len == dentry->d_name.len && - alias->d_parent == dentry->d_parent && - memcmp(alias->d_name.name, - dentry->d_name.name, - dentry->d_name.len) == 0) - goto replace_with_alias; - - spin_unlock(&alias->d_lock); - - /* Doh! Seem to be aliasing directories for some reason... */ - dput(alias); + if (S_ISDIR(inode->i_mode)) { + struct dentry *alias; + + /* Does an aliased dentry already exist? */ + alias = __d_find_alias(inode, 0); + if (alias) { + actual = alias; + /* Is this an anonymous mountpoint that we could splice + * into our tree? */ + if (IS_ROOT(alias)) { + spin_lock(&alias->d_lock); + __d_materialise_dentry(dentry, alias); + __d_drop(alias); + goto found; + } + /* Nope, but we must(!) avoid directory aliasing */ + actual = __d_unalias(dentry, alias); + if (IS_ERR(actual)) + dput(alias); + goto out_nolock; + } } /* Add a unique reference */ @@ -1628,7 +1701,7 @@ found: _d_rehash(actual); spin_unlock(&actual->d_lock); spin_unlock(&dcache_lock); - +out_nolock: if (actual == dentry) { security_d_instantiate(dentry, inode); return NULL; @@ -1637,16 +1710,6 @@ found: iput(inode); return actual; - /* Convert the anonymous/root alias into an ordinary dentry */ -connect_mountpoint: - __d_materialise_dentry(dentry, alias); - - /* Replace the candidate dentry with the alias in the tree */ -replace_with_alias: - __d_drop(alias); - actual = alias; - goto found; - shouldnt_be_hashed: spin_unlock(&dcache_lock); BUG(); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4133ef5..27b5a10 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -935,8 +935,11 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru no_entry: res = d_materialise_unique(dentry, inode); - if (res != NULL) + if (res != NULL) { + if (IS_ERR(res)) + goto out_unlock; dentry = res; + } nfs_renew_times(dentry); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out_unlock: @@ -1132,6 +1135,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) alias = d_materialise_unique(dentry, inode); if (alias != NULL) { dput(dentry); + if (IS_ERR(alias)) + return NULL; dentry = alias; } -- cgit v0.10.2 From fc22617e451f23b466d4d63bb016f5f6111b69e4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 21 Oct 2006 10:24:24 -0700 Subject: [PATCH] NFS: Cache invalidation fixup If someone has renamed a directory on the server, triggering the d_move code in d_materialise_unique(), then we need to invalidate the cached directory information in the source parent directory. Signed-off-by: Trond Myklebust Cc: Miklos Szeredi Cc: Maneesh Soni Cc: Dipankar Sarma Cc: Neil Brown Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 27b5a10..b34cd16 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -936,8 +936,14 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru no_entry: res = d_materialise_unique(dentry, inode); if (res != NULL) { + struct dentry *parent; if (IS_ERR(res)) goto out_unlock; + /* Was a directory renamed! */ + parent = dget_parent(res); + if (!IS_ROOT(parent)) + nfs_mark_for_revalidate(parent->d_inode); + dput(parent); dentry = res; } nfs_renew_times(dentry); -- cgit v0.10.2 From 224dc50ece1b40f8cff5ecadd42a6b2691e231de Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 21 Oct 2006 02:05:20 +0100 Subject: [MIPS] Cleanup remaining references to mips_counter_frequency. Noticed by Samium Gromoff but his patch got stale in flight ... Signed-off-by: Ralf Baechle diff --git a/Documentation/mips/time.README b/Documentation/mips/time.README index 69ddc5c..e1304b6 100644 --- a/Documentation/mips/time.README +++ b/Documentation/mips/time.README @@ -63,7 +63,7 @@ the following functions or values: a) board_time_init - a function pointer. Invoked at the beginnig of time_init(). It is optional. 1. (optional) set up RTC routines - 2. (optional) calibrate and set the mips_counter_frequency + 2. (optional) calibrate and set the mips_hpt_frequency b) plat_timer_setup - a function pointer. Invoked at the end of time_init() 1. (optional) over-ride any decisions made in time_init() @@ -72,7 +72,7 @@ the following functions or values: c) (optional) board-specific RTC routines. - d) (optional) mips_counter_frequency - It must be definied if the board + d) (optional) mips_hpt_frequency - It must be definied if the board is using CPU counter for timer interrupt or it is using fixed rate gettimeoffset(). @@ -104,7 +104,7 @@ Step 1: decide how you like to implement the time services. or use an exnternal timer? In order to use CPU counter register as the timer interrupt source, you - must know the counter speed (mips_counter_frequency). It is usually the + must know the counter speed (mips_hpt_frequency). It is usually the same as the CPU speed or an integral divisor of it. d) decide on whether you want to use high-level or low-level timer @@ -121,8 +121,8 @@ Step 3: implement rtc routines, board_time_init() and plat_timer_setup() if needed. board_time_init() - - a) (optional) set up RTC routines, - b) (optional) calibrate and set the mips_counter_frequency + a) (optional) set up RTC routines, + b) (optional) calibrate and set the mips_hpt_frequency (only needed if you intended to use fixed_rate_gettimeoffset or use cpu counter as timer interrupt source) diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 6f8a9fe..c079e2a 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -187,7 +187,7 @@ out: } /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c index c566b9b..24a4ed0 100644 --- a/arch/mips/mips-boards/sim/sim_time.c +++ b/arch/mips/mips-boards/sim/sim_time.c @@ -102,7 +102,7 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id) /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { -- cgit v0.10.2 From f8829caee311207afbc882794bdc5aa0db5caf33 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 21 Oct 2006 23:17:35 +0100 Subject: [MIPS] Fix aliasing bug in copy_to_user_page / copy_from_user_page The current implementation uses a sequence of a cacheflush and a copy. This is racy in case of a multithreaded debuggee and renders GDB virtually unusable. Aside this fixes a performance hog rendering access to /proc/cmdline very slow and resulting in a enough cache stalls for the 34K AP/SP programming model to make the bare metal code on the non-Linux VPE miss RT deadlines. The main part of this patch was originally written by Ralf Baechle; Atushi Nemoto did the the debugging. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 88b72c9..2de4d3c 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -30,11 +30,34 @@ #include #include #include +#include #include #include #include #include #include +#include + +/* Atomicity and interruptability */ +#ifdef CONFIG_MIPS_MT_SMTC + +#include + +#define ENTER_CRITICAL(flags) \ + { \ + unsigned int mvpflags; \ + local_irq_save(flags);\ + mvpflags = dvpe() +#define EXIT_CRITICAL(flags) \ + evpe(mvpflags); \ + local_irq_restore(flags); \ + } +#else + +#define ENTER_CRITICAL(flags) local_irq_save(flags) +#define EXIT_CRITICAL(flags) local_irq_restore(flags) + +#endif /* CONFIG_MIPS_MT_SMTC */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -80,13 +103,142 @@ unsigned long setup_zero_pages(void) return 1UL << order; } -#ifdef CONFIG_HIGHMEM -pte_t *kmap_pte; -pgprot_t kmap_prot; +/* + * These are almost like kmap_atomic / kunmap_atmic except they take an + * additional address argument as the hint. + */ #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)) +#ifdef CONFIG_MIPS_MT_SMTC +static pte_t *kmap_coherent_pte; +static void __init kmap_coherent_init(void) +{ + unsigned long vaddr; + + /* cache the first coherent kmap pte */ + vaddr = __fix_to_virt(FIX_CMAP_BEGIN); + kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); +} +#else +static inline void kmap_coherent_init(void) {} +#endif + +static inline void *kmap_coherent(struct page *page, unsigned long addr) +{ + enum fixed_addresses idx; + unsigned long vaddr, flags, entrylo; + unsigned long old_ctx; + pte_t pte; + int tlbidx; + + inc_preempt_count(); + idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); +#ifdef CONFIG_MIPS_MT_SMTC + idx += FIX_N_COLOURS * smp_processor_id(); +#endif + vaddr = __fix_to_virt(FIX_CMAP_END - idx); + pte = mk_pte(page, PAGE_KERNEL); +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) + entrylo = pte.pte_high; +#else + entrylo = pte_val(pte) >> 6; +#endif + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + write_c0_entryhi(vaddr & (PAGE_MASK << 1)); + write_c0_entrylo0(entrylo); + write_c0_entrylo1(entrylo); +#ifdef CONFIG_MIPS_MT_SMTC + set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte); + /* preload TLB instead of local_flush_tlb_one() */ + mtc0_tlbw_hazard(); + tlb_probe(); + tlb_probe_hazard(); + tlbidx = read_c0_index(); + mtc0_tlbw_hazard(); + if (tlbidx < 0) + tlb_write_random(); + else + tlb_write_indexed(); +#else + tlbidx = read_c0_wired(); + write_c0_wired(tlbidx + 1); + write_c0_index(tlbidx); + mtc0_tlbw_hazard(); + tlb_write_indexed(); +#endif + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); + + return (void*) vaddr; +} + +#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) + +static inline void kunmap_coherent(struct page *page) +{ +#ifndef CONFIG_MIPS_MT_SMTC + unsigned int wired; + unsigned long flags, old_ctx; + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + wired = read_c0_wired() - 1; + write_c0_wired(wired); + write_c0_index(wired); + write_c0_entryhi(UNIQUE_ENTRYHI(wired)); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); +#endif + dec_preempt_count(); + preempt_check_resched(); +} + +void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); + if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) + flush_cache_page(vma, vaddr, page_to_pfn(page)); +} + +EXPORT_SYMBOL(copy_to_user_page); + +void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vfrom = + kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); +} + +EXPORT_SYMBOL(copy_from_user_page); + + +#ifdef CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; + static void __init kmap_init(void) { unsigned long kmap_vstart; @@ -97,11 +249,12 @@ static void __init kmap_init(void) kmap_prot = PAGE_KERNEL; } +#endif /* CONFIG_HIGHMEM */ -#ifdef CONFIG_32BIT void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC) pgd_t *pgd; pud_t *pud; pmd_t *pmd; @@ -122,7 +275,7 @@ void __init fixrange_init(unsigned long start, unsigned long end, for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pmd(pmd, __pmd(pte)); + set_pmd(pmd, __pmd((unsigned long)pte)); if (pte != pte_offset_kernel(pmd, 0)) BUG(); } @@ -132,9 +285,8 @@ void __init fixrange_init(unsigned long start, unsigned long end, } j = 0; } +#endif } -#endif /* CONFIG_32BIT */ -#endif /* CONFIG_HIGHMEM */ #ifndef CONFIG_NEED_MULTIPLE_NODES extern void pagetable_init(void); @@ -175,6 +327,7 @@ void __init paging_init(void) #ifdef CONFIG_HIGHMEM kmap_init(); #endif + kmap_coherent_init(); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c index 4bdaa05..4a61e62 100644 --- a/arch/mips/mm/pgtable-32.c +++ b/arch/mips/mm/pgtable-32.c @@ -31,9 +31,10 @@ void pgd_init(unsigned long page) void __init pagetable_init(void) { -#ifdef CONFIG_HIGHMEM unsigned long vaddr; - pgd_t *pgd, *pgd_base; + pgd_t *pgd_base; +#ifdef CONFIG_HIGHMEM + pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -44,7 +45,6 @@ void __init pagetable_init(void) pgd_init((unsigned long)swapper_pg_dir + sizeof(pgd_t) * USER_PTRS_PER_PGD); -#ifdef CONFIG_HIGHMEM pgd_base = swapper_pg_dir; /* @@ -53,6 +53,7 @@ void __init pagetable_init(void) vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; fixrange_init(vaddr, 0, pgd_base); +#ifdef CONFIG_HIGHMEM /* * Permanent kmaps: */ diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 44b5e97f..8d600d3 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -8,6 +8,7 @@ */ #include #include +#include #include void pgd_init(unsigned long page) @@ -52,7 +53,17 @@ void pmd_init(unsigned long addr, unsigned long pagetable) void __init pagetable_init(void) { + unsigned long vaddr; + pgd_t *pgd_base; + /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + + pgd_base = swapper_pg_dir; + /* + * Fixed mappings: + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + fixrange_init(vaddr, 0, pgd_base); } diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index 9ab59e2..e3c9925 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h @@ -55,24 +55,13 @@ extern void (*flush_icache_range)(unsigned long start, unsigned long end); #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() -static inline void copy_to_user_page(struct vm_area_struct *vma, +extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, - unsigned long len) -{ - if (cpu_has_dc_aliases) - flush_cache_page(vma, vaddr, page_to_pfn(page)); - memcpy(dst, src, len); - __flush_icache_page(vma, page); -} + unsigned long len); -static inline void copy_from_user_page(struct vm_area_struct *vma, +extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, - unsigned long len) -{ - if (cpu_has_dc_aliases) - flush_cache_page(vma, vaddr, page_to_pfn(page)); - memcpy(dst, src, len); -} + unsigned long len); extern void (*flush_cache_sigtramp)(unsigned long addr); extern void (*flush_icache_all)(void); diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h index 6959bdb..02c8a13 100644 --- a/include/asm-mips/fixmap.h +++ b/include/asm-mips/fixmap.h @@ -45,8 +45,16 @@ * fix-mapped? */ enum fixed_addresses { +#define FIX_N_COLOURS 8 + FIX_CMAP_BEGIN, +#ifdef CONFIG_MIPS_MT_SMTC + FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS), +#else + FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, +#endif #ifdef CONFIG_HIGHMEM - FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ + /* reserved pte's for temporary kernel mappings */ + FIX_KMAP_BEGIN = FIX_CMAP_END + 1, FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, #endif __end_of_fixed_addresses @@ -70,9 +78,9 @@ extern void __set_fixmap (enum fixed_addresses idx, * at the top of mem.. */ #if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) -#define FIXADDR_TOP (0xff000000UL - 0x2000) +#define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000)) #else -#define FIXADDR_TOP (0xffffe000UL) +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) #endif #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) -- cgit v0.10.2 From 37b1bccfe75691f5f42bf210d8a349f931896887 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 22 Oct 2006 00:38:23 +0200 Subject: [PATCH] x86-64: Fix C3 timer test There was a typo in the C3 latency test to decide of the TSC should be used or not. It used the C2 latency threshold, not the C3 one. Fix that. This should fix the time on various dual core laptops. Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 1ba5a44..88722f1 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -948,7 +948,7 @@ __cpuinit int unsynchronized_tsc(void) if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { #ifdef CONFIG_ACPI /* But TSC doesn't tick in C3 so don't use it there */ - if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100) + if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000) return 1; #endif return 0; -- cgit v0.10.2 From b3edc9cec07ade41aaf1804f7c9e876afa90c862 Mon Sep 17 00:00:00 2001 From: Muli Ben-Yehuda Date: Sun, 22 Oct 2006 00:38:23 +0200 Subject: [PATCH] x86-64: increase PHB1 split transaction timeout This patch increases the timeout for PCI split transactions on PHB1 on the first Calgary to work around an issue with the aic94xx adapter. Fixes kernel.org bugzilla #7180 (http://bugzilla.kernel.org/show_bug.cgi?id=7180) Based on excellent debugging and a patch by Darrick J. Wong Signed-off-by: Muli Ben-Yehuda Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Acked-by: Darrick J. Wong diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c index b3296cc..37a7708 100644 --- a/arch/x86_64/kernel/pci-calgary.c +++ b/arch/x86_64/kernel/pci-calgary.c @@ -52,7 +52,8 @@ #define ONE_BASED_CHASSIS_NUM 1 /* register offsets inside the host bridge space */ -#define PHB_CSR_OFFSET 0x0110 +#define CALGARY_CONFIG_REG 0x0108 +#define PHB_CSR_OFFSET 0x0110 /* Channel Status */ #define PHB_PLSSR_OFFSET 0x0120 #define PHB_CONFIG_RW_OFFSET 0x0160 #define PHB_IOBASE_BAR_LOW 0x0170 @@ -83,6 +84,8 @@ #define TAR_VALID 0x0000000000000008UL /* CSR (Channel/DMA Status Register) */ #define CSR_AGENT_MASK 0xffe0ffff +/* CCR (Calgary Configuration Register) */ +#define CCR_2SEC_TIMEOUT 0x000000000000000EUL #define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ #define MAX_NUM_CHASSIS 8 /* max number of chassis */ @@ -732,6 +735,38 @@ static void calgary_watchdog(unsigned long data) } } +static void __init calgary_increase_split_completion_timeout(void __iomem *bbar, + unsigned char busnum) +{ + u64 val64; + void __iomem *target; + unsigned long phb_shift = -1; + u64 mask; + + switch (busno_to_phbid(busnum)) { + case 0: phb_shift = (63 - 19); + break; + case 1: phb_shift = (63 - 23); + break; + case 2: phb_shift = (63 - 27); + break; + case 3: phb_shift = (63 - 35); + break; + default: + BUG_ON(busno_to_phbid(busnum)); + } + + target = calgary_reg(bbar, CALGARY_CONFIG_REG); + val64 = be64_to_cpu(readq(target)); + + /* zero out this PHB's timer bits */ + mask = ~(0xFUL << phb_shift); + val64 &= mask; + val64 |= (CCR_2SEC_TIMEOUT << phb_shift); + writeq(cpu_to_be64(val64), target); + readq(target); /* flush */ +} + static void __init calgary_enable_translation(struct pci_dev *dev) { u32 val32; @@ -756,6 +791,13 @@ static void __init calgary_enable_translation(struct pci_dev *dev) writel(cpu_to_be32(val32), target); readl(target); /* flush */ + /* + * Give split completion a longer timeout on bus 1 for aic94xx + * http://bugzilla.kernel.org/show_bug.cgi?id=7180 + */ + if (busnum == 1) + calgary_increase_split_completion_timeout(bbar, busnum); + init_timer(&tbl->watchdog_timer); tbl->watchdog_timer.function = &calgary_watchdog; tbl->watchdog_timer.data = (unsigned long)dev; -- cgit v0.10.2 From aa026ede513b7d672fa7d9106b2f2a475455dcf2 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 22 Oct 2006 00:41:15 +0200 Subject: [PATCH] x86-64: Fix C3 timer test There was a typo in the C3 latency test to decide of the TSC should be used or not. It used the C2 latency threshold, not the C3 one. Fix that. This should fix the time on various dual core laptops. Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 1ba5a44..88722f1 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -948,7 +948,7 @@ __cpuinit int unsynchronized_tsc(void) if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { #ifdef CONFIG_ACPI /* But TSC doesn't tick in C3 so don't use it there */ - if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100) + if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000) return 1; #endif return 0; -- cgit v0.10.2 From cb01fc720c629261b9c616b2d5fcc3d93cd8bb09 Mon Sep 17 00:00:00 2001 From: Muli Ben-Yehuda Date: Sun, 22 Oct 2006 00:41:15 +0200 Subject: [PATCH] x86-64: increase PHB1 split transaction timeout This patch increases the timeout for PCI split transactions on PHB1 on the first Calgary to work around an issue with the aic94xx adapter. Fixes kernel.org bugzilla #7180 (http://bugzilla.kernel.org/show_bug.cgi?id=7180) Based on excellent debugging and a patch by Darrick J. Wong Signed-off-by: Muli Ben-Yehuda Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Acked-by: Darrick J. Wong diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c index b3296cc..37a7708 100644 --- a/arch/x86_64/kernel/pci-calgary.c +++ b/arch/x86_64/kernel/pci-calgary.c @@ -52,7 +52,8 @@ #define ONE_BASED_CHASSIS_NUM 1 /* register offsets inside the host bridge space */ -#define PHB_CSR_OFFSET 0x0110 +#define CALGARY_CONFIG_REG 0x0108 +#define PHB_CSR_OFFSET 0x0110 /* Channel Status */ #define PHB_PLSSR_OFFSET 0x0120 #define PHB_CONFIG_RW_OFFSET 0x0160 #define PHB_IOBASE_BAR_LOW 0x0170 @@ -83,6 +84,8 @@ #define TAR_VALID 0x0000000000000008UL /* CSR (Channel/DMA Status Register) */ #define CSR_AGENT_MASK 0xffe0ffff +/* CCR (Calgary Configuration Register) */ +#define CCR_2SEC_TIMEOUT 0x000000000000000EUL #define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ #define MAX_NUM_CHASSIS 8 /* max number of chassis */ @@ -732,6 +735,38 @@ static void calgary_watchdog(unsigned long data) } } +static void __init calgary_increase_split_completion_timeout(void __iomem *bbar, + unsigned char busnum) +{ + u64 val64; + void __iomem *target; + unsigned long phb_shift = -1; + u64 mask; + + switch (busno_to_phbid(busnum)) { + case 0: phb_shift = (63 - 19); + break; + case 1: phb_shift = (63 - 23); + break; + case 2: phb_shift = (63 - 27); + break; + case 3: phb_shift = (63 - 35); + break; + default: + BUG_ON(busno_to_phbid(busnum)); + } + + target = calgary_reg(bbar, CALGARY_CONFIG_REG); + val64 = be64_to_cpu(readq(target)); + + /* zero out this PHB's timer bits */ + mask = ~(0xFUL << phb_shift); + val64 &= mask; + val64 |= (CCR_2SEC_TIMEOUT << phb_shift); + writeq(cpu_to_be64(val64), target); + readq(target); /* flush */ +} + static void __init calgary_enable_translation(struct pci_dev *dev) { u32 val32; @@ -756,6 +791,13 @@ static void __init calgary_enable_translation(struct pci_dev *dev) writel(cpu_to_be32(val32), target); readl(target); /* flush */ + /* + * Give split completion a longer timeout on bus 1 for aic94xx + * http://bugzilla.kernel.org/show_bug.cgi?id=7180 + */ + if (busnum == 1) + calgary_increase_split_completion_timeout(bbar, busnum); + init_timer(&tbl->watchdog_timer); tbl->watchdog_timer.function = &calgary_watchdog; tbl->watchdog_timer.data = (unsigned long)dev; -- cgit v0.10.2 From 82709531a800fcf8de71bb8c5d8e92462fb81f84 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 11 Oct 2006 16:26:54 +0100 Subject: [DCCP]: Fix Oops in DCCPv6 I think I got the cause for the Oops observed in http://www.mail-archive.com/dccp@vger.kernel.org/msg00578.html The problem is always with applications listening on PF_INET6 sockets. Apart from the mentioned oops, I observed another one one, triggered at irregular intervals via timer interrupt: run_timer_softirq -> dccp_keepalive_timer -> inet_csk_reqsk_queue_prune -> reqsk_free -> dccp_v6_reqsk_destructor The latter function is the problem and is also the last function to be called in said kernel panic. In any case, there is a real problem with allocating the right request_sock which is what this patch tackles. It fixes the following problem: - application listens on PF_INET6 - DCCPv4 packet comes in, is handed over to dccp_v4_do_rcv, from there to dccp_v4_conn_request Now: socket is PF_INET6, packet is IPv4. The following code then furnishes the connection with IPv6 - request_sock operations: req = reqsk_alloc(sk->sk_prot->rsk_prot); The first problem is that all further incoming packets will get a Reset since the connection can not be looked up. The second problem is worse: --> reqsk_alloc is called instead of inet6_reqsk_alloc --> consequently inet6_rsk_offset is never set (dangling pointer) --> the request_sock_ops are nevertheless still dccp6_request_ops --> destructor is called via reqsk_free --> dccp_v6_reqsk_destructor tries to free random memory location (inet6_rsk_offset not set) --> panic I have tested this for a while, DCCP sockets are now handled correctly in all three scenarios (v4/v6 only/v4-mapped). Commiter note: I've added the dccp_request_sock_ops forward declaration to keep the tree building and to reduce the size of the patch for 2.6.19, later I'll move the functions to the top of the affected source code to match what we have in the TCP counterpart, where this problem hasn't existed in the first place, dumb me not to have done the same thing on DCCP land 8) Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 7e746c4..aaaf4d0 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -449,6 +449,8 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk, dccp_hdr(skb)->dccph_sport); } +static struct request_sock_ops dccp_request_sock_ops; + int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) { struct inet_request_sock *ireq; @@ -489,7 +491,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = reqsk_alloc(sk->sk_prot->rsk_prot); + req = reqsk_alloc(&dccp_request_sock_ops); if (req == NULL) goto drop; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 7171a78..91e7b12 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -672,7 +672,6 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) { - struct inet_request_sock *ireq; struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; @@ -701,7 +700,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot); + req = inet6_reqsk_alloc(&dccp6_request_sock_ops); if (req == NULL) goto drop; @@ -713,7 +712,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; ireq6 = inet6_rsk(req); - ireq = inet_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr); req->rcv_wnd = dccp_feat_default_sequence_window; -- cgit v0.10.2 From fd169f15a67b47f23bd1704919c719a8e8409a73 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 20 Oct 2006 19:44:17 -0700 Subject: [DCCP] ipv6: Fix opt_skb leak. Based upon a patch from Jesper Juhl. Try to match the TCP IPv6 code this was copied from as much as possible, so that it's easy to see where to add the ipv6 pktoptions support code. Signed-off-by: David S. Miller diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 91e7b12..c8bf89b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -995,6 +995,10 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (sk->sk_state == DCCP_OPEN) { /* Fast path */ if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len)) goto reset; + if (opt_skb) { + /* This is where we would goto ipv6_pktoptions. */ + __kfree_skb(opt_skb); + } return 0; } @@ -1019,6 +1023,10 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len)) goto reset; + if (opt_skb) { + /* This is where we would goto ipv6_pktoptions. */ + __kfree_skb(opt_skb); + } return 0; reset: -- cgit v0.10.2 From 97f80bc66f5c6384e3aab70c67340116b8c4284b Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 20 Oct 2006 19:48:42 -0700 Subject: [ATM]: handle sysfs errors Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index c0a4ae2..62f6ed1 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -141,7 +141,7 @@ static struct class atm_class = { int atm_register_sysfs(struct atm_dev *adev) { struct class_device *cdev = &adev->class_dev; - int i, err; + int i, j, err; cdev->class = &atm_class; class_set_devdata(cdev, adev); @@ -151,10 +151,19 @@ int atm_register_sysfs(struct atm_dev *adev) if (err < 0) return err; - for (i = 0; atm_attrs[i]; i++) - class_device_create_file(cdev, atm_attrs[i]); + for (i = 0; atm_attrs[i]; i++) { + err = class_device_create_file(cdev, atm_attrs[i]); + if (err) + goto err_out; + } return 0; + +err_out: + for (j = 0; j < i; j++) + class_device_remove_file(cdev, atm_attrs[j]); + class_device_del(cdev); + return err; } void atm_unregister_sysfs(struct atm_dev *adev) -- cgit v0.10.2 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 diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 323592d..9fffa7af 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 f593492..44268cb 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 v0.10.2 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 diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 40ab9b6..697ad82 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 v0.10.2 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 diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 632ede5..bd09045 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 v0.10.2 From 375216ad0c303adeed45281ce82e153d41de679a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 21 Oct 2006 20:20:54 -0700 Subject: [IPv6] fib: initialize tb6_lock in common place to give lockdep a key Signed-off-by: Thomas Graf Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 8fcae7a..f98ca30 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -169,7 +169,6 @@ static __inline__ void rt6_release(struct rt6_info *rt) static struct fib6_table fib6_main_tbl = { .tb6_id = RT6_TABLE_MAIN, - .tb6_lock = RW_LOCK_UNLOCKED, .tb6_root = { .leaf = &ip6_null_entry, .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, @@ -187,6 +186,12 @@ static void fib6_link_table(struct fib6_table *tb) { unsigned int h; + /* + * Initialize table lock at a single place to give lockdep a key, + * tables aren't visible prior to being linked to the list. + */ + rwlock_init(&tb->tb6_lock); + h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1); /* @@ -199,7 +204,6 @@ static void fib6_link_table(struct fib6_table *tb) #ifdef CONFIG_IPV6_MULTIPLE_TABLES static struct fib6_table fib6_local_tbl = { .tb6_id = RT6_TABLE_LOCAL, - .tb6_lock = RW_LOCK_UNLOCKED, .tb6_root = { .leaf = &ip6_null_entry, .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, @@ -213,7 +217,6 @@ static struct fib6_table *fib6_alloc_table(u32 id) table = kzalloc(sizeof(*table), GFP_ATOMIC); if (table != NULL) { table->tb6_id = id; - table->tb6_lock = RW_LOCK_UNLOCKED; table->tb6_root.leaf = &ip6_null_entry; table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; } -- cgit v0.10.2 From 185b1aa122f87052d9154bb74990bc785372a750 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 21 Oct 2006 20:24:01 -0700 Subject: [NET]: Reduce sizeof(struct flowi) by 20 bytes. As suggested by David, just kill off some unused fields in dnports to reduce sizef(struct flowi). If they come back, they should be moved to nl_u.dn_u in order not to enlarge again struct flowi [ Modified to really delete this stuff instead of using #if 0. -DaveM ] Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/include/net/dn.h b/include/net/dn.h index 465b783..ac4ce90 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -199,11 +199,6 @@ static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp) { fl->uli_u.dnports.sport = scp->addrloc; fl->uli_u.dnports.dport = scp->addrrem; - fl->uli_u.dnports.objnum = scp->addr.sdn_objnum; - if (fl->uli_u.dnports.objnum == 0) { - fl->uli_u.dnports.objnamel = (__u8)dn_ntohs(scp->addr.sdn_objnamel); - memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16); - } } extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu); diff --git a/include/net/flow.h b/include/net/flow.h index 3b44d72..5cda27c 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -68,9 +68,6 @@ struct flowi { struct { __le16 sport; __le16 dport; - __u8 objnum; - __u8 objnamel; /* Not 16 bits since max val is 16 */ - __u8 objname[16]; /* Not zero terminated */ } dnports; __be32 spi; -- cgit v0.10.2 From 4a81a21b6095997f50ac9ca37e4fdfe48d789ad7 Mon Sep 17 00:00:00 2001 From: Amit Choudhary Date: Mon, 9 Oct 2006 16:02:49 +0200 Subject: [ALSA] sound/isa/gus/interwave.c: check kmalloc() return value Check the return value of kmalloc() in function snd_interwave_pnp(), in file sound/isa/gus/interwave.c. Signed-off-by: Amit Choudhary Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index f12cd09..4ec2d79 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -564,6 +564,8 @@ static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); int err; + if (!cfg) + return -ENOMEM; iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); if (iwcard->dev == NULL) { kfree(cfg); -- cgit v0.10.2 From fbdbb2205a7ff3c3e19941477cde6f9a693637ef Mon Sep 17 00:00:00 2001 From: Amit Choudhary Date: Mon, 9 Oct 2006 16:03:23 +0200 Subject: [ALSA] sound/isa/cmi8330.c: check kmalloc() return value Check the return value of kmalloc() in function snd_cmi8330_pnp(), in file sound/isa/cmi8330.c. Signed-off-by: Amit Choudhary Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 3c1e9fd..d1f6dfc 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -289,6 +289,8 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); int err; + if (!cfg) + return -ENOMEM; acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL); if (acard->cap == NULL) { kfree(cfg); -- cgit v0.10.2 From b1e8a791c77bd35f88b678ce761928583efd8cd0 Mon Sep 17 00:00:00 2001 From: Amit Choudhary Date: Mon, 9 Oct 2006 16:03:52 +0200 Subject: [ALSA] sound/isa/ad1816a/ad1816a.c: check kmalloc() return value Check the return value of kmalloc() in function snd_card_ad1816a_pnp(), in file sound/isa/ad1816a/ad1816a.c. Signed-off-by: Amit Choudhary Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index b33a5fb..5903450 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -120,6 +120,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); int err; + if (!cfg) + return -ENOMEM; acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); if (acard->dev == NULL) { kfree(cfg); -- cgit v0.10.2 From 5019f75ea1a98c36e9139ffb2bf8614a2e9f0a03 Mon Sep 17 00:00:00 2001 From: Amit Choudhary Date: Mon, 9 Oct 2006 16:04:34 +0200 Subject: [ALSA] sound/isa/opti9xx/opti92x-ad1848.c: check kmalloc() return value Check the return value of kmalloc() in function snd_card_opti9xx_pnp(), in file sound/isa/opti9xx/opti92x-ad1848.c. Signed-off-by: Amit Choudhary Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index a1ad39a..df22737 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -1683,6 +1683,8 @@ static int __init snd_card_opti9xx_pnp(struct snd_opti9xx *chip, struct pnp_card struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); int err; + if (!cfg) + return -ENOMEM; chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); if (chip->dev == NULL) { kfree(cfg); -- cgit v0.10.2 From c06134d73cdc02bb8ab1fad180f6da1f28d2e049 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Oct 2006 18:49:13 +0200 Subject: [ALSA] hda-codec - Fix assignment of PCM devices for Realtek codecs Fixed the assignment of PCM devices for Realtek codecs. The secondary analog capture should be statically asigned to the third device regardless whether SPDIF exists or not. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 84a3eb8..0d728c6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1799,7 +1799,7 @@ static int alc_build_pcms(struct hda_codec *codec) /* SPDIF for stream index #1 */ if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms = 2; - info++; + info = spec->pcm_rec + 1; info->name = spec->stream_name_digital; if (spec->multiout.dig_out_nid && spec->stream_digital_playback) { @@ -1820,7 +1820,7 @@ static int alc_build_pcms(struct hda_codec *codec) if (spec->num_adc_nids > 1 && spec->stream_analog_capture && spec->adc_nids) { codec->num_pcms = 3; - info++; + info = spec->pcm_rec + 2; info->name = spec->stream_name_analog; /* No playback stream for second PCM */ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; -- cgit v0.10.2 From 30b35399ceb2398d05837863476dcb12f12f3a82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Oct 2006 18:52:53 +0200 Subject: [ALSA] Various fixes for suspend/resume of ALSA PCI drivers - Check the return value of pci_enable_device() and request_irq() in the suspend. If any error occurs there, disable the device using snd_card_disconnect(). - Call pci_set_power_state() properly with pci_choose_state(). - Fix the order to call pci_set_power_state(). - Removed obsolete house-made PM codes in some drivers. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 13a8cef..a7edd56 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2032,8 +2032,10 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) outl(0xffffffff, ALI_REG(chip, ALI_STOP)); spin_unlock_irq(&chip->reg_lock); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2048,8 +2050,15 @@ static int ali_resume(struct pci_dev *pci) if (! im) return 0; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "ali5451: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); spin_lock_irq(&chip->reg_lock); diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 9b16c29..95f70f3 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -768,9 +768,9 @@ static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -779,9 +779,14 @@ static int snd_als300_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_als300 *chip = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "als300: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_als300_init(chip); diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 15fc392..8fb55d3 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -804,9 +804,9 @@ static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_sbmixer_suspend(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -816,9 +816,14 @@ static int snd_als4000_resume(struct pci_dev *pci) struct snd_card_als4000 *acard = card->private_data; struct snd_sb *chip = acard->chip; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "als4000: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_als4000_configure(chip); diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 3e8fc5a..e3e99f3 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1442,9 +1442,9 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) snd_atiixp_aclink_down(chip); snd_atiixp_chip_stop(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1454,9 +1454,14 @@ static int snd_atiixp_resume(struct pci_dev *pci) struct atiixp *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "atiixp: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_atiixp_aclink_reset(chip); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c5dda1b..dc54f2c 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1128,9 +1128,9 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) snd_atiixp_aclink_down(chip); snd_atiixp_chip_stop(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1140,9 +1140,14 @@ static int snd_atiixp_resume(struct pci_dev *pci) struct atiixp_modem *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "atiixp-modem: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_atiixp_aclink_reset(chip); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 692f203..2414ee6 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1903,9 +1903,9 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1916,9 +1916,14 @@ snd_azf3328_resume(struct pci_dev *pci) struct snd_azf3328 *chip = card->private_data; int reg; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "azt3328: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1f7e710..0093cd1 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3122,9 +3122,9 @@ static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) /* disable ints */ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3134,9 +3134,14 @@ static int snd_cmipci_resume(struct pci_dev *pci) struct cmipci *cm = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cmipci: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* reset / initialize to a sane state */ diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d54924e..0905fa8 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -2050,6 +2050,7 @@ static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2060,8 +2061,14 @@ static int cs4281_resume(struct pci_dev *pci) unsigned int i; u32 ulCLK; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs4281: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 16d4ebf..2807b97 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3687,8 +3687,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) /* disable CLKRUN */ chip->active_ctrl(chip, -chip->amplifier); chip->amplifier = amp_saved; /* restore the status */ + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3698,9 +3700,16 @@ int snd_cs46xx_resume(struct pci_dev *pci) struct snd_cs46xx *chip = card->private_data; int amp_saved; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs46xx: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); + amp_saved = chip->amplifier; chip->amplifier = 0; chip->active_ctrl(chip, 1); /* force to on */ diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index aad0e69..3e4d198 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -73,9 +73,10 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) snd_ac97_suspend(cs5535au->ac97); /* save important regs, then disable aclink in hw */ snd_cs5535audio_stop_hardware(cs5535au); + pci_disable_device(pci); pci_save_state(pci); - + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -87,8 +88,14 @@ int snd_cs5535audio_resume(struct pci_dev *pci) int timeout; int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs5535audio: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* set LNK_WRM_RST to reset AC link */ diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 493ec08..55caf34 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -226,9 +226,9 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) snd_emu10k1_done(emu); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -237,11 +237,16 @@ static int snd_emu10k1_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_emu10k1 *emu = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "emu10k1: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - + snd_emu10k1_resume_init(emu); snd_emu10k1_efx_resume(emu); snd_ac97_resume(emu->ac97); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 8cb4fb2..d2a811f 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -2072,9 +2072,10 @@ static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) udelay(100); snd_ak4531_suspend(ensoniq->u.es1370.ak4531); #endif - pci_set_power_state(pci, PCI_D3hot); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2083,9 +2084,14 @@ static int snd_ensoniq_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct ensoniq *ensoniq = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR DRIVER_NAME ": pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_ensoniq_chip_init(ensoniq); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 2da988f..1a8d36d 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1481,10 +1481,14 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state) *d = snd_es1938_reg_read(chip, *s); outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1494,10 +1498,22 @@ static int es1938_resume(struct pci_dev *pci) struct es1938 *chip = card->private_data; unsigned char *s, *d; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); - request_irq(pci->irq, snd_es1938_interrupt, - IRQF_DISABLED|IRQF_SHARED, "ES1938", chip); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "es1938: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + + if (request_irq(pci->irq, snd_es1938_interrupt, + IRQF_DISABLED|IRQF_SHARED, "ES1938", chip)) { + printk(KERN_ERR "es1938: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; snd_es1938_chip_init(chip); @@ -1556,8 +1572,10 @@ static int snd_es1938_free(struct es1938 *chip) snd_es1938_free_gameport(chip); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + } pci_release_regions(chip->pci); pci_disable_device(chip->pci); kfree(chip); @@ -1602,6 +1620,7 @@ static int __devinit snd_es1938_create(struct snd_card *card, spin_lock_init(&chip->mixer_lock); chip->card = card; chip->pci = pci; + chip->irq = -1; if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) { kfree(chip); pci_disable_device(pci); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index b9d723c..092da53e 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -432,46 +432,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick."); #define ESM_MODE_PLAY 0 #define ESM_MODE_CAPTURE 1 -/* acpi states */ -enum { - ACPI_D0=0, - ACPI_D1, - ACPI_D2, - ACPI_D3 -}; - -/* bits in the acpi masks */ -#define ACPI_12MHZ ( 1 << 15) -#define ACPI_24MHZ ( 1 << 14) -#define ACPI_978 ( 1 << 13) -#define ACPI_SPDIF ( 1 << 12) -#define ACPI_GLUE ( 1 << 11) -#define ACPI__10 ( 1 << 10) /* reserved */ -#define ACPI_PCIINT ( 1 << 9) -#define ACPI_HV ( 1 << 8) /* hardware volume */ -#define ACPI_GPIO ( 1 << 7) -#define ACPI_ASSP ( 1 << 6) -#define ACPI_SB ( 1 << 5) /* sb emul */ -#define ACPI_FM ( 1 << 4) /* fm emul */ -#define ACPI_RB ( 1 << 3) /* ringbus / aclink */ -#define ACPI_MIDI ( 1 << 2) -#define ACPI_GP ( 1 << 1) /* game port */ -#define ACPI_WP ( 1 << 0) /* wave processor */ - -#define ACPI_ALL (0xffff) -#define ACPI_SLEEP (~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \ - ACPI_MIDI|ACPI_GP|ACPI_WP)) -#define ACPI_NONE (ACPI__10) - -/* these masks indicate which units we care about at - which states */ -static u16 acpi_state_mask[] = { - [ACPI_D0] = ACPI_ALL, - [ACPI_D1] = ACPI_SLEEP, - [ACPI_D2] = ACPI_SLEEP, - [ACPI_D3] = ACPI_NONE -}; - /* APU use in the driver */ enum snd_enum_apu_type { @@ -2160,21 +2120,6 @@ static void snd_es1968_reset(struct es1968 *chip) } /* - * power management - */ -static void snd_es1968_set_acpi(struct es1968 *chip, int state) -{ - u16 active_mask = acpi_state_mask[state]; - - pci_set_power_state(chip->pci, state); - /* make sure the units we care about are on - XXX we might want to do this before state flipping? */ - pci_write_config_word(chip->pci, 0x54, ~ active_mask); - pci_write_config_word(chip->pci, 0x56, ~ active_mask); -} - - -/* * initialize maestro chip */ static void snd_es1968_chip_init(struct es1968 *chip) @@ -2196,9 +2141,6 @@ static void snd_es1968_chip_init(struct es1968 *chip) * IRQs. */ - /* do config work at full power */ - snd_es1968_set_acpi(chip, ACPI_D0); - /* Config Reg A */ pci_read_config_word(pci, ESM_CONFIG_A, &w); @@ -2397,9 +2339,10 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); snd_es1968_bob_stop(chip); - snd_es1968_set_acpi(chip, ACPI_D3); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2413,9 +2356,16 @@ static int es1968_resume(struct pci_dev *pci) return 0; /* restore all our config */ + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "es1968: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); + snd_es1968_chip_init(chip); /* need to restore the base pointers.. */ @@ -2514,7 +2464,6 @@ static int snd_es1968_free(struct es1968 *chip) if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); snd_es1968_free_gameport(chip); - snd_es1968_set_acpi(chip, ACPI_D3); chip->master_switch = NULL; chip->master_volume = NULL; pci_release_regions(chip->pci); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 3ec7d7e..77e3d5c 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1531,9 +1531,9 @@ static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) chip->saved_regs[i] = inw(chip->port + saved_regs[i]); /* FIXME: tea575x suspend */ - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1543,9 +1543,14 @@ static int snd_fm801_resume(struct pci_dev *pci) struct fm801 *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "fm801: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_fm801_chip_init(chip, 1); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index feeed12..7c96361 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1379,12 +1379,16 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus, state); azx_free_cmd_io(chip); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } if (!disable_msi) pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1393,15 +1397,25 @@ static int azx_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct azx *chip = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "hda-intel: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); if (!disable_msi) pci_enable_msi(pci); - /* FIXME: need proper error handling */ - request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, - "HDA Intel", chip); + if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, + "HDA Intel", chip)) { + printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; - pci_set_master(pci); azx_init_chip(chip); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -1431,15 +1445,14 @@ static int azx_free(struct azx *chip) /* disable position buffer */ azx_writel(chip, DPLBASE, 0); azx_writel(chip, DPUBASE, 0); - - synchronize_irq(chip->irq); } if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, (void*)chip); - if (!disable_msi) - pci_disable_msi(chip->pci); } + if (!disable_msi) + pci_disable_msi(chip->pci); if (chip->remap_addr) iounmap(chip->remap_addr); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index f4319b8..7f22dab 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2476,10 +2476,14 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) if (chip->device_type == DEVICE_INTEL_ICH4) chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2489,11 +2493,22 @@ static int intel8x0_resume(struct pci_dev *pci) struct intel8x0 *chip = card->private_data; int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "intel8x0: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, - card->shortname, chip); + if (request_irq(pci->irq, snd_intel8x0_interrupt, + IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) { + printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; synchronize_irq(chip->irq); snd_intel8x0_chip_init(chip, 0); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 6703f5c..bd467c5 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1045,10 +1045,14 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < chip->pcm_devs; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_ac97_suspend(chip->ac97); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1057,11 +1061,22 @@ static int intel8x0m_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct intel8x0m *chip = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "intel8x0m: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, - card->shortname, chip); + if (request_irq(pci->irq, snd_intel8x0_interrupt, + IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) { + printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; snd_intel8x0_chip_init(chip, 0); snd_ac97_resume(chip->ac97); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 05605f4..8cab342 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2589,12 +2589,9 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) chip->suspend_mem[index++] = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); - /* power down apci registers */ - snd_m3_outw(chip, 0xffff, 0x54); - snd_m3_outw(chip, 0xffff, 0x56); - pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2607,8 +2604,14 @@ static int m3_resume(struct pci_dev *pci) if (chip->suspend_mem == NULL) return 0; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "maestor3: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* first lets just bring everything back. .*/ diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index b1bbdb9..945d21b 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1390,6 +1390,7 @@ static int nm256_suspend(struct pci_dev *pci, pm_message_t state) chip->coeffs_current = 0; pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1401,8 +1402,17 @@ static int nm256_resume(struct pci_dev *pci) /* Perform a full reset on the hardware */ chip->in_resume = 1; + + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "nm256: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); + snd_nm256_init_chip(chip); /* restore ac97 */ diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ec48991..56e0c01 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1178,9 +1178,9 @@ static int riptide_suspend(struct pci_dev *pci, pm_message_t state) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1189,9 +1189,14 @@ static int riptide_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_riptide *chip = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "riptide: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_riptide_initialize(chip); snd_ac97_resume(chip->ac97); diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 0d47887..1fbc432 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3966,15 +3966,9 @@ int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) snd_ac97_suspend(trident->ac97); snd_ac97_suspend(trident->ac97_sec); - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - case TRIDENT_DEVICE_ID_NX: - break; /* TODO */ - case TRIDENT_DEVICE_ID_SI7018: - break; - } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3983,9 +3977,15 @@ int snd_trident_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_trident *trident = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); - pci_set_master(pci); /* to be sure */ + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "trident: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); switch (trident->device) { case TRIDENT_DEVICE_ID_DX: diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index e6990e0..92b0736 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2185,9 +2185,9 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); } - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2197,9 +2197,15 @@ static int snd_via82xx_resume(struct pci_dev *pci) struct via82xx *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "via82xx: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); snd_via82xx_chip_init(chip); diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5ab1cf3..feb27c9 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -1032,9 +1032,10 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) snd_via82xx_channel_reset(chip, &chip->devs[i]); synchronize_irq(chip->irq); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1044,9 +1045,14 @@ static int snd_via82xx_resume(struct pci_dev *pci) struct via82xx_modem *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "via82xx-modem: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_via82xx_chip_init(chip); diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index e7cd8ac..af49e8a 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -266,9 +266,9 @@ static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state) int err; err = snd_vx_suspend(&vx->core, state); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return err; } @@ -277,9 +277,14 @@ static int snd_vx222_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_vx222 *vx = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "vx222: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); return snd_vx_resume(&vx->core); } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index ebc6da8..a40c108 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2218,6 +2218,7 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) snd_ymfpci_disable_dsp(chip); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2227,8 +2228,14 @@ int snd_ymfpci_resume(struct pci_dev *pci) struct snd_ymfpci *chip = card->private_data; unsigned int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "ymfpci: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_ymfpci_aclink_reset(pci); snd_ymfpci_codec_ready(chip, 0); -- cgit v0.10.2 From c9949452f221077c22a4765ef380841e169f034b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 12 Oct 2006 21:10:21 +0200 Subject: [ALSA] Fix dependency of snd-adlib driver in Kconfig Added the missing dependency on CONFIG_SND for snd-adlib driver. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 557c4de..57371f1 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -13,6 +13,7 @@ config SND_CS4231_LIB config SND_ADLIB tristate "AdLib FM card" + depends on SND select SND_OPL3_LIB help Say Y here to include support for AdLib FM cards. -- cgit v0.10.2 From 264e6e3b0c5af44d8975153bf0c88ccf2cb10a2f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Oct 2006 12:40:51 +0200 Subject: [ALSA] hda-codec - Add model entry for ASUS U5F laptop Added a model entry for ASUS U5F laptop with AD1986A codec. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 511df07..edd22de 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -818,6 +818,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7, .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */ + { .pci_subvendor = 0x1043, .pci_subdevice = 0x1263, + .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5F */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1297, .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, -- cgit v0.10.2 From 5b15c95f889c7bc43cb759c27211c597c0ad9f05 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Mon, 16 Oct 2006 12:49:47 +0200 Subject: [ALSA] hda_intel: add ATI RS690 HDMI audio support This patch adds support for the HDMI codec of the ATI RS690 IGP northbridge. Signed-off-by: Felix Kuehling Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7c96361..c177192 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -86,6 +86,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{ATI, SB450}," "{ATI, SB600}," "{ATI, RS600}," + "{ATI, RS690}," "{VIA, VT8251}," "{VIA, VT8237A}," "{SiS, SIS966}," @@ -1690,6 +1691,7 @@ static struct pci_device_id azx_ids[] = { { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ + { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index a27440f..7333f27 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c @@ -161,5 +161,6 @@ static int patch_atihdmi(struct hda_codec *codec) */ struct hda_codec_preset snd_hda_preset_atihdmi[] = { { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, + { .id = 0x1002791a, .name = "ATI RS690 HDMI", .patch = patch_atihdmi }, {} /* terminator */ }; -- cgit v0.10.2 From dbedca39fe30db87b6401e4396f959c63d90082e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 18 Oct 2006 19:09:46 +0200 Subject: [ALSA] Fix re-use of va_list The va_list is designed to be used only once. The current code may pass va_list arguments multiple times and may cause Oops. Copy/release the arguments temporarily to avoid this problem. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/core/info.c b/sound/core/info.c index e43662b..0b4aab3 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -120,7 +120,10 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) len = buffer->len - buffer->size; va_start(args, fmt); for (;;) { - res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); + va_list ap; + va_copy(ap, args); + res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap); + va_end(ap); if (res < len) break; err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); -- cgit v0.10.2 From da43deb116c0cea9ca2174f2ac64985c4d53077e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Oct 2006 15:20:08 +0200 Subject: [ALSA] Fix AC97 power-saving mode Fix the bug in AC97 power-saving mode that the power isn't turned on when power_save is set to 1 via sysfs during the power off state. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index a79e918..6577b23 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -570,8 +570,7 @@ int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value ac97->power_up &= ~(1 << (reg>>1)); else ac97->power_up |= 1 << (reg>>1); - if (power_save) - update_power_regs(ac97); + update_power_regs(ac97); } #endif return err; @@ -2337,10 +2336,7 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) } } - if (! power_save) - return 0; - - if (! powerup && ac97->power_workq) + if (power_save && !powerup && ac97->power_workq) /* adjust power-down bits after two seconds delay * (for avoiding loud click noises for many (OSS) apps * that open/close frequently) -- cgit v0.10.2 From ef35be7f52669cc00c780fa5a640abf0580d1ecf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Oct 2006 17:38:31 +0200 Subject: [ALSA] Fix addition of user-defined boolean controls Fixed the addition of user-defined boolean controls, the private data size is corrected to be handled properly. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/core/control.c b/sound/core/control.c index 6973a96..48ef0a0 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1018,10 +1018,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, } switch (info->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - private_size = sizeof(char); - if (info->count > 128) - return -EINVAL; - break; case SNDRV_CTL_ELEM_TYPE_INTEGER: private_size = sizeof(long); if (info->count > 128) -- cgit v0.10.2 From a5c81b648476f5b0594daeefb38bb98409da5340 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 22 Oct 2006 10:56:24 +0200 Subject: [ALSA] version 1.0.13 Signed-off-by: Jaroslav Kysela diff --git a/include/sound/version.h b/include/sound/version.h index 4ad86eb..52fd687 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by alsa/ksync script. */ #define CONFIG_SND_VERSION "1.0.13" -#define CONFIG_SND_DATE " (Fri Oct 06 18:28:19 2006 UTC)" +#define CONFIG_SND_DATE " (Sun Oct 22 08:56:16 2006 UTC)" -- cgit v0.10.2 From 6fb4efc68f5c0e095153510dcfa8b54a42e914ba Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Mon, 16 Oct 2006 13:50:05 -0700 Subject: [POWERPC] Add flatdevtree source Add the latest version of the flatdevtree code and corresponding glue. A phandle table now tracks values returned by ft_find_device(). The value returned by ft_find_device() is a phandle which is really an index into the phandle table. The phandle table contains the address of the corresponding node. When the flat dt is edited/moved, the node pointers in the phandle table are updated accordingly so no phandles kept by the caller become stale. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 37ddfca..8660cc5 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) -src-wlib := string.S stdio.c main.c div64.S $(zlib) +src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \ + $(zlib) src-plat := of.c src-boot := crt0.S $(src-wlib) $(src-plat) empty.c diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c new file mode 100644 index 0000000..c76c194 --- /dev/null +++ b/arch/powerpc/boot/flatdevtree.c @@ -0,0 +1,880 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright Pantelis Antoniou 2006 + * Copyright (C) IBM Corporation 2006 + * + * Authors: Pantelis Antoniou + * Hollis Blanchard + * Mark A. Greer + * Paul Mackerras + */ + +#include +#include +#include "flatdevtree.h" +#include "flatdevtree_env.h" + +#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1)) + +/* Routines for keeping node ptrs returned by ft_find_device current */ +/* First entry not used b/c it would return 0 and be taken as NULL/error */ +static void *ft_node_add(struct ft_cxt *cxt, char *node) +{ + unsigned int i; + + for (i = 1; i < cxt->nodes_used; i++) /* already there? */ + if (cxt->node_tbl[i] == node) + return (void *)i; + + if (cxt->nodes_used < cxt->node_max) { + cxt->node_tbl[cxt->nodes_used] = node; + return (void *)cxt->nodes_used++; + } + + return NULL; +} + +static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle) +{ + unsigned int i = (unsigned int)phandle; + + if (i < cxt->nodes_used) + return cxt->node_tbl[i]; + return NULL; +} + +static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift) +{ + unsigned int i; + + if (shift == 0) + return; + + for (i = 1; i < cxt->nodes_used; i++) + if (cxt->node_tbl[i] < addr) + cxt->node_tbl[i] += shift; +} + +static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift) +{ + unsigned int i; + + if (shift == 0) + return; + + for (i = 1; i < cxt->nodes_used; i++) + if (cxt->node_tbl[i] >= addr) + cxt->node_tbl[i] += shift; +} + +/* Struct used to return info from ft_next() */ +struct ft_atom { + u32 tag; + const char *name; + void *data; + u32 size; +}; + +/* Set ptrs to current one's info; return addr of next one */ +static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret) +{ + u32 sz; + + if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size) + return NULL; + + ret->tag = be32_to_cpu(*(u32 *) p); + p += 4; + + switch (ret->tag) { /* Tag */ + case OF_DT_BEGIN_NODE: + ret->name = p; + ret->data = (void *)(p - 4); /* start of node */ + p += _ALIGN(strlen(p) + 1, 4); + break; + case OF_DT_PROP: + ret->size = sz = be32_to_cpu(*(u32 *) p); + ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4)); + ret->data = (void *)(p + 8); + p += 8 + _ALIGN(sz, 4); + break; + case OF_DT_END_NODE: + case OF_DT_NOP: + break; + case OF_DT_END: + default: + p = NULL; + break; + } + + return p; +} + +#define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8) +#define EXPAND_INCR 1024 /* alloc this much extra when expanding */ + +/* See if the regions are in the standard order and non-overlapping */ +static int ft_ordered(struct ft_cxt *cxt) +{ + char *p = (char *)cxt->bph + HDR_SIZE; + enum ft_rgn_id r; + + for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) { + if (p > cxt->rgn[r].start) + return 0; + p = cxt->rgn[r].start + cxt->rgn[r].size; + } + return p <= (char *)cxt->bph + cxt->max_size; +} + +/* Copy the tree to a newly-allocated region and put things in order */ +static int ft_reorder(struct ft_cxt *cxt, int nextra) +{ + unsigned long tot; + enum ft_rgn_id r; + char *p, *pend; + int stroff; + + tot = HDR_SIZE + EXPAND_INCR; + for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) + tot += cxt->rgn[r].size; + if (nextra > 0) + tot += nextra; + tot = _ALIGN(tot, 8); + + if (!cxt->realloc) + return 0; + p = cxt->realloc(NULL, tot); + if (!p) + return 0; + + memcpy(p, cxt->bph, sizeof(struct boot_param_header)); + /* offsets get fixed up later */ + + cxt->bph = (struct boot_param_header *)p; + cxt->max_size = tot; + pend = p + tot; + p += HDR_SIZE; + + memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size); + cxt->rgn[FT_RSVMAP].start = p; + p += cxt->rgn[FT_RSVMAP].size; + + memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size); + ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, + p - cxt->rgn[FT_STRUCT].start); + cxt->p += p - cxt->rgn[FT_STRUCT].start; + cxt->rgn[FT_STRUCT].start = p; + + p = pend - cxt->rgn[FT_STRINGS].size; + memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size); + stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start; + cxt->rgn[FT_STRINGS].start = p; + cxt->str_anchor = p + stroff; + + cxt->isordered = 1; + return 1; +} + +static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r) +{ + if (r > FT_RSVMAP) + return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size; + return (char *)cxt->bph + HDR_SIZE; +} + +static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r) +{ + if (r < FT_STRINGS) + return cxt->rgn[r + 1].start; + return (char *)cxt->bph + cxt->max_size; +} + +/* + * See if we can expand region rgn by nextra bytes by using up + * free space after or before the region. + */ +static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, + int nextra) +{ + char *p = *pp; + char *rgn_start, *rgn_end; + + rgn_start = cxt->rgn[rgn].start; + rgn_end = rgn_start + cxt->rgn[rgn].size; + if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) { + /* move following stuff */ + if (p < rgn_end) { + if (nextra < 0) + memmove(p, p - nextra, rgn_end - p + nextra); + else + memmove(p + nextra, p, rgn_end - p); + if (rgn == FT_STRUCT) + ft_node_update_after(cxt, p, nextra); + } + cxt->rgn[rgn].size += nextra; + if (rgn == FT_STRINGS) + /* assumes strings only added at beginning */ + cxt->str_anchor += nextra; + return 1; + } + if (prev_end(cxt, rgn) <= rgn_start - nextra) { + /* move preceding stuff */ + if (p > rgn_start) { + memmove(rgn_start - nextra, rgn_start, p - rgn_start); + if (rgn == FT_STRUCT) + ft_node_update_before(cxt, p, -nextra); + } + *p -= nextra; + cxt->rgn[rgn].start -= nextra; + cxt->rgn[rgn].size += nextra; + return 1; + } + return 0; +} + +static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, + int nextra) +{ + unsigned long size, ssize, tot; + char *str, *next; + enum ft_rgn_id r; + + if (!cxt->isordered && !ft_reorder(cxt, nextra)) + return 0; + if (ft_shuffle(cxt, pp, rgn, nextra)) + return 1; + + /* See if there is space after the strings section */ + ssize = cxt->rgn[FT_STRINGS].size; + if (cxt->rgn[FT_STRINGS].start + ssize + < (char *)cxt->bph + cxt->max_size) { + /* move strings up as far as possible */ + str = (char *)cxt->bph + cxt->max_size - ssize; + cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start; + memmove(str, cxt->rgn[FT_STRINGS].start, ssize); + cxt->rgn[FT_STRINGS].start = str; + /* enough space now? */ + if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra)) + return 1; + } + + /* how much total free space is there following this region? */ + tot = 0; + for (r = rgn; r < FT_STRINGS; ++r) { + char *r_end = cxt->rgn[r].start + cxt->rgn[r].size; + tot += next_start(cxt, rgn) - r_end; + } + + /* cast is to shut gcc up; we know nextra >= 0 */ + if (tot < (unsigned int)nextra) { + /* have to reallocate */ + char *newp, *new_start; + int shift; + + if (!cxt->realloc) + return 0; + size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8); + newp = cxt->realloc(cxt->bph, size); + if (!newp) + return 0; + cxt->max_size = size; + shift = newp - (char *)cxt->bph; + + if (shift) { /* realloc can return same addr */ + cxt->bph = (struct boot_param_header *)newp; + ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, + shift); + for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) { + new_start = cxt->rgn[r].start + shift; + cxt->rgn[r].start = new_start; + } + *pp += shift; + cxt->str_anchor += shift; + } + + /* move strings up to the end */ + str = newp + size - ssize; + cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start; + memmove(str, cxt->rgn[FT_STRINGS].start, ssize); + cxt->rgn[FT_STRINGS].start = str; + + if (ft_shuffle(cxt, pp, rgn, nextra)) + return 1; + } + + /* must be FT_RSVMAP and we need to move FT_STRUCT up */ + if (rgn == FT_RSVMAP) { + next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size + + nextra; + ssize = cxt->rgn[FT_STRUCT].size; + if (next + ssize >= cxt->rgn[FT_STRINGS].start) + return 0; /* "can't happen" */ + memmove(next, cxt->rgn[FT_STRUCT].start, ssize); + ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra); + cxt->rgn[FT_STRUCT].start = next; + + if (ft_shuffle(cxt, pp, rgn, nextra)) + return 1; + } + + return 0; /* "can't happen" */ +} + +static void ft_put_word(struct ft_cxt *cxt, u32 v) +{ + *(u32 *) cxt->p = cpu_to_be32(v); + cxt->p += 4; +} + +static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz) +{ + unsigned long sza = _ALIGN(sz, 4); + + /* zero out the alignment gap if necessary */ + if (sz < sza) + *(u32 *) (cxt->p + sza - 4) = 0; + + /* copy in the data */ + memcpy(cxt->p, data, sz); + + cxt->p += sza; +} + +int ft_begin_node(struct ft_cxt *cxt, const char *name) +{ + unsigned long nlen = strlen(name) + 1; + unsigned long len = 8 + _ALIGN(nlen, 4); + + if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) + return -1; + ft_put_word(cxt, OF_DT_BEGIN_NODE); + ft_put_bin(cxt, name, strlen(name) + 1); + return 0; +} + +void ft_end_node(struct ft_cxt *cxt) +{ + ft_put_word(cxt, OF_DT_END_NODE); +} + +void ft_nop(struct ft_cxt *cxt) +{ + if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4)) + ft_put_word(cxt, OF_DT_NOP); +} + +#define NO_STRING 0x7fffffff + +static int lookup_string(struct ft_cxt *cxt, const char *name) +{ + char *p, *end; + + p = cxt->rgn[FT_STRINGS].start; + end = p + cxt->rgn[FT_STRINGS].size; + while (p < end) { + if (strcmp(p, (char *)name) == 0) + return p - cxt->str_anchor; + p += strlen(p) + 1; + } + + return NO_STRING; +} + +/* lookup string and insert if not found */ +static int map_string(struct ft_cxt *cxt, const char *name) +{ + int off; + char *p; + + off = lookup_string(cxt, name); + if (off != NO_STRING) + return off; + p = cxt->rgn[FT_STRINGS].start; + if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1)) + return NO_STRING; + strcpy(p, name); + return p - cxt->str_anchor; +} + +int ft_prop(struct ft_cxt *cxt, const char *name, const void *data, + unsigned int sz) +{ + int off, len; + + off = lookup_string(cxt, name); + if (off == NO_STRING) + return -1; + + len = 12 + _ALIGN(sz, 4); + if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) + return -1; + + ft_put_word(cxt, OF_DT_PROP); + ft_put_word(cxt, sz); + ft_put_word(cxt, off); + ft_put_bin(cxt, data, sz); + return 0; +} + +int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str) +{ + return ft_prop(cxt, name, str, strlen(str) + 1); +} + +int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val) +{ + u32 v = cpu_to_be32((u32) val); + + return ft_prop(cxt, name, &v, 4); +} + +/* Calculate the size of the reserved map */ +static unsigned long rsvmap_size(struct ft_cxt *cxt) +{ + struct ft_reserve *res; + + res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start; + while (res->start || res->len) + ++res; + return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start; +} + +/* Calculate the size of the struct region by stepping through it */ +static unsigned long struct_size(struct ft_cxt *cxt) +{ + char *p = cxt->rgn[FT_STRUCT].start; + char *next; + struct ft_atom atom; + + /* make check in ft_next happy */ + if (cxt->rgn[FT_STRUCT].size == 0) + cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p; + + while ((next = ft_next(cxt, p, &atom)) != NULL) + p = next; + return p + 4 - cxt->rgn[FT_STRUCT].start; +} + +/* add `adj' on to all string offset values in the struct area */ +static void adjust_string_offsets(struct ft_cxt *cxt, int adj) +{ + char *p = cxt->rgn[FT_STRUCT].start; + char *next; + struct ft_atom atom; + int off; + + while ((next = ft_next(cxt, p, &atom)) != NULL) { + if (atom.tag == OF_DT_PROP) { + off = be32_to_cpu(*(u32 *) (p + 8)); + *(u32 *) (p + 8) = cpu_to_be32(off + adj); + } + p = next; + } +} + +/* start construction of the flat OF tree from scratch */ +void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size, + void *(*realloc_fn) (void *, unsigned long)) +{ + struct boot_param_header *bph = blob; + char *p; + struct ft_reserve *pres; + + /* clear the cxt */ + memset(cxt, 0, sizeof(*cxt)); + + cxt->bph = bph; + cxt->max_size = max_size; + cxt->realloc = realloc_fn; + cxt->isordered = 1; + + /* zero everything in the header area */ + memset(bph, 0, sizeof(*bph)); + + bph->magic = cpu_to_be32(OF_DT_HEADER); + bph->version = cpu_to_be32(0x10); + bph->last_comp_version = cpu_to_be32(0x10); + + /* start pointers */ + cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE; + cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve); + pres = (struct ft_reserve *)p; + cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve); + cxt->rgn[FT_STRUCT].size = 4; + cxt->rgn[FT_STRINGS].start = blob + max_size; + cxt->rgn[FT_STRINGS].size = 0; + + /* init rsvmap and struct */ + pres->start = 0; + pres->len = 0; + *(u32 *) p = cpu_to_be32(OF_DT_END); + + cxt->str_anchor = blob; +} + +/* open up an existing blob to be examined or modified */ +int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size, + unsigned int max_find_device, + void *(*realloc_fn) (void *, unsigned long)) +{ + struct boot_param_header *bph = blob; + + /* can't cope with version < 16 */ + if (be32_to_cpu(bph->version) < 16) + return -1; + + /* clear the cxt */ + memset(cxt, 0, sizeof(*cxt)); + + /* alloc node_tbl to track node ptrs returned by ft_find_device */ + ++max_find_device; + cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *)); + if (!cxt->node_tbl) + return -1; + memset(cxt->node_tbl, 0, max_find_device * sizeof(char *)); + cxt->node_max = max_find_device; + cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */ + + cxt->bph = bph; + cxt->max_size = max_size; + cxt->realloc = realloc_fn; + + cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap); + cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt); + cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct); + cxt->rgn[FT_STRUCT].size = struct_size(cxt); + cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings); + cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size); + /* Leave as '0' to force first ft_make_space call to do a ft_reorder + * and move dt to an area allocated by realloc. + cxt->isordered = ft_ordered(cxt); + */ + + cxt->p = cxt->rgn[FT_STRUCT].start; + cxt->str_anchor = cxt->rgn[FT_STRINGS].start; + + return 0; +} + +/* add a reserver physical area to the rsvmap */ +int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) +{ + char *p; + struct ft_reserve *pres; + + p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size + - sizeof(struct ft_reserve); + if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve))) + return -1; + + pres = (struct ft_reserve *)p; + pres->start = cpu_to_be64(physaddr); + pres->len = cpu_to_be64(size); + + return 0; +} + +void ft_begin_tree(struct ft_cxt *cxt) +{ + cxt->p = cxt->rgn[FT_STRUCT].start; +} + +void ft_end_tree(struct ft_cxt *cxt) +{ + struct boot_param_header *bph = cxt->bph; + char *p, *oldstr, *str, *endp; + unsigned long ssize; + int adj; + + if (!cxt->isordered) + return; /* we haven't touched anything */ + + /* adjust string offsets */ + oldstr = cxt->rgn[FT_STRINGS].start; + adj = cxt->str_anchor - oldstr; + if (adj) + adjust_string_offsets(cxt, adj); + + /* make strings end on 8-byte boundary */ + ssize = cxt->rgn[FT_STRINGS].size; + endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start + + cxt->rgn[FT_STRUCT].size + ssize, 8); + str = endp - ssize; + + /* move strings down to end of structs */ + memmove(str, oldstr, ssize); + cxt->str_anchor = str; + cxt->rgn[FT_STRINGS].start = str; + + /* fill in header fields */ + p = (char *)bph; + bph->totalsize = cpu_to_be32(endp - p); + bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p); + bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p); + bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p); + bph->dt_strings_size = cpu_to_be32(ssize); +} + +void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) +{ + char *node; + + /* require absolute path */ + if (srch_path[0] != '/') + return NULL; + node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path); + return ft_node_add(cxt, node); +} + +void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) +{ + struct ft_atom atom; + char *p; + const char *cp, *q; + int cl; + int depth = -1; + int dmatch = 0; + const char *path_comp[FT_MAX_DEPTH]; + + cp = srch_path; + cl = 0; + p = top; + + while ((p = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + ++depth; + if (depth != dmatch) + break; + cxt->genealogy[depth] = atom.data; + cxt->genealogy[depth + 1] = NULL; + if (depth && !(strncmp(atom.name, cp, cl) == 0 + && (atom.name[cl] == '/' + || atom.name[cl] == '\0' + || atom.name[cl] == '@'))) + break; + path_comp[dmatch] = cp; + /* it matches so far, advance to next path component */ + cp += cl; + /* skip slashes */ + while (*cp == '/') + ++cp; + /* we're done if this is the end of the string */ + if (*cp == 0) + return atom.data; + /* look for end of this component */ + q = strchr(cp, '/'); + if (q) + cl = q - cp; + else + cl = strlen(cp); + ++dmatch; + break; + case OF_DT_END_NODE: + if (depth == 0) + return NULL; + if (dmatch > depth) { + --dmatch; + cl = cp - path_comp[dmatch] - 1; + cp = path_comp[dmatch]; + while (cl > 0 && cp[cl - 1] == '/') + --cl; + } + --depth; + break; + } + } + return NULL; +} + +void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) +{ + void *node; + int d; + struct ft_atom atom; + char *p; + + node = ft_node_ph2node(cxt, phandle); + if (node == NULL) + return NULL; + + for (d = 0; cxt->genealogy[d] != NULL; ++d) + if (cxt->genealogy[d] == node) + return cxt->genealogy[d > 0 ? d - 1 : 0]; + + /* have to do it the hard way... */ + p = cxt->rgn[FT_STRUCT].start; + d = 0; + while ((p = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + cxt->genealogy[d] = atom.data; + if (node == atom.data) { + /* found it */ + cxt->genealogy[d + 1] = NULL; + return d > 0 ? cxt->genealogy[d - 1] : node; + } + ++d; + break; + case OF_DT_END_NODE: + --d; + break; + } + } + return NULL; +} + +int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + void *buf, const unsigned int buflen) +{ + struct ft_atom atom; + void *node; + char *p; + int depth; + unsigned int size; + + node = ft_node_ph2node(cxt, phandle); + if (node == NULL) + return -1; + + depth = 0; + p = (char *)node; + + while ((p = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + ++depth; + break; + case OF_DT_PROP: + if ((depth != 1) || strcmp(atom.name, propname)) + break; + size = min(atom.size, buflen); + memcpy(buf, atom.data, size); + return atom.size; + case OF_DT_END_NODE: + if (--depth <= 0) + return -1; + } + } + return -1; +} + +int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + const void *buf, const unsigned int buflen) +{ + struct ft_atom atom; + void *node; + char *p, *next; + int nextra, depth; + + node = ft_node_ph2node(cxt, phandle); + if (node == NULL) + return -1; + + depth = 0; + p = node; + + while ((next = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + ++depth; + break; + case OF_DT_END_NODE: + if (--depth > 0) + break; + /* haven't found the property, insert here */ + cxt->p = p; + return ft_prop(cxt, propname, buf, buflen); + case OF_DT_PROP: + if ((depth != 1) || strcmp(atom.name, propname)) + break; + /* found an existing property, overwrite it */ + nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4); + cxt->p = atom.data; + if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT, + nextra)) + return -1; + *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen); + ft_put_bin(cxt, buf, buflen); + return 0; + } + p = next; + } + return -1; +} + +int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) +{ + struct ft_atom atom; + void *node; + char *p, *next; + int size; + + node = ft_node_ph2node(cxt, phandle); + if (node == NULL) + return -1; + + p = node; + while ((next = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + case OF_DT_END_NODE: + return -1; + case OF_DT_PROP: + if (strcmp(atom.name, propname)) + break; + /* found the property, remove it */ + size = 12 + -_ALIGN(atom.size, 4); + cxt->p = p; + if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size)) + return -1; + return 0; + } + p = next; + } + return -1; +} + +void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) +{ + struct ft_atom atom; + char *p, *next; + int depth = 0; + + p = cxt->rgn[FT_STRUCT].start; + while ((next = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + ++depth; + if (depth == 1 && strcmp(atom.name, path) == 0) + /* duplicate node path, return error */ + return NULL; + break; + case OF_DT_END_NODE: + --depth; + if (depth > 0) + break; + /* end of node, insert here */ + cxt->p = p; + ft_begin_node(cxt, path); + ft_end_node(cxt); + return p; + } + p = next; + } + return NULL; +} diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h index 761c8dc..b9cd9f6 100644 --- a/arch/powerpc/boot/flatdevtree.h +++ b/arch/powerpc/boot/flatdevtree.h @@ -17,7 +17,7 @@ #ifndef FLATDEVTREE_H #define FLATDEVTREE_H -#include "types.h" +#include "flatdevtree_env.h" /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* marker */ @@ -43,4 +43,64 @@ struct boot_param_header { u32 dt_strings_size; /* size of the DT strings block */ }; +struct ft_reserve { + u64 start; + u64 len; +}; + +struct ft_region { + char *start; + unsigned long size; +}; + +enum ft_rgn_id { + FT_RSVMAP, + FT_STRUCT, + FT_STRINGS, + FT_N_REGION +}; + +#define FT_MAX_DEPTH 50 + +struct ft_cxt { + struct boot_param_header *bph; + int max_size; /* maximum size of tree */ + int isordered; /* everything in standard order */ + void *(*realloc)(void *, unsigned long); + char *str_anchor; + char *p; /* current insertion point in structs */ + struct ft_region rgn[FT_N_REGION]; + void *genealogy[FT_MAX_DEPTH+1]; + char **node_tbl; + unsigned int node_max; + unsigned int nodes_used; +}; + +int ft_begin_node(struct ft_cxt *cxt, const char *name); +void ft_end_node(struct ft_cxt *cxt); + +void ft_begin_tree(struct ft_cxt *cxt); +void ft_end_tree(struct ft_cxt *cxt); + +void ft_nop(struct ft_cxt *cxt); +int ft_prop(struct ft_cxt *cxt, const char *name, + const void *data, unsigned int sz); +int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str); +int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val); +void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size, + void *(*realloc_fn)(void *, unsigned long)); +int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size, + unsigned int max_find_device, + void *(*realloc_fn)(void *, unsigned long)); +int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size); + +void ft_dump_blob(const void *bphp); +void ft_merge_blob(struct ft_cxt *cxt, void *blob); +void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); +void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); +int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + void *buf, const unsigned int buflen); +int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + const void *buf, const unsigned int buflen); + #endif /* FLATDEVTREE_H */ diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h new file mode 100644 index 0000000..83bc1c7 --- /dev/null +++ b/arch/powerpc/boot/flatdevtree_env.h @@ -0,0 +1,47 @@ +/* + * This file adds the header file glue so that the shared files + * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper. + * + * strncmp & strchr copied from + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Maintained by: Mark A. Greer + */ +#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_ +#define _PPC_BOOT_FLATDEVTREE_ENV_H_ + +#include +#include +#include "types.h" +#include "string.h" +#include "stdio.h" +#include "ops.h" + +#define be16_to_cpu(x) (x) +#define cpu_to_be16(x) (x) +#define be32_to_cpu(x) (x) +#define cpu_to_be32(x) (x) +#define be64_to_cpu(x) (x) +#define cpu_to_be64(x) (x) + +static inline int strncmp(const char *cs, const char *ct, size_t count) +{ + signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + return __res; +} + +static inline char *strchr(const char *s, int c) +{ + for (; *s != (char)c; ++s) + if (*s == '\0') + return NULL; + return (char *)s; +} + +#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */ diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c new file mode 100644 index 0000000..c7f9adb --- /dev/null +++ b/arch/powerpc/boot/flatdevtree_misc.c @@ -0,0 +1,56 @@ +/* + * This file does the necessary interface mapping between the bootwrapper + * device tree operations and the interface provided by shared source + * files flatdevicetree.[ch]. + * + * Author: Mark A. Greer + * + * 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include "flatdevtree.h" +#include "ops.h" + +static struct ft_cxt cxt; + +static void *ft_finddevice(const char *name) +{ + return ft_find_device(&cxt, name); +} + +static int ft_getprop(const void *phandle, const char *propname, void *buf, + const int buflen) +{ + return ft_get_prop(&cxt, phandle, propname, buf, buflen); +} + +static int ft_setprop(const void *phandle, const char *propname, + const void *buf, const int buflen) +{ + return ft_set_prop(&cxt, phandle, propname, buf, buflen); +} + +static void ft_pack(void) +{ + ft_end_tree(&cxt); +} + +static unsigned long ft_addr(void) +{ + return (unsigned long)cxt.bph; +} + +int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) +{ + dt_ops.finddevice = ft_finddevice; + dt_ops.getprop = ft_getprop; + dt_ops.setprop = ft_setprop; + dt_ops.ft_pack = ft_pack; + dt_ops.ft_addr = ft_addr; + + return ft_open(&cxt, dt_blob, max_size, max_find_device, + platform_ops.realloc); +} -- cgit v0.10.2 From 0c176fa80fdfa9b4e0753e37223b056994c818d2 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Mon, 16 Oct 2006 13:52:09 -0700 Subject: [POWERPC] Add non-OF serial console support Add serial console support for non-OF systems. There is a generic serial console layer which calls a serial console driver. Included is the serial console driver for the ns16550 class of uarts. Necessary support routines are added as well. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 8660cc5..62435d9 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -40,8 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) -src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \ - $(zlib) +src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ + ns16550.c serial.c div64.S util.S $(zlib) src-plat := of.c src-boot := crt0.S $(src-wlib) $(src-plat) empty.c diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h new file mode 100644 index 0000000..32974ed --- /dev/null +++ b/arch/powerpc/boot/io.h @@ -0,0 +1,53 @@ +#ifndef _IO_H +#define __IO_H +/* + * Low-level I/O routines. + * + * Copied from (which has no copyright) + */ +static inline int in_8(const volatile unsigned char *addr) +{ + int ret; + + __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_8(volatile unsigned char *addr, int val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; sync" + : "=m" (*addr) : "r" (val)); +} + +static inline unsigned in_le32(const volatile unsigned *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "r" (addr), "m" (*addr)); + return ret; +} + +static inline unsigned in_be32(const volatile unsigned *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_le32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr) + : "r" (val), "r" (addr)); +} + +static inline void out_be32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stw%U0%X0 %1,%0; sync" + : "=m" (*addr) : "r" (val)); +} + +#endif /* _IO_H */ diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c new file mode 100644 index 0000000..1ffe72e --- /dev/null +++ b/arch/powerpc/boot/ns16550.c @@ -0,0 +1,74 @@ +/* + * 16550 serial console support. + * + * Original copied from + * (which had no copyright) + * Modifications: 2006 (c) MontaVista Software, Inc. + * + * Modified by: Mark A. Greer + */ +#include +#include +#include "types.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" + +#define UART_DLL 0 /* Out: Divisor Latch Low */ +#define UART_DLM 1 /* Out: Divisor Latch High */ +#define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_LCR 3 /* Out: Line Control Register */ +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ +#define UART_MSR 6 /* In: Modem Status Register */ +#define UART_SCR 7 /* I/O: Scratch Register */ + +static unsigned char *reg_base; +static u32 reg_shift; + +static int ns16550_open(void) +{ + out_8(reg_base + (UART_FCR << reg_shift), 0x06); + return 0; +} + +static void ns16550_putc(unsigned char c) +{ + while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0); + out_8(reg_base, c); +} + +static unsigned char ns16550_getc(void) +{ + while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0); + return in_8(reg_base); +} + +static u8 ns16550_tstc(void) +{ + return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0); +} + +int ns16550_console_init(void *devp, struct serial_console_data *scdp) +{ + int n; + + n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base)); + if (n != sizeof(reg_base)) + return -1; + + n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); + if (n != sizeof(reg_shift)) + reg_shift = 0; + + scdp->open = ns16550_open; + scdp->putc = ns16550_putc; + scdp->getc = ns16550_getc; + scdp->tstc = ns16550_tstc; + scdp->close = NULL; + + return 0; +} diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c new file mode 100644 index 0000000..e8de4cf --- /dev/null +++ b/arch/powerpc/boot/serial.c @@ -0,0 +1,142 @@ +/* + * Generic serial console support + * + * Author: Mark A. Greer + * + * Code in serial_edit_cmdline() copied from + * and was written by Matt Porter . + * + * 2001,2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include "types.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" + +extern void udelay(long delay); + +static int serial_open(void) +{ + struct serial_console_data *scdp = console_ops.data; + return scdp->open(); +} + +static void serial_write(char *buf, int len) +{ + struct serial_console_data *scdp = console_ops.data; + + while (*buf != '\0') + scdp->putc(*buf++); +} + +static void serial_edit_cmdline(char *buf, int len) +{ + int timer = 0, count; + char ch, *cp; + struct serial_console_data *scdp = console_ops.data; + + cp = buf; + count = strlen(buf); + cp = &buf[count]; + count++; + + while (timer++ < 5*1000) { + if (scdp->tstc()) { + while (((ch = scdp->getc()) != '\n') && (ch != '\r')) { + /* Test for backspace/delete */ + if ((ch == '\b') || (ch == '\177')) { + if (cp != buf) { + cp--; + count--; + printf("\b \b"); + } + /* Test for ^x/^u (and wipe the line) */ + } else if ((ch == '\030') || (ch == '\025')) { + while (cp != buf) { + cp--; + count--; + printf("\b \b"); + } + } else if (count < len) { + *cp++ = ch; + count++; + scdp->putc(ch); + } + } + break; /* Exit 'timer' loop */ + } + udelay(1000); /* 1 msec */ + } + *cp = 0; +} + +static void serial_close(void) +{ + struct serial_console_data *scdp = console_ops.data; + + if (scdp->close) + scdp->close(); +} + +static void *serial_get_stdout_devp(void) +{ + void *devp; + char devtype[MAX_PROP_LEN]; + char path[MAX_PATH_LEN]; + + devp = finddevice("/chosen"); + if (devp == NULL) + goto err_out; + + if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) { + devp = finddevice(path); + if (devp == NULL) + goto err_out; + + if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0) + && !strcmp(devtype, "serial")) + return devp; + } +err_out: + return NULL; +} + +static struct serial_console_data serial_cd; + +/* Node's "compatible" property determines which serial driver to use */ +int serial_console_init(void) +{ + void *devp; + int rc = -1; + char compat[MAX_PROP_LEN]; + + devp = serial_get_stdout_devp(); + if (devp == NULL) + goto err_out; + + if (getprop(devp, "compatible", compat, sizeof(compat)) < 0) + goto err_out; + + if (!strcmp(compat, "ns16550")) + rc = ns16550_console_init(devp, &serial_cd); + + /* Add other serial console driver calls here */ + + if (!rc) { + console_ops.open = serial_open; + console_ops.write = serial_write; + console_ops.edit_cmdline = serial_edit_cmdline; + console_ops.close = serial_close; + console_ops.data = &serial_cd; + + return 0; + } +err_out: + return -1; +} diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S new file mode 100644 index 0000000..427ddfc --- /dev/null +++ b/arch/powerpc/boot/util.S @@ -0,0 +1,88 @@ +/* + * Copied from + * + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras. + * + * kexec bits: + * Copyright (C) 2002-2003 Eric Biederman + * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz + * + * 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 "ppc_asm.h" + +#define SPRN_PVR 0x11F /* Processor Version Register */ + + .text + +/* udelay (on non-601 processors) needs to know the period of the + * timebase in nanoseconds. This used to be hardcoded to be 60ns + * (period of 66MHz/4). Now a variable is used that is initialized to + * 60 for backward compatibility, but it can be overridden as necessary + * with code something like this: + * extern unsigned long timebase_period_ns; + * timebase_period_ns = 1000000000 / bd->bi_tbfreq; + */ + .data + .globl timebase_period_ns +timebase_period_ns: + .long 60 + + .text +/* + * Delay for a number of microseconds + */ + .globl udelay +udelay: + mfspr r4,SPRN_PVR + srwi r4,r4,16 + cmpwi 0,r4,1 /* 601 ? */ + bne .udelay_not_601 +00: li r0,86 /* Instructions / microsecond? */ + mtctr r0 +10: addi r0,r0,0 /* NOP */ + bdnz 10b + subic. r3,r3,1 + bne 00b + blr + +.udelay_not_601: + mulli r4,r3,1000 /* nanoseconds */ + /* Change r4 to be the number of ticks using: + * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns + * timebase_period_ns defaults to 60 (16.6MHz) */ + mflr r5 + bl 0f +0: mflr r6 + mtlr r5 + lis r5,0b@ha + addi r5,r5,0b@l + subf r5,r5,r6 /* In case we're relocated */ + addis r5,r5,timebase_period_ns@ha + lwz r5,timebase_period_ns@l(r5) + add r4,r4,r5 + addi r4,r4,-1 + divw r4,r4,r5 /* BUS ticks */ +1: mftbu r5 + mftb r6 + mftbu r7 + cmpw 0,r5,r7 + bne 1b /* Get [synced] base time */ + addc r9,r6,r4 /* Compute end time */ + addze r8,r5 +2: mftbu r5 + cmpw 0,r5,r8 + blt 2b + bgt 3f + mftb r6 + cmpw 0,r6,r9 + blt 2b +3: blr -- cgit v0.10.2 From 01a6372008ed450982ba38ee5fd91028b9f5a781 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Mon, 16 Oct 2006 13:54:52 -0700 Subject: [POWERPC] Add simple memory allocator to bootwrapper Provide primitive malloc, free, and realloc functions for bootwrapper. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 62435d9..9731c25 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -41,7 +41,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - ns16550.c serial.c div64.S util.S $(zlib) + ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib) src-plat := of.c src-boot := crt0.S $(src-wlib) $(src-plat) empty.c diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c new file mode 100644 index 0000000..cfe3a75 --- /dev/null +++ b/arch/powerpc/boot/simple_alloc.c @@ -0,0 +1,149 @@ +/* + * Implement primitive realloc(3) functionality. + * + * Author: Mark A. Greer + * + * 2006 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include "types.h" +#include "page.h" +#include "string.h" +#include "ops.h" + +#define ENTRY_BEEN_USED 0x01 +#define ENTRY_IN_USE 0x02 + +static struct alloc_info { + u32 flags; + u32 base; + u32 size; +} *alloc_tbl; + +static u32 tbl_entries; +static u32 alloc_min; +static u32 next_base; +static u32 space_left; + +/* + * First time an entry is used, its base and size are set. + * An entry can be freed and re-malloc'd but its base & size don't change. + * Should be smart enough for needs of bootwrapper. + */ +static void *simple_malloc(u32 size) +{ + u32 i; + struct alloc_info *p = alloc_tbl; + + if (size == 0) + goto err_out; + + size = _ALIGN_UP(size, alloc_min); + + for (i=0; iflags & ENTRY_BEEN_USED)) { /* never been used */ + if (size <= space_left) { + p->base = next_base; + p->size = size; + p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE; + next_base += size; + space_left -= size; + return (void *)p->base; + } + goto err_out; /* not enough space left */ + } + /* reuse an entry keeping same base & size */ + else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) { + p->flags |= ENTRY_IN_USE; + return (void *)p->base; + } +err_out: + return NULL; +} + +static struct alloc_info *simple_find_entry(void *ptr) +{ + u32 i; + struct alloc_info *p = alloc_tbl; + + for (i=0; iflags & ENTRY_BEEN_USED)) + break; + if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr)) + return p; + } + return NULL; +} + +static void simple_free(void *ptr) +{ + struct alloc_info *p = simple_find_entry(ptr); + + if (p != NULL) + p->flags &= ~ENTRY_IN_USE; +} + +/* + * Change size of area pointed to by 'ptr' to 'size'. + * If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free(). + * 'ptr' must be NULL or a pointer to a non-freed area previously returned by + * simple_realloc() or simple_malloc(). + */ +static void *simple_realloc(void *ptr, unsigned long size) +{ + struct alloc_info *p; + void *new; + + if (size == 0) { + simple_free(ptr); + return NULL; + } + + if (ptr == NULL) + return simple_malloc(size); + + p = simple_find_entry(ptr); + if (p == NULL) /* ptr not from simple_malloc/simple_realloc */ + return NULL; + if (size <= p->size) /* fits in current block */ + return ptr; + + new = simple_malloc(size); + memcpy(new, ptr, p->size); + simple_free(ptr); + return new; +} + +/* + * Returns addr of first byte after heap so caller can see if it took + * too much space. If so, change args & try again. + */ +void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, + u32 max_allocs) +{ + u32 heap_base, tbl_size; + + heap_size = _ALIGN_UP(heap_size, granularity); + alloc_min = granularity; + tbl_entries = max_allocs; + + tbl_size = tbl_entries * sizeof(struct alloc_info); + + alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8); + memset(alloc_tbl, 0, tbl_size); + + heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min); + + next_base = heap_base; + space_left = heap_size; + + platform_ops.malloc = simple_malloc; + platform_ops.free = simple_free; + platform_ops.realloc = simple_realloc; + + return (void *)(heap_base + heap_size); +} -- cgit v0.10.2 From 6a43487f43fbd4e03c606dcb62b98374a3af88fc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 22 Oct 2006 20:38:00 -0700 Subject: [NET]: kernel-doc fix for sock.h Fix kernel-doc warning in include/net/sock.h: Warning(/var/linsrc/linux-2619-rc1-pv//include/net/sock.h:894): No description found for parameter 'rcu' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/net/sock.h b/include/net/sock.h index 40bb90e..ac286a3 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -884,8 +884,7 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) /** * sk_filter_release: Release a socket filter - * @sk: socket - * @fp: filter to remove + * @rcu: rcu_head that contains the sk_filter info to remove * * Remove a filter from a socket and release its resources. */ -- cgit v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e8a7f1b..ecf8e4d 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 45939ba..ef8874b 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 v0.10.2 From a94b1d1fd7ca3129e1d38d38167779fa6ee69780 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 22 Oct 2006 21:53:30 -0700 Subject: [SPARC64]: 8-byte align return value from compat_alloc_user_space() Otherwise we get a ton of unaligned exceptions, for cases such as compat_sys_msgrcv() which go: p = compat_alloc_user_space(second + sizeof(struct msgbuf)); and here 'second' can for example be an arbitrary odd value. Based upon a bug report from Jurij Smakov. Signed-off-by: David S. Miller diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h index c73935d..36511ca 100644 --- a/include/asm-sparc64/compat.h +++ b/include/asm-sparc64/compat.h @@ -164,7 +164,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static __inline__ void __user *compat_alloc_user_space(long len) +static inline void __user *compat_alloc_user_space(long len) { struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; @@ -174,7 +174,10 @@ static __inline__ void __user *compat_alloc_user_space(long len) else usp &= 0xffffffffUL; - return (void __user *) (usp - len); + usp -= len; + usp &= ~0x7UL; + + return (void __user *) usp; } struct compat_ipc64_perm { -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index a6d42cf..4d56121 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 v0.10.2 From cbcdb93d4443568f17e93610d240043ec5ac067b Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 17 Oct 2006 23:08:35 +1000 Subject: [POWERPC] Simplify stolen time calculation In calculating stolen time, we were trying to actually account for time spent in the hypervisor. We don't really have enough information to do that accurately, so don't try. Instead, we now calculate stolen time as time that the current cpu thread is not actually dispatching instructions. On chips without a PURR, we cannot do this, so stolen time will always be zero. On chips with a PURR, this is merely the difference between the elapsed PURR values and the elapsed TB values. This gives us much more sane vaules from tools such as mpstat, even if they are still a bit strange e.g. 2 busy threads on one cpu will both appear to have 50% user time and 50% stolen time while 1 busy thread on a cpu will look like 100% user on one of them and 100% idle on the other. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 5b59bc1..a1b5e4b 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs) */ struct cpu_purr_data { int initialized; /* thread is running */ - u64 tb0; /* timebase at origin time */ - u64 purr0; /* PURR at origin time */ u64 tb; /* last TB value read */ u64 purr; /* last PURR value read */ - u64 stolen; /* stolen time so far */ spinlock_t lock; }; @@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data) { struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); - p->tb0 = mftb(); - p->purr0 = mfspr(SPRN_PURR); - p->tb = p->tb0; - p->purr = 0; + p->tb = mftb(); + p->purr = mfspr(SPRN_PURR); wmb(); p->initialized = 1; } @@ -258,37 +253,24 @@ void snapshot_timebases(void) void calculate_steal_time(void) { - u64 tb, purr, t0; + u64 tb, purr; s64 stolen; - struct cpu_purr_data *p0, *pme, *phim; - int cpu; + struct cpu_purr_data *pme; if (!cpu_has_feature(CPU_FTR_PURR)) return; - cpu = smp_processor_id(); - pme = &per_cpu(cpu_purr_data, cpu); + pme = &per_cpu(cpu_purr_data, smp_processor_id()); if (!pme->initialized) return; /* this can happen in early boot */ - p0 = &per_cpu(cpu_purr_data, cpu & ~1); - phim = &per_cpu(cpu_purr_data, cpu ^ 1); - spin_lock(&p0->lock); + spin_lock(&pme->lock); tb = mftb(); - purr = mfspr(SPRN_PURR) - pme->purr0; - if (!phim->initialized || !cpu_online(cpu ^ 1)) { - stolen = (tb - pme->tb) - (purr - pme->purr); - } else { - t0 = pme->tb0; - if (phim->tb0 < t0) - t0 = phim->tb0; - stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; - } - if (stolen > 0) { + purr = mfspr(SPRN_PURR); + stolen = (tb - pme->tb) - (purr - pme->purr); + if (stolen > 0) account_steal_time(current, stolen); - p0->stolen += stolen; - } pme->tb = tb; pme->purr = purr; - spin_unlock(&p0->lock); + spin_unlock(&pme->lock); } /* @@ -297,30 +279,17 @@ void calculate_steal_time(void) */ static void snapshot_purr(void) { - int cpu; - u64 purr; - struct cpu_purr_data *p0, *pme, *phim; + struct cpu_purr_data *pme; unsigned long flags; if (!cpu_has_feature(CPU_FTR_PURR)) return; - cpu = smp_processor_id(); - pme = &per_cpu(cpu_purr_data, cpu); - p0 = &per_cpu(cpu_purr_data, cpu & ~1); - phim = &per_cpu(cpu_purr_data, cpu ^ 1); - spin_lock_irqsave(&p0->lock, flags); - pme->tb = pme->tb0 = mftb(); - purr = mfspr(SPRN_PURR); - if (!phim->initialized) { - pme->purr = 0; - pme->purr0 = purr; - } else { - /* set p->purr and p->purr0 for no change in p0->stolen */ - pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; - pme->purr0 = purr - pme->purr; - } + pme = &per_cpu(cpu_purr_data, smp_processor_id()); + spin_lock_irqsave(&pme->lock, flags); + pme->tb = mftb(); + pme->purr = mfspr(SPRN_PURR); pme->initialized = 1; - spin_unlock_irqrestore(&p0->lock, flags); + spin_unlock_irqrestore(&pme->lock, flags); } #endif /* CONFIG_PPC_SPLPAR */ -- cgit v0.10.2 From c3386e40142e9d0c077460c2a548c4653fecaf15 Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Wed, 18 Oct 2006 11:18:58 +0800 Subject: [POWERPC] Fix compiler warning message on get_property call This fixes the warning message from the return value of function get_property(), by making sure that the variable that receives the value is marked as const. Signed-off-by: Roy Zang -- Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 11de090..97f37ef 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void) tsi = of_find_node_by_type(NULL, "tsi-bridge"); if (tsi) { unsigned int size; - void *prop = get_property(tsi, "reg", &size); + const void *prop = get_property(tsi, "reg", &size); tsi108_csr_base = of_translate_address(tsi, prop); of_node_put(tsi); }; @@ -79,7 +79,7 @@ static int __init tsi108_eth_of_init(void) hw_info tsi_eth_data; unsigned int *id; unsigned int *phy_id; - void *mac_addr; + const void *mac_addr; phandle *ph; memset(r, 0, sizeof(r)); -- cgit v0.10.2 From 7f8c4c50bda13d27afc03679d25aa1fcac8df551 Mon Sep 17 00:00:00 2001 From: Srinivasa Ds Date: Wed, 18 Oct 2006 17:34:49 +0530 Subject: [POWERPC] Fix build breakage with CONFIG_PPC32 low_cpu_die is called from the CPU hotplug code on 32-bit powermacs, but it is only defined if CONFIG_PM || CONFIG_CPU_FREQ_PMAC. This changes the ifdef so it is defined for CONFIG_HOTPLUG_CPU on 32-bit machines. Signed-off-by: Srinivasa DS Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/powermac/sleep.S b/arch/powerpc/platforms/powermac/sleep.S index 1174ca1..adee28d 100644 --- a/arch/powerpc/platforms/powermac/sleep.S +++ b/arch/powerpc/platforms/powermac/sleep.S @@ -45,7 +45,8 @@ .section .text .align 5 -#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) +#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \ + (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)) /* This gets called by via-pmu.c late during the sleep process. * The PMU was already send the sleep command and will shut us down -- cgit v0.10.2 From 362ff7b2ac0234152b4a334dd006b77f4fa2ab23 Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Wed, 18 Oct 2006 10:47:22 -0500 Subject: [POWERPC] Add 970GX cputable entry 970GX cputable entry from Steve Winiecki. Signed-off-by: Jake Moilanen arch/powerpc/kernel/cputable.c | 15 +++++++++++++++ arch/powerpc/oprofile/op_model_power4.c | 2 +- include/asm-powerpc/reg.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 95382f9..f23aad6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -227,6 +227,21 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, + { /* PPC970GX */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00450000, + .cpu_name = "PPC970GX", + .cpu_features = CPU_FTRS_PPC970, + .cpu_user_features = COMMON_USER_POWER4 | + PPC_FEATURE_HAS_ALTIVEC_COMP, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_ppc970, + .oprofile_cpu_type = "ppc64/970", + .oprofile_type = PPC_OPROFILE_POWER4, + .platform = "ppc970", + }, { /* Power5 GR */ .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 506f6b7..6a927ef 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -76,7 +76,7 @@ static inline int mmcra_must_set_sample(void) { if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) || __is_processor(PV_970) || __is_processor(PV_970FX) || - __is_processor(PV_970MP)) + __is_processor(PV_970MP) || __is_processor(PV_970GX)) return 1; return 0; diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 8fb9681..fde5c80 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -591,6 +591,7 @@ #define PV_630 0x0040 #define PV_630p 0x0041 #define PV_970MP 0x0044 +#define PV_970GX 0x0045 #define PV_BE 0x0070 #define PV_PA6T 0x0090 -- cgit v0.10.2 From 3688a0f484e980771c078ab90f74a2656c339106 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 18 Oct 2006 14:38:09 -0700 Subject: [POWERPC] Don't require execute perms on wrapper when building zImage.initrd Don't require that the wrapper script be executable when building zImage.initrds. This has already been fixed for zImages. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 37ddfca..4b2be61 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -115,7 +115,7 @@ endif quiet_cmd_wrap = WRAP $@ cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux quiet_cmd_wrap_initrd = WRAP $@ - cmd_wrap_initrd =$(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ + cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ -i $(obj)/ramdisk.image.gz vmlinux $(obj)/zImage.chrp: vmlinux $(wrapperbits) -- cgit v0.10.2 From aa7a32cbdac50bb46a75722faa359993dab07c61 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 18 Oct 2006 17:27:32 -0500 Subject: [POWERPC] Fix spelling errors in ucc_fast.c and ucc_slow.c In ucc_fast.c and ucc_slow.c, "illegal" is twice spelled "illagal". Signed-off-by: Timur Tabi Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index c2be734..75fa310 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -163,7 +163,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* check if the UCC port number is in range. */ if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { - uccf_err("ucc_fast_init: Illagal UCC number!"); + uccf_err("ucc_fast_init: Illegal UCC number!"); return -EINVAL; } diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index 1fb88ef..a49da6b 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -152,7 +152,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* check if the UCC port number is in range. */ if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { - uccs_err("ucc_slow_init: Illagal UCC number!"); + uccs_err("ucc_slow_init: Illegal UCC number!"); return -EINVAL; } -- cgit v0.10.2 From 68e7fffc0f3e95063ba5bd94ee6f9b8927247297 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Oct 2006 13:40:59 +0200 Subject: [ALSA] hda-intel - Add check of MSI availabity Check the availability of MSI and turn off MSI automatically when it's not available on the hardware. MSI seems broken on some hardwares but the kernel doesn't know exactly, thus we have to turn the MSI feature off on the sound driver manually. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c177192..0e292dc 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -337,6 +337,7 @@ struct azx { unsigned int initialized :1; unsigned int single_cmd :1; unsigned int polling_mode :1; + unsigned int msi :1; }; /* driver types */ @@ -397,6 +398,7 @@ static char *driver_short_names[] __devinitdata = { */ #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0) +static int azx_acquire_irq(struct azx *chip, int do_disconnect); /* * Interface for HD codec @@ -536,6 +538,18 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) schedule_timeout_interruptible(1); } while (time_after_eq(timeout, jiffies)); + if (chip->msi) { + snd_printk(KERN_WARNING "hda_intel: No response from codec, " + "disabling MSI...\n"); + free_irq(chip->irq, chip); + chip->irq = -1; + pci_disable_msi(chip->pci); + chip->msi = 0; + if (azx_acquire_irq(chip, 1) < 0) + return -1; + goto again; + } + if (!chip->polling_mode) { snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " "switching to polling mode...\n"); @@ -1364,6 +1378,20 @@ static int __devinit azx_init_stream(struct azx *chip) return 0; } +static int azx_acquire_irq(struct azx *chip, int do_disconnect) +{ + if (request_irq(chip->pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, + "HDA Intel", chip)) { + printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " + "disabling device\n", chip->pci->irq); + if (do_disconnect) + snd_card_disconnect(chip->card); + return -1; + } + chip->irq = chip->pci->irq; + return 0; +} + #ifdef CONFIG_PM /* @@ -1385,7 +1413,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) free_irq(chip->irq, chip); chip->irq = -1; } - if (!disable_msi) + if (chip->msi) pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); @@ -1407,16 +1435,11 @@ static int azx_resume(struct pci_dev *pci) return -EIO; } pci_set_master(pci); - if (!disable_msi) - pci_enable_msi(pci); - if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, - "HDA Intel", chip)) { - printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " - "disabling device\n", pci->irq); - snd_card_disconnect(card); + if (chip->msi) + if (pci_enable_msi(pci) < 0) + chip->msi = 0; + if (azx_acquire_irq(chip, 1) < 0) return -EIO; - } - chip->irq = pci->irq; azx_init_chip(chip); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -1452,7 +1475,7 @@ static int azx_free(struct azx *chip) synchronize_irq(chip->irq); free_irq(chip->irq, (void*)chip); } - if (!disable_msi) + if (chip->msi) pci_disable_msi(chip->pci); if (chip->remap_addr) iounmap(chip->remap_addr); @@ -1508,6 +1531,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; chip->driver_type = driver_type; + chip->msi = !disable_msi; chip->position_fix = position_fix; chip->single_cmd = single_cmd; @@ -1537,16 +1561,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } - if (!disable_msi) - pci_enable_msi(pci); + if (chip->msi) + if (pci_enable_msi(pci) < 0) + chip->msi = 0; - if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, - "HDA Intel", (void*)chip)) { - snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); + if (azx_acquire_irq(chip, 0) < 0) { err = -EBUSY; goto errout; } - chip->irq = pci->irq; pci_set_master(pci); synchronize_irq(chip->irq); -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index 4d56121..bd7727b 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 v0.10.2 From 04fed361dadb7921507a470947ac23d2f26352cf Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 22 Oct 2006 15:57:18 +0100 Subject: [PATCH] Remove __must_check for device_for_each_child() Eliminate more __must_check madness. The return code from device_for_each_child() depends on the values which the helper function returns. If the helper function always returns zero, it's utterly pointless to check the return code from device_for_each_child(). The only code which knows if the return value should be checked is the caller itself, so forcing the return code to always be checked is silly. Hence, remove the __must_check annotation. Signed-off-by: Russell King Signed-off-by: Linus Torvalds diff --git a/include/linux/device.h b/include/linux/device.h index 662e6a1..9d4f6a9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -393,7 +393,7 @@ extern void device_unregister(struct device * dev); extern void device_initialize(struct device * dev); extern int __must_check device_add(struct device * dev); extern void device_del(struct device * dev); -extern int __must_check device_for_each_child(struct device *, void *, +extern int device_for_each_child(struct device *, void *, int (*fn)(struct device *, void *)); extern int device_rename(struct device *dev, char *new_name); -- cgit v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ecf8e4d..e8a7f1b 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 v0.10.2 From 7059abedd2f04b68bd7e1a79c9c72f7aeee134c0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 23 Oct 2006 16:02:02 -0700 Subject: Linux 2.6.19-rc3 diff --git a/Makefile b/Makefile index 389ff0c..25b3599 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc3 NAME=Avast! A bilge rat! # *DOCUMENTATION* -- cgit v0.10.2 From 0cfcccb4687862a34eb609d16e75b39b6cb54c80 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Oct 2006 10:07:01 -0500 Subject: [POWERPC] Add mktree utility to arch/powerpc/boot This patch adds the mktree program that is needed to post process zImage wrappers for various PowerPC 4xx boards Signed-off-by: Josh Boyer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 9731c25..1e71a45 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -94,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S $(obj)/wrapper.a: $(obj-wlib) $(call cmd,bootar) -hostprogs-y := addnote addRamDisk hack-coff +hostprogs-y := addnote addRamDisk hack-coff mktree extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ $(obj)/zImage.lds $(obj)/zImage.coff.lds wrapper :=$(srctree)/$(src)/wrapper -wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff) +wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) ############# # Bits for building various flavours of zImage diff --git a/arch/powerpc/boot/mktree.c b/arch/powerpc/boot/mktree.c new file mode 100644 index 0000000..4cb8929 --- /dev/null +++ b/arch/powerpc/boot/mktree.c @@ -0,0 +1,152 @@ +/* + * Makes a tree bootable image for IBM Evaluation boards. + * Basically, just take a zImage, skip the ELF header, and stuff + * a 32 byte header on the front. + * + * We use htonl, which is a network macro, to make sure we're doing + * The Right Thing on an LE machine. It's non-obvious, but it should + * work on anything BSD'ish. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __sun__ +#include +#else +#include +#endif + +/* This gets tacked on the front of the image. There are also a few + * bytes allocated after the _start label used by the boot rom (see + * head.S for details). + */ +typedef struct boot_block { + uint32_t bb_magic; /* 0x0052504F */ + uint32_t bb_dest; /* Target address of the image */ + uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */ + uint32_t bb_debug_flag; /* Run debugger or image after load */ + uint32_t bb_entry_point; /* The image address to start */ + uint32_t bb_checksum; /* 32 bit checksum including header */ + uint32_t reserved[2]; +} boot_block_t; + +#define IMGBLK 512 +char tmpbuf[IMGBLK]; + +int main(int argc, char *argv[]) +{ + int in_fd, out_fd; + int nblks, i; + uint cksum, *cp; + struct stat st; + boot_block_t bt; + + if (argc < 3) { + fprintf(stderr, "usage: %s [entry-point]\n",argv[0]); + exit(1); + } + + if (stat(argv[1], &st) < 0) { + perror("stat"); + exit(2); + } + + nblks = (st.st_size + IMGBLK) / IMGBLK; + + bt.bb_magic = htonl(0x0052504F); + + /* If we have the optional entry point parameter, use it */ + if (argc == 4) + bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0)); + else + bt.bb_dest = bt.bb_entry_point = htonl(0x500000); + + /* We know these from the linker command. + * ...and then move it up into memory a little more so the + * relocation can happen. + */ + bt.bb_num_512blocks = htonl(nblks); + bt.bb_debug_flag = 0; + + bt.bb_checksum = 0; + + /* To be neat and tidy :-). + */ + bt.reserved[0] = 0; + bt.reserved[1] = 0; + + if ((in_fd = open(argv[1], O_RDONLY)) < 0) { + perror("zImage open"); + exit(3); + } + + if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { + perror("bootfile open"); + exit(3); + } + + cksum = 0; + cp = (void *)&bt; + for (i=0; i 0) { + if (read(in_fd, tmpbuf, IMGBLK) < 0) { + perror("zImage read"); + exit(5); + } + cp = (uint *)tmpbuf; + for (i=0; i Date: Mon, 16 Oct 2006 16:03:33 -0500 Subject: [POWERPC] Fix up the OF functions to only do PCI stuff if PCI is actually configured The original problem that inspired this patch was solved quite some time ago (Turning off PCI didn't work), but this patch neatens things up a little (I think), by putting all the PCI stuff inside a single CONFIG_PCI block. It also removes the OF PCI bus matching entries if CONFIG_PCI is off. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 603dff3..346fb7b 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -25,6 +25,12 @@ #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ (ns) > 0) +static struct of_bus *of_match_bus(struct device_node *np); +static int __of_address_to_resource(struct device_node *dev, + const u32 *addrp, u64 size, unsigned int flags, + struct resource *r); + + /* Debug utility */ #ifdef DEBUG static void of_dump_addr(const char *s, const u32 *addr, int na) @@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr) } +#ifdef CONFIG_PCI /* * PCI bus specific translator */ @@ -162,6 +169,145 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr) return flags; } +const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, + unsigned int *flags) +{ + const u32 *prop; + unsigned int psize; + struct device_node *parent; + struct of_bus *bus; + int onesize, i, na, ns; + + /* Get parent & match bus type */ + parent = of_get_parent(dev); + if (parent == NULL) + return NULL; + bus = of_match_bus(parent); + if (strcmp(bus->name, "pci")) { + of_node_put(parent); + return NULL; + } + bus->count_cells(dev, &na, &ns); + of_node_put(parent); + if (!OF_CHECK_COUNTS(na, ns)) + return NULL; + + /* Get "reg" or "assigned-addresses" property */ + prop = get_property(dev, bus->addresses, &psize); + if (prop == NULL) + return NULL; + psize /= 4; + + onesize = na + ns; + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) + if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { + if (size) + *size = of_read_number(prop + na, ns); + if (flags) + *flags = bus->get_flags(prop); + return prop; + } + return NULL; +} +EXPORT_SYMBOL(of_get_pci_address); + +int of_pci_address_to_resource(struct device_node *dev, int bar, + struct resource *r) +{ + const u32 *addrp; + u64 size; + unsigned int flags; + + addrp = of_get_pci_address(dev, bar, &size, &flags); + if (addrp == NULL) + return -EINVAL; + return __of_address_to_resource(dev, addrp, size, flags, r); +} +EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +static u8 of_irq_pci_swizzle(u8 slot, u8 pin) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) +{ + struct device_node *dn, *ppnode; + struct pci_dev *ppdev; + u32 lspec; + u32 laddr[3]; + u8 pin; + int rc; + + /* Check if we have a device node, if yes, fallback to standard OF + * parsing + */ + dn = pci_device_to_OF_node(pdev); + if (dn) + return of_irq_map_one(dn, 0, out_irq); + + /* Ok, we don't, time to have fun. Let's start by building up an + * interrupt spec. we assume #interrupt-cells is 1, which is standard + * for PCI. If you do different, then don't use that routine. + */ + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (rc != 0) + return rc; + /* No pin, exit */ + if (pin == 0) + return -ENODEV; + + /* Now we walk up the PCI tree */ + lspec = pin; + for (;;) { + /* Get the pci_dev of our parent */ + ppdev = pdev->bus->self; + + /* Ouch, it's a host bridge... */ + if (ppdev == NULL) { +#ifdef CONFIG_PPC64 + ppnode = pci_bus_to_OF_node(pdev->bus); +#else + struct pci_controller *host; + host = pci_bus_to_host(pdev->bus); + ppnode = host ? host->arch_data : NULL; +#endif + /* No node for host bridge ? give up */ + if (ppnode == NULL) + return -EINVAL; + } else + /* We found a P2P bridge, check if it has a node */ + ppnode = pci_device_to_OF_node(ppdev); + + /* Ok, we have found a parent with a device-node, hand over to + * the OF parsing code. + * We build a unit address from the linux device to be used for + * resolution. Note that we use the linux bus number which may + * not match your firmware bus numbering. + * Fortunately, in most cases, interrupt-map-mask doesn't include + * the bus number as part of the matching. + * You should still be careful about that though if you intend + * to rely on this function (you ship a firmware that doesn't + * create device nodes for all PCI devices). + */ + if (ppnode) + break; + + /* We can only get here if we hit a P2P bridge with no node, + * let's do standard swizzling and try again + */ + lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); + pdev = ppdev; + } + + laddr[0] = (pdev->bus->number << 16) + | (pdev->devfn << 8); + laddr[1] = laddr[2] = 0; + return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); +} +EXPORT_SYMBOL_GPL(of_irq_map_pci); +#endif /* CONFIG_PCI */ + /* * ISA bus specific translator */ @@ -223,6 +369,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr) */ static struct of_bus of_busses[] = { +#ifdef CONFIG_PCI /* PCI */ { .name = "pci", @@ -233,6 +380,7 @@ static struct of_bus of_busses[] = { .translate = of_bus_pci_translate, .get_flags = of_bus_pci_get_flags, }, +#endif /* CONFIG_PCI */ /* ISA */ { .name = "isa", @@ -445,48 +593,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size, } EXPORT_SYMBOL(of_get_address); -const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, - unsigned int *flags) -{ - const u32 *prop; - unsigned int psize; - struct device_node *parent; - struct of_bus *bus; - int onesize, i, na, ns; - - /* Get parent & match bus type */ - parent = of_get_parent(dev); - if (parent == NULL) - return NULL; - bus = of_match_bus(parent); - if (strcmp(bus->name, "pci")) { - of_node_put(parent); - return NULL; - } - bus->count_cells(dev, &na, &ns); - of_node_put(parent); - if (!OF_CHECK_COUNTS(na, ns)) - return NULL; - - /* Get "reg" or "assigned-addresses" property */ - prop = get_property(dev, bus->addresses, &psize); - if (prop == NULL) - return NULL; - psize /= 4; - - onesize = na + ns; - for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) - if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { - if (size) - *size = of_read_number(prop + na, ns); - if (flags) - *flags = bus->get_flags(prop); - return prop; - } - return NULL; -} -EXPORT_SYMBOL(of_get_pci_address); - static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, u64 size, unsigned int flags, struct resource *r) @@ -529,20 +635,6 @@ int of_address_to_resource(struct device_node *dev, int index, } EXPORT_SYMBOL_GPL(of_address_to_resource); -int of_pci_address_to_resource(struct device_node *dev, int bar, - struct resource *r) -{ - const u32 *addrp; - u64 size; - unsigned int flags; - - addrp = of_get_pci_address(dev, bar, &size, &flags); - if (addrp == NULL) - return -EINVAL; - return __of_address_to_resource(dev, addrp, size, flags, r); -} -EXPORT_SYMBOL_GPL(of_pci_address_to_resource); - void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, unsigned long *busno, unsigned long *phys, unsigned long *size) { @@ -898,87 +990,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq return res; } EXPORT_SYMBOL_GPL(of_irq_map_one); - -#ifdef CONFIG_PCI -static u8 of_irq_pci_swizzle(u8 slot, u8 pin) -{ - return (((pin - 1) + slot) % 4) + 1; -} - -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) -{ - struct device_node *dn, *ppnode; - struct pci_dev *ppdev; - u32 lspec; - u32 laddr[3]; - u8 pin; - int rc; - - /* Check if we have a device node, if yes, fallback to standard OF - * parsing - */ - dn = pci_device_to_OF_node(pdev); - if (dn) - return of_irq_map_one(dn, 0, out_irq); - - /* Ok, we don't, time to have fun. Let's start by building up an - * interrupt spec. we assume #interrupt-cells is 1, which is standard - * for PCI. If you do different, then don't use that routine. - */ - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); - if (rc != 0) - return rc; - /* No pin, exit */ - if (pin == 0) - return -ENODEV; - - /* Now we walk up the PCI tree */ - lspec = pin; - for (;;) { - /* Get the pci_dev of our parent */ - ppdev = pdev->bus->self; - - /* Ouch, it's a host bridge... */ - if (ppdev == NULL) { -#ifdef CONFIG_PPC64 - ppnode = pci_bus_to_OF_node(pdev->bus); -#else - struct pci_controller *host; - host = pci_bus_to_host(pdev->bus); - ppnode = host ? host->arch_data : NULL; -#endif - /* No node for host bridge ? give up */ - if (ppnode == NULL) - return -EINVAL; - } else - /* We found a P2P bridge, check if it has a node */ - ppnode = pci_device_to_OF_node(ppdev); - - /* Ok, we have found a parent with a device-node, hand over to - * the OF parsing code. - * We build a unit address from the linux device to be used for - * resolution. Note that we use the linux bus number which may - * not match your firmware bus numbering. - * Fortunately, in most cases, interrupt-map-mask doesn't include - * the bus number as part of the matching. - * You should still be careful about that though if you intend - * to rely on this function (you ship a firmware that doesn't - * create device nodes for all PCI devices). - */ - if (ppnode) - break; - - /* We can only get here if we hit a P2P bridge with no node, - * let's do standard swizzling and try again - */ - lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); - pdev = ppdev; - } - - laddr[0] = (pdev->bus->number << 16) - | (pdev->devfn << 8); - laddr[1] = laddr[2] = 0; - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); -} -EXPORT_SYMBOL_GPL(of_irq_map_pci); -#endif /* CONFIG_PCI */ -- cgit v0.10.2 From 41999295b6c25d799dacbbca089fdbc19f6d60f5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 18 Oct 2006 15:53:20 +1000 Subject: [POWERPC] Move iSeries initrd logic into device tree Remove the iSeries initrd logic, instead just store the initrd location and size in the device tree so generic code can do the rest for us. The iSeries code had a "feature" which the generic code lacks, ie. if the compressed initrd is bigger than the configured ram disk size, we make the ram disk size bigger. That's bogus, as the compressed size of the initrd tells us nothing about how big the ram disk needs to be. If the ram disk isn't big enough you just need to make CONFIG_BLK_DEV_RAM_SIZE larger. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index e305dee..9e8a334 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -41,6 +41,7 @@ #include "call_pci.h" #include "pci.h" #include "it_exp_vpd_panel.h" +#include "naca.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -205,13 +206,11 @@ static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, dt_prop(dt, name, &data, sizeof(u32)); } -#ifdef notyet static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, u64 data) { dt_prop(dt, name, &data, sizeof(u64)); } -#endif static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, const char *name, u64 *data, int n) @@ -306,6 +305,17 @@ static void __init dt_model(struct iseries_flat_dt *dt) dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); } +static void __init dt_initrd(struct iseries_flat_dt *dt) +{ +#ifdef CONFIG_BLK_DEV_INITRD + if (naca.xRamDisk) { + dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk); + dt_prop_u64(dt, "linux,initrd-end", + (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE); + } +#endif +} + static void __init dt_do_vdevice(struct iseries_flat_dt *dt, const char *name, u32 reg, int unit, const char *type, const char *compat, int end) @@ -641,6 +651,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size) /* /chosen */ dt_start_node(iseries_dt, "chosen"); dt_prop_str(iseries_dt, "bootargs", cmd_line); + dt_initrd(iseries_dt); dt_end_node(iseries_dt); dt_cpus(iseries_dt); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a0ff7ba..08d1473 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -80,8 +79,6 @@ extern void iSeries_pci_final_fixup(void); static void iSeries_pci_final_fixup(void) { } #endif -extern int rd_size; /* Defined in drivers/block/rd.c */ - extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; @@ -295,24 +292,6 @@ static void __init iSeries_init_early(void) { DBG(" -> iSeries_init_early()\n"); -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured and there is - * a non-zero starting address for it, set it up - */ - if (naca.xRamDisk) { - initrd_start = (unsigned long)__va(naca.xRamDisk); - initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE; - initrd_below_start_ok = 1; // ramdisk in kernel space - ROOT_DEV = Root_RAM0; - if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize) - rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024; - } else -#endif /* CONFIG_BLK_DEV_INITRD */ - { - /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */ - } - iSeries_recal_tb = get_tb(); iSeries_recal_titan = HvCallXm_loadTod(); @@ -331,17 +310,6 @@ static void __init iSeries_init_early(void) mf_init(); - /* If we were passed an initrd, set the ROOT_DEV properly if the values - * look sensible. If not, clear initrd reference. - */ -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && - initrd_end > initrd_start) - ROOT_DEV = Root_RAM0; - else - initrd_start = initrd_end = 0; -#endif /* CONFIG_BLK_DEV_INITRD */ - DBG(" <- iSeries_init_early()\n"); } -- cgit v0.10.2 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 diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 26bdf2c..d14477b 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 feac5f0..6e04fdd 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 v0.10.2 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 diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59c7520..a9a84f8 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 v0.10.2 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 diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index e30f556..be49dbb 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 v0.10.2 From cf610ca226a484f3182a59f168402cb27dcc1c53 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 20 Oct 2006 20:16:24 +0100 Subject: [ARM] Fix breakage in 7281c248f797723f66244b7ecef204620f664648 A couple of missing semicolons. Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c index 9ee6383..0fdd03a 100644 --- a/arch/arm/mach-ixp2000/ixdp2400.c +++ b/arch/arm/mach-ixp2000/ixdp2400.c @@ -135,11 +135,11 @@ static void ixdp2400_pci_postinit(void) if (ixdp2x00_master_npu()) { dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN); pci_remove_bus_device(dev); - pci_dev_put(dev) + pci_dev_put(dev); } else { dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN); pci_remove_bus_device(dev); - pci_dev_put(dev) + pci_dev_put(dev); ixdp2x00_slave_pci_postinit(); } -- cgit v0.10.2 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 diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 2ebbfd9..6697778 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 v0.10.2 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 diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 6697778..d07ecb5 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 v0.10.2 From 52f0c67340ca306d5802b52140a186fcfa4b340e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 22 Oct 2006 16:04:29 +0100 Subject: [ARM] Comment out missing configuration symbols HAS_TOUCHSCREEN_ADS7843_LH7 and HAS_TOUCHSCREEN_ADC_LH7 are referenced but not defined in the LH7A40x configuration. Comment them out to prevent them causing warnings. Marc Singer said: Feel free to remove the Kconfig lines. I'll add it back with the rest of the config entries. Signed-off-by: Russell King diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig index 558a34f..147b019 100644 --- a/arch/arm/mach-lh7a40x/Kconfig +++ b/arch/arm/mach-lh7a40x/Kconfig @@ -14,7 +14,7 @@ config MACH_LPD7A400 bool "LPD7A400 Card Engine" select ARCH_LH7A400 # select IDE_POLL - select HAS_TOUCHSCREEN_ADS7843_LH7 +# select HAS_TOUCHSCREEN_ADS7843_LH7 help Say Y here if you are using Logic Product Development's LPD7A400 CardEngine. For the time being, the LPD7A400 and @@ -24,7 +24,7 @@ config MACH_LPD7A404 bool "LPD7A404 Card Engine" select ARCH_LH7A404 # select IDE_POLL - select HAS_TOUCHSCREEN_ADC_LH7 +# select HAS_TOUCHSCREEN_ADC_LH7 help Say Y here if you are using Logic Product Development's LPD7A404 CardEngine. For the time being, the LPD7A400 and -- cgit v0.10.2 From 64271c4d909a15bc588f053a739db2e6df336d7d Mon Sep 17 00:00:00 2001 From: Craig Hughes Date: Tue, 24 Oct 2006 00:47:35 +0100 Subject: [ARM] 3902/1: Enable GPIO81-84 on PXA255 The PXA255 has 84 GPIO lines available. This patch allows access to 81-84 Signed-off-by: Craig Hughes Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index f3bc70e..67ed436 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -73,7 +73,7 @@ #define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i)) #if defined(CONFIG_PXA25x) -#define PXA_LAST_GPIO 80 +#define PXA_LAST_GPIO 84 #elif defined(CONFIG_PXA27x) #define PXA_LAST_GPIO 127 #endif -- cgit v0.10.2 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 diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 773821e..71fb278 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 fa84983..fb83082 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 71fb278..c564adb 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 112447f..449a603 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fb83082..7362e12 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7362e12..e75909e 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e75909e..66ed920 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 66ed920..8d04752 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 v0.10.2 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 diff --git a/drivers/net/e100.c b/drivers/net/e100.c index a3a08a5d..19ab344 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 v0.10.2 From 82571026b9771c4035b0c62abbbe588fe73373ea Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Oct 2006 15:18:36 -0700 Subject: [IPV4] ipconfig: fix RARP ic_servaddr breakage memcpy 4 bytes to address of auto unsigned long variable followed by comparison with u32 is a bloody bad idea. Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index f8ce847..955a07a 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -420,7 +420,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt { struct arphdr *rarp; unsigned char *rarp_ptr; - unsigned long sip, tip; + u32 sip, tip; unsigned char *sha, *tha; /* s for "source", t for "target" */ struct ic_device *d; -- cgit v0.10.2 From 2fab22f2d3290ff7c602fe62f22e825c48e97a06 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 24 Oct 2006 15:34:00 -0700 Subject: [XFRM]: Fix xfrm_state accounting xfrm_state_num needs to be increased for XFRM_STATE_ACQ states created by xfrm_state_find() to prevent the counter from going negative when the state is destroyed. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 84bbf84..899de9e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -505,6 +505,14 @@ __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) x->id.proto, family); } +static void xfrm_hash_grow_check(int have_hash_collision) +{ + if (have_hash_collision && + (xfrm_state_hmask + 1) < xfrm_state_hashmax && + xfrm_state_num > xfrm_state_hmask) + schedule_work(&xfrm_hash_work); +} + struct xfrm_state * xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, @@ -598,6 +606,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; add_timer(&x->timer); + xfrm_state_num++; + xfrm_hash_grow_check(x->bydst.next != NULL); } else { x->km.state = XFRM_STATE_DEAD; xfrm_state_put(x); @@ -614,14 +624,6 @@ out: return x; } -static void xfrm_hash_grow_check(int have_hash_collision) -{ - if (have_hash_collision && - (xfrm_state_hmask + 1) < xfrm_state_hashmax && - xfrm_state_num > xfrm_state_hmask) - schedule_work(&xfrm_hash_work); -} - static void __xfrm_state_insert(struct xfrm_state *x) { unsigned int h; -- cgit v0.10.2 From d1752aa884ec0ac3027c1a3d456bf69bf765c8b8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 25 Oct 2006 01:00:22 +0200 Subject: [PATCH] x86-64: Simplify the vector allocator. There is no reason to remember a per cpu position of which vector to try. Keeping a global position is simpler and more likely to result in a global vector allocation even if I don't need or require it. For level triggered interrupts this means we are less likely to acknowledge another cpus irq, and cause the level triggered irq to harmlessly refire. This simplification makes it easier to only access data structures of online cpus, by having fewer special cases to deal with. Signed-off-by: Eric W. Biederman Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index b000017..0e89ae7 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -612,10 +612,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) * Also, we've got to be careful not to trash gate * 0x80, because int 0x80 is hm, kind of importantish. ;) */ - static struct { - int vector; - int offset; - } pos[NR_CPUS] = { [ 0 ... NR_CPUS - 1] = {FIRST_DEVICE_VECTOR, 0} }; + static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; int old_vector = -1; int cpu; @@ -631,14 +628,13 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) for_each_cpu_mask(cpu, mask) { cpumask_t domain; - int first, new_cpu; + int new_cpu; int vector, offset; domain = vector_allocation_domain(cpu); - first = first_cpu(domain); - vector = pos[first].vector; - offset = pos[first].offset; + vector = current_vector; + offset = current_offset; next: vector += 8; if (vector >= FIRST_SYSTEM_VECTOR) { @@ -646,7 +642,7 @@ next: offset = (offset + 1) % 8; vector = FIRST_DEVICE_VECTOR + offset; } - if (unlikely(pos[first].vector == vector)) + if (unlikely(current_vector == vector)) continue; if (vector == IA32_SYSCALL_VECTOR) goto next; @@ -654,10 +650,8 @@ next: if (per_cpu(vector_irq, new_cpu)[vector] != -1) goto next; /* Found one! */ - for_each_cpu_mask(new_cpu, domain) { - pos[new_cpu].vector = vector; - pos[new_cpu].offset = offset; - } + current_vector = vector; + current_offset = offset; if (old_vector >= 0) { int old_cpu; for_each_cpu_mask(old_cpu, irq_domain[irq]) -- cgit v0.10.2 From 70a0a5357db20c291d46c04011d646d5d84c868c Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 25 Oct 2006 01:00:23 +0200 Subject: [PATCH] x86-64: Only look at per_cpu data for online cpus. When I generalized __assign_irq_vector I failed to pay attention to what happens when you access a per cpu data structure for a cpu that is not online. It is an undefined case making any code that does it have undefined behavior as well. The code still needs to be able to allocate a vector across cpus that are not online to properly handle combinations like lowest priority interrupt delivery and cpu_hotplug. Not that we can do that today but the infrastructure shouldn't prevent it. So this patch updates the places where we touch per cpu data to only touch online cpus, it makes cpu vector allocation an atomic operation with respect to cpu hotplug, and it updates the cpu start code to properly initialize vector_irq so we don't have inconsistencies. Signed-off-by: Eric W. Biederman Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 0e89ae7..fe429e5 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -63,7 +63,7 @@ int timer_over_8254 __initdata = 1; static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static DEFINE_SPINLOCK(ioapic_lock); -static DEFINE_SPINLOCK(vector_lock); +DEFINE_SPINLOCK(vector_lock); /* * # of IRQ routing registers @@ -618,6 +618,9 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) BUG_ON((unsigned)irq >= NR_IRQ_VECTORS); + /* Only try and allocate irqs on cpus that are present */ + cpus_and(mask, mask, cpu_online_map); + if (irq_vector[irq] > 0) old_vector = irq_vector[irq]; if (old_vector > 0) { @@ -627,11 +630,12 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) } for_each_cpu_mask(cpu, mask) { - cpumask_t domain; + cpumask_t domain, new_mask; int new_cpu; int vector, offset; domain = vector_allocation_domain(cpu); + cpus_and(new_mask, domain, cpu_online_map); vector = current_vector; offset = current_offset; @@ -646,18 +650,20 @@ next: continue; if (vector == IA32_SYSCALL_VECTOR) goto next; - for_each_cpu_mask(new_cpu, domain) + for_each_cpu_mask(new_cpu, new_mask) if (per_cpu(vector_irq, new_cpu)[vector] != -1) goto next; /* Found one! */ current_vector = vector; current_offset = offset; if (old_vector >= 0) { + cpumask_t old_mask; int old_cpu; - for_each_cpu_mask(old_cpu, irq_domain[irq]) + cpus_and(old_mask, irq_domain[irq], cpu_online_map); + for_each_cpu_mask(old_cpu, old_mask) per_cpu(vector_irq, old_cpu)[old_vector] = -1; } - for_each_cpu_mask(new_cpu, domain) + for_each_cpu_mask(new_cpu, new_mask) per_cpu(vector_irq, new_cpu)[vector] = irq; irq_vector[irq] = vector; irq_domain[irq] = domain; @@ -678,6 +684,32 @@ static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) return vector; } +void __setup_vector_irq(int cpu) +{ + /* Initialize vector_irq on a new cpu */ + /* This function must be called with vector_lock held */ + unsigned long flags; + int irq, vector; + + + /* Mark the inuse vectors */ + for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) { + if (!cpu_isset(cpu, irq_domain[irq])) + continue; + vector = irq_vector[irq]; + per_cpu(vector_irq, cpu)[vector] = irq; + } + /* Mark the free vectors */ + for (vector = 0; vector < NR_VECTORS; ++vector) { + irq = per_cpu(vector_irq, cpu)[vector]; + if (irq < 0) + continue; + if (!cpu_isset(cpu, irq_domain[irq])) + per_cpu(vector_irq, cpu)[vector] = -1; + } +} + + extern void (*interrupt[NR_IRQS])(void); static struct irq_chip ioapic_chip; diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 7b7a687..62c2e74 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -581,12 +581,16 @@ void __cpuinit start_secondary(void) * smp_call_function(). */ lock_ipi_call_lock(); + spin_lock(&vector_lock); + /* Setup the per cpu irq handling data structures */ + __setup_vector_irq(smp_processor_id()); /* * Allow the master to continue. */ cpu_set(smp_processor_id(), cpu_online_map); per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; + spin_unlock(&vector_lock); unlock_ipi_call_lock(); cpu_idle(); @@ -799,7 +803,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) cpu, node); } - alternatives_smp_switch(1); c_idle.idle = get_idle_for_cpu(cpu); @@ -1246,8 +1249,10 @@ int __cpu_disable(void) local_irq_disable(); remove_siblinginfo(cpu); + spin_lock(&vector_lock); /* It's now safe to remove this processor from the online map */ cpu_clear(cpu, cpu_online_map); + spin_unlock(&vector_lock); remove_cpu_from_maps(); fixup_irqs(cpu_online_map); return 0; diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index 792dd52..179cce7 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h @@ -76,6 +76,8 @@ #ifndef __ASSEMBLY__ typedef int vector_irq_t[NR_VECTORS]; DECLARE_PER_CPU(vector_irq_t, vector_irq); +extern void __setup_vector_irq(int cpu); +extern spinlock_t vector_lock; /* * Various low-level irq details needed by irq.c, process.c, -- cgit v0.10.2 From 51d8b1a65291a6956b79374b6adbbadc2263bcf6 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 24 Oct 2006 16:14:04 -0700 Subject: [NETFILTER]: Fix ip6_tables protocol bypass bug As reported by Mark Dowd , ip6_tables is susceptible to a fragmentation attack causing false negatives on protocol matches. When the protocol header doesn't follow the fragment header immediately, the fragment header contains the protocol number of the next extension header. When the extension header and the protocol header are sent in a second fragment a rule like "ip6tables .. -p udp -j DROP" will never match. Drop fragments that are at offset 0 and don't contain the final protocol header regardless of the ruleset, since this should not happen normally. With help from Yasuyuki KOZAKAI . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 4ab368f..f0328c7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -111,7 +111,7 @@ ip6_packet_match(const struct sk_buff *skb, const char *outdev, const struct ip6t_ip6 *ip6info, unsigned int *protoff, - int *fragoff) + int *fragoff, int *hotdrop) { size_t i; unsigned long ret; @@ -169,9 +169,11 @@ ip6_packet_match(const struct sk_buff *skb, unsigned short _frag_off; protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); - if (protohdr < 0) + if (protohdr < 0) { + if (_frag_off == 0) + *hotdrop = 1; return 0; - + } *fragoff = _frag_off; dprintf("Packet protocol %hi ?= %s%hi.\n", @@ -290,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb, IP_NF_ASSERT(e); IP_NF_ASSERT(back); if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, - &protoff, &offset)) { + &protoff, &offset, &hotdrop)) { struct ip6t_entry_target *t; if (IP6T_MATCH_ITERATE(e, do_match, -- cgit v0.10.2 From 6d381634d213580d40d431e7664dfb45f641b884 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 24 Oct 2006 16:15:10 -0700 Subject: [NETFILTER]: Fix ip6_tables extension header bypass bug As reported by Mark Dowd , ip6_tables is susceptible to a fragmentation attack causing false negatives on extension header matches. When extension headers occur in the non-first fragment after the fragment header (possibly with an incorrect nexthdr value in the fragment header) a rule looking for this extension header will never match. Drop fragments that are at offset 0 and don't contain the final protocol header regardless of the ruleset, since this should not happen normally. Since all extension headers are before the protocol header this makes sure an extension header is either not present or in the first fragment, where we can properly parse it. With help from Yasuyuki KOZAKAI . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f0328c7..53bf977 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1440,6 +1440,9 @@ static void __exit ip6_tables_fini(void) * If target header is found, its offset is set in *offset and return protocol * number. Otherwise, return -1. * + * If the first fragment doesn't contain the final protocol header or + * NEXTHDR_NONE it is considered invalid. + * * Note that non-1st fragment is special case that "the protocol number * of last header" is "next header" field in Fragment header. In this case, * *offset is meaningless and fragment offset is stored in *fragoff if fragoff @@ -1463,12 +1466,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { if (target < 0) break; - return -1; + return -ENOENT; } hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); if (hp == NULL) - return -1; + return -EBADMSG; if (nexthdr == NEXTHDR_FRAGMENT) { unsigned short _frag_off, *fp; fp = skb_header_pointer(skb, @@ -1477,7 +1480,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, sizeof(_frag_off), &_frag_off); if (fp == NULL) - return -1; + return -EBADMSG; _frag_off = ntohs(*fp) & ~0x7; if (_frag_off) { @@ -1488,7 +1491,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, *fragoff = _frag_off; return hp->nexthdr; } - return -1; + return -ENOENT; } hdrlen = 8; } else if (nexthdr == NEXTHDR_AUTH) diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index ec1b160..4648664 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -54,9 +54,14 @@ match(const struct sk_buff *skb, const struct ip6t_ah *ahinfo = matchinfo; unsigned int ptr; unsigned int hdrlen = 0; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); if (ah == NULL) { diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 78d9c8b..cd22eaa 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -52,9 +52,14 @@ match(const struct sk_buff *skb, struct frag_hdr _frag, *fh; const struct ip6t_frag *fraginfo = matchinfo; unsigned int ptr; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); if (fh == NULL) { diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index d32a205..3f25bab 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -65,9 +65,14 @@ match(const struct sk_buff *skb, u8 _opttype, *tp = NULL; u8 _optlen, *lp = NULL; unsigned int optlen; + int err; - if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, match->data, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); if (oh == NULL) { diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index bcb2e16..54d7d14 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -58,9 +58,14 @@ match(const struct sk_buff *skb, unsigned int hdrlen = 0; unsigned int ret = 0; struct in6_addr *ap, _addr; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); if (rh == NULL) { -- cgit v0.10.2 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 diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 44268cb..4dc1010 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 v0.10.2 From 0e64e94e477f8ed04e9295b11a5898d443c28a47 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 24 Oct 2006 16:17:51 -0700 Subject: [DCCP]: Update documentation references. Updates the references to spec documents throughout the code, taking into account that * the DCCP, CCID 2, and CCID 3 drafts all became RFCs in March this year * RFC 1063 was obsoleted by RFC 1191 * draft-ietf-tcpimpl-pmtud-0x.txt was published as an Informational RFC, RFC 2923 on 2000-09-22. All references verified. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index e2a095d..ef8919c 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig @@ -4,15 +4,15 @@ menu "DCCP Configuration (EXPERIMENTAL)" config IP_DCCP tristate "The DCCP Protocol (EXPERIMENTAL)" ---help--- - Datagram Congestion Control Protocol + Datagram Congestion Control Protocol (RFC 4340) - From draft-ietf-dccp-spec-11 . + From http://www.ietf.org/rfc/rfc4340.txt: The Datagram Congestion Control Protocol (DCCP) is a transport protocol that implements bidirectional, unicast connections of congestion-controlled, unreliable datagrams. It should be suitable for use by applications such as streaming media, Internet telephony, - and on-line games + and on-line games. To compile this protocol support as a module, choose M here: the module will be called dccp. diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 4d176d3..f820887 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -113,7 +113,7 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) memcpy(to, from, len); /* - * From draft-ietf-dccp-spec-11.txt: + * From RFC 4340, A.2: * * For each acknowledgement it sends, the HC-Receiver will add an * acknowledgement record. ack_seqno will equal the HC-Receiver @@ -224,7 +224,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, } /* - * Implements the draft-ietf-dccp-spec-11.txt Appendix A + * Implements the RFC 4340, Appendix A */ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, const u64 ackno, const u8 state) @@ -237,7 +237,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, * We may well decide to do buffer compression, etc, but for now lets * just drop. * - * From Appendix A: + * From Appendix A.1.1 (`New Packets'): * * Of course, the circular buffer may overflow, either when the * HC-Sender is sending data at a very high rate, when the @@ -274,9 +274,9 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, /* * A.1.2. Old Packets * - * When a packet with Sequence Number S arrives, and - * S <= buf_ackno, the HC-Receiver will scan the table - * for the byte corresponding to S. (Indexing structures + * When a packet with Sequence Number S <= buf_ackno + * arrives, the HC-Receiver will scan the table for + * the byte corresponding to S. (Indexing structures * could reduce the complexity of this scan.) */ u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index 2424eff..cf8f20c 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h @@ -28,8 +28,7 @@ /** struct dccp_ackvec - ack vector * - * This data structure is the one defined in the DCCP draft - * Appendix A. + * This data structure is the one defined in RFC 4340, Appendix A. * * @dccpav_buf_head - circular buffer head * @dccpav_buf_tail - circular buffer tail diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 32752f7..8533dab 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -22,11 +22,11 @@ config IP_DCCP_CCID2 for lost packets, would prefer CCID 2 to CCID 3. On-line games may also prefer CCID 2. - CCID 2 is further described in: - http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid2-10.txt + CCID 2 is further described in RFC 4341, + http://www.ietf.org/rfc/rfc4341.txt - This text was extracted from: - http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt + This text was extracted from RFC 4340 (sec. 10.1), + http://www.ietf.org/rfc/rfc4340.txt If in doubt, say M. @@ -53,15 +53,14 @@ config IP_DCCP_CCID3 suitable than CCID 2 for applications such streaming media where a relatively smooth sending rate is of importance. - CCID 3 is further described in: - - http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid3-11.txt. + CCID 3 is further described in RFC 4342, + http://www.ietf.org/rfc/rfc4342.txt The TFRC congestion control algorithms were initially described in RFC 3448. - This text was extracted from: - http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt + This text was extracted from RFC 4340 (sec. 10.2), + http://www.ietf.org/rfc/rfc4340.txt If in doubt, say M. diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 2efb505..2fbb84b 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -23,7 +23,7 @@ */ /* - * This implementation should follow: draft-ietf-dccp-ccid2-10.txt + * This implementation should follow RFC 4341 * * BUGS: * - sequence number wrapping diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 67d2dc0..cec23ad 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -379,8 +379,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) packet->dccphtx_seqno = dp->dccps_gss; /* * Check if win_count have changed - * Algorithm in "8.1. Window Counter Valuer" in - * draft-ietf-dccp-ccid3-11.txt + * Algorithm in "8.1. Window Counter Value" in RFC 4342. */ quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); if (likely(hctx->ccid3hctx_rtt > 8)) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 0a21be4..272e858 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -50,7 +50,7 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); #define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT * state, about 60 seconds */ -/* draft-ietf-dccp-spec-11.txt initial RTO value */ +/* RFC 1122, 4.2.3.1 initial RTO value */ #define DCCP_TIMEOUT_INIT ((unsigned)(3 * HZ)) /* Maximal interval between probes for local resources. */ diff --git a/net/dccp/input.c b/net/dccp/input.c index 7f9dc6a..1d24881 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -216,11 +216,11 @@ send_sync: dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNCACK); /* - * From the draft: + * From RFC 4340, sec. 5.7 * * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets * MAY have non-zero-length application data areas, whose - * contents * receivers MUST ignore. + * contents receivers MUST ignore. */ goto discard; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index aaaf4d0..e08e768 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -183,7 +183,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, dccp_sync_mss(sk, mtu); /* - * From: draft-ietf-dccp-spec-11.txt + * From RFC 4340, sec. 14.1: * * DCCP-Sync packets are the best choice for upward * probing, since DCCP-Sync probes do not risk application @@ -733,7 +733,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) dccp_hdr_reset(skb)->dccph_reset_code = DCCP_SKB_CB(rxskb)->dccpd_reset_code; - /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */ + /* See "8.3.1. Abnormal Termination" in RFC 4340 */ seqno = 0; if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index c8bf89b..eb0ff7a 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -550,7 +550,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) dccp_hdr_reset(skb)->dccph_reset_code = DCCP_SKB_CB(rxskb)->dccpd_reset_code; - /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */ + /* See "8.3.1. Abnormal Termination" in RFC 4340 */ seqno = 0; if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1); diff --git a/net/dccp/options.c b/net/dccp/options.c index 07a3469..fb0db1f 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -215,7 +215,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) elapsed_time); break; /* - * From draft-ietf-dccp-spec-11.txt: + * From RFC 4340, sec. 10.3: * * Option numbers 128 through 191 are for * options sent from the HC-Sender to the -- cgit v0.10.2 From fb20f65a01a97bdf4bb746eecfc24a08561e2648 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 20 Oct 2006 15:57:15 +0200 Subject: [POWERPC] Fix hang in start_ldr if _end or _edata is unaligned Quick fix for lack of memset(__bss_start, 0, _end-__bss_start) in load_kernel(). If edata is unaligned, the loop will overwrite all memory because r3 and r4 will never be equal. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S index 0c02155..1bbbcd2 100644 --- a/arch/ppc/boot/simple/relocate.S +++ b/arch/ppc/boot/simple/relocate.S @@ -154,8 +154,8 @@ do_relocate_out: start_ldr: /* Clear all of BSS and set up stack for C calls */ - lis r3,edata@h - ori r3,r3,edata@l + lis r3,__bss_start@h + ori r3,r3,__bss_start@l lis r4,end@h ori r4,r4,end@l subi r3,r3,4 @@ -163,7 +163,7 @@ start_ldr: li r0,0 50: stwu r0,4(r3) cmpw cr0,r3,r4 - bne 50b + blt 50b 90: mr r9,r1 /* Save old stack pointer (in case it matters) */ lis r1,.stack@h ori r1,r1,.stack@l -- cgit v0.10.2 From 42c4aaadb737e0e672b3fb86b2c41ff59f0fb8bc Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 24 Oct 2006 16:42:40 +1000 Subject: [POWERPC] Consolidate feature fixup code There are currently two versions of the functions for applying the feature fixups, one for CPU features and one for firmware features. In addition, they are both in assembly and with separate implementations for 32 and 64 bits. identify_cpu() is also implemented in assembly and separately for 32 and 64 bits. This patch replaces them with a pair of C functions. The call sites are slightly moved on ppc64 as well to be called from C instead of from assembly, though it's a very small change, and thus shouldn't cause any problem. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index f23aad6..6fdfaa4 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -18,6 +18,7 @@ #include #include +#include /* for PTRRELOC on ARCH=ppc */ struct cpu_spec* cur_cpu_spec = NULL; EXPORT_SYMBOL(cur_cpu_spec); @@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void); #define PPC_FEATURE_SPE_COMP 0 #endif -struct cpu_spec cpu_specs[] = { +static struct cpu_spec cpu_specs[] = { #ifdef CONFIG_PPC64 { /* Power3 */ .pvr_mask = 0xffff0000, @@ -1167,3 +1168,72 @@ struct cpu_spec cpu_specs[] = { #endif /* !CLASSIC_PPC */ #endif /* CONFIG_PPC32 */ }; + +struct cpu_spec *identify_cpu(unsigned long offset) +{ + struct cpu_spec *s = cpu_specs; + struct cpu_spec **cur = &cur_cpu_spec; + unsigned int pvr = mfspr(SPRN_PVR); + int i; + + s = PTRRELOC(s); + cur = PTRRELOC(cur); + + if (*cur != NULL) + return PTRRELOC(*cur); + + for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) + if ((pvr & s->pvr_mask) == s->pvr_value) { + *cur = cpu_specs + i; +#ifdef CONFIG_PPC64 + /* ppc64 expects identify_cpu to also call setup_cpu + * for that processor. I will consolidate that at a + * later time, for now, just use our friend #ifdef. + * we also don't need to PTRRELOC the function pointer + * on ppc64 as we are running at 0 in real mode. + */ + if (s->cpu_setup) { + s->cpu_setup(offset, s); + } +#endif /* CONFIG_PPC64 */ + return s; + } + BUG(); + return NULL; +} + +void do_feature_fixups(unsigned long offset, unsigned long value, + void *fixup_start, void *fixup_end) +{ + struct fixup_entry { + unsigned long mask; + unsigned long value; + unsigned int *start; + unsigned int *end; + } *fcur, *fend; + + fcur = fixup_start; + fend = fixup_end; + + for (; fcur < fend; fcur++) { + unsigned int *pstart, *pend, *p; + + if ((value & fcur->mask) == fcur->value) + continue; + + /* These PTRRELOCs will disappear once the new scheme for + * modules and vdso is implemented + */ + pstart = PTRRELOC(fcur->start); + pend = PTRRELOC(fcur->end); + + for (p = pstart; p < pend; p++) { + *p = 0x60000000u; + asm volatile ("dcbst 0, %0" : : "r" (p)); + } + asm volatile ("sync" : : : "memory"); + for (p = pstart; p < pend; p++) + asm volatile ("icbi 0,%0" : : "r" (p)); + asm volatile ("sync; isync" : : : "memory"); + } +} diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 645c7f1..f12e3c5 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1580,11 +1580,6 @@ _STATIC(__start_initialization_iSeries) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - LOAD_REG_IMMEDIATE(r3,cpu_specs) - LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) - li r5,0 - bl .identify_cpu - LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1964,13 +1959,6 @@ _STATIC(start_here_multiplatform) addi r2,r2,0x4000 add r2,r2,r26 - LOAD_REG_IMMEDIATE(r3, cpu_specs) - add r3,r3,r26 - LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) - add r4,r4,r26 - mr r5,r26 - bl .identify_cpu - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ @@ -2000,13 +1988,6 @@ _STATIC(start_here_common) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - /* Apply the CPUs-specific fixups (nop out sections not relevant - * to this CPU - */ - li r3,0 - bl .do_cpu_ftr_fixups - bl .do_fw_ftr_fixups - /* ptr to current */ LOAD_REG_IMMEDIATE(r4, init_task) std r4,PACACURRENT(r13) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 88fd73f..412bea3 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -102,80 +102,6 @@ _GLOBAL(reloc_got2) blr /* - * identify_cpu, - * called with r3 = data offset and r4 = CPU number - * doesn't change r3 - */ -_GLOBAL(identify_cpu) - addis r8,r3,cpu_specs@ha - addi r8,r8,cpu_specs@l - mfpvr r7 -1: - lwz r5,CPU_SPEC_PVR_MASK(r8) - and r5,r5,r7 - lwz r6,CPU_SPEC_PVR_VALUE(r8) - cmplw 0,r6,r5 - beq 1f - addi r8,r8,CPU_SPEC_ENTRY_SIZE - b 1b -1: - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - sub r8,r8,r3 - stw r8,0(r6) - blr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - lwz r4,0(r6) - add r4,r4,r3 - lwz r4,CPU_SPEC_FEATURES(r4) - - /* Get the fixup table */ - addis r6,r3,__start___ftr_fixup@ha - addi r6,r6,__start___ftr_fixup@l - addis r7,r3,__stop___ftr_fixup@ha - addi r7,r7,__stop___ftr_fixup@l - - /* Do the fixup */ -1: cmplw 0,r6,r7 - bgelr - addi r6,r6,16 - lwz r8,-16(r6) /* mask */ - and r8,r8,r4 - lwz r9,-12(r6) /* value */ - cmplw 0,r8,r9 - beq 1b - lwz r8,-8(r6) /* section begin */ - lwz r9,-4(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - add r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* * call_setup_cpu - call the setup_cpu function for this cpu * r3 = data offset, r24 = cpu number * diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index c70e207..21fd2c6 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache) isync blr -/* - * identify_cpu and calls setup_cpu - * In: r3 = base of the cpu_specs array - * r4 = address of cur_cpu_spec - * r5 = relocation offset - */ -_GLOBAL(identify_cpu) - mfpvr r7 -1: - lwz r8,CPU_SPEC_PVR_MASK(r3) - and r8,r8,r7 - lwz r9,CPU_SPEC_PVR_VALUE(r3) - cmplw 0,r9,r8 - beq 1f - addi r3,r3,CPU_SPEC_ENTRY_SIZE - b 1b -1: - sub r0,r3,r5 - std r0,0(r4) - ld r4,CPU_SPEC_SETUP(r3) - cmpdi 0,r4,0 - add r4,r4,r5 - beqlr - ld r4,0(r4) - add r4,r4,r5 - mtctr r4 - /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ - mr r4,r3 - mr r3,r5 - bctr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) - sub r6,r6,r3 - ld r4,0(r6) - sub r4,r4,r3 - ld r4,CPU_SPEC_FEATURES(r4) - /* Get the fixup table */ - LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) - sub r6,r6,r3 - LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) - sub r7,r7,r3 - /* Do the fixup */ -1: cmpld r6,r7 - bgelr - addi r6,r6,32 - ld r8,-32(r6) /* mask */ - and r8,r8,r4 - ld r9,-24(r6) /* value */ - cmpld r8,r9 - beq 1b - ld r8,-16(r6) /* section begin */ - ld r9,-8(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - sub r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* - * do_fw_ftr_fixups - goes through the list of firmware feature fixups - * and writes nop's over sections of code that don't apply for this firmware. - * r3 = data offset (not changed) - */ -_GLOBAL(do_fw_ftr_fixups) - /* Get firmware features */ - LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features) - sub r6,r6,r3 - ld r4,0(r6) - /* Get the fixup table */ - LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup) - sub r6,r6,r3 - LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup) - sub r7,r7,r3 - /* Do the fixup */ -1: cmpld r6,r7 - bgelr - addi r6,r6,32 - ld r8,-32(r6) /* mask */ - and r8,r8,r4 - ld r9,-24(r6) /* value */ - cmpld r8,r9 - beq 1b - ld r8,-16(r6) /* section begin */ - ld r9,-8(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - sub r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) -BEGIN_FTR_SECTION - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE) - addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) /* diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 191d0ab..769e511 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -91,6 +91,7 @@ int ucache_bsize; unsigned long __init early_init(unsigned long dt_ptr) { unsigned long offset = reloc_offset(); + struct cpu_spec *spec; /* First zero the BSS -- use memset_io, some platforms don't have * caches on yet */ @@ -100,8 +101,11 @@ unsigned long __init early_init(unsigned long dt_ptr) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - identify_cpu(offset, 0); - do_cpu_ftr_fixups(offset); + spec = identify_cpu(offset); + + do_feature_fixups(offset, spec->cpu_features, + PTRRELOC(&__start___ftr_fixup), + PTRRELOC(&__stop___ftr_fixup)); return KERNELBASE + offset; } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4b2e32e..1969b56 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -170,6 +170,9 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { + /* Identify CPU type */ + identify_cpu(0); + /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); @@ -348,6 +351,14 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); + /* Apply the CPUs-specific and firmware specific fixups to kernel + * text (nop out sections not relevant to this CPU or this firmware) + */ + do_feature_fixups(0, cur_cpu_spec->cpu_features, + &__start___ftr_fixup, &__stop___ftr_fixup); + do_feature_fixups(0, powerpc_firmware_features, + &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); + /* * Unflatten the device-tree passed by prom_init or kexec */ diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a0ff7ba..6f73469 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -694,6 +694,11 @@ void * __init iSeries_early_setup(void) { unsigned long phys_mem_size; + /* Identify CPU type. This is done again by the common code later + * on but calling this function multiple times is fine. + */ + identify_cpu(0); + powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_LPAR; diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 5f66840..d319f9b 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -110,80 +110,6 @@ _GLOBAL(reloc_got2) blr /* - * identify_cpu, - * called with r3 = data offset and r4 = CPU number - * doesn't change r3 - */ -_GLOBAL(identify_cpu) - addis r8,r3,cpu_specs@ha - addi r8,r8,cpu_specs@l - mfpvr r7 -1: - lwz r5,CPU_SPEC_PVR_MASK(r8) - and r5,r5,r7 - lwz r6,CPU_SPEC_PVR_VALUE(r8) - cmplw 0,r6,r5 - beq 1f - addi r8,r8,CPU_SPEC_ENTRY_SIZE - b 1b -1: - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - sub r8,r8,r3 - stw r8,0(r6) - blr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - lwz r4,0(r6) - add r4,r4,r3 - lwz r4,CPU_SPEC_FEATURES(r4) - - /* Get the fixup table */ - addis r6,r3,__start___ftr_fixup@ha - addi r6,r6,__start___ftr_fixup@l - addis r7,r3,__stop___ftr_fixup@ha - addi r7,r7,__stop___ftr_fixup@l - - /* Do the fixup */ -1: cmplw 0,r6,r7 - bgelr - addi r6,r6,16 - lwz r8,-16(r6) /* mask */ - and r8,r8,r4 - lwz r9,-12(r6) /* value */ - cmplw 0,r8,r9 - beq 1b - lwz r8,-8(r6) /* section begin */ - lwz r9,-4(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - add r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* * call_setup_cpu - call the setup_cpu function for this cpu * r3 = data offset, r24 = cpu number * diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 75fe138..41a640f 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -38,6 +38,7 @@ #include #include #include +#include #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \ defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \ @@ -53,8 +54,6 @@ extern void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void identify_cpu(unsigned long offset, unsigned long cpu); -extern void do_cpu_ftr_fixups(unsigned long offset); extern void reloc_got2(unsigned long offset); extern void ppc6xx_idle(void); @@ -301,6 +300,7 @@ early_init(int r3, int r4, int r5) { unsigned long phys; unsigned long offset = reloc_offset(); + struct cpu_spec *spec; /* Default */ phys = offset + KERNELBASE; @@ -313,8 +313,10 @@ early_init(int r3, int r4, int r5) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - identify_cpu(offset, 0); - do_cpu_ftr_fixups(offset); + spec = identify_cpu(offset); + do_feature_fixups(offset, spec->cpu_features, + PTRRELOC(&__start___ftr_fixup), + PTRRELOC(&__stop___ftr_fixup)); return phys; } diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 12707ab..4d22218 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -89,8 +89,11 @@ struct cpu_spec { extern struct cpu_spec *cur_cpu_spec; -extern void identify_cpu(unsigned long offset, unsigned long cpu); -extern void do_cpu_ftr_fixups(unsigned long offset); +extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; + +extern struct cpu_spec *identify_cpu(unsigned long offset); +extern void do_feature_fixups(unsigned long offset, unsigned long value, + void *fixup_start, void *fixup_end); #endif /* __ASSEMBLY__ */ diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index 1022737..c16e0a6 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -96,6 +96,8 @@ extern void machine_check_fwnmi(void); /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; +extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup; + #else /* __ASSEMBLY__ */ #define BEGIN_FW_FTR_SECTION 96: -- cgit v0.10.2 From 7aeb732428fc8e2ecae6d432873770c12f04a979 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Oct 2006 11:47:16 +1000 Subject: [POWERPC] Support nested cpu feature sections This patch adds some macros that can be used with an explicit label in order to nest cpu features. This should be used very careful but is necessary for the upcoming cell TB fixup. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 4d22218..65faf32 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -434,30 +434,34 @@ static inline int cpu_has_feature(unsigned long feature) #ifdef __ASSEMBLY__ -#define BEGIN_FTR_SECTION 98: +#define BEGIN_FTR_SECTION_NESTED(label) label: +#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(98) #ifndef __powerpc64__ -#define END_FTR_SECTION(msk, val) \ +#define END_FTR_SECTION_NESTED(msk, val, label) \ 99: \ .section __ftr_fixup,"a"; \ .align 2; \ .long msk; \ .long val; \ - .long 98b; \ + .long label##b; \ .long 99b; \ .previous #else /* __powerpc64__ */ -#define END_FTR_SECTION(msk, val) \ +#define END_FTR_SECTION_NESTED(msk, val, label) \ 99: \ .section __ftr_fixup,"a"; \ .align 3; \ .llong msk; \ .llong val; \ - .llong 98b; \ + .llong label##b; \ .llong 99b; \ .previous #endif /* __powerpc64__ */ +#define END_FTR_SECTION(msk, val) \ + END_FTR_SECTION_NESTED(msk, val, 98) + #define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) #define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) #endif /* __ASSEMBLY__ */ -- cgit v0.10.2 From 0909c8c2d547e45ca50e2492b08ec93a37b35237 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Oct 2006 11:47:18 +1000 Subject: [POWERPC] Support feature fixups in vdso's This patch reworks the feature fixup mecanism so vdso's can be fixed up. The main issue was that the construct: .long label (or .llong on 64 bits) will not work in the case of a shared library like the vdso. It will generate an empty placeholder in the fixup table along with a reloc, which is not something we can deal with in the vdso. The idea here (thanks Alan Modra !) is to instead use something like: 1: .long label - 1b That is, the feature fixup tables no longer contain addresses of bits of code to patch, but offsets of such code from the fixup table entry itself. That is properly resolved by ld when building the .so's. I've modified the fixup mecanism generically to use that method for the rest of the kernel as well. Another trick is that the 32 bits vDSO included in the 64 bits kernel need to have a table in the 64 bits format. However, gas does not support 32 bits code with a statement of the form: .llong label - 1b (Or even just .llong label) That is, it cannot emit the right fixup/relocation for the linker to use to assign a 32 bits address to an .llong field. Thus, in the specific case of the 32 bits vdso built as part of the 64 bits kernel, we are using a modified macro that generates: .long 0xffffffff .llong label - 1b Note that is assumes that the value is negative which is enforced by the .lds (those offsets are always negative as the .text is always before the fixup table and gas doesn't support emiting the reloc the other way around). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 6fdfaa4..bfd499e 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1202,14 +1202,13 @@ struct cpu_spec *identify_cpu(unsigned long offset) return NULL; } -void do_feature_fixups(unsigned long offset, unsigned long value, - void *fixup_start, void *fixup_end) +void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) { struct fixup_entry { unsigned long mask; unsigned long value; - unsigned int *start; - unsigned int *end; + long start_off; + long end_off; } *fcur, *fend; fcur = fixup_start; @@ -1224,8 +1223,8 @@ void do_feature_fixups(unsigned long offset, unsigned long value, /* These PTRRELOCs will disappear once the new scheme for * modules and vdso is implemented */ - pstart = PTRRELOC(fcur->start); - pend = PTRRELOC(fcur->end); + pstart = ((unsigned int *)fcur) + (fcur->start_off / 4); + pend = ((unsigned int *)fcur) + (fcur->end_off / 4); for (p = pstart; p < pend; p++) { *p = 0x60000000u; diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 769e511..a4c2964 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -103,7 +103,7 @@ unsigned long __init early_init(unsigned long dt_ptr) */ spec = identify_cpu(offset); - do_feature_fixups(offset, spec->cpu_features, + do_feature_fixups(spec->cpu_features, PTRRELOC(&__start___ftr_fixup), PTRRELOC(&__stop___ftr_fixup)); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 1969b56..1627896 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -354,9 +354,9 @@ void __init setup_system(void) /* Apply the CPUs-specific and firmware specific fixups to kernel * text (nop out sections not relevant to this CPU or this firmware) */ - do_feature_fixups(0, cur_cpu_spec->cpu_features, + do_feature_fixups(cur_cpu_spec->cpu_features, &__start___ftr_fixup, &__stop___ftr_fixup); - do_feature_fixups(0, powerpc_firmware_features, + do_feature_fixups(powerpc_firmware_features, &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); /* diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 1a7e19c..c913ad5 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -36,6 +36,8 @@ #include #include +#include "setup.h" + #undef DEBUG #ifdef DEBUG @@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, return 0; } + +static __init int vdso_fixup_features(struct lib32_elfinfo *v32, + struct lib64_elfinfo *v64) +{ + void *start32; + unsigned long size32; + +#ifdef CONFIG_PPC64 + void *start64; + unsigned long size64; + + start64 = find_section64(v64->hdr, "__ftr_fixup", &size64); + if (start64) + do_feature_fixups(cur_cpu_spec->cpu_features, + start64, start64 + size64); + + start64 = find_section64(v64->hdr, "__fw_ftr_fixup", &size64); + if (start64) + do_feature_fixups(powerpc_firmware_features, + start64, start64 + size64); +#endif /* CONFIG_PPC64 */ + + start32 = find_section32(v32->hdr, "__ftr_fixup", &size32); + if (start32) + do_feature_fixups(cur_cpu_spec->cpu_features, + start32, start32 + size32); + +#ifdef CONFIG_PPC64 + start32 = find_section32(v32->hdr, "__fw_ftr_fixup", &size32); + if (start32) + do_feature_fixups(powerpc_firmware_features, + start32, start32 + size32); +#endif /* CONFIG_PPC64 */ + + return 0; +} + static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, struct lib64_elfinfo *v64) { @@ -634,6 +673,9 @@ static __init int vdso_setup(void) if (vdso_fixup_datapage(&v32, &v64)) return -1; + if (vdso_fixup_features(&v32, &v64)) + return -1; + if (vdso_fixup_alt_funcs(&v32, &v64)) return -1; @@ -714,6 +756,7 @@ void __init vdso_init(void) * Setup the syscall map in the vDOS */ vdso_setup_syscall_map(); + /* * Initialize the vDSO images in memory, that is do necessary * fixups of vDSO symbols, locate trampolines, etc... diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S index 6187af2..26e138c 100644 --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S @@ -32,6 +32,18 @@ SECTIONS PROVIDE (_etext = .); PROVIDE (etext = .); + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } + +#ifdef CONFIG_PPC64 + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } +#endif + /* Other stuff is appended to the text segment: */ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S index 4a2b6dc..2d70f35 100644 --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S @@ -31,6 +31,16 @@ SECTIONS PROVIDE (_etext = .); PROVIDE (etext = .); + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } + + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } + /* Other stuff is appended to the text segment: */ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 41a640f..27faeca 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -314,7 +314,7 @@ early_init(int r3, int r4, int r5) * that depend on which cpu we have. */ spec = identify_cpu(offset); - do_feature_fixups(offset, spec->cpu_features, + do_feature_fixups(spec->cpu_features, PTRRELOC(&__start___ftr_fixup), PTRRELOC(&__stop___ftr_fixup)); diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h index 8e64be0..c89bd58 100644 --- a/include/asm-powerpc/asm-compat.h +++ b/include/asm-powerpc/asm-compat.h @@ -14,6 +14,58 @@ # define ASM_CONST(x) __ASM_CONST(x) #endif + +/* + * Feature section common macros + * + * Note that the entries now contain offsets between the table entry + * and the code rather than absolute code pointers in order to be + * useable with the vdso shared library. There is also an assumption + * that values will be negative, that is, the fixup table has to be + * located after the code it fixes up. + */ +#ifdef CONFIG_PPC64 +#ifdef __powerpc64__ +/* 64 bits kernel, 64 bits code */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 3; \ +98: \ + .llong msk; \ + .llong val; \ + .llong label##b-98b; \ + .llong 99b-98b; \ + .previous +#else /* __powerpc64__ */ +/* 64 bits kernel, 32 bits code (ie. vdso32) */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 3; \ +98: \ + .llong msk; \ + .llong val; \ + .long 0xffffffff; \ + .long label##b-98b; \ + .long 0xffffffff; \ + .long 99b-98b; \ + .previous +#endif /* !__powerpc64__ */ +#else /* CONFIG_PPC64 */ +/* 32 bits kernel, 32 bits code */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 2; \ +98: \ + .long msk; \ + .long val; \ + .long label##b-98b; \ + .long 99b-98b; \ + .previous +#endif /* !CONFIG_PPC64 */ + #ifdef __powerpc64__ /* operations for longs and pointers */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 65faf32..02e52d6 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -92,8 +92,8 @@ extern struct cpu_spec *cur_cpu_spec; extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; extern struct cpu_spec *identify_cpu(unsigned long offset); -extern void do_feature_fixups(unsigned long offset, unsigned long value, - void *fixup_start, void *fixup_end); +extern void do_feature_fixups(unsigned long value, void *fixup_start, + void *fixup_end); #endif /* __ASSEMBLY__ */ @@ -435,32 +435,11 @@ static inline int cpu_has_feature(unsigned long feature) #ifdef __ASSEMBLY__ #define BEGIN_FTR_SECTION_NESTED(label) label: -#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(98) - -#ifndef __powerpc64__ -#define END_FTR_SECTION_NESTED(msk, val, label) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 2; \ - .long msk; \ - .long val; \ - .long label##b; \ - .long 99b; \ - .previous -#else /* __powerpc64__ */ +#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(97) #define END_FTR_SECTION_NESTED(msk, val, label) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong label##b; \ - .llong 99b; \ - .previous -#endif /* __powerpc64__ */ - + MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup) #define END_FTR_SECTION(msk, val) \ - END_FTR_SECTION_NESTED(msk, val, 98) + END_FTR_SECTION_NESTED(msk, val, 97) #define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) #define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index c16e0a6..fdf9aff 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -100,17 +100,12 @@ extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup; #else /* __ASSEMBLY__ */ -#define BEGIN_FW_FTR_SECTION 96: - +#define BEGIN_FW_FTR_SECTION_NESTED(label) label: +#define BEGIN_FW_FTR_SECTION BEGIN_FW_FTR_SECTION_NESTED(97) +#define END_FW_FTR_SECTION_NESTED(msk, val, label) \ + MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup) #define END_FW_FTR_SECTION(msk, val) \ -97: \ - .section __fw_ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong 96b; \ - .llong 97b; \ - .previous + END_FW_FTR_SECTION_NESTED(msk, val, 97) #define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk)) #define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0) diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h index 3b9a8e7..e3f08cf 100644 --- a/include/asm-powerpc/timex.h +++ b/include/asm-powerpc/timex.h @@ -30,13 +30,15 @@ static inline cycles_t get_cycles(void) ret = 0; __asm__ __volatile__( - "98: mftb %0\n" + "97: mftb %0\n" "99:\n" ".section __ftr_fixup,\"a\"\n" + ".align 2\n" + "98:\n" " .long %1\n" " .long 0\n" - " .long 98b\n" - " .long 99b\n" + " .long 97b-98b\n" + " .long 99b-98b\n" ".previous" : "=r" (ret) : "i" (CPU_FTR_601)); #endif -- cgit v0.10.2 From 21c4ff80cba5e24932f3ef79c8482c0491630b2b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Oct 2006 11:47:19 +1000 Subject: [POWERPC] Support feature fixups in modules This patch adds support for feature fixups in modules. This involves adding support for R_PPC64_REL64 relocs to the 64 bits module loader. It also modifies modpost.c to ignore the powerpc fixup sections (or it would warn when used in .init.text). Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index 92f4e5f..e2c3c6a 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -24,6 +24,8 @@ #include #include +#include "setup.h" + #if 0 #define DEBUGP printk #else @@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, return 0; } +static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) +{ + char *secstrings; + unsigned int i; + + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) + if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) + return &sechdrs[i]; + return NULL; +} + int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - char *secstrings; - unsigned int i; + const Elf_Shdr *sect; me->arch.bug_table = NULL; me->arch.num_bugs = 0; /* Find the __bug_table section, if present */ - secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - for (i = 1; i < hdr->e_shnum; i++) { - if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) - continue; - me->arch.bug_table = (void *) sechdrs[i].sh_addr; - me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); - break; + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); } - /* + /* * Strictly speaking this should have a spinlock to protect against * traversals, but since we only traverse on BUG()s, a spinlock * could potentially lead to deadlock and thus be counter-productive. */ list_add(&me->arch.bug_list, &module_bug_list); + /* Apply feature fixups */ + sect = find_section(hdr, sechdrs, "__ftr_fixup"); + if (sect != NULL) + do_feature_fixups(cur_cpu_spec->cpu_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + return 0; } diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ba34001..8dd1f0a 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -22,6 +22,9 @@ #include #include #include +#include + +#include "setup.h" /* FIXME: We don't do .init separately. To do this, we'd need to have a separate r2 value in the init and core section, and stub between @@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | (value & 0x03fffffc); break; + case R_PPC64_REL64: + /* 64 bits relative (used by features fixups) */ + *location = value - (unsigned long)location; + break; + default: printk("%s: Unknown ADD relocation: %lu\n", me->name, @@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, LIST_HEAD(module_bug_list); -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, struct module *me) +static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) { char *secstrings; unsigned int i; + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) + if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) + return &sechdrs[i]; + return NULL; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, struct module *me) +{ + const Elf_Shdr *sect; + me->arch.bug_table = NULL; me->arch.num_bugs = 0; /* Find the __bug_table section, if present */ - secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - for (i = 1; i < hdr->e_shnum; i++) { - if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) - continue; - me->arch.bug_table = (void *) sechdrs[i].sh_addr; - me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); - break; + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); } /* @@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr, */ list_add(&me->arch.bug_list, &module_bug_list); + /* Apply feature fixups */ + sect = find_section(hdr, sechdrs, "__ftr_fixup"); + if (sect != NULL) + do_feature_fixups(cur_cpu_spec->cpu_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + + sect = find_section(hdr, sechdrs, "__fw_ftr_fixup"); + if (sect != NULL) + do_feature_fixups(powerpc_firmware_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + return 0; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4127796..2e11416 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -921,6 +921,8 @@ static int init_section_ref_ok(const char *name) ".fixup", ".smp_locks", ".plt", /* seen on ARCH=um build on x86_64. Harmless */ + "__ftr_fixup", /* powerpc cpu feature fixup */ + "__fw_ftr_fixup", /* powerpc firmware feature fixup */ NULL }; /* Start of section names */ -- cgit v0.10.2 From 859deea949c382d9ccb6397fe33df3703ecef45d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Oct 2006 14:37:05 +1000 Subject: [POWERPC] Cell timebase bug workaround The Cell CPU timebase has an erratum. When reading the entire 64 bits of the timebase with one mftb instruction, there is a handful of cycles window during which one might read a value with the low order 32 bits already reset to 0x00000000 but the high order bits not yet incremeted by one. This fixes it by reading the timebase again until the low order 32 bits is no longer 0. That might introduce occasional latencies if hitting mftb just at the wrong time, but no more than 70ns on a cell blade, and that was considered acceptable. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index 56e76ff..40ffd9b 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -229,8 +229,10 @@ V_FUNCTION_BEGIN(__do_get_xsec) xor r0,r8,r8 /* create dependency */ add r3,r3,r0 - /* Get TB & offset it */ - mftb r7 + /* Get TB & offset it. We use the MFTB macro which will generate + * workaround code for Cell. + */ + MFTB(r7) ld r9,CFG_TB_ORIG_STAMP(r3) subf r7,r9,r7 diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 02e52d6..a9a4014 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -147,6 +147,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) +#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) #ifndef __ASSEMBLY__ @@ -335,7 +336,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ - CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE) + CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG) #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index a940cfe..fa083d8 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -30,9 +30,9 @@ BEGIN_FTR_SECTION; \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ BEGIN_FTR_SECTION; \ - mftb ra; /* or get TB if no PURR */ \ + MFTB(ra); /* or get TB if no PURR */ \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ - ld rb,PACA_STARTPURR(r13); \ + ld rb,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \ subf rb,rb,ra; /* subtract start value */ \ ld ra,PACA_USER_TIME(r13); \ @@ -45,9 +45,9 @@ BEGIN_FTR_SECTION; \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ BEGIN_FTR_SECTION; \ - mftb ra; /* or get TB if no PURR */ \ + MFTB(ra); /* or get TB if no PURR */ \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ - ld rb,PACA_STARTPURR(r13); \ + ld rb,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \ subf rb,rb,ra; /* subtract start value */ \ ld ra,PACA_SYSTEM_TIME(r13); \ @@ -274,6 +274,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) #define ISYNC_601 #endif +#ifdef CONFIG_PPC_CELL +#define MFTB(dest) \ +90: mftb dest; \ +BEGIN_FTR_SECTION_NESTED(96); \ + cmpwi dest,0; \ + beq- 90b; \ +END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96) +#else +#define MFTB(dest) mftb dest +#endif #ifndef CONFIG_SMP #define TLBSYNC diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index fde5c80..6faae7b 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -619,10 +619,35 @@ : "=r" (rval)); rval;}) #define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)) +#ifdef __powerpc64__ +#ifdef CONFIG_PPC_CELL +#define mftb() ({unsigned long rval; \ + asm volatile( \ + "90: mftb %0;\n" \ + "97: cmpwi %0,0;\n" \ + " beq- 90b;\n" \ + "99:\n" \ + ".section __ftr_fixup,\"a\"\n" \ + ".align 3\n" \ + "98:\n" \ + " .llong %1\n" \ + " .llong %1\n" \ + " .llong 97b-98b\n" \ + " .llong 99b-98b\n" \ + ".previous" \ + : "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG)); rval;}) +#else #define mftb() ({unsigned long rval; \ asm volatile("mftb %0" : "=r" (rval)); rval;}) +#endif /* !CONFIG_PPC_CELL */ + +#else /* __powerpc64__ */ + #define mftbl() ({unsigned long rval; \ asm volatile("mftbl %0" : "=r" (rval)); rval;}) +#define mftbu() ({unsigned long rval; \ + asm volatile("mftbu %0" : "=r" (rval)); rval;}) +#endif /* !__powerpc64__ */ #define mttbl(v) asm volatile("mttbl %0":: "r"(v)) #define mttbu(v) asm volatile("mttbu %0":: "r"(v)) diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index b051d4c..a782850 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -82,30 +82,35 @@ struct div_result { #define __USE_RTC() 0 #endif -/* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */ +#ifdef CONFIG_PPC64 + +/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */ +#define get_tbl get_tb + +#else + static inline unsigned long get_tbl(void) { - unsigned long tbl; - #if defined(CONFIG_403GCX) + unsigned long tbl; asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); + return tbl; #else - asm volatile("mftb %0" : "=r" (tbl)); + return mftbl(); #endif - return tbl; } static inline unsigned int get_tbu(void) { +#ifdef CONFIG_403GCX unsigned int tbu; - -#if defined(CONFIG_403GCX) asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); + return tbu; #else - asm volatile("mftbu %0" : "=r" (tbu)); + return mftbu(); #endif - return tbu; } +#endif /* !CONFIG_PPC64 */ static inline unsigned int get_rtcl(void) { @@ -131,7 +136,7 @@ static inline u64 get_tb(void) { return mftb(); } -#else +#else /* CONFIG_PPC64 */ static inline u64 get_tb(void) { unsigned int tbhi, tblo, tbhi2; @@ -144,7 +149,7 @@ static inline u64 get_tb(void) return ((u64)tbhi << 32) | tblo; } -#endif +#endif /* !CONFIG_PPC64 */ static inline void set_tb(unsigned int upper, unsigned int lower) { diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h index e3f08cf..92dedde 100644 --- a/include/asm-powerpc/timex.h +++ b/include/asm-powerpc/timex.h @@ -8,6 +8,7 @@ */ #include +#include #define CLOCK_TICK_RATE 1024000 /* Underlying HZ */ @@ -15,13 +16,11 @@ typedef unsigned long cycles_t; static inline cycles_t get_cycles(void) { - cycles_t ret; - #ifdef __powerpc64__ - - __asm__ __volatile__("mftb %0" : "=r" (ret) : ); - + return mftb(); #else + cycles_t ret; + /* * For the "cycle" counter we use the timebase lower half. * Currently only used on SMP. @@ -41,9 +40,8 @@ static inline cycles_t get_cycles(void) " .long 99b-98b\n" ".previous" : "=r" (ret) : "i" (CPU_FTR_601)); -#endif - return ret; +#endif } #endif /* __KERNEL__ */ -- cgit v0.10.2 From e2100efb266c9335925191afe79f81f8d0a5807e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Oct 2006 11:49:54 +1000 Subject: [POWERPC] Fix device_is_compatible() const warning Fix a const'ification related warning with device_is_compatible() and friends related to get_property() not properly having const on it's input device node argument. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 865b964..bdb412d 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1014,7 +1014,7 @@ EXPORT_SYMBOL(find_all_nodes); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int device_is_compatible(struct device_node *device, const char *compat) +int device_is_compatible(const struct device_node *device, const char *compat) { const char* cp; int cplen, l; @@ -1491,7 +1491,8 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif -struct property *of_find_property(struct device_node *np, const char *name, +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp) { struct property *pp; @@ -1512,7 +1513,8 @@ struct property *of_find_property(struct device_node *np, const char *name, * Find a property with a given name for a given node * and return the value. */ -const void *get_property(struct device_node *np, const char *name, int *lenp) +const void *get_property(const struct device_node *np, const char *name, + int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 5246297..ec11d44 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -134,7 +134,7 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev); extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); -extern struct property *of_find_property(struct device_node *np, +extern struct property *of_find_property(const struct device_node *np, const char *name, int *lenp); extern struct device_node *of_node_get(struct device_node *node); @@ -158,10 +158,12 @@ extern void of_detach_node(const struct device_node *); extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); -extern int device_is_compatible(struct device_node *device, const char *); +extern int device_is_compatible(const struct device_node *device, + const char *); extern int machine_is_compatible(const char *compat); -extern const void *get_property(struct device_node *node, const char *name, - int *lenp); +extern const void *get_property(const struct device_node *node, + const char *name, + int *lenp); extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); -- cgit v0.10.2 From f6b301b89b7bf0bb872da4f37dc28240413cbae7 Mon Sep 17 00:00:00 2001 From: Dwayne Grant Mcconnell Date: Tue, 24 Oct 2006 18:27:30 +0200 Subject: [POWERPC] spufs: fix signal2 file to report signal2 This fixes the /signal2 file to actually give signal2 data. Signed-off-by: Dwayne Grant Mcconnell Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index efc452e..d805ffe 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -147,7 +147,7 @@ static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) static u32 spu_hw_signal2_read(struct spu_context *ctx) { - return in_be32(&ctx->spu->problem->signal_notify1); + return in_be32(&ctx->spu->problem->signal_notify2); } static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) -- cgit v0.10.2 From 274cef5e9d0e494ad84dbc28513b0bb6e3d847ae Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 24 Oct 2006 18:01:42 +0200 Subject: [POWERPC] spufs: fix another off-by-one bug in spufs_mbox_read Currently, spufs_mbox_read transfers more bytes than requested on a read. If you ask for four bytes, you get eight. This fixes it to transfer the largest multiple of four bytes that is less than or equal to the number you asked for. Note: one nasty property of this file in spufs is that you can only read multiples of four bytes in the first place, since there is no way to atomically put back a few bytes into the hardware register. Thus, reading less than four bytes returns -EINVAL. Asking for more than four returns the largest possible multiple of four. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 0de8e11..533e272 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -385,7 +385,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf, udata = (void __user *)buf; spu_acquire(ctx); - for (count = 0; count <= len; count += 4, udata++) { + for (count = 0; (count + 4) <= len; count += 4, udata++) { int ret; ret = ctx->ops->mbox_read(ctx, &mbox_data); if (ret == 0) -- cgit v0.10.2 From b910ecf6bf221bb06f37e44765307c42b20db205 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 24 Oct 2006 18:01:43 +0200 Subject: [POWERPC] cell: update defconfig =================================================================== Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 892d5dd..0aba06d 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -254,6 +254,7 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y +# CONFIG_INET_XFRM_MODE_BEET is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -275,7 +276,9 @@ CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y +# CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set @@ -406,6 +409,12 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -738,7 +747,6 @@ CONFIG_GEN_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -802,6 +810,7 @@ CONFIG_I2C_ALGOBIT=y # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -810,14 +819,9 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_HWMON_VID is not set # -# Misc devices -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -923,6 +927,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -930,6 +935,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -1129,6 +1135,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_FORCED_INLINING is not set +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -- cgit v0.10.2 From f84c39da766b4c8f13872282f58286a57ad05b3e Mon Sep 17 00:00:00 2001 From: Liu Dave-r63238 Date: Wed, 18 Oct 2006 16:36:56 +0800 Subject: [POWERPC] Fix the UCC rx/tx clock of QE MPC8323EMDS board ethernet interface with RMII uses the CLK16 divisor for the rx and tx clock, but the ucc_set_qe_mux_rxtx() function doesn't handle the CLK16 setting of the CMXUCR3 and CMXUCR4 registers. This fixes it. Signed-off-by: Dave Liu Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c index 916c9e5..ac12a44 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc.c +++ b/arch/powerpc/sysdev/qe_lib/ucc.c @@ -207,6 +207,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode) case QE_CLK18: source = 8; break; case QE_CLK7: source = 9; break; case QE_CLK8: source = 10; break; + case QE_CLK16: source = 11; break; default: source = -1; break; } break; @@ -222,6 +223,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode) case QE_CLK22: source = 8; break; case QE_CLK7: source = 9; break; case QE_CLK8: source = 10; break; + case QE_CLK16: source = 11; break; default: source = -1; break; } break; -- cgit v0.10.2 From f49196a5f53aa62a964b08ffa2c59699a0c8eb53 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 23 Oct 2006 11:35:22 -0500 Subject: [POWERPC] IPIC: Fix spinlock recursion in set_irq_handler This causes ipic_set_irq_type to set the handler directly rather than call set_irq_handler, which causes spinlock recursion because the lock is already held when ipic_set_irq_type is called. I'm also not convinced that ipic_set_irq_type should be changing the handler at all. There seem to be several controllers that don't and several that do. Those that do would break what appears to be a common usage of calling set_irq_chip_and_handler followed by set_irq_type, if a non-standard handler were to be used. OTOH, irq_create_of_mapping() doesn't set the handler, but only calls set_irq_type(). This patch gets things working in the spinlock-debugging-enabled case, but I'm curious as to where the handler setting is ideally supposed to be done. I don't see any documentation on set_irq_type() that clarifies what the semantics are supposed to be. Signed-off-by: Scott Wood Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index bc4d4a7..746f78c 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -473,9 +473,9 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; if (flow_type & IRQ_TYPE_LEVEL_LOW) { desc->status |= IRQ_LEVEL; - set_irq_handler(virq, handle_level_irq); + desc->handle_irq = handle_level_irq; } else { - set_irq_handler(virq, handle_edge_irq); + desc->handle_irq = handle_edge_irq; } /* only EXT IRQ senses are programmable on ipic -- cgit v0.10.2 From f4d4c354bca18210296cc0a8f592c0cdb720bf20 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 25 Oct 2006 13:22:27 +1000 Subject: [POWERPC] Fix CHRP platforms with only 8259 On CHRP platforms with only a 8259 controller, we should set the default IRQ host to the 8259 driver's one for the IRQ probing fallbacks to work in case the IRQ tree is incorrect (like on Pegasos for example). Without this fix, we get a bunch of WARN_ON's during boot. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index cae3d13..49b8dab 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -477,8 +477,10 @@ static void __init chrp_find_8259(void) " address, polling\n"); i8259_init(pic, chrp_int_ack); - if (ppc_md.get_irq == NULL) + if (ppc_md.get_irq == NULL) { ppc_md.get_irq = i8259_irq; + irq_set_default_host(i8259_get_host()); + } if (chrp_mpic != NULL) { cascade_irq = irq_of_parse_and_map(pic, 0); if (cascade_irq == NO_IRQ) diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 0450265..ad87adc9 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -224,6 +224,11 @@ static struct irq_host_ops i8259_host_ops = { .xlate = i8259_host_xlate, }; +struct irq_host *i8259_get_host(void) +{ + return i8259_host; +} + /** * i8259_init - Initialize the legacy controller * @node: device node of the legacy PIC (can be NULL, but then, it will match diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h index 78489fb..db1362f 100644 --- a/include/asm-powerpc/i8259.h +++ b/include/asm-powerpc/i8259.h @@ -7,6 +7,7 @@ #ifdef CONFIG_PPC_MERGE extern void i8259_init(struct device_node *node, unsigned long intack_addr); extern unsigned int i8259_irq(void); +extern struct irq_host *i8259_get_host(void); #else extern void i8259_init(unsigned long intack_addr, int offset); extern int i8259_irq(void); -- cgit v0.10.2 From a0f467261ae041864414103b8dd6fc4487a3c7de Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Mon, 23 Oct 2006 14:26:57 -0500 Subject: [POWERPC] Fixed some missing files to be deleted when running make clean Fixed some missing files to be deleted when running make clean Signed-off-by: Matthew McClintock Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 1e71a45..789def3 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -75,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ - $(obj)/empty.c + empty.c zImage.coff.lds zImage.lds zImage.sandpoint quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< -- cgit v0.10.2 From 5414c6be57dd02e089c3eba1f5134f441733d013 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 24 Oct 2006 13:37:34 +1000 Subject: [POWERPC] Make irq_dispose_mapping(NO_IRQ) a nop It makes for a friendlier API if irq_dispose_mapping(NO_IRQ) is a nop, rather than triggering a WARN_ON. Signed-off-by: Michael Ellerman Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 67b21a0..eb9fc62 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -648,10 +648,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); void irq_dispose_mapping(unsigned int virq) { - struct irq_host *host = irq_map[virq].host; + struct irq_host *host; irq_hw_number_t hwirq; unsigned long flags; + if (virq == NO_IRQ) + return; + + host = irq_map[virq].host; WARN_ON (host == NULL); if (host == NULL) return; -- cgit v0.10.2 From 24f43b33f74c8e8c8aabc40b728eaf9137802942 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Tue, 24 Oct 2006 18:31:14 +0200 Subject: [POWERPC] spufs: wrap mfc sdr access SPRN_SDR1 and the SPE's MFC SDR are hypervisor resources and are not accessible from a logical partition. This change adds an access wrapper. When running on bare H/W, the spufs needs to only set the SPE's MFC SDR to the value of the PPE's SPRN_SDR1 once at SPE initialization, so this change renames mfc_sdr_set() to mfc_sdr_setup() and moves the access of SPRN_SDR1 into the mmio wrapper. It also removes the now unneeded member mfc_sdr_RW from struct spu_priv1_collapsed. Signed-off-by: Masato Noguchi Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann -- Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d0fb959..d41ad1d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -805,7 +805,7 @@ static int __init create_spu(struct device_node *spe) if (ret) goto out_unmap; spin_lock_init(&spu->register_lock); - spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); + spu_mfc_sdr_setup(spu); spu_mfc_sr1_set(spu, 0x33); mutex_lock(&spu_mutex); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 71b69f0..90011f9 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -84,9 +84,9 @@ static void mfc_dsisr_set(struct spu *spu, u64 dsisr) out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); } -static void mfc_sdr_set(struct spu *spu, u64 sdr) +static void mfc_sdr_setup(struct spu *spu) { - out_be64(&spu->priv1->mfc_sdr_RW, sdr); + out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1)); } static void mfc_sr1_set(struct spu *spu, u64 sr1) @@ -146,7 +146,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops = .mfc_dar_get = mfc_dar_get, .mfc_dsisr_get = mfc_dsisr_get, .mfc_dsisr_set = mfc_dsisr_set, - .mfc_sdr_set = mfc_sdr_set, + .mfc_sdr_setup = mfc_sdr_setup, .mfc_sr1_set = mfc_sr1_set, .mfc_sr1_get = mfc_sr1_get, .mfc_tclass_id_set = mfc_tclass_id_set, diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 0f782ca..b85347f 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2165,9 +2165,6 @@ static void init_priv1(struct spu_state *csa) MFC_STATE1_PROBLEM_STATE_MASK | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; - /* Set storage description. */ - csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1); - /* Enable OS-specific set of interrupts. */ csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index 964c2d3..bdbf906 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h @@ -151,7 +151,6 @@ struct spu_priv1_collapsed { u64 mfc_fir_chkstp_enable_RW; u64 smf_sbi_signal_sel; u64 smf_ato_signal_sel; - u64 mfc_sdr_RW; u64 tlb_index_hint_RO; u64 tlb_index_W; u64 tlb_vpn_RW; diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h index 300c458..4f9a04d 100644 --- a/include/asm-powerpc/spu_priv1.h +++ b/include/asm-powerpc/spu_priv1.h @@ -37,7 +37,7 @@ struct spu_priv1_ops u64 (*mfc_dar_get) (struct spu *spu); u64 (*mfc_dsisr_get) (struct spu *spu); void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); - void (*mfc_sdr_set) (struct spu *spu, u64 sdr); + void (*mfc_sdr_setup) (struct spu *spu); void (*mfc_sr1_set) (struct spu *spu, u64 sr1); u64 (*mfc_sr1_get) (struct spu *spu); void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); @@ -112,9 +112,9 @@ spu_mfc_dsisr_set (struct spu *spu, u64 dsisr) } static inline void -spu_mfc_sdr_set (struct spu *spu, u64 sdr) +spu_mfc_sdr_setup (struct spu *spu) { - spu_priv1_ops->mfc_sdr_set(spu, sdr); + spu_priv1_ops->mfc_sdr_setup(spu); } static inline void -- cgit v0.10.2 From cc21a66d7f727ab97b27af9cf763bc0b51510ffa Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 24 Oct 2006 18:31:15 +0200 Subject: [POWERPC] cell: remove unused struct spu variable Remove the mostly unused variable isrc from struct spu and a forgotten function declaration. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d41ad1d..f6c94087 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -364,8 +364,7 @@ struct spu *spu_alloc_node(int node) if (!list_empty(&spu_list[node])) { spu = list_entry(spu_list[node].next, struct spu, list); list_del_init(&spu->list); - pr_debug("Got SPU %x %d %d\n", - spu->isrc, spu->number, spu->node); + pr_debug("Got SPU %d %d\n", spu->number, spu->node); spu_init_channels(spu); } mutex_unlock(&spu_mutex); @@ -591,7 +590,6 @@ static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np /* Add the node number */ isrc |= spu->node << IIC_IRQ_NODE_SHIFT; - spu->isrc = isrc; /* Now map interrupts of all 3 classes */ spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); @@ -733,16 +731,6 @@ struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; -static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) -{ - struct spu *spu = container_of(sysdev, struct spu, sysdev); - return sprintf(buf, "%d\n", spu->isrc); - -} -static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); - -extern int attach_sysdev_to_node(struct sys_device *dev, int nid); - static int spu_create_sysdev(struct spu *spu) { int ret; @@ -756,8 +744,6 @@ static int spu_create_sysdev(struct spu *spu) return ret; } - if (spu->isrc != 0) - sysdev_create_file(&spu->sysdev, &attr_isrc); sysfs_add_device_to_node(&spu->sysdev, spu->nid); return 0; @@ -765,7 +751,6 @@ static int spu_create_sysdev(struct spu *spu) static void spu_destroy_sysdev(struct spu *spu) { - sysdev_remove_file(&spu->sysdev, &attr_isrc); sysfs_remove_device_from_node(&spu->sysdev, spu->nid); sysdev_unregister(&spu->sysdev); } @@ -821,8 +806,8 @@ static int __init create_spu(struct device_node *spe) list_add(&spu->list, &spu_list[spu->node]); mutex_unlock(&spu_mutex); - pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", - spu->name, spu->isrc, spu->local_store, + pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", + spu->name, spu->local_store, spu->problem, spu->priv1, spu->priv2, spu->number); goto out; diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index e73ea00..cac4ad9 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -118,7 +118,6 @@ struct spu { int number; int nid; unsigned int irqs[3]; - u32 isrc; u32 node; u64 flags; u64 dar; -- cgit v0.10.2 From 5737edd1ddbde5ab7f63bb3cb36015edbdb7c295 Mon Sep 17 00:00:00 2001 From: Mark Nutter Date: Tue, 24 Oct 2006 18:31:16 +0200 Subject: [POWERPC] spufs: add support for nonschedulable contexts This adds two new flags to spu_create: SPU_CREATE_NONSCHED: create a context that is never moved away from an SPE once it has started running. This flag can only be used by tasks with the CAP_SYS_NICE capability. SPU_CREATE_ISOLATED: create a nonschedulable context that enters isolation mode upon first run. This requires the SPU_CREATE_NONSCHED flag. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 0de8e11..8ca3306 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -1531,3 +1531,25 @@ struct tree_descr spufs_dir_contents[] = { { "object-id", &spufs_object_id_ops, 0666, }, {}, }; + +struct tree_descr spufs_dir_nosched_contents[] = { + { "mem", &spufs_mem_fops, 0666, }, + { "mbox", &spufs_mbox_fops, 0444, }, + { "ibox", &spufs_ibox_fops, 0444, }, + { "wbox", &spufs_wbox_fops, 0222, }, + { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, + { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, + { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, + { "signal1", &spufs_signal1_fops, 0666, }, + { "signal2", &spufs_signal2_fops, 0666, }, + { "signal1_type", &spufs_signal1_type, 0666, }, + { "signal2_type", &spufs_signal2_type, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, + { "mfc", &spufs_mfc_fops, 0666, }, + { "cntl", &spufs_cntl_fops, 0666, }, + { "npc", &spufs_npc_ops, 0666, }, + { "psmap", &spufs_psmap_fops, 0666, }, + { "phys-id", &spufs_id_ops, 0666, }, + { "object-id", &spufs_object_id_ops, 0666, }, + {}, +}; diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index efc452e..2ad534a 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -219,8 +219,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx) static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) { - eieio(); + spin_lock_irq(&ctx->spu->register_lock); + if (val & SPU_RUNCNTL_ISOLATE) + out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL); out_be32(&ctx->spu->problem->spu_runcntl_RW, val); + spin_unlock_irq(&ctx->spu->register_lock); } static void spu_hw_runcntl_stop(struct spu_context *ctx) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 427d00a..787ae71 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -258,7 +258,12 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; - ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); + if (flags & SPU_CREATE_NOSCHED) + ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, + mode, ctx); + else + ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); + if (ret) goto out_free_ctx; @@ -307,6 +312,16 @@ static int spufs_create_context(struct inode *inode, { int ret; + ret = -EPERM; + if ((flags & SPU_CREATE_NOSCHED) && + !capable(CAP_SYS_NICE)) + goto out_unlock; + + ret = -EINVAL; + if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) + == SPU_CREATE_ISOLATE) + goto out_unlock; + ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); if (ret) goto out_unlock; diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 63df8cf..0c03a04 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -51,11 +51,17 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) static inline int spu_run_init(struct spu_context *ctx, u32 * npc) { int ret; + unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; if ((ret = spu_acquire_runnable(ctx)) != 0) return ret; - ctx->ops->npc_write(ctx, *npc); - ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); + + if (ctx->flags & SPU_CREATE_ISOLATE) + runcntl |= SPU_RUNCNTL_ISOLATE; + else + ctx->ops->npc_write(ctx, *npc); + + ctx->ops->runcntl_write(ctx, runcntl); return 0; } diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index a0f55ca..b17b809 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -135,6 +135,7 @@ struct spufs_inode_info { container_of(inode, struct spufs_inode_info, vfs_inode) extern struct tree_descr spufs_dir_contents[]; +extern struct tree_descr spufs_dir_nosched_contents[]; /* system call implementation */ long spufs_run_spu(struct file *file, diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index b85347f..b47fb50 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu) wait_spu_stopped(prev, spu); /* Step 57. */ } +static void force_spu_isolate_exit(struct spu *spu) +{ + struct spu_problem __iomem *prob = spu->problem; + struct spu_priv2 __iomem *priv2 = spu->priv2; + + /* Stop SPE execution and wait for completion. */ + out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); + iobarrier_rw(); + POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); + + /* Restart SPE master runcntl. */ + spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); + iobarrier_w(); + + /* Initiate isolate exit request and wait for completion. */ + out_be64(&priv2->spu_privcntl_RW, 4LL); + iobarrier_w(); + out_be32(&prob->spu_runcntl_RW, 2); + iobarrier_rw(); + POLL_WHILE_FALSE((in_be32(&prob->spu_status_R) + & SPU_STATUS_STOPPED_BY_STOP)); + + /* Reset load request to normal. */ + out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL); + iobarrier_w(); +} + +/** + * stop_spu_isolate + * Check SPU run-control state and force isolated + * exit function as necessary. + */ +static void stop_spu_isolate(struct spu *spu) +{ + struct spu_problem __iomem *prob = spu->problem; + + if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) { + /* The SPU is in isolated state; the only way + * to get it out is to perform an isolated + * exit (clean) operation. + */ + force_spu_isolate_exit(spu); + } +} + static void harvest(struct spu_state *prev, struct spu *spu) { /* @@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) inhibit_user_access(prev, spu); /* Step 3. */ terminate_spu_app(prev, spu); /* Step 4. */ set_switch_pending(prev, spu); /* Step 5. */ + stop_spu_isolate(spu); /* NEW. */ remove_other_spu_access(prev, spu); /* Step 6. */ suspend_mfc(prev, spu); /* Step 7. */ wait_suspend_mfc_complete(prev, spu); /* Step 8. */ @@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu) acquire_spu_lock(spu); /* Step 1. */ rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); - if (rc) { + if (rc != 0 && rc != 2 && rc != 6) { panic("%s failed on SPU[%d], rc=%d.\n", __func__, spu->number, rc); } - return rc; + return 0; } EXPORT_SYMBOL_GPL(spu_save); diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index cac4ad9..a1cf476 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -181,8 +181,10 @@ extern struct spufs_calls { */ #define SPU_CREATE_EVENTS_ENABLED 0x0001 #define SPU_CREATE_GANG 0x0002 +#define SPU_CREATE_NOSCHED 0x0004 +#define SPU_CREATE_ISOLATE 0x0008 -#define SPU_CREATE_FLAG_ALL 0x0003 /* mask of all valid flags */ +#define SPU_CREATE_FLAG_ALL 0x000f /* mask of all valid flags */ #ifdef CONFIG_SPU_FS_MODULE @@ -276,6 +278,7 @@ struct spu_problem { u32 spu_runcntl_RW; /* 0x401c */ #define SPU_RUNCNTL_STOP 0L #define SPU_RUNCNTL_RUNNABLE 1L +#define SPU_RUNCNTL_ISOLATE 2L u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ u32 spu_status_R; /* 0x4024 */ #define SPU_STOP_STATUS_SHIFT 16 -- cgit v0.10.2 From eb758ce5b0d84e13cb643b6cc7cb429f6fa28258 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Tue, 24 Oct 2006 18:31:17 +0200 Subject: [POWERPC] spufs: "stautus" isnt a word. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index b47fb50..c08981f 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu) * saved at this time. */ isolate_state = SPU_STATUS_ISOLATED_STATE | - SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; + SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS; return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; } @@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu) */ if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { if (in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_EXIT_STAUTUS) { + SPU_STATUS_ISOLATED_EXIT_STATUS) { POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); } if ((in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_LOAD_STAUTUS) + SPU_STATUS_ISOLATED_LOAD_STATUS) || (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE)) { out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); @@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) */ if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { if (in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_EXIT_STAUTUS) { + SPU_STATUS_ISOLATED_EXIT_STATUS) { spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); eieio(); @@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) SPU_STATUS_RUNNING); } if ((in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_LOAD_STAUTUS) + SPU_STATUS_ISOLATED_LOAD_STATUS) || (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE)) { spu_mfc_sr1_set(spu, diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index a1cf476..704e8a8 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -291,8 +291,8 @@ struct spu_problem { #define SPU_STATUS_INVALID_INSTR 0x20 #define SPU_STATUS_INVALID_CH 0x40 #define SPU_STATUS_ISOLATED_STATE 0x80 -#define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200 -#define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400 +#define SPU_STATUS_ISOLATED_LOAD_STATUS 0x200 +#define SPU_STATUS_ISOLATED_EXIT_STATUS 0x400 u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */ u32 spu_spe_R; /* 0x402c */ u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */ -- cgit v0.10.2 From 0afacde3df4c9980f505d9afd7cb0058389732ca Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Tue, 24 Oct 2006 18:31:18 +0200 Subject: [POWERPC] spufs: allow isolated mode apps by starting the SPE loader This patch adds general support for isolated mode SPE apps. Isolated apps are started indirectly, by a dedicated loader "kernel". This patch starts the loader when spe_create is invoked with the ISOLATE flag. We do this at spe_create time to allow libspe to pass the isolated app in before calling spe_run. The loader is read from the device tree, at the location "/spu-isolation/loader". If the loader is not present, an attempt to start an isolated SPE binary will fail with -ENODEV. Update: loader needs to be correctly aligned - copy to a kmalloced buf. Update: remove workaround for systemsim/spurom 'L-bit' bug, which has been fixed. Update: don't write to runcntl on spu_run_init: SPU is already running. Update: do spu_setup_isolated earlier Tested on systemsim. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index f6c94087..d78b0af 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -89,7 +89,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) printk("%s: invalid access during switch!\n", __func__); return 1; } - if (!mm || (REGION_ID(ea) != USER_REGION_ID)) { + esid = (ea & ESID_MASK) | SLB_ESID_V; + + switch(REGION_ID(ea)) { + case USER_REGION_ID: +#ifdef CONFIG_HUGETLB_PAGE + if (in_hugepage_area(mm->context, ea)) + llp = mmu_psize_defs[mmu_huge_psize].sllp; + else +#endif + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | + SLB_VSID_USER | llp; + break; + case VMALLOC_REGION_ID: + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + SLB_VSID_KERNEL | llp; + break; + case KERNEL_REGION_ID: + llp = mmu_psize_defs[mmu_linear_psize].sllp; + vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + SLB_VSID_KERNEL | llp; + break; + default: /* Future: support kernel segments so that drivers * can use SPUs. */ @@ -97,16 +120,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) return 1; } - esid = (ea & ESID_MASK) | SLB_ESID_V; -#ifdef CONFIG_HUGETLB_PAGE - if (in_hugepage_area(mm->context, ea)) - llp = mmu_psize_defs[mmu_huge_psize].sllp; - else -#endif - llp = mmu_psize_defs[mmu_virtual_psize].sllp; - vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | - SLB_VSID_USER | llp; - out_be64(&priv2->slb_index_W, spu->slb_replace); out_be64(&priv2->slb_vsid_RW, vsid); out_be64(&priv2->slb_esid_RW, esid); diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 787ae71..c875193 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -33,6 +33,8 @@ #include #include +#include +#include #include #include #include @@ -41,6 +43,7 @@ #include "spufs.h" static kmem_cache_t *spufs_inode_cache; +static char *isolated_loader; static struct inode * spufs_alloc_inode(struct super_block *sb) @@ -232,6 +235,89 @@ struct file_operations spufs_context_fops = { .fsync = simple_sync_file, }; +static int spu_setup_isolated(struct spu_context *ctx) +{ + int ret; + u64 __iomem *mfc_cntl; + u64 sr1; + u32 status; + unsigned long timeout; + const u32 status_loading = SPU_STATUS_RUNNING + | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; + + if (!isolated_loader) + return -ENODEV; + + if ((ret = spu_acquire_runnable(ctx)) != 0) + return ret; + + mfc_cntl = &ctx->spu->priv2->mfc_control_RW; + + /* purge the MFC DMA queue to ensure no spurious accesses before we + * enter kernel mode */ + timeout = jiffies + HZ; + out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST); + while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK) + != MFC_CNTL_PURGE_DMA_COMPLETE) { + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", + __FUNCTION__); + ret = -EIO; + goto out_unlock; + } + cond_resched(); + } + + /* put the SPE in kernel mode to allow access to the loader */ + sr1 = spu_mfc_sr1_get(ctx->spu); + sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK; + spu_mfc_sr1_set(ctx->spu, sr1); + + /* start the loader */ + ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32); + ctx->ops->signal2_write(ctx, + (unsigned long)isolated_loader & 0xffffffff); + + ctx->ops->runcntl_write(ctx, + SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); + + ret = 0; + timeout = jiffies + HZ; + while (((status = ctx->ops->status_read(ctx)) & status_loading) == + status_loading) { + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "%s: timeout waiting for loader\n", + __FUNCTION__); + ret = -EIO; + goto out_drop_priv; + } + cond_resched(); + } + + if (!(status & SPU_STATUS_RUNNING)) { + /* If isolated LOAD has failed: run SPU, we will get a stop-and + * signal later. */ + pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); + ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); + ret = -EACCES; + + } else if (!(status & SPU_STATUS_ISOLATED_STATE)) { + /* This isn't allowed by the CBEA, but check anyway */ + pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); + ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); + ret = -EINVAL; + } + +out_drop_priv: + /* Finished accessing the loader. Drop kernel mode */ + sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; + spu_mfc_sr1_set(ctx->spu, sr1); + +out_unlock: + up_write(&ctx->state_sema); + return ret; +} + static int spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, int mode) @@ -255,6 +341,11 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, goto out_iput; ctx->flags = flags; + if (flags & SPU_CREATE_ISOLATE) { + ret = spu_setup_isolated(ctx); + if (ret) + goto out_iput; + } inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; @@ -555,6 +646,30 @@ spufs_parse_options(char *options, struct inode *root) return 1; } +static void +spufs_init_isolated_loader(void) +{ + struct device_node *dn; + const char *loader; + int size; + + dn = of_find_node_by_path("/spu-isolation"); + if (!dn) + return; + + loader = get_property(dn, "loader", &size); + if (!loader) + return; + + /* kmalloc should align on a 16 byte boundary..* */ + isolated_loader = kmalloc(size, GFP_KERNEL); + if (!isolated_loader) + return; + + memcpy(isolated_loader, loader, size); + printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); +} + static int spufs_create_root(struct super_block *sb, void *data) { @@ -640,6 +755,8 @@ static int __init spufs_init(void) ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; + + spufs_init_isolated_loader(); return 0; out_fs: unregister_filesystem(&spufs_type); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 0c03a04..a4a0080c 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -1,3 +1,5 @@ +#define DEBUG + #include #include @@ -56,12 +58,12 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) if ((ret = spu_acquire_runnable(ctx)) != 0) return ret; - if (ctx->flags & SPU_CREATE_ISOLATE) - runcntl |= SPU_RUNCNTL_ISOLATE; - else + /* if we're in isolated mode, we would have started the SPU + * earlier, so don't do it again now. */ + if (!(ctx->flags & SPU_CREATE_ISOLATE)) { ctx->ops->npc_write(ctx, *npc); - - ctx->ops->runcntl_write(ctx, runcntl); + ctx->ops->runcntl_write(ctx, runcntl); + } return 0; } -- cgit v0.10.2 From 099814bb1f9bd9081d7c85867f8eb8c049abc1b9 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 24 Oct 2006 18:31:19 +0200 Subject: [POWERPC] spufs: Add isolated-mode SPE recycling support When in isolated mode, SPEs have access to an area of persistent storage, which is per-SPE. In order for isolated-mode apps to communicate arbitrary data through this storage, we need to ensure that isolated physical SPEs can be reused for subsequent applications. Add a file ("recycle") in a spethread dir to enable isolated-mode recycling. By writing to this file, the kernel will reload the isolated-mode loader kernel, allowing a new app to be run on the same physical SPE. This requires the spu_acquire_exclusive function to enforce exclusive access to the SPE while the loader is initialised. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 034cf6a..48eb050 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -120,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx) unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); } +int spu_acquire_exclusive(struct spu_context *ctx) +{ + int ret = 0; + + down_write(&ctx->state_sema); + /* ctx is about to be freed, can't acquire any more */ + if (!ctx->owner) { + ret = -EINVAL; + goto out; + } + + if (ctx->state == SPU_STATE_SAVED) { + ret = spu_activate(ctx, 0); + if (ret) + goto out; + ctx->state = SPU_STATE_RUNNABLE; + } else { + /* We need to exclude userspace access to the context. */ + spu_unmap_mappings(ctx); + } + +out: + if (ret) + up_write(&ctx->state_sema); + return ret; +} + int spu_acquire_runnable(struct spu_context *ctx) { int ret = 0; diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 8ca3306..5b8ba6c 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -1343,6 +1343,37 @@ static struct file_operations spufs_mfc_fops = { .mmap = spufs_mfc_mmap, }; + +static int spufs_recycle_open(struct inode *inode, struct file *file) +{ + file->private_data = SPUFS_I(inode)->i_ctx; + return nonseekable_open(inode, file); +} + +static ssize_t spufs_recycle_write(struct file *file, + const char __user *buffer, size_t size, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret; + + if (!(ctx->flags & SPU_CREATE_ISOLATE)) + return -EINVAL; + + if (size < 1) + return -EINVAL; + + ret = spu_recycle_isolated(ctx); + + if (ret) + return ret; + return size; +} + +static struct file_operations spufs_recycle_fops = { + .open = spufs_recycle_open, + .write = spufs_recycle_write, +}; + static void spufs_npc_set(void *data, u64 val) { struct spu_context *ctx = data; @@ -1551,5 +1582,6 @@ struct tree_descr spufs_dir_nosched_contents[] = { { "psmap", &spufs_psmap_fops, 0666, }, { "phys-id", &spufs_id_ops, 0666, }, { "object-id", &spufs_object_id_ops, 0666, }, + { "recycle", &spufs_recycle_fops, 0222, }, {}, }; diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index c875193..9e457be 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -248,7 +248,7 @@ static int spu_setup_isolated(struct spu_context *ctx) if (!isolated_loader) return -ENODEV; - if ((ret = spu_acquire_runnable(ctx)) != 0) + if ((ret = spu_acquire_exclusive(ctx)) != 0) return ret; mfc_cntl = &ctx->spu->priv2->mfc_control_RW; @@ -314,10 +314,16 @@ out_drop_priv: spu_mfc_sr1_set(ctx->spu, sr1); out_unlock: - up_write(&ctx->state_sema); + spu_release_exclusive(ctx); return ret; } +int spu_recycle_isolated(struct spu_context *ctx) +{ + ctx->ops->runcntl_stop(ctx); + return spu_setup_isolated(ctx); +} + static int spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, int mode) @@ -341,12 +347,6 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, goto out_iput; ctx->flags = flags; - if (flags & SPU_CREATE_ISOLATE) { - ret = spu_setup_isolated(ctx); - if (ret) - goto out_iput; - } - inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; if (flags & SPU_CREATE_NOSCHED) @@ -432,6 +432,13 @@ static int spufs_create_context(struct inode *inode, out_unlock: mutex_unlock(&inode->i_mutex); out: + if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) { + int setup_err = spu_setup_isolated( + SPUFS_I(dentry->d_inode)->i_ctx); + if (setup_err) + ret = setup_err; + } + dput(dentry); return ret; } diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index b17b809..f438f0b 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -163,6 +163,12 @@ void spu_acquire(struct spu_context *ctx); void spu_release(struct spu_context *ctx); int spu_acquire_runnable(struct spu_context *ctx); void spu_acquire_saved(struct spu_context *ctx); +int spu_acquire_exclusive(struct spu_context *ctx); + +static inline void spu_release_exclusive(struct spu_context *ctx) +{ + up_write(&ctx->state_sema); +} int spu_activate(struct spu_context *ctx, u64 flags); void spu_deactivate(struct spu_context *ctx); @@ -170,6 +176,7 @@ void spu_yield(struct spu_context *ctx); int __init spu_sched_init(void); void __exit spu_sched_exit(void); +int spu_recycle_isolated(struct spu_context *ctx); /* * spufs_wait * Same as wait_event_interruptible(), except that here -- cgit v0.10.2 From 22b8c9f5baeb440a716ea760ff05290221565b4c Mon Sep 17 00:00:00 2001 From: David Erb Date: Tue, 24 Oct 2006 18:31:20 +0200 Subject: [POWERPC] cell: update Cell BE register definitions There are a few definitions that are required by subsequent patches, so add them here. The original patch is from David Erb, but is significantly cleaned up by Kevon Corry. Cc: Kevin Corry Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 2f194ba..5e3e0e9 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -16,8 +17,6 @@ #include "cbe_regs.h" -#define MAX_CBE 2 - /* * Current implementation uses "cpu" nodes. We build our own mapping * array of cpu numbers to cpu nodes locally for now to allow interrupt @@ -30,6 +29,7 @@ static struct cbe_regs_map struct device_node *cpu_node; struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; + struct cbe_mic_tm_regs __iomem *mic_tm_regs; } cbe_regs_maps[MAX_CBE]; static int cbe_regs_map_count; @@ -42,6 +42,19 @@ static struct cbe_thread_map static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; + struct device_node *tmp_np; + + if (strcasecmp(np->type, "spe") == 0) { + if (np->data == NULL) { + /* walk up path until cpu node was found */ + tmp_np = np->parent; + while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) + tmp_np = tmp_np->parent; + + np->data = cbe_find_map(tmp_np); + } + return np->data; + } for (i = 0; i < cbe_regs_map_count; i++) if (cbe_regs_maps[i].cpu_node == np) @@ -56,6 +69,7 @@ struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) return NULL; return map->pmd_regs; } +EXPORT_SYMBOL_GPL(cbe_get_pmd_regs); struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) { @@ -64,7 +78,7 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) return NULL; return map->pmd_regs; } - +EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs); struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) { @@ -73,6 +87,7 @@ struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) return NULL; return map->iic_regs; } + struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) { struct cbe_regs_map *map = cbe_thread_map[cpu].regs; @@ -81,6 +96,24 @@ struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) return map->iic_regs; } +struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->mic_tm_regs; +} + +struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->mic_tm_regs; +} +EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); + + void __init cbe_regs_init(void) { int i; @@ -119,6 +152,11 @@ void __init cbe_regs_init(void) prop = get_property(cpu, "iic", NULL); if (prop != NULL) map->iic_regs = ioremap(prop->address, prop->len); + + prop = (struct address_prop *)get_property(cpu, "mic-tm", + NULL); + if (prop != NULL) + map->mic_tm_regs = ioremap(prop->address, prop->len); } } diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index e76e4a6..02bdbc1 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -4,6 +4,11 @@ * This file is intended to hold the various register definitions for CBE * on-chip system devices (memory controller, IO controller, etc...) * + * (C) Copyright IBM Corporation 2001,2006 + * + * Authors: Maximino Aguilar (maguilar@us.ibm.com) + * David J. Erb (djerb@us.ibm.com) + * * (c) 2006 Benjamin Herrenschmidt , IBM Corp. */ @@ -22,6 +27,7 @@ #define HID0_CBE_THERM_INT_EN 0x0000000400000000ul #define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul +#define MAX_CBE 2 /* * @@ -29,45 +35,86 @@ * */ +union spe_reg { + u64 val; + u8 spe[8]; +}; + +union ppe_spe_reg { + u64 val; + struct { + u32 ppe; + u32 spe; + }; +}; + + struct cbe_pmd_regs { - u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ + /* Debug Bus Control */ + u64 pad_0x0000; /* 0x0000 */ + + u64 group_control; /* 0x0008 */ + + u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */ + + u64 debug_bus_control; /* 0x00a8 */ + + u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */ + + u64 trace_aux_data; /* 0x0100 */ + u64 trace_buffer_0_63; /* 0x0108 */ + u64 trace_buffer_64_127; /* 0x0110 */ + u64 trace_address; /* 0x0118 */ + u64 ext_tr_timer; /* 0x0120 */ + + u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */ + + /* Performance Monitor */ + u64 pm_status; /* 0x0400 */ + u64 pm_control; /* 0x0408 */ + u64 pm_interval; /* 0x0410 */ + u64 pm_ctr[4]; /* 0x0418 */ + u64 pm_start_stop; /* 0x0438 */ + u64 pm07_control[8]; /* 0x0440 */ + + u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */ /* Thermal Sensor Registers */ - u64 ts_ctsr1; /* 0x0800 */ - u64 ts_ctsr2; /* 0x0808 */ - u64 ts_mtsr1; /* 0x0810 */ - u64 ts_mtsr2; /* 0x0818 */ - u64 ts_itr1; /* 0x0820 */ - u64 ts_itr2; /* 0x0828 */ - u64 ts_gitr; /* 0x0830 */ - u64 ts_isr; /* 0x0838 */ - u64 ts_imr; /* 0x0840 */ - u64 tm_cr1; /* 0x0848 */ - u64 tm_cr2; /* 0x0850 */ - u64 tm_simr; /* 0x0858 */ - u64 tm_tpr; /* 0x0860 */ - u64 tm_str1; /* 0x0868 */ - u64 tm_str2; /* 0x0870 */ - u64 tm_tsr; /* 0x0878 */ + union spe_reg ts_ctsr1; /* 0x0800 */ + u64 ts_ctsr2; /* 0x0808 */ + union spe_reg ts_mtsr1; /* 0x0810 */ + u64 ts_mtsr2; /* 0x0818 */ + union spe_reg ts_itr1; /* 0x0820 */ + u64 ts_itr2; /* 0x0828 */ + u64 ts_gitr; /* 0x0830 */ + u64 ts_isr; /* 0x0838 */ + u64 ts_imr; /* 0x0840 */ + union spe_reg tm_cr1; /* 0x0848 */ + u64 tm_cr2; /* 0x0850 */ + u64 tm_simr; /* 0x0858 */ + union ppe_spe_reg tm_tpr; /* 0x0860 */ + union spe_reg tm_str1; /* 0x0868 */ + u64 tm_str2; /* 0x0870 */ + union ppe_spe_reg tm_tsr; /* 0x0878 */ /* Power Management */ - u64 pm_control; /* 0x0880 */ -#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 - u64 pm_status; /* 0x0888 */ + u64 pmcr; /* 0x0880 */ +#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 + u64 pmsr; /* 0x0888 */ /* Time Base Register */ - u64 tbr; /* 0x0890 */ + u64 tbr; /* 0x0890 */ - u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ + u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ /* Fault Isolation Registers */ - u64 checkstop_fir; /* 0x0c00 */ - u64 recoverable_fir; - u64 spec_att_mchk_fir; - u64 fir_mode_reg; - u64 fir_enable_mask; + u64 checkstop_fir; /* 0x0c00 */ + u64 recoverable_fir; /* 0x0c08 */ + u64 spec_att_mchk_fir; /* 0x0c10 */ + u64 fir_mode_reg; /* 0x0c18 */ + u64 fir_enable_mask; /* 0x0c20 */ - u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ + u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ }; extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); @@ -102,18 +149,20 @@ struct cbe_iic_regs { /* IIC interrupt registers */ struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ - u64 iic_ir; /* 0x0440 */ - u64 iic_is; /* 0x0448 */ + + u64 iic_ir; /* 0x0440 */ + u64 iic_is; /* 0x0448 */ +#define CBE_IIC_IS_PMI 0x2 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ /* IOC FIR */ u64 ioc_fir_reset; /* 0x0500 */ - u64 ioc_fir_set; - u64 ioc_checkstop_enable; - u64 ioc_fir_error_mask; - u64 ioc_syserr_enable; - u64 ioc_fir; + u64 ioc_fir_set; /* 0x0508 */ + u64 ioc_checkstop_enable; /* 0x0510 */ + u64 ioc_fir_error_mask; /* 0x0518 */ + u64 ioc_syserr_enable; /* 0x0520 */ + u64 ioc_fir; /* 0x0528 */ u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ }; @@ -122,6 +171,48 @@ extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); +struct cbe_mic_tm_regs { + u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */ + + u64 mic_ctl_cnfg2; /* 0x0040 */ +#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL +#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL +#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL +#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL + + u64 pad_0x0048; /* 0x0048 */ + + u64 mic_aux_trc_base; /* 0x0050 */ + u64 mic_aux_trc_max_addr; /* 0x0058 */ + u64 mic_aux_trc_cur_addr; /* 0x0060 */ + u64 mic_aux_trc_grf_addr; /* 0x0068 */ + u64 mic_aux_trc_grf_data; /* 0x0070 */ + + u64 pad_0x0078; /* 0x0078 */ + + u64 mic_ctl_cnfg_0; /* 0x0080 */ +#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL + + u64 pad_0x0088; /* 0x0088 */ + + u64 slow_fast_timer_0; /* 0x0090 */ + u64 slow_next_timer_0; /* 0x0098 */ + + u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */ + + u64 mic_ctl_cnfg_1; /* 0x01c0 */ +#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL + u64 pad_0x01c8; /* 0x01c8 */ + + u64 slow_fast_timer_1; /* 0x01d0 */ + u64 slow_next_timer_1; /* 0x01d8 */ + + u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */ +}; + +extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); +extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); + /* Init this module early */ extern void cbe_regs_init(void); diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 9f2e4ed..fdcd89e 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -54,9 +54,9 @@ static void __init cbe_enable_pause_zero(void) pr_debug("Power Management: CPU %d\n", smp_processor_id()); /* Enable Pause(0) control bit */ - temp_register = in_be64(&pregs->pm_control); + temp_register = in_be64(&pregs->pmcr); - out_be64(&pregs->pm_control, + out_be64(&pregs->pmcr, temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); /* Enable DEC and EE interrupt request */ @@ -87,7 +87,7 @@ static void cbe_idle(void) unsigned long ctrl; /* Why do we do that on every idle ? Couldn't that be done once for - * all or do we lose the state some way ? Also, the pm_control + * all or do we lose the state some way ? Also, the pmcr * register setting, that can't be set once at boot ? We really want * to move that away in order to implement a simple powersave */ -- cgit v0.10.2 From bffd4927ba4377aa38be5450e20e0fecd2523fe3 Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Tue, 24 Oct 2006 18:31:21 +0200 Subject: [POWERPC] cell: add shadow registers for pmd_reg Many of the registers in the performance monitoring unit are write-only. We need to save a "shadow" copy when we write to those registers so we can retrieve the values if we need them later. The new cbe_pmd_shadow_regs structure is added to the cbe_regs_map structure so we have the appropriate per-node copies of these shadow values. Signed-off-by: Kevin Corry Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 5e3e0e9..5a91b75 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -30,6 +30,7 @@ static struct cbe_regs_map struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; + struct cbe_pmd_shadow_regs pmd_shadow_regs; } cbe_regs_maps[MAX_CBE]; static int cbe_regs_map_count; @@ -80,6 +81,22 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs); +struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return &map->pmd_shadow_regs; +} + +struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return &map->pmd_shadow_regs; +} + struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) { struct cbe_regs_map *map = cbe_find_map(np); diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index 02bdbc1..d352f11 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -121,6 +121,41 @@ extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); /* + * PMU shadow registers + * + * Many of the registers in the performance monitoring unit are write-only, + * so we need to save a copy of what we write to those registers. + * + * The actual data counters are read/write. However, writing to the counters + * only takes effect if the PMU is enabled. Otherwise the value is stored in + * a hardware latch until the next time the PMU is enabled. So we save a copy + * of the counter values if we need to read them back while the PMU is + * disabled. The counter_value_in_latch field is a bitmap indicating which + * counters currently have a value waiting to be written. + */ + +#define NR_PHYS_CTRS 4 +#define NR_CTRS (NR_PHYS_CTRS * 2) + +struct cbe_pmd_shadow_regs { + u32 group_control; + u32 debug_bus_control; + u32 trace_address; + u32 ext_tr_timer; + u32 pm_status; + u32 pm_control; + u32 pm_interval; + u32 pm_start_stop; + u32 pm07_control[NR_CTRS]; + + u32 pm_ctr[NR_PHYS_CTRS]; + u32 counter_value_in_latch; +}; + +extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np); +extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu); + +/* * * IIC unit register definitions * -- cgit v0.10.2 From d8bf96e0793f9576da545bac333b2de304958d68 Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Tue, 24 Oct 2006 18:31:22 +0200 Subject: [POWERPC] cell: add low-level performance monitoring code Add routines for accessing the registers and counters in the performance monitoring unit. Signed-off-by: Kevin Corry Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index c89cdd6..412649b 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ - cbe_regs.o spider-pic.o pervasive.o + cbe_regs.o spider-pic.o pervasive.o \ + pmu.o obj-$(CONFIG_CBE_RAS) += ras.o ifeq ($(CONFIG_SMP),y) diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index d352f11..91083f5 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -35,6 +35,11 @@ * */ +/* Macros for the pm_control register. */ +#define CBE_PM_16BIT_CTR(ctr) (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1)))) +#define CBE_PM_ENABLE_PERF_MON 0x80000000 + + union spe_reg { u64 val; u8 spe[8]; diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c new file mode 100644 index 0000000..30d17ce --- /dev/null +++ b/arch/powerpc/platforms/cell/pmu.c @@ -0,0 +1,328 @@ +/* + * Cell Broadband Engine Performance Monitor + * + * (C) Copyright IBM Corporation 2001,2006 + * + * Author: + * David Erb (djerb@us.ibm.com) + * Kevin Corry (kevcorry@us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "cbe_regs.h" +#include "interrupt.h" +#include "pmu.h" + +/* + * When writing to write-only mmio addresses, save a shadow copy. All of the + * registers are 32-bit, but stored in the upper-half of a 64-bit field in + * pmd_regs. + */ + +#define WRITE_WO_MMIO(reg, x) \ + do { \ + u32 _x = (x); \ + struct cbe_pmd_regs __iomem *pmd_regs; \ + struct cbe_pmd_shadow_regs *shadow_regs; \ + pmd_regs = cbe_get_cpu_pmd_regs(cpu); \ + shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \ + out_be64(&(pmd_regs->reg), (((u64)_x) << 32)); \ + shadow_regs->reg = _x; \ + } while (0) + +#define READ_SHADOW_REG(val, reg) \ + do { \ + struct cbe_pmd_shadow_regs *shadow_regs; \ + shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \ + (val) = shadow_regs->reg; \ + } while (0) + +#define READ_MMIO_UPPER32(val, reg) \ + do { \ + struct cbe_pmd_regs __iomem *pmd_regs; \ + pmd_regs = cbe_get_cpu_pmd_regs(cpu); \ + (val) = (u32)(in_be64(&pmd_regs->reg) >> 32); \ + } while (0) + +/* + * Physical counter registers. + * Each physical counter can act as one 32-bit counter or two 16-bit counters. + */ + +u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr) +{ + u32 val_in_latch, val = 0; + + if (phys_ctr < NR_PHYS_CTRS) { + READ_SHADOW_REG(val_in_latch, counter_value_in_latch); + + /* Read the latch or the actual counter, whichever is newer. */ + if (val_in_latch & (1 << phys_ctr)) { + READ_SHADOW_REG(val, pm_ctr[phys_ctr]); + } else { + READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]); + } + } + + return val; +} + +void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val) +{ + struct cbe_pmd_shadow_regs *shadow_regs; + u32 pm_ctrl; + + if (phys_ctr < NR_PHYS_CTRS) { + /* Writing to a counter only writes to a hardware latch. + * The new value is not propagated to the actual counter + * until the performance monitor is enabled. + */ + WRITE_WO_MMIO(pm_ctr[phys_ctr], val); + + pm_ctrl = cbe_read_pm(cpu, pm_control); + if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) { + /* The counters are already active, so we need to + * rewrite the pm_control register to "re-enable" + * the PMU. + */ + cbe_write_pm(cpu, pm_control, pm_ctrl); + } else { + shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); + shadow_regs->counter_value_in_latch |= (1 << phys_ctr); + } + } +} + +/* + * "Logical" counter registers. + * These will read/write 16-bits or 32-bits depending on the + * current size of the counter. Counters 4 - 7 are always 16-bit. + */ + +u32 cbe_read_ctr(u32 cpu, u32 ctr) +{ + u32 val; + u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1); + + val = cbe_read_phys_ctr(cpu, phys_ctr); + + if (cbe_get_ctr_size(cpu, phys_ctr) == 16) + val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff); + + return val; +} + +void cbe_write_ctr(u32 cpu, u32 ctr, u32 val) +{ + u32 phys_ctr; + u32 phys_val; + + phys_ctr = ctr & (NR_PHYS_CTRS - 1); + + if (cbe_get_ctr_size(cpu, phys_ctr) == 16) { + phys_val = cbe_read_phys_ctr(cpu, phys_ctr); + + if (ctr < NR_PHYS_CTRS) + val = (val << 16) | (phys_val & 0xffff); + else + val = (val & 0xffff) | (phys_val & 0xffff0000); + } + + cbe_write_phys_ctr(cpu, phys_ctr, val); +} + +/* + * Counter-control registers. + * Each "logical" counter has a corresponding control register. + */ + +u32 cbe_read_pm07_control(u32 cpu, u32 ctr) +{ + u32 pm07_control = 0; + + if (ctr < NR_CTRS) + READ_SHADOW_REG(pm07_control, pm07_control[ctr]); + + return pm07_control; +} + +void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val) +{ + if (ctr < NR_CTRS) + WRITE_WO_MMIO(pm07_control[ctr], val); +} + +/* + * Other PMU control registers. Most of these are write-only. + */ + +u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg) +{ + u32 val = 0; + + switch (reg) { + case group_control: + READ_SHADOW_REG(val, group_control); + break; + + case debug_bus_control: + READ_SHADOW_REG(val, debug_bus_control); + break; + + case trace_address: + READ_MMIO_UPPER32(val, trace_address); + break; + + case ext_tr_timer: + READ_SHADOW_REG(val, ext_tr_timer); + break; + + case pm_status: + READ_MMIO_UPPER32(val, pm_status); + break; + + case pm_control: + READ_SHADOW_REG(val, pm_control); + break; + + case pm_interval: + READ_SHADOW_REG(val, pm_interval); + break; + + case pm_start_stop: + READ_SHADOW_REG(val, pm_start_stop); + break; + } + + return val; +} + +void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val) +{ + switch (reg) { + case group_control: + WRITE_WO_MMIO(group_control, val); + break; + + case debug_bus_control: + WRITE_WO_MMIO(debug_bus_control, val); + break; + + case trace_address: + WRITE_WO_MMIO(trace_address, val); + break; + + case ext_tr_timer: + WRITE_WO_MMIO(ext_tr_timer, val); + break; + + case pm_status: + WRITE_WO_MMIO(pm_status, val); + break; + + case pm_control: + WRITE_WO_MMIO(pm_control, val); + break; + + case pm_interval: + WRITE_WO_MMIO(pm_interval, val); + break; + + case pm_start_stop: + WRITE_WO_MMIO(pm_start_stop, val); + break; + } +} + +/* + * Get/set the size of a physical counter to either 16 or 32 bits. + */ + +u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr) +{ + u32 pm_ctrl, size = 0; + + if (phys_ctr < NR_PHYS_CTRS) { + pm_ctrl = cbe_read_pm(cpu, pm_control); + size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32; + } + + return size; +} + +void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size) +{ + u32 pm_ctrl; + + if (phys_ctr < NR_PHYS_CTRS) { + pm_ctrl = cbe_read_pm(cpu, pm_control); + switch (ctr_size) { + case 16: + pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr); + break; + + case 32: + pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr); + break; + } + cbe_write_pm(cpu, pm_control, pm_ctrl); + } +} + +/* + * Enable/disable the entire performance monitoring unit. + * When we enable the PMU, all pending writes to counters get committed. + */ + +void cbe_enable_pm(u32 cpu) +{ + struct cbe_pmd_shadow_regs *shadow_regs; + u32 pm_ctrl; + + shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); + shadow_regs->counter_value_in_latch = 0; + + pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON; + cbe_write_pm(cpu, pm_control, pm_ctrl); +} + +void cbe_disable_pm(u32 cpu) +{ + u32 pm_ctrl; + pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON; + cbe_write_pm(cpu, pm_control, pm_ctrl); +} + +/* + * Reading from the trace_buffer. + * The trace buffer is two 64-bit registers. Reading from + * the second half automatically increments the trace_address. + */ + +void cbe_read_trace_buffer(u32 cpu, u64 *buf) +{ + struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu); + + *buf++ = in_be64(&pmd_regs->trace_buffer_0_63); + *buf++ = in_be64(&pmd_regs->trace_buffer_64_127); +} + diff --git a/arch/powerpc/platforms/cell/pmu.h b/arch/powerpc/platforms/cell/pmu.h new file mode 100644 index 0000000..eb1e8e0 --- /dev/null +++ b/arch/powerpc/platforms/cell/pmu.h @@ -0,0 +1,57 @@ +/* + * Cell Broadband Engine Performance Monitor + * + * (C) Copyright IBM Corporation 2001,2006 + * + * Author: + * David Erb (djerb@us.ibm.com) + * Kevin Corry (kevcorry@us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +#ifndef __PERFMON_H__ +#define __PERFMON_H__ + +enum pm_reg_name { + group_control, + debug_bus_control, + trace_address, + ext_tr_timer, + pm_status, + pm_control, + pm_interval, + pm_start_stop, +}; + +extern u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr); +extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); +extern u32 cbe_read_ctr(u32 cpu, u32 ctr); +extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val); + +extern u32 cbe_read_pm07_control(u32 cpu, u32 ctr); +extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val); +extern u32 cbe_read_pm (u32 cpu, enum pm_reg_name reg); +extern void cbe_write_pm (u32 cpu, enum pm_reg_name reg, u32 val); + +extern u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr); +extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); + +extern void cbe_enable_pm(u32 cpu); +extern void cbe_disable_pm(u32 cpu); + +extern void cbe_read_trace_buffer(u32 cpu, u64 *buf); + +#endif -- cgit v0.10.2 From e570beb6bb1a623849901efbf939063ec4775c9e Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Tue, 24 Oct 2006 18:31:23 +0200 Subject: [POWERPC] cell: add support for registering sysfs attributes to spus In order to add sysfs attributes to all spu's, there is a need for a list of all available spu's. Adding the device_node makes also sense, as it is needed for proper register access. This patch also adds two functions to create and remove sysfs attributes and attribute_groups to all spus. That allows to group spu attributes in a subdirectory like: /sys/devices/system/spu/spuX/group_name/what_ever This will be used by cbe_thermal to group all attributes dealing with thermal support in one directory. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d78b0af..b75b091 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -333,6 +333,7 @@ static void spu_free_irqs(struct spu *spu) } static struct list_head spu_list[MAX_NUMNODES]; +static LIST_HEAD(spu_full_list); static DEFINE_MUTEX(spu_mutex); static void spu_init_channels(struct spu *spu) @@ -744,6 +745,57 @@ struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; +int spu_add_sysdev_attr(struct sysdev_attribute *attr) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysdev_create_file(&spu->sysdev, attr); + + mutex_unlock(&spu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr); + +int spu_add_sysdev_attr_group(struct attribute_group *attrs) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysfs_create_group(&spu->sysdev.kobj, attrs); + + mutex_unlock(&spu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group); + + +void spu_remove_sysdev_attr(struct sysdev_attribute *attr) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysdev_remove_file(&spu->sysdev, attr); + + mutex_unlock(&spu_mutex); +} +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr); + +void spu_remove_sysdev_attr_group(struct attribute_group *attrs) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysfs_remove_group(&spu->sysdev.kobj, attrs); + + mutex_unlock(&spu_mutex); +} +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group); + static int spu_create_sysdev(struct spu *spu) { int ret; @@ -817,6 +869,9 @@ static int __init create_spu(struct device_node *spe) goto out_free_irqs; list_add(&spu->list, &spu_list[spu->node]); + list_add(&spu->full_list, &spu_full_list); + spu->devnode = of_node_get(spe); + mutex_unlock(&spu_mutex); pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", @@ -839,6 +894,9 @@ out: static void destroy_spu(struct spu *spu) { list_del_init(&spu->list); + list_del_init(&spu->full_list); + + of_node_put(spu->devnode); spu_destroy_sysdev(spu); spu_free_irqs(spu); diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 704e8a8..ffa4df0 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -115,6 +115,7 @@ struct spu { struct spu_priv2 __iomem *priv2; struct list_head list; struct list_head sched_list; + struct list_head full_list; int number; int nid; unsigned int irqs[3]; @@ -143,6 +144,8 @@ struct spu { char irq_c1[8]; char irq_c2[8]; + struct device_node *devnode; + struct sys_device sysdev; }; @@ -200,6 +203,12 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) } #endif /* MODULE */ +int spu_add_sysdev_attr(struct sysdev_attribute *attr); +void spu_remove_sysdev_attr(struct sysdev_attribute *attr); + +int spu_add_sysdev_attr_group(struct attribute_group *attrs); +void spu_remove_sysdev_attr_group(struct attribute_group *attrs); + /* * Notifier blocks: -- cgit v0.10.2 From 0344c6c5387ba335bba5a66fd44714b94c98573f Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Tue, 24 Oct 2006 18:31:24 +0200 Subject: [POWERPC] sysfs: add support for adding/removing spu sysfs attributes This patch adds two functions to create and remove sysfs attributes and attribute_group to all cpus. That allows to register sysfs attributes in a subdirectory like: /sys/devices/system/cpu/cpuX/group_name/what_ever This will be used by cbe_thermal to group all attributes dealing with thermal support in one directory. Signed-of-by: Christian Krafft Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d45a168..cda21a2 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -299,6 +299,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; +static DEFINE_MUTEX(cpu_mutex); + +int cpu_add_sysdev_attr(struct sysdev_attribute *attr) +{ + int cpu; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { + sysdev_create_file(get_cpu_sysdev(cpu), attr); + } + + mutex_unlock(&cpu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr); + +int cpu_add_sysdev_attr_group(struct attribute_group *attrs) +{ + int cpu; + struct sys_device *sysdev; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { + sysdev = get_cpu_sysdev(cpu); + sysfs_create_group(&sysdev->kobj, attrs); + } + + mutex_unlock(&cpu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group); + + +void cpu_remove_sysdev_attr(struct sysdev_attribute *attr) +{ + int cpu; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { + sysdev_remove_file(get_cpu_sysdev(cpu), attr); + } + + mutex_unlock(&cpu_mutex); +} +EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr); + +void cpu_remove_sysdev_attr_group(struct attribute_group *attrs) +{ + int cpu; + struct sys_device *sysdev; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { + sysdev = get_cpu_sysdev(cpu); + sysfs_remove_group(&sysdev->kobj, attrs); + } + + mutex_unlock(&cpu_mutex); +} +EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group); + + /* NUMA stuff */ #ifdef CONFIG_NUMA diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 3fef7d6..f02d71b 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -33,6 +33,14 @@ struct cpu { extern int register_cpu(struct cpu *cpu, int num); extern struct sys_device *get_cpu_sysdev(unsigned cpu); + +extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr); +extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr); + +extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs); +extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs); + + #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *cpu); #endif -- cgit v0.10.2 From b3d7dc1967d1303d4897ff9537d29f6e077de147 Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Tue, 24 Oct 2006 18:31:25 +0200 Subject: [POWERPC] cell: add temperature to SPU and CPU sysfs entries This patch adds a module that registers sysfs attributes to CPU and SPU containing the temperature of the CBE. They can be found under /sys/devices/system/spu/cpuX/thermal/temperature[0|1] /sys/devices/system/spu/spuX/thermal/temperature The temperature is read from the on-chip temperature sensors. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 892d5dd..910a331 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -149,6 +149,7 @@ CONFIG_MMIO_NVRAM=y CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y +CONFIG_CBE_THERM=m # # Kernel options diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3e430b4..77ae619 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -20,4 +20,9 @@ config CBE_RAS bool "RAS features for bare metal Cell BE" default y +config CBE_THERM + tristate "CBE thermal support" + default m + depends on CBE_RAS + endmenu diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 412649b..90e1314 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -3,6 +3,8 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ pmu.o obj-$(CONFIG_CBE_RAS) += ras.o +obj-$(CONFIG_CBE_THERM) += cbe_thermal.o + ifeq ($(CONFIG_SMP),y) obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o endif diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c new file mode 100644 index 0000000..17831a9 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -0,0 +1,225 @@ +/* + * thermal support for the cell processor + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Christian Krafft + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cbe_regs.h" + +static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) +{ + struct spu *spu; + + spu = container_of(sysdev, struct spu, sysdev); + + return cbe_get_pmd_regs(spu->devnode); +} + +/* returns the value for a given spu in a given register */ +static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) +{ + unsigned int *id; + union spe_reg value; + struct spu *spu; + + /* getting the id from the reg attribute will not work on future device-tree layouts + * in future we should store the id to the spu struct and use it here */ + spu = container_of(sysdev, struct spu, sysdev); + id = (unsigned int *)get_property(spu->devnode, "reg", NULL); + value.val = in_be64(®->val); + + return value.spe[*id]; +} + +static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) +{ + int value; + struct cbe_pmd_regs __iomem *pmd_regs; + + pmd_regs = get_pmd_regs(sysdev); + + value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); + /* clear all other bits */ + value &= 0x3F; + /* temp is stored in steps of 2 degrees */ + value *= 2; + /* base temp is 65 degrees */ + value += 65; + + return sprintf(buf, "%d\n", (int) value); +} + +static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) +{ + struct cbe_pmd_regs __iomem *pmd_regs; + u64 value; + + pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); + value = in_be64(&pmd_regs->ts_ctsr2); + + /* access the corresponding byte */ + value >>= pos; + /* clear all other bits */ + value &= 0x3F; + /* temp is stored in steps of 2 degrees */ + value *= 2; + /* base temp is 65 degrees */ + value += 65; + + return sprintf(buf, "%d\n", (int) value); +} + + +/* shows the temperature of the DTS on the PPE, + * located near the linear thermal sensor */ +static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf) +{ + return ppe_show_temp(sysdev, buf, 32); +} + +/* shows the temperature of the second DTS on the PPE */ +static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) +{ + return ppe_show_temp(sysdev, buf, 0); +} + +static struct sysdev_attribute attr_spu_temperature = { + .attr = {.name = "temperature", .mode = 0400 }, + .show = spu_show_temp, +}; + +static struct attribute *spu_attributes[] = { + &attr_spu_temperature.attr, +}; + +static struct attribute_group spu_attribute_group = { + .name = "thermal", + .attrs = spu_attributes, +}; + +static struct sysdev_attribute attr_ppe_temperature0 = { + .attr = {.name = "temperature0", .mode = 0400 }, + .show = ppe_show_temp0, +}; + +static struct sysdev_attribute attr_ppe_temperature1 = { + .attr = {.name = "temperature1", .mode = 0400 }, + .show = ppe_show_temp1, +}; + +static struct attribute *ppe_attributes[] = { + &attr_ppe_temperature0.attr, + &attr_ppe_temperature1.attr, +}; + +static struct attribute_group ppe_attribute_group = { + .name = "thermal", + .attrs = ppe_attributes, +}; + +/* + * initialize throttling with default values + */ +static void __init init_default_values(void) +{ + int cpu; + struct cbe_pmd_regs __iomem *pmd_regs; + struct sys_device *sysdev; + union ppe_spe_reg tpr; + union spe_reg str1; + u64 str2; + union spe_reg cr1; + u64 cr2; + + /* TPR defaults */ + /* ppe + * 1F - no full stop + * 08 - dynamic throttling starts if over 80 degrees + * 03 - dynamic throttling ceases if below 70 degrees */ + tpr.ppe = 0x1F0803; + /* spe + * 10 - full stopped when over 96 degrees + * 08 - dynamic throttling starts if over 80 degrees + * 03 - dynamic throttling ceases if below 70 degrees + */ + tpr.spe = 0x100803; + + /* STR defaults */ + /* str1 + * 10 - stop 16 of 32 cycles + */ + str1.val = 0x1010101010101010ull; + /* str2 + * 10 - stop 16 of 32 cycles + */ + str2 = 0x10; + + /* CR defaults */ + /* cr1 + * 4 - normal operation + */ + cr1.val = 0x0404040404040404ull; + /* cr2 + * 4 - normal operation + */ + cr2 = 0x04; + + for_each_possible_cpu (cpu) { + pr_debug("processing cpu %d\n", cpu); + sysdev = get_cpu_sysdev(cpu); + pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); + + out_be64(&pmd_regs->tm_str2, str2); + out_be64(&pmd_regs->tm_str1.val, str1.val); + out_be64(&pmd_regs->tm_tpr.val, tpr.val); + out_be64(&pmd_regs->tm_cr1.val, cr1.val); + out_be64(&pmd_regs->tm_cr2, cr2); + } +} + + +static int __init thermal_init(void) +{ + init_default_values(); + + spu_add_sysdev_attr_group(&spu_attribute_group); + cpu_add_sysdev_attr_group(&ppe_attribute_group); + + return 0; +} +module_init(thermal_init); + +static void __exit thermal_exit(void) +{ + spu_remove_sysdev_attr_group(&spu_attribute_group); + cpu_remove_sysdev_attr_group(&ppe_attribute_group); +} +module_exit(thermal_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Krafft "); + -- cgit v0.10.2 From 302eca184fb844670fb128c69e22a8a28bbce48a Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Tue, 24 Oct 2006 18:31:26 +0200 Subject: [POWERPC] cell: use ppc_md->power_save instead of cbe_idle_loop This moves the cell idle function to use the default cpu_idle with a special power_save callback, like all other platforms except iSeries already do. It also makes it possible to disable this power_save function with a new powerpc-specific boot option "powersave=off". Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 4180c39..8994af3 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -39,6 +39,13 @@ #define cpu_should_die() 0 #endif +static int __init powersave_off(char *arg) +{ + ppc_md.power_save = NULL; + return 0; +} +__setup("powersave=off", powersave_off); + /* * The body of the idle task. */ diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index fdcd89e..c68fabd 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -38,32 +38,16 @@ #include "pervasive.h" #include "cbe_regs.h" -static DEFINE_SPINLOCK(cbe_pervasive_lock); - -static void __init cbe_enable_pause_zero(void) +static void cbe_power_save(void) { - unsigned long thread_switch_control; - unsigned long temp_register; - struct cbe_pmd_regs __iomem *pregs; - - spin_lock_irq(&cbe_pervasive_lock); - pregs = cbe_get_cpu_pmd_regs(smp_processor_id()); - if (pregs == NULL) - goto out; - - pr_debug("Power Management: CPU %d\n", smp_processor_id()); - - /* Enable Pause(0) control bit */ - temp_register = in_be64(&pregs->pmcr); - - out_be64(&pregs->pmcr, - temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); + unsigned long ctrl, thread_switch_control; + ctrl = mfspr(SPRN_CTRLF); /* Enable DEC and EE interrupt request */ thread_switch_control = mfspr(SPRN_TSC_CELL); thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; - switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { + switch (ctrl & CTRL_CT) { case CTRL_CT0: thread_switch_control |= TSC_CELL_DEC_ENABLE_0; break; @@ -75,58 +59,21 @@ static void __init cbe_enable_pause_zero(void) __FUNCTION__); break; } - mtspr(SPRN_TSC_CELL, thread_switch_control); -out: - spin_unlock_irq(&cbe_pervasive_lock); -} - -static void cbe_idle(void) -{ - unsigned long ctrl; - - /* Why do we do that on every idle ? Couldn't that be done once for - * all or do we lose the state some way ? Also, the pmcr - * register setting, that can't be set once at boot ? We really want - * to move that away in order to implement a simple powersave + /* + * go into low thread priority, medium priority will be + * restored for us after wake-up. */ - cbe_enable_pause_zero(); - - while (1) { - if (!need_resched()) { - local_irq_disable(); - while (!need_resched()) { - /* go into low thread priority */ - HMT_low(); - - /* - * atomically disable thread execution - * and runlatch. - * External and Decrementer exceptions - * are still handled when the thread - * is disabled but now enter in - * cbe_system_reset_exception() - */ - ctrl = mfspr(SPRN_CTRLF); - ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); - mtspr(SPRN_CTRLT, ctrl); - } - /* restore thread prio */ - HMT_medium(); - local_irq_enable(); - } + HMT_low(); - /* - * turn runlatch on again before scheduling the - * process we just woke up - */ - ppc64_runlatch_on(); - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } + /* + * atomically disable thread execution and runlatch. + * External and Decrementer exceptions are still handled when the + * thread is disabled but now enter in cbe_system_reset_exception() + */ + ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); + mtspr(SPRN_CTRLT, ctrl); } static int cbe_system_reset_exception(struct pt_regs *regs) @@ -158,9 +105,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs) void __init cbe_pervasive_init(void) { + int cpu; if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) return; - ppc_md.idle_loop = cbe_idle; + for_each_possible_cpu(cpu) { + struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); + if (!regs) + continue; + + /* Enable Pause(0) control bit */ + out_be64(®s->pmcr, in_be64(®s->pmcr) | + CBE_PMD_PAUSE_ZERO_CONTROL); + } + + ppc_md.power_save = cbe_power_save; ppc_md.system_reset_exception = cbe_system_reset_exception; } -- cgit v0.10.2 From ff8a8f25976aa58bbae7883405b00dcbaf4cc823 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 24 Oct 2006 18:31:27 +0200 Subject: [POWERPC] add support for stopping spus from xmon This patch adds support for stopping, and restarting, spus from xmon. We use the spu master runcntl bit to stop execution, this is apparently the "right" way to control spu execution and spufs will be changed in the future to use this bit. Testing has shown that to restart execution we have to turn the master runcntl bit on and also rewrite the spu runcntl bit, even if it is already set to 1 (running). Stopping spus is triggered by the xmon command 'ss' - "spus stop" perhaps. Restarting them is triggered via 'sr'. Restart doesn't start execution on spus unless they were running prior to being stopped by xmon. Walking the spu->full_list in xmon after a panic, would mean corruption of any spu struct would make all the others inaccessible. To avoid this, and also to make the next patch easier, we cache pointers to all spus during boot. We attempt to catch and recover from errors while stopping and restarting the spus, but as with most xmon functionality there are no guarantees that performing these operations won't crash xmon itself. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index b75b091..032bc92 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "interrupt.h" @@ -943,6 +944,9 @@ static int __init init_spu_base(void) break; } } + + xmon_register_spus(&spu_full_list); + return ret; } module_init(init_spu_base); diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index f56ffef..6a2ed8b 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #ifdef CONFIG_PPC64 #include @@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid, const char *after); static const char *getvecname(unsigned long vec); +static int do_spu_cmd(void); + int xmon_no_auto_backtrace; extern int print_insn_powerpc(unsigned long, unsigned long, int); @@ -209,8 +213,12 @@ Commands:\n\ mi show information about memory allocation\n\ p call a procedure\n\ r print registers\n\ - s single step\n\ - S print special registers\n\ + s single step\n" +#ifdef CONFIG_PPC_CELL +" ss stop execution on all spus\n\ + sr restore execution on stopped spus\n" +#endif +" S print special registers\n\ t print backtrace\n\ x exit monitor and recover\n\ X exit monitor and dont recover\n" @@ -518,6 +526,7 @@ int xmon(struct pt_regs *excp) xmon_save_regs(®s); excp = ®s; } + return xmon_core(excp, 0); } EXPORT_SYMBOL(xmon); @@ -809,6 +818,8 @@ cmds(struct pt_regs *excp) cacheflush(); break; case 's': + if (do_spu_cmd() == 0) + break; if (do_step(excp)) return cmd; break; @@ -2630,3 +2641,130 @@ void __init xmon_setup(void) if (xmon_early) debugger(NULL); } + +#ifdef CONFIG_PPC_CELL + +struct spu_info { + struct spu *spu; + u64 saved_mfc_sr1_RW; + u32 saved_spu_runcntl_RW; + u8 stopped_ok; +}; + +#define XMON_NUM_SPUS 16 /* Enough for current hardware */ + +static struct spu_info spu_info[XMON_NUM_SPUS]; + +void xmon_register_spus(struct list_head *list) +{ + struct spu *spu; + + list_for_each_entry(spu, list, full_list) { + if (spu->number >= XMON_NUM_SPUS) { + WARN_ON(1); + continue; + } + + spu_info[spu->number].spu = spu; + spu_info[spu->number].stopped_ok = 0; + } +} + +static void stop_spus(void) +{ + struct spu *spu; + int i; + u64 tmp; + + for (i = 0; i < XMON_NUM_SPUS; i++) { + if (!spu_info[i].spu) + continue; + + if (setjmp(bus_error_jmp) == 0) { + catch_memory_errors = 1; + sync(); + + spu = spu_info[i].spu; + + spu_info[i].saved_spu_runcntl_RW = + in_be32(&spu->problem->spu_runcntl_RW); + + tmp = spu_mfc_sr1_get(spu); + spu_info[i].saved_mfc_sr1_RW = tmp; + + tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; + spu_mfc_sr1_set(spu, tmp); + + sync(); + __delay(200); + + spu_info[i].stopped_ok = 1; + printf("Stopped spu %.2d\n", i); + } else { + catch_memory_errors = 0; + printf("*** Error stopping spu %.2d\n", i); + } + catch_memory_errors = 0; + } +} + +static void restart_spus(void) +{ + struct spu *spu; + int i; + + for (i = 0; i < XMON_NUM_SPUS; i++) { + if (!spu_info[i].spu) + continue; + + if (!spu_info[i].stopped_ok) { + printf("*** Error, spu %d was not successfully stopped" + ", not restarting\n", i); + continue; + } + + if (setjmp(bus_error_jmp) == 0) { + catch_memory_errors = 1; + sync(); + + spu = spu_info[i].spu; + spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); + out_be32(&spu->problem->spu_runcntl_RW, + spu_info[i].saved_spu_runcntl_RW); + + sync(); + __delay(200); + + printf("Restarted spu %.2d\n", i); + } else { + catch_memory_errors = 0; + printf("*** Error restarting spu %.2d\n", i); + } + catch_memory_errors = 0; + } +} + +static int do_spu_cmd(void) +{ + int cmd; + + cmd = inchar(); + switch (cmd) { + case 's': + stop_spus(); + break; + case 'r': + restart_spus(); + break; + default: + return -1; + } + + return 0; +} +#else /* ! CONFIG_PPC_CELL */ +static int do_spu_cmd(void) +{ + return -1; +} +#endif diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index f1d337e..88320a0 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h @@ -14,8 +14,10 @@ #ifdef CONFIG_XMON extern void xmon_setup(void); +extern void xmon_register_spus(struct list_head *list); #else static inline void xmon_setup(void) { }; +static inline void xmon_register_spus(struct list_head *list) { }; #endif #endif /* __KERNEL __ */ -- cgit v0.10.2 From a898497088f46252e6750405504064e2dce53117 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 24 Oct 2006 18:31:28 +0200 Subject: [POWERPC] add support for dumping spu info from xmon This patch adds a command to xmon for dumping information about spu structs. The command is 'sf' for "spu fields" perhaps, and takes the spu number as an argument. This is the same value as the spu->number field, or the "phys-id" value of a context when it is bound to a physical spu. We try to catch memory errors as we dump each field, hopefully this will make the command reasonably robust, but YMMV. If people see a need we can easily add more fields to the dump in future. Output looks something like this: 0:mon> sf 0 Dumping spu fields at address c00000001ffd9e80: number = 0x0 name = spe devnode->full_name = /cpus/PowerPC,BE@0/spes/spe@0 nid = 0x0 local_store_phys = 0x20000000000 local_store = 0xd0000800801e0000 ls_size = 0x0 isrc = 0x4 node = 0x0 flags = 0x0 dar = 0x0 dsisr = 0x0 class_0_pending = 0 irqs[0] = 0x16 irqs[1] = 0x17 irqs[2] = 0x24 slb_replace = 0x0 pid = 0 prio = 0 mm = 0x0000000000000000 ctx = 0x0000000000000000 rq = 0x0000000000000000 timestamp = 0x0000000000000000 problem_phys = 0x20000040000 problem = 0xd000080080220000 problem->spu_runcntl_RW = 0x0 problem->spu_status_R = 0x0 problem->spu_npc_RW = 0x0 priv1 = 0xd000080080240000 priv1->mfc_sr1_RW = 0x33 priv2 = 0xd000080080250000 Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 6a2ed8b..0689c08 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -216,7 +216,8 @@ Commands:\n\ s single step\n" #ifdef CONFIG_PPC_CELL " ss stop execution on all spus\n\ - sr restore execution on stopped spus\n" + sr restore execution on stopped spus\n\ + sf # dump spu fields for spu # (in hex)\n" #endif " S print special registers\n\ t print backtrace\n\ @@ -2744,8 +2745,66 @@ static void restart_spus(void) } } +#define DUMP_WIDTH 23 +#define DUMP_FIELD(obj, format, field) \ +do { \ + if (setjmp(bus_error_jmp) == 0) { \ + catch_memory_errors = 1; \ + sync(); \ + printf(" %-*s = "format"\n", DUMP_WIDTH, \ + #field, obj->field); \ + sync(); \ + __delay(200); \ + } else { \ + catch_memory_errors = 0; \ + printf(" %-*s = *** Error reading field.\n", \ + DUMP_WIDTH, #field); \ + } \ + catch_memory_errors = 0; \ +} while (0) + +static void dump_spu_fields(struct spu *spu) +{ + printf("Dumping spu fields at address %p:\n", spu); + + DUMP_FIELD(spu, "0x%x", number); + DUMP_FIELD(spu, "%s", name); + DUMP_FIELD(spu, "%s", devnode->full_name); + DUMP_FIELD(spu, "0x%x", nid); + DUMP_FIELD(spu, "0x%lx", local_store_phys); + DUMP_FIELD(spu, "0x%p", local_store); + DUMP_FIELD(spu, "0x%lx", ls_size); + DUMP_FIELD(spu, "0x%x", node); + DUMP_FIELD(spu, "0x%lx", flags); + DUMP_FIELD(spu, "0x%lx", dar); + DUMP_FIELD(spu, "0x%lx", dsisr); + DUMP_FIELD(spu, "%d", class_0_pending); + DUMP_FIELD(spu, "0x%lx", irqs[0]); + DUMP_FIELD(spu, "0x%lx", irqs[1]); + DUMP_FIELD(spu, "0x%lx", irqs[2]); + DUMP_FIELD(spu, "0x%x", slb_replace); + DUMP_FIELD(spu, "%d", pid); + DUMP_FIELD(spu, "%d", prio); + DUMP_FIELD(spu, "0x%p", mm); + DUMP_FIELD(spu, "0x%p", ctx); + DUMP_FIELD(spu, "0x%p", rq); + DUMP_FIELD(spu, "0x%p", timestamp); + DUMP_FIELD(spu, "0x%lx", problem_phys); + DUMP_FIELD(spu, "0x%p", problem); + DUMP_FIELD(spu, "0x%x", problem->spu_runcntl_RW); + DUMP_FIELD(spu, "0x%x", problem->spu_status_R); + DUMP_FIELD(spu, "0x%x", problem->spu_npc_RW); + DUMP_FIELD(spu, "0x%p", priv1); + + if (spu->priv1) + DUMP_FIELD(spu, "0x%lx", priv1->mfc_sr1_RW); + + DUMP_FIELD(spu, "0x%p", priv2); +} + static int do_spu_cmd(void) { + unsigned long num = 0; int cmd; cmd = inchar(); @@ -2756,6 +2815,12 @@ static int do_spu_cmd(void) case 'r': restart_spus(); break; + case 'f': + if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu) + dump_spu_fields(spu_info[num].spu); + else + printf("*** Error: invalid spu number\n"); + break; default: return -1; } -- cgit v0.10.2 From 36ca4ba4b9728f3c420a589a3322c2fbd7ec88b7 Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Tue, 24 Oct 2006 18:39:45 +0200 Subject: [POWERPC] cell: add cpufreq driver for Cell BE processor This patch adds a cpufreq backend driver to enable frequency scaling on cell. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 910a331..c5c54f4 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -139,7 +139,19 @@ CONFIG_RTAS_FLASH=y CONFIG_MMIO_NVRAM=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set -# CONFIG_CPU_FREQ is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPU_FREQ_PMAC64 is not set # CONFIG_WANT_EARLY_SERIAL is not set # CONFIG_MPIC is not set @@ -150,6 +162,7 @@ CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y CONFIG_CBE_THERM=m +CONFIG_CBE_CPUFREQ=m # # Kernel options diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 865b964..f8e44c0 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1672,6 +1672,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) } return NULL; } +EXPORT_SYMBOL(of_get_cpu_node); #ifdef DEBUG static struct debugfs_blob_wrapper flat_dt_blob; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 35c6309..9b28c23 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); +EXPORT_SYMBOL(cpu_sibling_map); /* SMP operations for this machine */ struct smp_ops_t *smp_ops; diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 77ae619..06a85b7 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -25,4 +25,13 @@ config CBE_THERM default m depends on CBE_RAS +config CBE_CPUFREQ + tristate "CBE frequency scaling" + depends on CBE_RAS && CPU_FREQ + default m + help + This adds the cpufreq driver for Cell BE processors. + For details, take a look at . + If you don't have such processor, say N + endmenu diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 90e1314..0f31db7 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_CBE_THERM) += cbe_thermal.o +obj-$(CONFIG_CBE_CPUFREQ) += cbe_cpufreq.o ifeq ($(CONFIG_SMP),y) obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c new file mode 100644 index 0000000..a3850fd --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -0,0 +1,248 @@ +/* + * cpufreq driver for the cell processor + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Christian Krafft + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "cbe_regs.h" + +static DEFINE_MUTEX(cbe_switch_mutex); + + +/* the CBE supports an 8 step frequency scaling */ +static struct cpufreq_frequency_table cbe_freqs[] = { + {1, 0}, + {2, 0}, + {3, 0}, + {4, 0}, + {5, 0}, + {6, 0}, + {8, 0}, + {10, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +/* to write to MIC register */ +static u64 MIC_Slow_Fast_Timer_table[] = { + [0 ... 7] = 0x007fc00000000000ull, +}; + +/* more values for the MIC */ +static u64 MIC_Slow_Next_Timer_table[] = { + 0x0000240000000000ull, + 0x0000268000000000ull, + 0x000029C000000000ull, + 0x00002D0000000000ull, + 0x0000300000000000ull, + 0x0000334000000000ull, + 0x000039C000000000ull, + 0x00003FC000000000ull, +}; + +/* + * hardware specific functions + */ + +static int get_pmode(int cpu) +{ + int ret; + struct cbe_pmd_regs __iomem *pmd_regs; + + pmd_regs = cbe_get_cpu_pmd_regs(cpu); + ret = in_be64(&pmd_regs->pmsr) & 0x07; + + return ret; +} + +static int set_pmode(int cpu, unsigned int pmode) +{ + struct cbe_pmd_regs __iomem *pmd_regs; + struct cbe_mic_tm_regs __iomem *mic_tm_regs; + u64 flags; + u64 value; + + local_irq_save(flags); + + mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu); + pmd_regs = cbe_get_cpu_pmd_regs(cpu); + + pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr); + pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0); + + out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]); + out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]); + + out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]); + out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]); + + value = in_be64(&pmd_regs->pmcr); + /* set bits to zero */ + value &= 0xFFFFFFFFFFFFFFF8ull; + /* set bits to next pmode */ + value |= pmode; + + out_be64(&pmd_regs->pmcr, value); + + /* wait until new pmode appears in status register */ + value = in_be64(&pmd_regs->pmsr) & 0x07; + while(value != pmode) { + cpu_relax(); + value = in_be64(&pmd_regs->pmsr) & 0x07; + } + + local_irq_restore(flags); + + return 0; +} + +/* + * cpufreq functions + */ + +static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) +{ + u32 *max_freq; + int i, cur_pmode; + struct device_node *cpu; + + cpu = of_get_cpu_node(policy->cpu, NULL); + + if(!cpu) + return -ENODEV; + + pr_debug("init cpufreq on CPU %d\n", policy->cpu); + + max_freq = (u32*) get_property(cpu, "clock-frequency", NULL); + + if(!max_freq) + return -EINVAL; + + // we need the freq in kHz + *max_freq /= 1000; + + pr_debug("max clock-frequency is at %u kHz\n", *max_freq); + pr_debug("initializing frequency table\n"); + + // initialize frequency table + for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { + cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index; + pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); + } + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + /* if DEBUG is enabled set_pmode() measures the correct latency of a transition */ + policy->cpuinfo.transition_latency = 25000; + + cur_pmode = get_pmode(policy->cpu); + pr_debug("current pmode is at %d\n",cur_pmode); + + policy->cur = cbe_freqs[cur_pmode].frequency; + +#ifdef CONFIG_SMP + policy->cpus = cpu_sibling_map[policy->cpu]; +#endif + + cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu); + + /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */ + return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs); +} + +static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static int cbe_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, cbe_freqs); +} + + +static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, + unsigned int relation) +{ + int rc; + struct cpufreq_freqs freqs; + int cbe_pmode_new; + + cpufreq_frequency_table_target(policy, + cbe_freqs, + target_freq, + relation, + &cbe_pmode_new); + + freqs.old = policy->cur; + freqs.new = cbe_freqs[cbe_pmode_new].frequency; + freqs.cpu = policy->cpu; + + mutex_lock (&cbe_switch_mutex); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", + policy->cpu, + cbe_freqs[cbe_pmode_new].frequency, + cbe_freqs[cbe_pmode_new].index); + + rc = set_pmode(policy->cpu, cbe_pmode_new); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + mutex_unlock(&cbe_switch_mutex); + + return rc; +} + +static struct cpufreq_driver cbe_cpufreq_driver = { + .verify = cbe_cpufreq_verify, + .target = cbe_cpufreq_target, + .init = cbe_cpufreq_cpu_init, + .exit = cbe_cpufreq_cpu_exit, + .name = "cbe-cpufreq", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, +}; + +/* + * module init and destoy + */ + +static int __init cbe_cpufreq_init(void) +{ + return cpufreq_register_driver(&cbe_cpufreq_driver); +} + +static void __exit cbe_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&cbe_cpufreq_driver); +} + +module_init(cbe_cpufreq_init); +module_exit(cbe_cpufreq_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Krafft "); -- cgit v0.10.2 From 6c50444723f2e6487b3377450f90d813a88e6c31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Oct 2006 13:34:11 -0700 Subject: [PATCH] Merge headphone and speaker volume controls for Panasonic R4 laptop Signed-off-by: Keith Packard Signed-off-by: Linus Torvalds diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 7f22dab..9c1bce7 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1962,6 +1962,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .type = AC97_TUNE_HP_ONLY }, { + .subvendor = 0x10f7, + .subdevice = 0x834c, + .name = "Panasonic CF-R4", + .type = AC97_TUNE_HP_ONLY, + }, + { .subvendor = 0x110a, .subdevice = 0x0056, .name = "Fujitsu-Siemens Scenic", /* AD1981? */ -- cgit v0.10.2 From 3a51237dc11efe283b40ea0248f4e26ab935dbd1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Oct 2006 11:15:29 +0100 Subject: [PATCH] uml: mconsole fixes * when we have stop/sysrq/go, we get pt_regs of whatever executes mc_work_proc(). Would be better to see what we had at the time of interrupt that got us stop. * stop/stop/stop..... will give stack overflow. Shouldn't allow stop from mconsole_stop(). * stop/stop/go leaves us inside mconsole_stop() with os_set_fd_block(req->originating_fd, 0); reactivate_fd(req->originating_fd, MCONSOLE_IRQ); just done by nested mconsole_stop(). Ditto. * once we'd seen stop, there's a period when INTR commands are executed out of order (as they should; we might have the things stuck badly enough to never reach mconsole_stop(), but still not badly enough to block mconsole_interrupt(); in that situation we _want_ things like "cad" to be executed immediately). Once we enter monsole_stop(), all INTR commands will be executed in order, mixed with PROC ones. We'd better let user see that such change of behaviour has happened. (Suggested by lennert). * stack footprint of monsole_interrupt() is an atrocity; AFAICS we can safely make struct mc_request req; static in function there. Signed-off-by: Al Viro Acked-by: Jeff Dike Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d08bd03..7b17216 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) /* long to avoid size mismatch warnings from gcc */ long fd; struct mconsole_entry *new; - struct mc_request req; + static struct mc_request req; /* that's OK */ fd = (long) dev_id; while (mconsole_get_request(fd, &req)){ @@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) mconsole_reply(&req, "Out of memory", 1, 0); else { new->request = req; + new->request.regs = get_irq_regs()->regs; list_add(&new->list, &mc_requests); } } @@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req) { deactivate_fd(req->originating_fd, MCONSOLE_IRQ); os_set_fd_block(req->originating_fd, 1); - mconsole_reply(req, "", 0, 0); - while(mconsole_get_request(req->originating_fd, req)){ - if(req->cmd->handler == mconsole_go) break; + mconsole_reply(req, "stopped", 0, 0); + while (mconsole_get_request(req->originating_fd, req)) { + if (req->cmd->handler == mconsole_go) + break; + if (req->cmd->handler == mconsole_stop) { + mconsole_reply(req, "Already stopped", 1, 0); + continue; + } + if (req->cmd->handler == mconsole_sysrq) { + struct pt_regs *old_regs; + old_regs = set_irq_regs((struct pt_regs *)&req->regs); + mconsole_sysrq(req); + set_irq_regs(old_regs); + continue; + } (*req->cmd->handler)(req); } os_set_fd_block(req->originating_fd, 0); @@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), static void sysrq_proc(void *arg) { char *op = arg; - struct pt_regs *old_regs = set_irq_regs(¤t->thread.regs); handle_sysrq(*op, NULL); - set_irq_regs(old_regs); } void mconsole_sysrq(struct mc_request *req) diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 17068eb..75aef6f 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -14,6 +14,7 @@ #include #include #include "user.h" +#include "sysdep/ptrace.h" #include "mconsole.h" #include "umid.h" #include "user_util.h" diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 58f67d3..2666815 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -61,6 +61,7 @@ struct mc_request struct mconsole_request request; struct mconsole_command *cmd; + union uml_pt_regs regs; }; extern char mconsole_socket_name[]; -- cgit v0.10.2 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 diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b6c045d..00db31c 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index ea16078..d1105e5 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 v0.10.2 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 diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 1c3c14a..79354bb 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 2bacff6..0fdc55b 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 v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e2ed249..e38846e 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 fee318e..133dcc8 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 f7e84e9..a64be6c 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 v0.10.2 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 diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index ef2581d..1ca1e9c 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 v0.10.2 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 diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 51ad98c..ba4b8de 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 v0.10.2 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 diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 029baea..6eafff1 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 v0.10.2 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 diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index eeeeff9..eae60f9 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 v0.10.2 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 diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index eae60f9..a958368 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 v0.10.2 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 diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 5ec5af8..3b3f305 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 e625b4c..d56d85d 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 834dab4..a1103b3 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 e8faab1..92def31 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 v0.10.2 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 diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c index e072535..2e7db18 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 8fd5555..2606264 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 v0.10.2 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 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3babdc7..e1a52c5 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 v0.10.2 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 diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index d03aa6c..fa5382e 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 v0.10.2 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 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 178fcdd..4fa0153 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index f8e6048..d8d6687 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 43ab753..ad8578e 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 v0.10.2 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 diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 90dad7e..5b12278 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 7da6983..b51ce8f 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 833b930..d5e0a12 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 3f20d76..34b6eb7 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 3e99dcf..d861c3b 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 2c803ed..1b221ff 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 ef82399..b721dc5 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 4fa0153..5b8db61 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 v0.10.2 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 diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index c537d71..a4afad4 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 e57bb03..1dd4917 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index bcd7fff..46eed10 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 v0.10.2 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 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 743f67e..d2c02df 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 v0.10.2 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 diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 1b53afb..3add7c2 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 v0.10.2 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 diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index a720c92..ac0419e 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 6a59876..21ebb92 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 v0.10.2 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 diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index b1d3460..f2d79c3 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 a88714f..625ca97 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 62e5c60..2f75fe6 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 d705773..ef593b7 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 v0.10.2 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 diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 22d1747..ca4e67a 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 c397c84..1ac6133 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 v0.10.2 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 diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 8f88269..74c0eac 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 4d2bc79..452d96f 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 v0.10.2 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 diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ee75a71..285c8e8 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 v0.10.2 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 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b51ce8f..ca2f660 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 d5e0a12..08cb5e3 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 34b6eb7..54f561d 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 v0.10.2 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 diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bab33f6..c4fc40f 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 ca2f660..32ebeec 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 626c717..d3b6df4 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 54f561d..208607b 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 v0.10.2 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 diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e57bf45..1fa0bce 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 v0.10.2 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 diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 669ea4f..fbc1d5c 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 v0.10.2 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 diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h index 14319d1..7b6aca0 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 99743ca..a4cc432 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 83574b5..de7c04d 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 v0.10.2 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 diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c0edb66..7bac86d 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 v0.10.2 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 diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e7fe565..e1a9166 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 v0.10.2 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 diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 41b05fc4..2a96424 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 v0.10.2 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 diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7b0019c..2d3baa9 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 39e8332..4b95c89 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 v0.10.2 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 diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c542d0e..1000fe9 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 401192e..61eebec 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 v0.10.2 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 diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1000fe9..e3a2ec2 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 v0.10.2 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 diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index e3a2ec2..f5a9560 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 v0.10.2 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 diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f5a9560..2865ebd 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 v0.10.2 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 diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 2521d54..16af5b7 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 v0.10.2 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 diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 9c0f358..30ee3d7 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 84a6d5f..8a3f0bd 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index df3346b..c58ac6a 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 653818d..6adcf79 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 d8d6687..77ef4d9 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 62ff8c3..4850820 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 93e4e409..46bd7bc 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 ad8578e..8eb1211 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index c58ac6a..b19a07c 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 6adcf79..7d53c64 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 a3266e0..2ceb67f 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 77ef4d9..5e13046 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 fb3d4dd..3a67fc5 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 4b53542..2001fe8 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 14850f3..c077358 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 c5f0ee5..6b28beb 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 4850820..5802f33 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 8eb1211..ed85057 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 a87a4ce..a36b338 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 d20ca51..ea5687d 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 63cab2d..09c8172 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index b19a07c..170a434 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 7d53c64..4c2b5a81 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 v0.10.2 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 diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 9496e87..2a4e02e 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 v0.10.2 From 4a531e8c79fe459e922347461ccc0f0c13de20d5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 20 Oct 2006 09:08:18 +0900 Subject: [SCSI] replace u8 and u32 with __u8 and __u32 in scsi.h for user space Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 8a3f0bd..5c0e979 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -433,7 +433,7 @@ struct scsi_lun { #define SCSI_IOCTL_GET_PCI 0x5387 /* Pull a u32 out of a SCSI message (using BE SCSI conventions) */ -static inline u32 scsi_to_u32(u8 *ptr) +static inline __u32 scsi_to_u32(__u8 *ptr) { return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3]; } -- cgit v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 4c2b5a81..07a86a3 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); @@ -7985,6 +8026,11 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) ahd_clear_fifo(ahd, 1); /* + * Clear SCSI interrupt status + */ + ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); + + /* * Reenable selections */ ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); @@ -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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 5e13046..e7a32f8 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 5802f33..954c7c2 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 46bd7bc..50ef785 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 ed85057..660f26e 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 a36b338..85ae5d8 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 5914b4a..99e5443 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 v0.10.2 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 diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index e7a32f8..9bfcca5 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 v0.10.2 From 190a24f5605d95b786c92280bf7a51ebef43f29f Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 25 Oct 2006 17:32:40 -0500 Subject: [POWERPC] Make sure __cpu_preinit_ppc970 gets called on 970GX processors Add check for 970GX for __cpu_preinit_ppc970. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index f12e3c5..291e362 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1641,6 +1641,8 @@ _GLOBAL(__start_initialization_multiplatform) cmpwi r0,0x3c /* 970FX */ beq 1f cmpwi r0,0x44 /* 970MP */ + beq 1f + cmpwi r0,0x45 /* 970GX */ bne 2f 1: bl .__cpu_preinit_ppc970 2: -- cgit v0.10.2 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 diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 7f5df9a..f8db6e3 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 v0.10.2 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 diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 686d895..f63909e 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 v0.10.2 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 diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 74cebd4..b9201c2 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 v0.10.2 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 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 74b3124..af392bf 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 v0.10.2 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 diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 82715f4..d316d95 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 c83a0a6..a70f97f 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 26229d9..9ced52a 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 v0.10.2 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 diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index d316d95..c2ea07a 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 v0.10.2 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 diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index d5dd0ce..5387de6 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 v0.10.2 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 diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index f8db6e3..3bcb7dc 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 5387de6..551bde5 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 e070a28..3b72be8 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 c8e838c..06bf7f4 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 v0.10.2 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 diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 3627e52..e433704 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 v0.10.2 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 diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 9ad18e6..310ede5 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 9ced52a..da471bd 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 v0.10.2 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 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index af392bf..0f70192 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 v0.10.2 From 0430fb20a2a9f06262cb5ccc98869d54cdaa3963 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:39 +0200 Subject: [PATCH] AVR32: Minor Makefile cleanup Don't generate listing by default, remove unused LIBGCC variable and rename generated disassembly and listing files to vmlinux.{s,lst}. Also make sure that files generated during the build are actually removed with make clean. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index cefc95a..7b842e9 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -7,7 +7,7 @@ # Default target when executing plain make .PHONY: all -all: uImage vmlinux.elf linux.lst +all: uImage vmlinux.elf KBUILD_DEFCONFIG := atstk1002_defconfig @@ -21,9 +21,7 @@ cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000 CFLAGS += $(cpuflags-y) AFLAGS += $(cpuflags-y) -CHECKFLAGS += -D__avr32__ - -LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +CHECKFLAGS += -D__avr32__ -D__BIG_ENDIAN head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o head-y += arch/avr32/kernel/head.o @@ -32,7 +30,7 @@ core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/ core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ core-y += arch/avr32/kernel/ core-y += arch/avr32/mm/ -libs-y += arch/avr32/lib/ #$(LIBGCC) +libs-y += arch/avr32/lib/ archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap @@ -48,6 +46,8 @@ endif archprepare: include/asm-avr32/.arch +CLEAN_FILES += include/asm-avr32/.arch include/asm-avr32/arch + BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec .PHONY: $(BOOT_TARGETS) install @@ -71,14 +71,19 @@ vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux install: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ -linux.s: vmlinux +vmlinux.s: vmlinux $(call if_changed,disasm) -linux.lst: vmlinux +vmlinux.lst: vmlinux $(call if_changed,listing) +CLEAN_FILES += vmlinux.s vmlinux.lst + +archclean: + $(Q)$(MAKE) $(clean)=$(boot) + define archhelp @echo '* vmlinux.elf - ELF image with load address 0' @echo ' vmlinux.cso - PathFinder CSO image' - @echo ' uImage - Create a bootable image for U-Boot' + @echo '* uImage - Create a bootable image for U-Boot' endef diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile index ccd74eee..219720a 100644 --- a/arch/avr32/boot/images/Makefile +++ b/arch/avr32/boot/images/Makefile @@ -37,14 +37,12 @@ OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \ --change-section-lma .data-0x80000000 \ --change-section-lma .init-0x80000000 \ --change-section-lma .bss-0x80000000 \ - --change-section-lma .initrd-0x80000000 \ --change-section-lma __param-0x80000000 \ --change-section-lma __ksymtab-0x80000000 \ --change-section-lma __ksymtab_gpl-0x80000000 \ --change-section-lma __kcrctab-0x80000000 \ --change-section-lma __kcrctab_gpl-0x80000000 \ --change-section-lma __ksymtab_strings-0x80000000 \ - --change-section-lma .got-0x80000000 \ --set-start 0xa0000000 $(obj)/vmlinux.elf: vmlinux FORCE $(call if_changed,objcopy) @@ -59,4 +57,4 @@ install: $(BOOTIMAGE) sh $(srctree)/install-kernel.sh $< # Generated files to be removed upon make clean -clean-files := vmlinux* uImage uImage.srec +clean-files := vmlinux.elf vmlinux.bin vmlinux.gz uImage uImage.srec -- cgit v0.10.2 From 6ea850b5eb17f6d21ac1b3d99406d213a10c64e9 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:40 +0200 Subject: [PATCH] AVR32: Silence some compile warnings Silence a few compile warnings which are basically harmless, but easy to fix. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index 6caf9e8..ca41fc1 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c @@ -109,7 +109,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) void *addr = (void *)regs->pc; int ret = 0; - pr_debug("kprobe_handler: kprobe_running=%d\n", + pr_debug("kprobe_handler: kprobe_running=%p\n", kprobe_running()); /* diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index dfc32f2..b599eae 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c @@ -263,7 +263,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, * value of PC. Just subtract the value of * GOT, and we're done. */ - pr_debug("GOTPC: PC=0x%lx, got_offset=0x%lx, core=0x%p\n", + pr_debug("GOTPC: PC=0x%x, got_offset=0x%lx, core=0x%p\n", relocation, module->arch.got_offset, module->module_core); relocation -= ((unsigned long)module->module_core @@ -282,7 +282,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, && (relocation & 0xffff0000) != 0xffff0000) return reloc_overflow(module, "R_AVR32_GOT16S", relocation); - pr_debug("GOT reloc @ 0x%lx -> %lu\n", + pr_debug("GOT reloc @ 0x%x -> %u\n", rel->r_offset, relocation); value = *location; value = ((value & 0xffff0000) diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 3c89e59..f2e81cd 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -157,7 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) unsigned long tmp; int ret; - pr_debug("arch_ptrace(%ld, %ld, %#lx, %#lx)\n", + pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n", request, child->pid, addr, data); pr_debug("ptrace: Enabling monitor mode...\n"); diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index 3e6c410..70da689 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c @@ -206,7 +206,7 @@ void __init setup_bootmem(void) if (mem_ramdisk) { #ifdef CONFIG_BLK_DEV_INITRD - initrd_start = __va(mem_ramdisk->addr); + initrd_start = (unsigned long)__va(mem_ramdisk->addr); initrd_end = initrd_start + mem_ramdisk->size; print_memory_map("RAMDISK images", mem_ramdisk); -- cgit v0.10.2 From bee8ce809fb1c877388be032b468574a1cfff9ef Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:41 +0200 Subject: [PATCH] AVR32: Don't try to iounmap P2 segment addresses While ioremap() will happily map a physical address through the P2 (uncached) segment when appropriate, iounmap() doesn't know how to handle those mappings. This patch makes iounmap() do the right thing, i.e. nothing, for such mappings. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c index 8cfec65..3437c82 100644 --- a/arch/avr32/mm/ioremap.c +++ b/arch/avr32/mm/ioremap.c @@ -77,6 +77,8 @@ void __iounmap(void __iomem *addr) if ((unsigned long)addr >= P4SEG) return; + if (PXSEG(addr) == P2SEG) + return; p = remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr)); if (unlikely(!p)) { -- cgit v0.10.2 From fa3522407f01ead1ec14bdd6b785ea08d17d500d Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:42 +0200 Subject: [PATCH] AVR32: Fix oversize immediates in atomic.h When calling e.g. atomic_sub_return with a large constant, the compiler may output an immediate that is too large for the sub instruction in the middle of the loop. Fix this by explicitly specifying the number of bits allowed in the constraint. Also stop atomic_add_return() and friends from falling back to their respective "sub" variants if the constant is too large to fit in an immediate. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/include/asm-avr32/atomic.h b/include/asm-avr32/atomic.h index e0b9c44..c40b603 100644 --- a/include/asm-avr32/atomic.h +++ b/include/asm-avr32/atomic.h @@ -41,7 +41,7 @@ static inline int atomic_sub_return(int i, atomic_t *v) " stcond %1, %0\n" " brne 1b" : "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "ir"(i) + : "m"(v->counter), "rKs21"(i) : "cc"); return result; @@ -58,7 +58,7 @@ static inline int atomic_add_return(int i, atomic_t *v) { int result; - if (__builtin_constant_p(i)) + if (__builtin_constant_p(i) && (i >= -1048575) && (i <= 1048576)) result = atomic_sub_return(-i, v); else asm volatile( @@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u) " mov %1, 1\n" "1:" : "=&r"(tmp), "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "ir"(a), "ir"(u) + : "m"(v->counter), "rKs21"(a), "rKs21"(u) : "cc", "memory"); return result; @@ -121,7 +121,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) { int tmp, result; - if (__builtin_constant_p(a)) + if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576)) result = atomic_sub_unless(v, -a, u); else { result = 0; -- cgit v0.10.2 From 065834ab3988fece5608088e83724891c8190a2f Mon Sep 17 00:00:00 2001 From: Ben Nizette Date: Tue, 24 Oct 2006 10:12:43 +0200 Subject: [PATCH] AVR32: add io{read,write}{8,16,32}{be,} support A number of new drivers require io{read,write}{8,16,32}{be,} family of io operations. These are provided for the AVR32 by this patch in the form of a series of macros. Access to the (memory mapped) io space through these macros is defined to be little endian only as little endian devices (such as PCI) are the main consumer of IO access. If high speed access is required, io{read,write}{16,32}be macros are supplied to perform native big endian access to this io space. Signed-off-by: Ben Nizette Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/include/asm-avr32/io.h b/include/asm-avr32/io.h index 2fc8f11..eec4750 100644 --- a/include/asm-avr32/io.h +++ b/include/asm-avr32/io.h @@ -76,6 +76,39 @@ static inline unsigned int readl(const volatile void __iomem *addr) #define readsw(p, d, l) __raw_readsw((unsigned int)p, d, l) #define readsl(p, d, l) __raw_readsl((unsigned int)p, d, l) + +/* + * io{read,write}{8,16,32} macros in both le (for PCI style consumers) and native be + */ +#ifndef ioread8 + +#define ioread8(p) ({ unsigned int __v = __raw_readb(p); __v; }) + +#define ioread16(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; }) +#define ioread16be(p) ({ unsigned int __v = be16_to_cpu(__raw_readw(p)); __v; }) + +#define ioread32(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; }) +#define ioread32be(p) ({ unsigned int __v = be32_to_cpu(__raw_readl(p)); __v; }) + +#define iowrite8(v,p) __raw_writeb(v, p) + +#define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p) +#define iowrite16be(v,p) __raw_writew(cpu_to_be16(v), p) + +#define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p) +#define iowrite32be(v,p) __raw_writel(cpu_to_be32(v), p) + +#define ioread8_rep(p,d,c) __raw_readsb(p,d,c) +#define ioread16_rep(p,d,c) __raw_readsw(p,d,c) +#define ioread32_rep(p,d,c) __raw_readsl(p,d,c) + +#define iowrite8_rep(p,s,c) __raw_writesb(p,s,c) +#define iowrite16_rep(p,s,c) __raw_writesw(p,s,c) +#define iowrite32_rep(p,s,c) __raw_writesl(p,s,c) + +#endif + + /* * These two are only here because ALSA _thinks_ it needs them... */ -- cgit v0.10.2 From d68041cc9fde550fe6b6a6de1d7a110daff3cb60 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:44 +0200 Subject: [PATCH] AVR32: Implement and export __raw_{read,write}s[bwl] Implement __raw_readsb and __raw_writesb. Export __raw_reads[bwl] and __raw_writes[bwl] for use by modules. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 04f767a..372e3f8 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include @@ -53,3 +54,11 @@ EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); EXPORT_SYMBOL(generic_find_next_zero_le_bit); + +/* I/O primitives (lib/io-*.S) */ +EXPORT_SYMBOL(__raw_readsb); +EXPORT_SYMBOL(__raw_readsw); +EXPORT_SYMBOL(__raw_readsl); +EXPORT_SYMBOL(__raw_writesb); +EXPORT_SYMBOL(__raw_writesw); +EXPORT_SYMBOL(__raw_writesl); diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile index 09ac43e..084d95b 100644 --- a/arch/avr32/lib/Makefile +++ b/arch/avr32/lib/Makefile @@ -7,4 +7,5 @@ lib-y += strncpy_from_user.o strnlen_user.o lib-y += delay.o memset.o memcpy.o findbit.o lib-y += csum_partial.o csum_partial_copy_generic.o lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o +lib-y += io-readsb.o io-writesb.o lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o diff --git a/arch/avr32/lib/io-readsb.S b/arch/avr32/lib/io-readsb.S new file mode 100644 index 0000000..b319d5e --- /dev/null +++ b/arch/avr32/lib/io-readsb.S @@ -0,0 +1,47 @@ +/* + * 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. + */ + + .text +.Lnot_word_aligned: +1: ld.ub r8, r12[0] + sub r10, 1 + st.b r11++, r8 + reteq r12 + tst r11, r9 + brne 1b + + /* fall through */ + + .global __raw_readsb + .type __raw_readsb,@function +__raw_readsb: + cp.w r10, 0 + mov r9, 3 + reteq r12 + + tst r11, r9 + brne .Lnot_word_aligned + + sub r10, 4 + brlt 2f + +1: ldins.b r8:t, r12[0] + ldins.b r8:u, r12[0] + ldins.b r8:l, r12[0] + ldins.b r8:b, r12[0] + st.w r11++, r8 + sub r10, 4 + brge 1b + +2: sub r10, -4 + reteq r12 + +3: ld.uh r8, r12[0] + sub r10, 1 + st.b r11++, r8 + brne 3b diff --git a/arch/avr32/lib/io-writesb.S b/arch/avr32/lib/io-writesb.S new file mode 100644 index 0000000..b4ebaac --- /dev/null +++ b/arch/avr32/lib/io-writesb.S @@ -0,0 +1,52 @@ +/* + * 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. + */ + + .text +.Lnot_word_aligned: +1: ld.ub r8, r11++ + sub r10, 1 + st.b r12[0], r8 + reteq r12 + tst r11, r9 + brne 1b + + /* fall through */ + + .global __raw_writesb + .type __raw_writesb,@function +__raw_writesb: + cp.w r10, 0 + mov r9, 3 + reteq r12 + + tst r11, r9 + brne .Lnot_word_aligned + + sub r10, 4 + brlt 2f + +1: ld.w r8, r11++ + bfextu r9, r8, 24, 8 + st.b r12[0], r9 + bfextu r9, r8, 16, 8 + st.b r12[0], r9 + bfextu r9, r8, 8, 8 + st.b r12[0], r9 + st.b r12[0], r8 + sub r10, 4 + brge 1b + +2: sub r10, -4 + reteq r12 + +3: ld.ub r8, r11++ + sub r10, 1 + st.b r12[0], r8 + brne 3b + + retal r12 -- cgit v0.10.2 From 452976b29864f9adcdd6d4ea81001aa5483592c2 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:45 +0200 Subject: [PATCH] AVR32: Use __raw MMIO access for internal peripherals The read[bwl] and write[bwl] functions are meant for accessing PCI devices. How this is achieved on AVR32 is unknown, as there are no systems with a PCI bridge available yet. On-chip peripheral access, however, should not depend on how we end up implementing PCI access, so using __raw_read[bwl]/__raw_write[bwl] is the right thing to do for on-chip peripherals. This patch converts the drivers for the static memory controller, interrupt controller, PIO controller and system manager to use __raw MMIO access. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/mach-at32ap/hsmc.h b/arch/avr32/mach-at32ap/hsmc.h index 5681276..d1d48e2 100644 --- a/arch/avr32/mach-at32ap/hsmc.h +++ b/arch/avr32/mach-at32ap/hsmc.h @@ -120,8 +120,8 @@ /* Register access macros */ #define hsmc_readl(port,reg) \ - readl((port)->regs + HSMC_##reg) + __raw_readl((port)->regs + HSMC_##reg) #define hsmc_writel(port,reg,value) \ - writel((value), (port)->regs + HSMC_##reg) + __raw_writel((value), (port)->regs + HSMC_##reg) #endif /* __ASM_AVR32_HSMC_H__ */ diff --git a/arch/avr32/mach-at32ap/intc.h b/arch/avr32/mach-at32ap/intc.h index d289ca2..4d3664e 100644 --- a/arch/avr32/mach-at32ap/intc.h +++ b/arch/avr32/mach-at32ap/intc.h @@ -321,7 +321,9 @@ #define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET) #define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1)) -#define intc_readl(port,reg) readl((port)->regs + INTC_##reg) -#define intc_writel(port,reg,value) writel((value), (port)->regs + INTC_##reg) +#define intc_readl(port,reg) \ + __raw_readl((port)->regs + INTC_##reg) +#define intc_writel(port,reg,value) \ + __raw_writel((value), (port)->regs + INTC_##reg) #endif /* __ASM_AVR32_PERIHP_INTC_H__ */ diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h index cfea123..50fa3ac 100644 --- a/arch/avr32/mach-at32ap/pio.h +++ b/arch/avr32/mach-at32ap/pio.h @@ -170,8 +170,10 @@ #define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value)) /* Register access macros */ -#define pio_readl(port,reg) readl((port)->regs + PIO_##reg) -#define pio_writel(port,reg,value) writel((value), (port)->regs + PIO_##reg) +#define pio_readl(port,reg) \ + __raw_readl((port)->regs + PIO_##reg) +#define pio_writel(port,reg,value) \ + __raw_writel((value), (port)->regs + PIO_##reg) void at32_init_pio(struct platform_device *pdev); diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h index 2756582..cad02b5 100644 --- a/arch/avr32/mach-at32ap/sm.h +++ b/arch/avr32/mach-at32ap/sm.h @@ -234,7 +234,9 @@ #define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value)) /* Register access macros */ -#define sm_readl(port,reg) readl((port)->regs + SM_##reg) -#define sm_writel(port,reg,value) writel((value), (port)->regs + SM_##reg) +#define sm_readl(port,reg) \ + __raw_readl((port)->regs + SM_##reg) +#define sm_writel(port,reg,value) \ + __raw_writel((value), (port)->regs + SM_##reg) #endif /* __ASM_AVR32_SM_H__ */ -- cgit v0.10.2 From 291b58d663862c3d42d2e8092f8b0dd3f15a94f8 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 24 Oct 2006 10:12:46 +0200 Subject: [PATCH] AVR32: Update defconfig Sync atstk1002_defconfig with latest git, turn off non-existent drivers and enable a few more userspace-visible options like SysV IPC and inotify support. Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig index 6c2c5e0..ae92a14 100644 --- a/arch/avr32/configs/atstk1002_defconfig +++ b/arch/avr32/configs/atstk1002_defconfig @@ -1,13 +1,14 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Tue Jul 11 12:41:36 2006 +# Linux kernel version: 2.6.19-rc2 +# Fri Oct 20 11:52:37 2006 # CONFIG_AVR32=y CONFIG_GENERIC_HARDIRQS=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_TIME=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -25,16 +26,23 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +# CONFIG_UTS_NS is not set +CONFIG_AUDIT=y # CONFIG_IKCONFIG is not set -# CONFIG_RELAY is not set +CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_TASK_XACCT is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -43,14 +51,15 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y # CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y CONFIG_SHMEM=y -# CONFIG_SLAB is not set -# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=1 -CONFIG_SLOB=y +# CONFIG_SLOB is not set # # Loadable module support @@ -65,6 +74,7 @@ CONFIG_MODULE_UNLOAD=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # @@ -166,10 +176,12 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_TUNNEL is not set # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -199,7 +211,6 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -212,7 +223,6 @@ CONFIG_TCP_CONG_BIC=y # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_TCPPROBE is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -239,7 +249,84 @@ CONFIG_STANDALONE=y # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set # # Parallel port support @@ -260,11 +347,18 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set @@ -274,6 +368,12 @@ CONFIG_BLK_DEV_INITRD=y # # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set # # Multi-device support (RAID and LVM) @@ -305,14 +405,11 @@ CONFIG_TUN=m # # PHY device support # -# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) # -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_MACB=y +# CONFIG_NET_ETHERNET is not set # # Ethernet (1000 Mbit) @@ -341,10 +438,11 @@ CONFIG_PPP=m CONFIG_PPP_ASYNC=m # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_BSDCOMP=m # CONFIG_PPP_MPPE is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set @@ -417,7 +515,6 @@ CONFIG_UNIX98_PTYS=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -427,23 +524,13 @@ CONFIG_UNIX98_PTYS=y # # SPI support # -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -CONFIG_SPI_ATMEL=m -# CONFIG_SPI_BITBANG is not set - -# -# SPI Protocol Masters -# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -452,14 +539,9 @@ CONFIG_SPI_ATMEL=m # CONFIG_HWMON_VID is not set # -# Misc devices -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -470,28 +552,8 @@ CONFIG_VIDEO_V4L2=y # Graphics support # # CONFIG_FIRMWARE_EDID is not set -CONFIG_FB=m -CONFIG_FB_CFB_FILLRECT=m -CONFIG_FB_CFB_COPYAREA=m -CONFIG_FB_CFB_IMAGEBLIT=m -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set -CONFIG_FB_SIDSA=m -CONFIG_FB_SIDSA_DEFAULT_BPP=24 -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set -CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_BACKLIGHT_CLASS_DEVICE is not set -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_DEVICE=y -CONFIG_LCD_LTV350QV=m +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -561,18 +623,21 @@ CONFIG_LCD_LTV350QV=m # # File systems # -CONFIG_EXT2_FS=y +CONFIG_EXT2_FS=m # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set CONFIG_MINIX_FS=m -CONFIG_ROMFS_FS=m -# CONFIG_INOTIFY is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set @@ -600,8 +665,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y CONFIG_CONFIGFS_FS=m @@ -616,6 +683,16 @@ CONFIG_CONFIGFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -626,26 +703,10 @@ CONFIG_CONFIGFS_FS=m # # Network File Systems # -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFS_FS is not set # CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_WEAK_PW_HASH is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_DEBUG2 is not set -# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -665,7 +726,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_850 is not set # CONFIG_NLS_CODEPAGE_852 is not set # CONFIG_NLS_CODEPAGE_855 is not set # CONFIG_NLS_CODEPAGE_857 is not set @@ -705,13 +766,17 @@ CONFIG_NLS_UTF8=m # Kernel hacking # CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RWSEMS is not set @@ -722,11 +787,13 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FRAME_POINTER=y # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set -CONFIG_KPROBES=y +# CONFIG_KPROBES is not set # # Security options @@ -740,15 +807,13 @@ CONFIG_KPROBES=y # CONFIG_CRYPTO is not set # -# Hardware crypto devices -# - -# # Library routines # CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set -CONFIG_CRC32=m +CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y -- cgit v0.10.2 From 4130a4b206e7c628482aa12ec30949382c8cdc5e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 25 Oct 2006 22:31:06 -0700 Subject: [SPARC64]: Fix central/FHC bus handling on Ex000 systems. 1) probe_other_fhcs() wants to see only non-central FHC busses, so skip FHCs that don't sit off the root 2) Like SBUS, FHC can lack the appropriate address and size cell count properties, so add an of_busses[] entry and handlers for that. 3) Central FHC irq translator probing was buggy. We were trying to use dp->child in irq_trans_init but that linkage is not setup at this point. So instead, pass in the parent of "dp" and look for the child "fhc" with parent "central". Thanks to the tireless assistence of Ben Collins in tracking down these problems and testing out these fixes. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index b66336d..e724c54 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -126,6 +126,10 @@ static void probe_other_fhcs(void) int board; u32 tmp; + if (dp->parent && + dp->parent->parent != NULL) + continue; + fhc = (struct linux_fhc *) central_alloc_bootmem(sizeof(struct linux_fhc)); if (fhc == NULL) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index d3dfb2a..983ca5f 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -402,16 +402,22 @@ static void of_bus_sbus_count_cells(struct device_node *child, *sizec = 1; } -static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) -{ - return of_bus_default_map(addr, range, na, ns, pna); -} - -static unsigned int of_bus_sbus_get_flags(u32 *addr) +/* + * FHC/Central bus specific translator. + * + * This is just needed to hard-code the address and size cell + * counts. 'fhc' and 'central' nodes lack the #address-cells and + * #size-cells properties, and if you walk to the root on such + * Enterprise boxes all you'll get is a #size-cells of 2 which is + * not what we want to use. + */ +static int of_bus_fhc_match(struct device_node *np) { - return IORESOURCE_MEM; + return !strcmp(np->name, "fhc") || + !strcmp(np->name, "central"); } +#define of_bus_fhc_count_cells of_bus_sbus_count_cells /* * Array of bus specific translators @@ -433,8 +439,17 @@ static struct of_bus of_busses[] = { .addr_prop_name = "reg", .match = of_bus_sbus_match, .count_cells = of_bus_sbus_count_cells, - .map = of_bus_sbus_map, - .get_flags = of_bus_sbus_get_flags, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, + /* FHC */ + { + .name = "fhc", + .addr_prop_name = "reg", + .match = of_bus_fhc_match, + .count_cells = of_bus_fhc_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, }, /* Default */ { diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index e21cd6a..c60efb3 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1079,23 +1079,22 @@ static void sun4v_vdev_irq_trans_init(struct device_node *dp) static void irq_trans_init(struct device_node *dp) { - const char *model; #ifdef CONFIG_PCI + const char *model; int i; #endif +#ifdef CONFIG_PCI model = of_get_property(dp, "model", NULL); if (!model) model = of_get_property(dp, "compatible", NULL); - if (!model) - return; - -#ifdef CONFIG_PCI - for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { - struct irq_trans *t = &pci_irq_trans_table[i]; + if (model) { + for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { + struct irq_trans *t = &pci_irq_trans_table[i]; - if (!strcmp(model, t->name)) - return t->init(dp); + if (!strcmp(model, t->name)) + return t->init(dp); + } } #endif #ifdef CONFIG_SBUS @@ -1103,8 +1102,9 @@ static void irq_trans_init(struct device_node *dp) !strcmp(dp->name, "sbi")) return sbus_irq_trans_init(dp); #endif - if (!strcmp(dp->name, "central")) - return central_irq_trans_init(dp->child); + if (!strcmp(dp->name, "fhc") && + !strcmp(dp->parent->name, "central")) + return central_irq_trans_init(dp); if (!strcmp(dp->name, "virtual-devices")) return sun4v_vdev_irq_trans_init(dp); } @@ -1516,7 +1516,7 @@ static char * __init get_one_property(phandle node, const char *name) return buf; } -static struct device_node * __init create_node(phandle node) +static struct device_node * __init create_node(phandle node, struct device_node *parent) { struct device_node *dp; @@ -1525,6 +1525,7 @@ static struct device_node * __init create_node(phandle node) dp = prom_early_alloc(sizeof(*dp)); dp->unique_id = unique_id++; + dp->parent = parent; kref_init(&dp->kref); @@ -1543,12 +1544,11 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl { struct device_node *dp; - dp = create_node(node); + dp = create_node(node, parent); if (dp) { *(*nextp) = dp; *nextp = &dp->allnext; - dp->parent = parent; dp->path_component_name = build_path_component(dp); dp->full_name = build_full_name(dp); @@ -1564,7 +1564,7 @@ void __init prom_build_devicetree(void) { struct device_node **nextp; - allnodes = create_node(prom_root_node); + allnodes = create_node(prom_root_node, NULL); allnodes->path_component_name = ""; allnodes->full_name = "/"; -- cgit v0.10.2 From 012d64ff68f304df1c35ce5902f5023dc14b643f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 25 Oct 2006 22:33:07 -0700 Subject: [SPARC64]: Fix memory corruption in pci_4u_free_consistent(). The second argument to free_npages() was being incorrectly calculated, which would thus access far past the end of the arena->map[] bitmap. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 82e5455..2e7f142 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -281,7 +281,7 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, spin_lock_irqsave(&iommu->lock, flags); - free_npages(iommu, dvma, npages); + free_npages(iommu, dvma - iommu->page_table_map_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); -- cgit v0.10.2 From 22119240b1c8f64eebb6ffb368c927b2f8be4136 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 25 Oct 2006 23:04:12 -0700 Subject: [TCP] cubic: scaling error Doug Leith observed a discrepancy between the version of CUBIC described in the papers and the version in 2.6.18. A math error related to scaling causes Cubic to grow too slowly. Patch is from "Sangtae Ha" . I validated that it does fix the problems. See the following to show behavior over 500ms 100 Mbit link. Sender (2.6.19-rc3) --- Bridge (2.6.18-rt7) ------- Receiver (2.6.19-rc3) 1G [netem] 100M http://developer.osdl.org/shemminger/tcp/2.6.19-rc3/cubic-orig.png http://developer.osdl.org/shemminger/tcp/2.6.19-rc3/cubic-fix.png Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index a60ef38..6ad1848 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -190,7 +190,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) */ /* change the unit from HZ to bictcp_HZ */ - t = ((tcp_time_stamp + ca->delay_min - ca->epoch_start) + t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start) << BICTCP_HZ) / HZ; if (t < ca->bic_K) /* t - K */ @@ -259,7 +259,7 @@ static inline void measure_delay(struct sock *sk) (s32)(tcp_time_stamp - ca->epoch_start) < HZ) return; - delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr; + delay = (tcp_time_stamp - tp->rx_opt.rcv_tsecr)<<3; if (delay == 0) delay = 1; @@ -366,7 +366,7 @@ static int __init cubictcp_register(void) beta_scale = 8*(BICTCP_BETA_SCALE+beta)/ 3 / (BICTCP_BETA_SCALE - beta); - cube_rtt_scale = (bic_scale << 3) / 10; /* 1024*c/rtt */ + cube_rtt_scale = (bic_scale * 10); /* 1024*c/rtt */ /* calculate the "K" for (wmax-cwnd) = c/rtt * K^3 * so K = cubic_root( (wmax-cwnd)*rtt/c ) -- cgit v0.10.2 From 2a272f98619f188efe22119b0415aac6bc34a13f Mon Sep 17 00:00:00 2001 From: Gavin McCullagh Date: Wed, 25 Oct 2006 23:05:52 -0700 Subject: [TCP] H-TCP: fix integer overflow When using H-TCP with a single flow on a 500Mbit connection (or less actually), alpha can exceed 65000, so alpha needs to be a u32. Signed-off-by: Gavin McCullagh Signed-off-by: Doug Leith Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 682e7d5..283be3c 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -23,7 +23,7 @@ module_param(use_bandwidth_switch, int, 0644); MODULE_PARM_DESC(use_bandwidth_switch, "turn on/off bandwidth switcher"); struct htcp { - u16 alpha; /* Fixed point arith, << 7 */ + u32 alpha; /* Fixed point arith, << 7 */ u8 beta; /* Fixed point arith, << 7 */ u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */ u32 last_cong; /* Time since last congestion event end */ -- cgit v0.10.2 From 1842c4bef61f985fbec6df7150041b85d8b52b1a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 25 Oct 2006 23:07:37 -0700 Subject: [BRIDGE]: correct print message typo Correct message typo/spello. Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 96bcb2f..de9d1a9 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -376,7 +376,7 @@ int br_sysfs_addbr(struct net_device *dev) err = sysfs_create_bin_file(brobj, &bridge_forward); if (err) { - pr_info("%s: can't create attribue file %s/%s\n", + pr_info("%s: can't create attribute file %s/%s\n", __FUNCTION__, dev->name, bridge_forward.attr.name); goto out2; } -- cgit v0.10.2 From f2454a1a4b2aca38d3b7887619f43291d773c1ee Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Wed, 25 Oct 2006 05:49:53 -0400 Subject: [IA64] don't double >> PAGE_SHIFT pointer for /dev/kmem access Don't PAGE_SHIFT pointer before handing it to virt_to_page() in xlate_dev_kmem_ptr() as it results in a double shift. Spotted by Bob Montgomery. Signed-off-by: Jes Sorensen Signed-off-by: Tony Luck diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h index 9adb512..449c8c0 100644 --- a/include/asm-ia64/uaccess.h +++ b/include/asm-ia64/uaccess.h @@ -389,7 +389,7 @@ xlate_dev_kmem_ptr (char * p) struct page *page; char * ptr; - page = virt_to_page((unsigned long)p >> PAGE_SHIFT); + page = virt_to_page((unsigned long)p); if (PageUncached(page)) ptr = (char *)__pa(p) + __IA64_UNCACHED_OFFSET; else -- cgit v0.10.2 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 diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 75ac24d..ba58c3a 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 74bef2a..46200c4 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 2df25c2..35bf895 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 0f3aec7..f028e68 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 983ca5f..8cc14fc 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 935952e..98fcbb3 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 v0.10.2 From f4880391860f2e38bb6ff400a0bd6c85443c5b9e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 27 Oct 2006 12:39:10 +0200 Subject: [S390] sys_getcpu compat wrapper. Looking at the new syscall additions, I noticed that sys_getcpu_wrapper wraps in to sys_tee, in what appears to be a copy and paste error. Switch it to point to sys_getcpu.. Signed-off-by: Paul Mundt Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index cb0efae..71e54ef 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1664,4 +1664,4 @@ sys_getcpu_wrapper: llgtr %r2,%r2 # unsigned * llgtr %r3,%r3 # unsigned * llgtr %r4,%r4 # struct getcpu_cache * - jg sys_tee + jg sys_getcpu -- cgit v0.10.2 From 95425f19beed99cb9b0a79f69731eda907d9db99 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Fri, 27 Oct 2006 12:39:13 +0200 Subject: [S390] Initialize interval value to 0. sscanf() could leave the interval value unchanged in which case it would be used uninitialized. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 45c9fa7..af1e8fc 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -310,6 +310,7 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp, if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) { return -EFAULT; } + interval = 0; sscanf(buf, "%i", &interval); if (interval <= 0) { P_ERROR("Timer CPU interval has to be > 0!\n"); -- cgit v0.10.2 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 diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index a2dee5b..ad7f7e1 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 v0.10.2 From 12bae23507129a7337378e6433bff6f8696bdb45 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 27 Oct 2006 12:39:22 +0200 Subject: [S390] uaccess error handling. Consider return values for all user space access function and return -EFAULT on error. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 2001767..5b33f82 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -757,7 +757,9 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp))) error = -EFAULT; } - copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); + if (copy_to_user(args->__unused, tmp.__unused, + sizeof(tmp.__unused))) + error = -EFAULT; } return error; } diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index d49b876..861888a 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -169,12 +169,12 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act, compat_old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(sa_handler, &act->sa_handler) || - __get_user(sa_restorer, &act->sa_restorer)) + __get_user(sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; new_ka.sa.sa_handler = (__sighandler_t) sa_handler; new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -185,10 +185,10 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act, sa_restorer = (unsigned long) old_ka.sa.sa_restorer; if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(sa_handler, &oact->sa_handler) || - __put_user(sa_restorer, &oact->sa_restorer)) + __put_user(sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 4392a77..4c8a795 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -80,10 +80,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -92,10 +92,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 66375a5..92ecffb 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -462,7 +462,8 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) local_irq_enable(); if (regs->psw.mask & PSW_MASK_PSTATE) { - get_user(*((__u16 *) opcode), (__u16 __user *) location); + if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + return; if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { if (current->ptrace & PT_PTRACED) force_sig(SIGTRAP, current); @@ -470,20 +471,25 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) signal = SIGILL; #ifdef CONFIG_MATHEMU } else if (opcode[0] == 0xb3) { - get_user(*((__u16 *) (opcode+2)), location+1); + if (get_user(*((__u16 *) (opcode+2)), location+1)) + return; signal = math_emu_b3(opcode, regs); } else if (opcode[0] == 0xed) { - get_user(*((__u32 *) (opcode+2)), - (__u32 __user *)(location+1)); + if (get_user(*((__u32 *) (opcode+2)), + (__u32 __user *)(location+1))) + return; signal = math_emu_ed(opcode, regs); } else if (*((__u16 *) opcode) == 0xb299) { - get_user(*((__u16 *) (opcode+2)), location+1); + if (get_user(*((__u16 *) (opcode+2)), location+1)) + return; signal = math_emu_srnm(opcode, regs); } else if (*((__u16 *) opcode) == 0xb29c) { - get_user(*((__u16 *) (opcode+2)), location+1); + if (get_user(*((__u16 *) (opcode+2)), location+1)) + return; signal = math_emu_stfpc(opcode, regs); } else if (*((__u16 *) opcode) == 0xb29d) { - get_user(*((__u16 *) (opcode+2)), location+1); + if (get_user(*((__u16 *) (opcode+2)), location+1)) + return; signal = math_emu_lfpc(opcode, regs); #endif } else -- cgit v0.10.2 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 diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index c5ccd20..79d89c3 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 v0.10.2 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 diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 94bdd4d..39c98f9 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 c6140cc..9233b5c 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c44311a..16167b0 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 v0.10.2 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 diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 908b410..c1949ff 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -343,6 +343,61 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_ro 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. * * We pretend to bring them out of full D3 state, and restore the proper diff --git a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile index e66889e..fb14dc5 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 0000000..245dc1f --- /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 e8a7f1b..687ab4a 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 43e4a49..e1dcefc 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 v0.10.2 From 3095fc0c9772b4afb3c81f76664f341ef716d380 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 20 Oct 2006 14:45:33 -0700 Subject: PCI: x86-64: mmconfig missing printk levels Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index 7732f42..e61093b 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -220,7 +220,7 @@ void __init pci_mmcfg_init(int type) pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); if (pci_mmcfg_virt == NULL) { - printk("PCI: Can not allocate memory for mmconfig structures\n"); + printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); return; } for (i = 0; i < pci_mmcfg_config_num; ++i) { @@ -228,7 +228,8 @@ void __init pci_mmcfg_init(int type) pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_MAX); if (!pci_mmcfg_virt[i].virt) { - printk("PCI: Cannot map mmconfig aperture for segment %d\n", + printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " + "segment %d\n", pci_mmcfg_config[i].pci_segment_group_number); return; } -- cgit v0.10.2 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 diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b1c0c70..194f1d2 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -265,6 +265,13 @@ static int pci_device_remove(struct device * dev) } /* + * 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 * unfortunate fact is there are too many odd BIOS and bridge setups @@ -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 v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 687ab4a..204b1c8 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 v0.10.2 From 61ce1efe6e40233663d27ab8ac9ba9710eebcaad Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 27 Oct 2006 11:41:44 -0700 Subject: [PATCH] vmlinux.lds: consolidate initcall sections Add a vmlinux.lds.h helper macro for defining the eight-level initcall table, teach all the architectures to use it. This is a prerequisite for a patch which performs initcall synchronisation for multithreaded-probing. Cc: Greg KH Signed-off-by: Andrew Morton [ Added AVR32 as well ] Signed-off-by: Haavard Skinnemoen Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 71470e9..76bf071 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -48,13 +48,7 @@ SECTIONS . = ALIGN(8); __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 3ca574e..a8fa75e 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -45,13 +45,7 @@ SECTIONS *(.early_param.init) __early_end = .; __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS __initcall_end = .; __con_initcall_start = .; *(.con_initcall.init) diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c index cdd627c..5c4424e 100644 --- a/arch/avr32/kernel/vmlinux.lds.c +++ b/arch/avr32/kernel/vmlinux.lds.c @@ -38,13 +38,7 @@ SECTIONS __setup_end = .; . = ALIGN(4); __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS __initcall_end = .; __con_initcall_start = .; *(.con_initcall.init) diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index f474534..9c1fb12 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -44,13 +44,7 @@ SECTIONS __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index 6406c38..756325d 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S @@ -118,13 +118,7 @@ SECTIONS . = ALIGN(0x4) ; ___setup_end = .; ___initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS ___initcall_end = .; ___con_initcall_start = .; *(.con_initcall.init) diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 1e7ac1c..adc1f23 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -126,13 +126,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index b3b2e38..d6083a0 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -128,13 +128,7 @@ SECTIONS .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS __initcall_end = .; } diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S index 13c7bb6..358b9ce 100644 --- a/arch/m32r/kernel/vmlinux.lds.S +++ b/arch/m32r/kernel/vmlinux.lds.S @@ -83,13 +83,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index ccd2ceb..58afa8b 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -140,13 +140,7 @@ SECTIONS { *(.init.setup) __setup_end = .; __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS __initcall_end = .; __con_initcall_start = .; *(.con_initcall.init) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 0bb9cd8..25ed333 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -91,13 +91,7 @@ SECTIONS __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index b3677fc..7b943b4 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -153,13 +153,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index cb0e8d4..e8342d8 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -108,13 +108,7 @@ SECTIONS .initcall.init : { __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS __initcall_end = .; } diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S index 095fd33..16e8661 100644 --- a/arch/ppc/kernel/vmlinux.lds.S +++ b/arch/ppc/kernel/vmlinux.lds.S @@ -115,13 +115,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index af9e69a0..fe0f2e9 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -83,13 +83,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 5eb9309..77b4026 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -76,13 +76,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S index a8fcc3a..95c4d75 100644 --- a/arch/sh64/kernel/vmlinux.lds.S +++ b/arch/sh64/kernel/vmlinux.lds.S @@ -108,13 +108,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : C_PHYS(.initcall.init) { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 1dd78c8..5cc5ff7 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -49,13 +49,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index b097379..bd9de8c 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S @@ -57,13 +57,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S index 6339921..88d087f 100644 --- a/arch/v850/kernel/vmlinux.lds.S +++ b/arch/v850/kernel/vmlinux.lds.S @@ -140,13 +140,7 @@ ___setup_end = . ; \ ___initcall_start = . ; \ *(.initcall.init) \ - *(.initcall1.init) \ - *(.initcall2.init) \ - *(.initcall3.init) \ - *(.initcall4.init) \ - *(.initcall5.init) \ - *(.initcall6.init) \ - *(.initcall7.init) \ + INITCALLS \ . = ALIGN (4) ; \ ___initcall_end = . ; \ ___con_initcall_start = .; \ diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 1283614..edb24aa 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -175,13 +175,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index ab6cdbd..cfe75f5 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -184,13 +184,7 @@ SECTIONS __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 9d0d11c..e3e83bc 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -213,3 +213,13 @@ #define NOTES \ .notes : { *(.note.*) } :note + +#define INITCALLS \ + *(.initcall1.init) \ + *(.initcall2.init) \ + *(.initcall3.init) \ + *(.initcall4.init) \ + *(.initcall5.init) \ + *(.initcall6.init) \ + *(.initcall7.init) + -- cgit v0.10.2 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 diff --git a/drivers/base/dd.c b/drivers/base/dd.c index db01b95..c5d6bb4 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 e3e83bc..9d87316 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 e92b145..ff40ea1 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 v0.10.2 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 diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index baece61..41bfcae 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 v0.10.2 From c97d4869a23c439d2bc23cb26c1147c099f9ff78 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Oct 2006 13:59:16 +0100 Subject: [ARM] Fix SMP irqflags support The IRQ changes a while back broke the build for SMP machines. Fix up the SMP code to use set_irq_regs/get_irq_regs as appropriate. Also, fix a warning in arch/arm/kernel/time.c where 'regs' becomes unused for SMP builds. Signed-off-by: Russell King diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 421329f..a07d202 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -474,25 +476,26 @@ void show_local_irqs(struct seq_file *p) seq_putc(p, '\n'); } -static void ipi_timer(struct pt_regs *regs) +static void ipi_timer(void) { - int user = user_mode(regs); - irq_enter(); - profile_tick(CPU_PROFILING, regs); - update_process_times(user); + profile_tick(CPU_PROFILING); + update_process_times(user_mode(get_irq_regs())); irq_exit(); } #ifdef CONFIG_LOCAL_TIMERS asmlinkage void do_local_timer(struct pt_regs *regs) { + struct pt_regs *old_regs = set_irq_regs(regs); int cpu = smp_processor_id(); if (local_timer_ack()) { irq_stat[cpu].local_timer_irqs++; - ipi_timer(regs); + ipi_timer(); } + + set_irq_regs(old_regs); } #endif @@ -551,6 +554,7 @@ asmlinkage void do_IPI(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct ipi_data *ipi = &per_cpu(ipi_data, cpu); + struct pt_regs *old_regs = set_irq_regs(regs); ipi->ipi_count++; @@ -574,7 +578,7 @@ asmlinkage void do_IPI(struct pt_regs *regs) switch (nextmsg) { case IPI_TIMER: - ipi_timer(regs); + ipi_timer(); break; case IPI_RESCHEDULE: @@ -599,6 +603,8 @@ asmlinkage void do_IPI(struct pt_regs *regs) } } while (msgs); } + + set_irq_regs(old_regs); } void smp_send_reschedule(int cpu) diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index c03cab5..0c5a609 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -327,13 +327,12 @@ EXPORT_SYMBOL(restore_time_delta); */ void timer_tick(void) { - struct pt_regs *regs = get_irq_regs(); profile_tick(CPU_PROFILING); do_leds(); do_set_rtc(); do_timer(1); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode(get_irq_regs())); #endif } -- cgit v0.10.2 From a233bf9ee819c726c581af48010e0c0f1cdde245 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Oct 2006 14:25:52 +0100 Subject: [ARM] Add realview SMP default configuration Signed-off-by: Russell King diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig new file mode 100644 index 0000000..ffd905f --- /dev/null +++ b/arch/arm/configs/realview-smp_defconfig @@ -0,0 +1,994 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc3 +# Wed Oct 25 14:12:00 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set +CONFIG_STOP_MACHINE=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +CONFIG_ARCH_REALVIEW=y +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# RealView platform type +# +CONFIG_MACH_REALVIEW_EB=y +CONFIG_REALVIEW_MPCORE=y + +# +# Processor Type +# +CONFIG_CPU_32=y +# CONFIG_CPU_ARM926T is not set +CONFIG_CPU_V6=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +CONFIG_ARM_GIC=y +CONFIG_ICST307=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_ARM_INTEGRATOR=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_ARMAACI=m + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_TIFM_SD is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_PL031=y +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_INOTIFY_USER is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RWSEMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y -- cgit v0.10.2 From 9957329800b8b554b1af669bcc6878282338c34e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 26 Oct 2006 10:27:42 +0100 Subject: [ARM] Add __must_check to uaccess functions Signed-off-by: Russell King diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index 09ad0ca..5f420a0 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -383,19 +383,19 @@ do { \ #ifdef CONFIG_MMU -extern unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n); -extern unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __clear_user(void __user *addr, unsigned long n); +extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n); +extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); #else #define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) #define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) #define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) #endif -extern unsigned long __strncpy_from_user(char *to, const char __user *from, unsigned long count); -extern unsigned long __strnlen_user(const char __user *s, long n); +extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count); +extern unsigned long __must_check __strnlen_user(const char __user *s, long n); -static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) +static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) n = __copy_from_user(to, from, n); @@ -404,7 +404,7 @@ static inline unsigned long copy_from_user(void *to, const void __user *from, un return n; } -static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) +static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) n = __copy_to_user(to, from, n); @@ -414,14 +414,14 @@ static inline unsigned long copy_to_user(void __user *to, const void *from, unsi #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -static inline unsigned long clear_user(void __user *to, unsigned long n) +static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) n = __clear_user(to, n); return n; } -static inline long strncpy_from_user(char *dst, const char __user *src, long count) +static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) @@ -431,7 +431,7 @@ static inline long strncpy_from_user(char *dst, const char __user *src, long cou #define strlen_user(s) strnlen_user(s, ~0UL >> 1) -static inline long strnlen_user(const char __user *s, long n) +static inline long __must_check strnlen_user(const char __user *s, long n) { unsigned long res = 0; -- cgit v0.10.2 From 75e31aaaf43b53517fd2b36cedc08bd4e4af14d5 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 25 Oct 2006 23:07:50 +0100 Subject: [ARM] 3909/1: Disable UWIND_INFO for ARM (again) According to Daniel Jacobowitz, UNWIND_INFO is not useful on ARM, and in fact doesn't even compile. This patch disables the option for ARM. Signed-off-by: Kevin Hilman Signed-off-by: Russell King diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 77491e3..d367910 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -341,7 +341,7 @@ config FRAME_POINTER config UNWIND_INFO bool "Compile the kernel with frame unwind information" - depends on !IA64 && !PARISC + depends on !IA64 && !PARISC && !ARM depends on !MODULES || !(MIPS || PPC || SUPERH || V850) help If you say Y here the resulting kernel image will be slightly larger -- cgit v0.10.2 From e816d71a50a714b532e3965364f3f53c23a53d42 Mon Sep 17 00:00:00 2001 From: Takashi Ohmasa Date: Mon, 23 Oct 2006 08:30:35 +0100 Subject: [ARM] 3899/1: Fix the normalization of the denormal double precision number. The significand should be shifted until the value of bit [62] is 1 to normalize the denormal double number. Signed-off-by: Takashi Ohmasa Signed-off-by: Russell King diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 4fc05ee..e44b9ed 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -56,7 +56,7 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd) { int bits = 31 - fls(vd->significand >> 32); if (bits == 31) - bits = 62 - fls(vd->significand); + bits = 63 - fls(vd->significand); vfp_double_dump("normalise_denormal: in", vd); -- cgit v0.10.2 From e0f205d9c656da9dad6340f75e33a96014b7d23f Mon Sep 17 00:00:00 2001 From: Takashi Ohmasa Date: Mon, 23 Oct 2006 11:19:40 +0100 Subject: [ARM] 3900/1: Fix VFP Division by Zero exception handling. The SIGFPE signal should be generated if Division by Zero exception is detected. Signed-off-by: Takashi Ohmasa Signed-off-by: Russell King diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index a657a28..f08eafb 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -148,6 +148,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ /* * These are arranged in priority order, least to highest. */ + RAISE(FPSCR_DZC, FPSCR_DZE, FPE_FLTDIV); RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES); RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND); RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); -- cgit v0.10.2 From 2ae88149a27cadf2840e0ab8155bef13be285c03 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Sat, 28 Oct 2006 10:38:23 -0700 Subject: [PATCH] mm: clean up pagecache allocation - Consolidate page_cache_alloc - Fix splice: only the pagecache pages and filesystem data need to use mapping_gfp_mask. - Fix grab_cache_page_nowait: same as splice, also honour NUMA placement. Signed-off-by: Nick Piggin Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/splice.c b/fs/splice.c index 49fb9f1..8d70595 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -74,7 +74,7 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe, wait_on_page_writeback(page); if (PagePrivate(page)) - try_to_release_page(page, mapping_gfp_mask(mapping)); + try_to_release_page(page, GFP_KERNEL); /* * If we succeeded in removing the mapping, set LRU flag @@ -333,7 +333,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, break; error = add_to_page_cache_lru(page, mapping, index, - mapping_gfp_mask(mapping)); + GFP_KERNEL); if (unlikely(error)) { page_cache_release(page); if (error == -EEXIST) @@ -557,7 +557,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, { struct file *file = sd->file; struct address_space *mapping = file->f_mapping; - gfp_t gfp_mask = mapping_gfp_mask(mapping); unsigned int offset, this_len; struct page *page; pgoff_t index; @@ -591,7 +590,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, goto find_page; page = buf->page; - if (add_to_page_cache(page, mapping, index, gfp_mask)) { + if (add_to_page_cache(page, mapping, index, GFP_KERNEL)) { unlock_page(page); goto find_page; } @@ -613,7 +612,7 @@ find_page: * This will also lock the page */ ret = add_to_page_cache_lru(page, mapping, index, - gfp_mask); + GFP_KERNEL); if (unlikely(ret)) goto out; } diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 64f9509..c3e255b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -52,19 +52,23 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask) void release_pages(struct page **pages, int nr, int cold); #ifdef CONFIG_NUMA -extern struct page *page_cache_alloc(struct address_space *x); -extern struct page *page_cache_alloc_cold(struct address_space *x); +extern struct page *__page_cache_alloc(gfp_t gfp); #else +static inline struct page *__page_cache_alloc(gfp_t gfp) +{ + return alloc_pages(gfp, 0); +} +#endif + static inline struct page *page_cache_alloc(struct address_space *x) { - return alloc_pages(mapping_gfp_mask(x), 0); + return __page_cache_alloc(mapping_gfp_mask(x)); } static inline struct page *page_cache_alloc_cold(struct address_space *x) { - return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); + return __page_cache_alloc(mapping_gfp_mask(x)|__GFP_COLD); } -#endif typedef int filler_t(void *, struct page *); diff --git a/mm/filemap.c b/mm/filemap.c index cb26e33..7b84dc8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -467,25 +467,15 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping, } #ifdef CONFIG_NUMA -struct page *page_cache_alloc(struct address_space *x) +struct page *__page_cache_alloc(gfp_t gfp) { if (cpuset_do_page_mem_spread()) { int n = cpuset_mem_spread_node(); - return alloc_pages_node(n, mapping_gfp_mask(x), 0); + return alloc_pages_node(n, gfp, 0); } - return alloc_pages(mapping_gfp_mask(x), 0); + return alloc_pages(gfp, 0); } -EXPORT_SYMBOL(page_cache_alloc); - -struct page *page_cache_alloc_cold(struct address_space *x) -{ - if (cpuset_do_page_mem_spread()) { - int n = cpuset_mem_spread_node(); - return alloc_pages_node(n, mapping_gfp_mask(x)|__GFP_COLD, 0); - } - return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); -} -EXPORT_SYMBOL(page_cache_alloc_cold); +EXPORT_SYMBOL(__page_cache_alloc); #endif static int __sleep_on_page_lock(void *word) @@ -826,7 +816,6 @@ struct page * grab_cache_page_nowait(struct address_space *mapping, unsigned long index) { struct page *page = find_get_page(mapping, index); - gfp_t gfp_mask; if (page) { if (!TestSetPageLocked(page)) @@ -834,9 +823,8 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) page_cache_release(page); return NULL; } - gfp_mask = mapping_gfp_mask(mapping) & ~__GFP_FS; - page = alloc_pages(gfp_mask, 0); - if (page && add_to_page_cache_lru(page, mapping, index, gfp_mask)) { + page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~__GFP_FS); + if (page && add_to_page_cache_lru(page, mapping, index, GFP_KERNEL)) { page_cache_release(page); page = NULL; } -- cgit v0.10.2 From 3bb1a852ab6c9cdf211a2f4a2f502340c8c38eca Mon Sep 17 00:00:00 2001 From: Martin Bligh Date: Sat, 28 Oct 2006 10:38:24 -0700 Subject: [PATCH] vmscan: Fix temp_priority race The temp_priority field in zone is racy, as we can walk through a reclaim path, and just before we copy it into prev_priority, it can be overwritten (say with DEF_PRIORITY) by another reclaimer. The same bug is contained in both try_to_free_pages and balance_pgdat, but it is fixed slightly differently. In balance_pgdat, we keep a separate priority record per zone in a local array. In try_to_free_pages there is no need to do this, as the priority level is the same for all zones that we reclaim from. Impact of this bug is that temp_priority is copied into prev_priority, and setting this artificially high causes reclaimers to set distress artificially low. They then fail to reclaim mapped pages, when they are, in fact, under severe memory pressure (their priority may be as low as 0). This causes the OOM killer to fire incorrectly. From: Andrew Morton __zone_reclaim() isn't modifying zone->prev_priority. But zone->prev_priority is used in the decision whether or not to bring mapped pages onto the inactive list. Hence there's a risk here that __zone_reclaim() will fail because zone->prev_priority ir large (ie: low urgency) and lots of mapped pages end up stuck on the active list. Fix that up by decreasing (ie making more urgent) zone->prev_priority as __zone_reclaim() scans the zone's pages. This bug perhaps explains why ZONE_RECLAIM_PRIORITY was created. It should be possible to remove that now, and to just start out at DEF_PRIORITY? Cc: Nick Piggin Cc: Christoph Lameter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ed0762b..e06683e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -218,13 +218,9 @@ struct zone { * under - it drives the swappiness decision: whether to unmap mapped * pages. * - * temp_priority is used to remember the scanning priority at which - * this zone was successfully refilled to free_pages == pages_high. - * - * Access to both these fields is quite racy even on uniprocessor. But + * Access to both this field is quite racy even on uniprocessor. But * it is expected to average out OK. */ - int temp_priority; int prev_priority; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f5fc454..ecf853b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2407,7 +2407,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat, zone->zone_pgdat = pgdat; zone->free_pages = 0; - zone->temp_priority = zone->prev_priority = DEF_PRIORITY; + zone->prev_priority = DEF_PRIORITY; zone_pcp_init(zone); INIT_LIST_HEAD(&zone->active_list); diff --git a/mm/vmscan.c b/mm/vmscan.c index f05527b..b32560e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -723,6 +723,20 @@ done: return nr_reclaimed; } +/* + * We are about to scan this zone at a certain priority level. If that priority + * level is smaller (ie: more urgent) than the previous priority, then note + * that priority level within the zone. This is done so that when the next + * process comes in to scan this zone, it will immediately start out at this + * priority level rather than having to build up its own scanning priority. + * Here, this priority affects only the reclaim-mapped threshold. + */ +static inline void note_zone_scanning_priority(struct zone *zone, int priority) +{ + if (priority < zone->prev_priority) + zone->prev_priority = priority; +} + static inline int zone_is_near_oom(struct zone *zone) { return zone->pages_scanned >= (zone->nr_active + zone->nr_inactive)*3; @@ -972,9 +986,7 @@ static unsigned long shrink_zones(int priority, struct zone **zones, if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->temp_priority = priority; - if (zone->prev_priority > priority) - zone->prev_priority = priority; + note_zone_scanning_priority(zone, priority); if (zone->all_unreclaimable && priority != DEF_PRIORITY) continue; /* Let kswapd poll it */ @@ -1024,7 +1036,6 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->temp_priority = DEF_PRIORITY; lru_pages += zone->nr_active + zone->nr_inactive; } @@ -1065,13 +1076,22 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) if (!sc.all_unreclaimable) ret = 1; out: + /* + * Now that we've scanned all the zones at this priority level, note + * that level within the zone so that the next thread which performs + * scanning of this zone will immediately start out at this priority + * level. This affects only the decision whether or not to bring + * mapped pages onto the inactive list. + */ + if (priority < 0) + priority = 0; for (i = 0; zones[i] != 0; i++) { struct zone *zone = zones[i]; if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->prev_priority = zone->temp_priority; + zone->prev_priority = priority; } return ret; } @@ -1111,6 +1131,11 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) .swap_cluster_max = SWAP_CLUSTER_MAX, .swappiness = vm_swappiness, }; + /* + * temp_priority is used to remember the scanning priority at which + * this zone was successfully refilled to free_pages == pages_high. + */ + int temp_priority[MAX_NR_ZONES]; loop_again: total_scanned = 0; @@ -1118,11 +1143,8 @@ loop_again: sc.may_writepage = !laptop_mode; count_vm_event(PAGEOUTRUN); - for (i = 0; i < pgdat->nr_zones; i++) { - struct zone *zone = pgdat->node_zones + i; - - zone->temp_priority = DEF_PRIORITY; - } + for (i = 0; i < pgdat->nr_zones; i++) + temp_priority[i] = DEF_PRIORITY; for (priority = DEF_PRIORITY; priority >= 0; priority--) { int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ @@ -1183,10 +1205,9 @@ scan: if (!zone_watermark_ok(zone, order, zone->pages_high, end_zone, 0)) all_zones_ok = 0; - zone->temp_priority = priority; - if (zone->prev_priority > priority) - zone->prev_priority = priority; + temp_priority[i] = priority; sc.nr_scanned = 0; + note_zone_scanning_priority(zone, priority); nr_reclaimed += shrink_zone(priority, zone, &sc); reclaim_state->reclaimed_slab = 0; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, @@ -1226,10 +1247,15 @@ scan: break; } out: + /* + * Note within each zone the priority level at which this zone was + * brought into a happy state. So that the next thread which scans this + * zone will start out at that priority level. + */ for (i = 0; i < pgdat->nr_zones; i++) { struct zone *zone = pgdat->node_zones + i; - zone->prev_priority = zone->temp_priority; + zone->prev_priority = temp_priority[i]; } if (!all_zones_ok) { cond_resched(); @@ -1614,6 +1640,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) */ priority = ZONE_RECLAIM_PRIORITY; do { + note_zone_scanning_priority(zone, priority); nr_reclaimed += shrink_zone(priority, zone, &sc); priority--; } while (priority >= 0 && nr_reclaimed < nr_pages); diff --git a/mm/vmstat.c b/mm/vmstat.c index 45b124e..8614e8f 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -587,11 +587,9 @@ static int zoneinfo_show(struct seq_file *m, void *arg) seq_printf(m, "\n all_unreclaimable: %u" "\n prev_priority: %i" - "\n temp_priority: %i" "\n start_pfn: %lu", zone->all_unreclaimable, zone->prev_priority, - zone->temp_priority, zone->zone_start_pfn); spin_unlock_irqrestore(&zone->lock, flags); seq_putc(m, '\n'); -- cgit v0.10.2 From bbdb396a60b2ebf7de3b717991e5d3e28c8b7bbd Mon Sep 17 00:00:00 2001 From: Martin Bligh Date: Sat, 28 Oct 2006 10:38:25 -0700 Subject: [PATCH] Use min of two prio settings in calculating distress for reclaim If try_to_free_pages / balance_pgdat are called with a gfp_mask specifying GFP_IO and/or GFP_FS, they will reclaim the requisite number of pages, and the reset prev_priority to DEF_PRIORITY (or to some other high (ie: unurgent) value). However, another reclaimer without those gfp_mask flags set (say, GFP_NOIO) may still be struggling to reclaim pages. The concurrent overwrite of zone->prev_priority will cause this GFP_NOIO thread to unexpectedly cease deactivating mapped pages, thus causing reclaim difficulties. Fix this is to key the distress calculation not off zone->prev_priority, but also take into account the local caller's priority by using min(zone->prev_priority, sc->priority) Signed-off-by: Martin J. Bligh Cc: Nick Piggin Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/vmscan.c b/mm/vmscan.c index b32560e..518540a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -760,7 +760,7 @@ static inline int zone_is_near_oom(struct zone *zone) * But we had to alter page->flags anyway. */ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, - struct scan_control *sc) + struct scan_control *sc, int priority) { unsigned long pgmoved; int pgdeactivate = 0; @@ -784,7 +784,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, * `distress' is a measure of how much trouble we're having * reclaiming pages. 0 -> no problems. 100 -> great trouble. */ - distress = 100 >> zone->prev_priority; + distress = 100 >> min(zone->prev_priority, priority); /* * The point of this algorithm is to decide when to start @@ -936,7 +936,7 @@ static unsigned long shrink_zone(int priority, struct zone *zone, nr_to_scan = min(nr_active, (unsigned long)sc->swap_cluster_max); nr_active -= nr_to_scan; - shrink_active_list(nr_to_scan, zone, sc); + shrink_active_list(nr_to_scan, zone, sc, priority); } if (nr_inactive) { @@ -1384,7 +1384,7 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int pass, if (zone->nr_scan_active >= nr_pages || pass > 3) { zone->nr_scan_active = 0; nr_to_scan = min(nr_pages, zone->nr_active); - shrink_active_list(nr_to_scan, zone, sc); + shrink_active_list(nr_to_scan, zone, sc, prio); } } -- cgit v0.10.2 From 1939e49a0cb9d73785857bf312f4f65661b4b513 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Oct 2006 10:38:26 -0700 Subject: [PATCH] ext4: fix printk format warnings fs/ext4/resize.c:72: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:76: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:81: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:85: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:89: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:89: warning: long long unsigned int format, __u64 arg (arg 5) fs/ext4/resize.c:93: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:93: warning: long long unsigned int format, __u64 arg (arg 5) fs/ext4/resize.c:98: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:103: warning: long long unsigned int format, __u64 arg (arg 4) fs/ext4/resize.c:109: warning: long long unsigned int format, __u64 arg (arg 4) Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 1e95780..4fe49c3 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -69,44 +69,49 @@ static int verify_group_input(struct super_block *sb, else if (outside(input->block_bitmap, start, end)) ext4_warning(sb, __FUNCTION__, "Block bitmap not in group (block %llu)", - input->block_bitmap); + (unsigned long long)input->block_bitmap); else if (outside(input->inode_bitmap, start, end)) ext4_warning(sb, __FUNCTION__, "Inode bitmap not in group (block %llu)", - input->inode_bitmap); + (unsigned long long)input->inode_bitmap); else if (outside(input->inode_table, start, end) || outside(itend - 1, start, end)) ext4_warning(sb, __FUNCTION__, "Inode table not in group (blocks %llu-%llu)", - input->inode_table, itend - 1); + (unsigned long long)input->inode_table, itend - 1); else if (input->inode_bitmap == input->block_bitmap) ext4_warning(sb, __FUNCTION__, "Block bitmap same as inode bitmap (%llu)", - input->block_bitmap); + (unsigned long long)input->block_bitmap); else if (inside(input->block_bitmap, input->inode_table, itend)) ext4_warning(sb, __FUNCTION__, "Block bitmap (%llu) in inode table (%llu-%llu)", - input->block_bitmap, input->inode_table, itend-1); + (unsigned long long)input->block_bitmap, + (unsigned long long)input->inode_table, itend - 1); else if (inside(input->inode_bitmap, input->inode_table, itend)) ext4_warning(sb, __FUNCTION__, "Inode bitmap (%llu) in inode table (%llu-%llu)", - input->inode_bitmap, input->inode_table, itend-1); + (unsigned long long)input->inode_bitmap, + (unsigned long long)input->inode_table, itend - 1); else if (inside(input->block_bitmap, start, metaend)) ext4_warning(sb, __FUNCTION__, "Block bitmap (%llu) in GDT table" " (%llu-%llu)", - input->block_bitmap, start, metaend - 1); + (unsigned long long)input->block_bitmap, + start, metaend - 1); else if (inside(input->inode_bitmap, start, metaend)) ext4_warning(sb, __FUNCTION__, "Inode bitmap (%llu) in GDT table" " (%llu-%llu)", - input->inode_bitmap, start, metaend - 1); + (unsigned long long)input->inode_bitmap, + start, metaend - 1); else if (inside(input->inode_table, start, metaend) || inside(itend - 1, start, metaend)) ext4_warning(sb, __FUNCTION__, "Inode table (%llu-%llu) overlaps" "GDT table (%llu-%llu)", - input->inode_table, itend - 1, start, metaend - 1); + (unsigned long long)input->inode_table, + itend - 1, start, metaend - 1); else err = 0; brelse(bh); -- cgit v0.10.2 From f58a74dca88d48b0669609b4957f3dd757bdc898 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sat, 28 Oct 2006 10:38:27 -0700 Subject: [PATCH] jbd: journal_dirty_data re-check for unmapped buffers When running several fsx's and other filesystem stress tests, we found cases where an unmapped buffer was still being sent to submit_bh by the ext3 dirty data journaling code. I saw this happen in two ways, both related to another thread doing a truncate which would unmap the buffer in question. Either we would get into journal_dirty_data with a bh which was already unmapped (although journal_dirty_data_fn had checked for this earlier, the state was not locked at that point), or it would get unmapped in the middle of journal_dirty_data when we dropped locks to call sync_dirty_buffer. By re-checking for mapped state after we've acquired the bh state lock, we should avoid these races. If we find a buffer which is no longer mapped, we essentially ignore it, because journal_unmap_buffer has already decided that this buffer can go away. I've also added tracepoints in these two cases, and made a couple other tracepoint changes that I found useful in debugging this. Signed-off-by: Eric Sandeen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index d5c6304..4f82bcd6 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -967,6 +967,13 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) */ jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + + /* Now that we have bh_state locked, are we really still mapped? */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); + goto no_journal; + } + if (jh->b_transaction) { JBUFFER_TRACE(jh, "has transaction"); if (jh->b_transaction != handle->h_transaction) { @@ -1028,6 +1035,11 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) sync_dirty_buffer(bh); jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + /* Since we dropped the lock... */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "buffer got unmapped"); + goto no_journal; + } /* The buffer may become locked again at any time if it is redirtied */ } @@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } } } else if (transaction == journal->j_committing_transaction) { + JBUFFER_TRACE(jh, "on committing transaction"); if (jh->b_jlist == BJ_Locked) { /* * The buffer is on the committing transaction's locked @@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * can remove it's next_transaction pointer from the * running transaction if that is set, but nothing * else. */ - JBUFFER_TRACE(jh, "on committing transaction"); set_buffer_freed(bh); if (jh->b_next_transaction) { J_ASSERT(jh->b_next_transaction == @@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * i_size already for this truncate so recovery will not * expose the disk blocks we are discarding here.) */ J_ASSERT_JH(jh, transaction == journal->j_running_transaction); + JBUFFER_TRACE(jh, "on running transaction"); may_free = __dispose_buffer(jh, transaction); } -- cgit v0.10.2 From 9b57988db9b2c81794546cb792133f0cfd064ea8 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sat, 28 Oct 2006 10:38:28 -0700 Subject: [PATCH] jbd2: journal_dirty_data re-check for unmapped buffers When running several fsx's and other filesystem stress tests, we found cases where an unmapped buffer was still being sent to submit_bh by the ext3 dirty data journaling code. I saw this happen in two ways, both related to another thread doing a truncate which would unmap the buffer in question. Either we would get into journal_dirty_data with a bh which was already unmapped (although journal_dirty_data_fn had checked for this earlier, the state was not locked at that point), or it would get unmapped in the middle of journal_dirty_data when we dropped locks to call sync_dirty_buffer. By re-checking for mapped state after we've acquired the bh state lock, we should avoid these races. If we find a buffer which is no longer mapped, we essentially ignore it, because journal_unmap_buffer has already decided that this buffer can go away. I've also added tracepoints in these two cases, and made a couple other tracepoint changes that I found useful in debugging this. Signed-off-by: Eric Sandeen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b6cf2be..c051a94 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -967,6 +967,13 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) */ jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + + /* Now that we have bh_state locked, are we really still mapped? */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); + goto no_journal; + } + if (jh->b_transaction) { JBUFFER_TRACE(jh, "has transaction"); if (jh->b_transaction != handle->h_transaction) { @@ -1028,6 +1035,11 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) sync_dirty_buffer(bh); jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + /* Since we dropped the lock... */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "buffer got unmapped"); + goto no_journal; + } /* The buffer may become locked again at any time if it is redirtied */ } @@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } } } else if (transaction == journal->j_committing_transaction) { + JBUFFER_TRACE(jh, "on committing transaction"); if (jh->b_jlist == BJ_Locked) { /* * The buffer is on the committing transaction's locked @@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * can remove it's next_transaction pointer from the * running transaction if that is set, but nothing * else. */ - JBUFFER_TRACE(jh, "on committing transaction"); set_buffer_freed(bh); if (jh->b_next_transaction) { J_ASSERT(jh->b_next_transaction == @@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * i_size already for this truncate so recovery will not * expose the disk blocks we are discarding here.) */ J_ASSERT_JH(jh, transaction == journal->j_running_transaction); + JBUFFER_TRACE(jh, "on running transaction"); may_free = __dispose_buffer(jh, transaction); } -- cgit v0.10.2 From ae74589cb381cc2838107f92d4e0e1f178c6825d Mon Sep 17 00:00:00 2001 From: "bibo,mao" Date: Sat, 28 Oct 2006 10:38:29 -0700 Subject: [PATCH] fix efi_memory_present_wrapper() efi_memory_present_wrapper() parameter start/end is physical address, but function memory_present parameter is PFN, this patch converts physical address to PFN. Signed-off-by: bibo, mao Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 519e63c..141041d 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -846,7 +846,7 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) static int __init efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) { - memory_present(0, start, end); + memory_present(0, PFN_UP(start), PFN_DOWN(end)); return 0; } -- cgit v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index 7daa7b1..c40ce9f 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 v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index c40ce9f..50ab4a9 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 v0.10.2 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 diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index a6260f0..14da37f 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 v0.10.2 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 diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index dc9d2de..656fae9 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 74f17a9..7492d60 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 v0.10.2 From f2d0aa5bf8d4f7ae4cb1a7feebf5b1afddd0b9b0 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Sat, 28 Oct 2006 10:38:32 -0700 Subject: [PATCH] memory hotplug: __GFP_NOWARN is better for __kmalloc_section_memmap() Add __GFP_NOWARN flag to calling of __alloc_pages() in __kmalloc_section_memmap(). It can reduce noisy failure message. In ia64, section size is 1 GB, this means that order 8 pages are necessary for each section's memmap. It is often very hard requirement under heavy memory pressure as you know. So, __alloc_pages() gives up allocation and shows many noisy stack traces which means no page for each sections. (Current my environment shows 32 times of stack trace....) But, __kmalloc_section_memmap() calls vmalloc() after failure of it, and it can succeed allocation of memmap. So, its stack trace warning becomes just noisy. I suppose it shouldn't be shown. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/sparse.c b/mm/sparse.c index 86c52ab..b3c82ba 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -211,7 +211,7 @@ static struct page *__kmalloc_section_memmap(unsigned long nr_pages) struct page *page, *ret; unsigned long memmap_size = sizeof(struct page) * nr_pages; - page = alloc_pages(GFP_KERNEL, get_order(memmap_size)); + page = alloc_pages(GFP_KERNEL|__GFP_NOWARN, get_order(memmap_size)); if (page) goto got_map_page; -- cgit v0.10.2 From 6a2aae06cc1e87e9712a26a639f6a2f3442e2027 Mon Sep 17 00:00:00 2001 From: Pavel Emelianov Date: Sat, 28 Oct 2006 10:38:33 -0700 Subject: [PATCH] Fix potential OOPs in blkdev_open() blkdev_open() calls bc_acquire() to get a struct block_device. Since bc_acquire() may return NULL when system is out of memory an appropriate check is required. Signed-off-by: Pavel Emelianov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/block_dev.c b/fs/block_dev.c index bc8f27c..702b88c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1131,6 +1131,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) filp->f_flags |= O_LARGEFILE; bdev = bd_acquire(inode); + if (bdev == NULL) + return -ENOMEM; res = do_open(bdev, filp, BD_MUTEX_NORMAL); if (res) -- cgit v0.10.2 From 52fd24ca1db3a741f144bbc229beefe044202cac Mon Sep 17 00:00:00 2001 From: Giridhar Pemmasani Date: Sat, 28 Oct 2006 10:38:34 -0700 Subject: [PATCH] __vmalloc with GFP_ATOMIC causes 'sleeping from invalid context' If __vmalloc is called to allocate memory with GFP_ATOMIC in atomic context, the chain of calls results in __get_vm_area_node allocating memory for vm_struct with GFP_KERNEL, causing the 'sleeping from invalid context' warning. This patch fixes it by passing the gfp flags along so __get_vm_area_node allocates memory for vm_struct with the same flags. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index ce5f148..dc9a29d 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -60,7 +60,8 @@ extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags); extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end); extern struct vm_struct *get_vm_area_node(unsigned long size, - unsigned long flags, int node); + unsigned long flags, int node, + gfp_t gfp_mask); extern struct vm_struct *remove_vm_area(void *addr); extern int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 1133dd3..6d381df 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -160,13 +160,15 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages) return err; } -struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags, - unsigned long start, unsigned long end, int node) +static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags, + unsigned long start, unsigned long end, + int node, gfp_t gfp_mask) { struct vm_struct **p, *tmp, *area; unsigned long align = 1; unsigned long addr; + BUG_ON(in_interrupt()); if (flags & VM_IOREMAP) { int bit = fls(size); @@ -180,7 +182,7 @@ struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags, addr = ALIGN(start, align); size = PAGE_ALIGN(size); - area = kmalloc_node(sizeof(*area), GFP_KERNEL, node); + area = kmalloc_node(sizeof(*area), gfp_mask, node); if (unlikely(!area)) return NULL; @@ -236,7 +238,7 @@ out: struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end) { - return __get_vm_area_node(size, flags, start, end, -1); + return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL); } /** @@ -253,9 +255,11 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags) return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END); } -struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags, int node) +struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags, + int node, gfp_t gfp_mask) { - return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node); + return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node, + gfp_mask); } /* Caller must hold vmlist_lock */ @@ -487,7 +491,7 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot, if (!size || (size >> PAGE_SHIFT) > num_physpages) return NULL; - area = get_vm_area_node(size, VM_ALLOC, node); + area = get_vm_area_node(size, VM_ALLOC, node, gfp_mask); if (!area) return NULL; -- cgit v0.10.2 From 08d892f11aae7125fe078cf93ec5cf6af288c5e7 Mon Sep 17 00:00:00 2001 From: Andrey Panin Date: Sat, 28 Oct 2006 10:38:35 -0700 Subject: [PATCH] visws build fix Fix this: > Subject : CONFIG_X86_VISWS=3Dy, CONFIG_SMP=3Dn compile error > References : http://lkml.org/lkml/2006/10/7/51 > Submitter : Jesper Juhl > Caused-By : David Howells > commit 7d12e780e003f93433d49ce78cfedf4b4c52adc5 > Status : unknown Via undescribed means. Signed-off-by: Andrey Panin Cc: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/mach-visws/visws_apic.c b/arch/i386/mach-visws/visws_apic.c index 07097ed..38c2b13 100644 --- a/arch/i386/mach-visws/visws_apic.c +++ b/arch/i386/mach-visws/visws_apic.c @@ -122,7 +122,7 @@ static void end_cobalt_irq(unsigned int irq) spin_unlock_irqrestore(&cobalt_lock, flags); } -static struct hw_interrupt_type cobalt_irq_type = { +static struct irq_chip cobalt_irq_type = { .typename = "Cobalt-APIC", .startup = startup_cobalt_irq, .shutdown = disable_cobalt_irq, @@ -159,7 +159,7 @@ static void end_piix4_master_irq(unsigned int irq) spin_unlock_irqrestore(&cobalt_lock, flags); } -static struct hw_interrupt_type piix4_master_irq_type = { +static struct irq_chip piix4_master_irq_type = { .typename = "PIIX4-master", .startup = startup_piix4_master_irq, .ack = ack_cobalt_irq, @@ -167,9 +167,8 @@ static struct hw_interrupt_type piix4_master_irq_type = { }; -static struct hw_interrupt_type piix4_virtual_irq_type = { +static struct irq_chip piix4_virtual_irq_type = { .typename = "PIIX4-virtual", - .startup = startup_8259A_irq, .shutdown = disable_8259A_irq, .enable = enable_8259A_irq, .disable = disable_8259A_irq, diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h deleted file mode 100644 index 21cd696..0000000 --- a/include/asm-i386/mach-visws/do_timer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* defines for inline arch setup functions */ - -#include -#include -#include "cobalt.h" - -static inline void do_timer_interrupt_hook(void) -{ - /* Clear the interrupt */ - co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR); - - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode_vm(irq_regs)); -#endif -/* - * In the SMP case we use the local APIC timer interrupt to do the - * profiling, except when we simulate SMP mode on a uniprocessor - * system, in that case we have to call the local interrupt handler. - */ -#ifndef CONFIG_X86_LOCAL_APIC - profile_tick(CPU_PROFILING); -#else - if (!using_apic_timer) - smp_local_timer_interrupt(); -#endif -} - -static inline int do_timer_overflow(int count) -{ - int i; - - spin_lock(&i8259A_lock); - /* - * This is tricky when I/O APICs are used; - * see do_timer_interrupt(). - */ - i = inb(0x20); - spin_unlock(&i8259A_lock); - - /* assumption about timer being IRQ0 */ - if (i & 0x01) { - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - return count; -} diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h index de438c71..18afe6b 100644 --- a/include/asm-i386/mach-visws/mach_apic.h +++ b/include/asm-i386/mach-visws/mach_apic.h @@ -51,6 +51,11 @@ static inline void clustered_apic_check(void) { } +static inline int apicid_to_node(int logical_apicid) +{ + return 0; +} + /* Mapping from cpu number to logical apicid */ static inline int cpu_to_logical_apicid(int cpu) { -- cgit v0.10.2 From 1d4d262769cd1894a0306b9c57e72f005cd9e75a Mon Sep 17 00:00:00 2001 From: Jan Dittmer Date: Sat, 28 Oct 2006 10:38:38 -0700 Subject: [PATCH] Add missing space in module.c for taintskernel Obvious fix. Signed-off-by: Jan Dittmer Acked-by: Florin Malita Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/module.c b/kernel/module.c index 67009bd..5072a94 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1342,7 +1342,7 @@ static void set_license(struct module *mod, const char *license) if (!license_is_gpl_compatible(license)) { if (!(tainted & TAINT_PROPRIETARY_MODULE)) - printk(KERN_WARNING "%s: module license '%s' taints" + printk(KERN_WARNING "%s: module license '%s' taints " "kernel.\n", mod->name, license); add_taint_module(mod, TAINT_PROPRIETARY_MODULE); } -- cgit v0.10.2 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 diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 79354bb..b995a15 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 v0.10.2 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 diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index bc66026..6ffe2b2 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 v0.10.2 From b9d7e6ae82da124dc9c579fe1061264ef2a69407 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sat, 28 Oct 2006 10:38:41 -0700 Subject: [PATCH] hugetlb: fix size=4G parsing On 32-bit machines, mount -t hugetlbfs -o size=4G gave a 0GB filesystem, size=5G gave a 1GB filesystem etc: there's no point in masking size with HPAGE_MASK just before shifting its lower bits away, and since HPAGE_MASK is a UL, that removed all the higher bits of the unsigned long long size. Signed-off-by: Hugh Dickins Cc: Adam Litke Cc: David Gibson Cc: "Chen, Kenneth W" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4ee3f00..0b23b96 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -624,7 +624,6 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) do_div(size, 100); rest++; } - size &= HPAGE_MASK; pconfig->nr_blocks = (size >> HPAGE_SHIFT); value = rest; } else if (!strcmp(opt,"nr_inodes")) { -- cgit v0.10.2 From 856fc29505556cf263f3dcda2533cf3766c14ab6 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sat, 28 Oct 2006 10:38:43 -0700 Subject: [PATCH] hugetlb: fix prio_tree unit hugetlb_vmtruncate_list was misconverted to prio_tree: its prio_tree is in units of PAGE_SIZE (PAGE_CACHE_SIZE) like any other, not HPAGE_SIZE (whereas its radix_tree is kept in units of HPAGE_SIZE, otherwise slots would be absurdly sparse). At first I thought the error benign, just calling __unmap_hugepage_range on more vmas than necessary; but on 32-bit machines, when the prio_tree is searched correctly, it happens to ensure the v_offset calculation won't overflow. As it stood, when truncating at or beyond 4GB, it was liable to discard pages COWed from lower offsets; or even to clear pmd entries of preceding vmas, triggering exit_mmap's BUG_ON(nr_ptes). Signed-off-by: Hugh Dickins Cc: Adam Litke Cc: David Gibson Cc: "Chen, Kenneth W" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 0b23b96..0bea6a6 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -271,26 +271,24 @@ static void hugetlbfs_drop_inode(struct inode *inode) hugetlbfs_forget_inode(inode); } -/* - * h_pgoff is in HPAGE_SIZE units. - * vma->vm_pgoff is in PAGE_SIZE units. - */ static inline void -hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) +hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff) { struct vm_area_struct *vma; struct prio_tree_iter iter; - vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) { - unsigned long h_vm_pgoff; + vma_prio_tree_foreach(vma, &iter, root, pgoff, ULONG_MAX) { unsigned long v_offset; - h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); - v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT; /* - * Is this VMA fully outside the truncation point? + * Can the expression below overflow on 32-bit arches? + * No, because the prio_tree returns us only those vmas + * which overlap the truncated area starting at pgoff, + * and no vma on a 32-bit arch can span beyond the 4GB. */ - if (h_vm_pgoff >= h_pgoff) + if (vma->vm_pgoff < pgoff) + v_offset = (pgoff - vma->vm_pgoff) << PAGE_SHIFT; + else v_offset = 0; __unmap_hugepage_range(vma, @@ -303,14 +301,14 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) */ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) { - unsigned long pgoff; + pgoff_t pgoff; struct address_space *mapping = inode->i_mapping; if (offset > inode->i_size) return -EINVAL; BUG_ON(offset & ~HPAGE_MASK); - pgoff = offset >> HPAGE_SHIFT; + pgoff = offset >> PAGE_SHIFT; inode->i_size = offset; spin_lock(&mapping->i_mmap_lock); -- cgit v0.10.2 From ebed4bfc8da8df5b6b0bc4a5064a949f04683509 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sat, 28 Oct 2006 10:38:43 -0700 Subject: [PATCH] hugetlb: fix absurd HugePages_Rsvd If you truncated an mmap'ed hugetlbfs file, then faulted on the truncated area, /proc/meminfo's HugePages_Rsvd wrapped hugely "negative". Reinstate my preliminary i_size check before attempting to allocate the page (though this only fixes the most obvious case: more work will be needed here). Signed-off-by: Hugh Dickins Cc: Adam Litke Cc: David Gibson Cc: "Chen, Kenneth W" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 2dbec90..a088f59 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -478,6 +478,9 @@ int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, retry: page = find_lock_page(mapping, idx); if (!page) { + size = i_size_read(mapping->host) >> HPAGE_SHIFT; + if (idx >= size) + goto out; if (hugetlb_get_quota(mapping)) goto out; page = alloc_huge_page(vma, address); -- cgit v0.10.2 From 6eac3f93f5e6b7256fb20b7608d62ec192da12be Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Sat, 28 Oct 2006 10:38:44 -0700 Subject: [PATCH] missing unused dentry in prune_dcache()? On the the following patch: http://linux.bkbits.net:8080/linux-2.6/gnupatch@449b144ecSF1rYskg3q-SeR2vf88zg # ChangeSet # 2006/06/22 15:05:57-07:00 neilb@suse.de # [PATCH] Fix dcache race during umount # If prune_dcache finds a dentry that it cannot free, it leaves it where it # is (at the tail of the list) and exits, on the assumption that some other # thread will be removing that dentry soon. However as far as I see this comment is not correct: when we cannot take s_umount rw_semaphore (for example because it was taken in do_remount) this dentry is already extracted from dentry_unused list and we do not add it into the list again. Therefore dentry will not be found by prune_dcache() and shrink_dcache_sb() and will leave in memory very long time until the partition will be unmounted. The patch adds this dentry into tail of the dentry_unused list. Signed-off-by: Vasily Averin Cc: Neil Brown Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/dcache.c b/fs/dcache.c index a1ff91e..a5b76b6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -478,11 +478,12 @@ static void prune_dcache(int count, struct super_block *sb) up_read(s_umount); } spin_unlock(&dentry->d_lock); - /* Cannot remove the first dentry, and it isn't appropriate - * to move it to the head of the list, so give up, and try - * later + /* + * Insert dentry at the head of the list as inserting at the + * tail leads to a cycle. */ - break; + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; } spin_unlock(&dcache_lock); } -- cgit v0.10.2 From f87135762de4328c6f17897e803e6909bc056feb Mon Sep 17 00:00:00 2001 From: David Howells Date: Sat, 28 Oct 2006 10:38:46 -0700 Subject: [PATCH] VFS: Fix an error in unused dentry counting With Vasily Averin Fix an error in unused dentry counting in shrink_dcache_for_umount_subtree() in which the count is modified without the dcache_lock held. Signed-off-by: David Howells Cc: Vasily Averin Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/dcache.c b/fs/dcache.c index a5b76b6..fd4a428 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -557,6 +557,7 @@ repeat: static void shrink_dcache_for_umount_subtree(struct dentry *dentry) { struct dentry *parent; + unsigned detached = 0; BUG_ON(!IS_ROOT(dentry)); @@ -621,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) atomic_dec(&parent->d_count); list_del(&dentry->d_u.d_child); - dentry_stat.nr_dentry--; /* For d_free, below */ + detached++; inode = dentry->d_inode; if (inode) { @@ -639,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) * otherwise we ascend to the parent and move to the * next sibling if there is one */ if (!parent) - return; + goto out; dentry = parent; @@ -648,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) dentry = list_entry(dentry->d_subdirs.next, struct dentry, d_u.d_child); } +out: + /* several dentries were freed, need to correct nr_dentry */ + spin_lock(&dcache_lock); + dentry_stat.nr_dentry -= detached; + spin_unlock(&dcache_lock); } /* -- cgit v0.10.2 From 5fa3839a64203b2ab727dcb37da9b2d7079fca28 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sat, 28 Oct 2006 10:38:46 -0700 Subject: [PATCH] Constify compat_get_bitmap argument This means we can call it when the bitmap we want to fetch is declared const. Signed-off-by: Stephen Rothwell Cc: Christoph Lameter Cc: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compat.h b/include/linux/compat.h index f4ebf96..f155319 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -196,7 +196,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, #define BITS_TO_COMPAT_LONGS(bits) \ (((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG) -long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask, +long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, unsigned long bitmap_size); long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, unsigned long bitmap_size); diff --git a/kernel/compat.c b/kernel/compat.c index 75573e5..d4898aa 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -678,7 +678,7 @@ int get_compat_sigevent(struct sigevent *event, ? -EFAULT : 0; } -long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask, +long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, unsigned long bitmap_size) { int i, j; -- cgit v0.10.2 From 6e6d9fa6f95e382bb2d5725dda18b9e811418e79 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Sat, 28 Oct 2006 10:38:47 -0700 Subject: [PATCH] strstrip remove last blank fix strstrip() does not remove the last blank from strings which only consist of blanks. Example: char string[] = " "; strstrip(string); results in " ", but should produce an empty string! The following patch solves this problem: Acked-by: Martin Schwidefsky Signed-off-by: Michael Holzheu Acked-by: Pekka Enberg Acked-by Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/string.c b/lib/string.c index 6307726..a485d75 100644 --- a/lib/string.c +++ b/lib/string.c @@ -320,7 +320,7 @@ char *strstrip(char *s) return s; end = s + size - 1; - while (end != s && isspace(*end)) + while (end >= s && isspace(*end)) end--; *(end + 1) = '\0'; -- cgit v0.10.2 From fca178c0c6e8d52a1875be36b070f30884ebfae9 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:49 -0700 Subject: [PATCH] fill_tgid: fix task_struct leak and possible oops 1. fill_tgid() forgets to do put_task_struct(first). 2. release_task(first) can happen after fill_tgid() drops tasklist_lock, it is unsafe to dereference first->signal. This is a temporary fix, imho the locking should be reworked. Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 5d6a8c5..9aeee51 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -237,14 +237,17 @@ static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, } else get_task_struct(first); - /* Start with stats from dead tasks */ - spin_lock_irqsave(&first->signal->stats_lock, flags); - if (first->signal->stats) - memcpy(stats, first->signal->stats, sizeof(*stats)); - spin_unlock_irqrestore(&first->signal->stats_lock, flags); tsk = first; read_lock(&tasklist_lock); + /* Start with stats from dead tasks */ + if (first->signal) { + spin_lock_irqsave(&first->signal->stats_lock, flags); + if (first->signal->stats) + memcpy(stats, first->signal->stats, sizeof(*stats)); + spin_unlock_irqrestore(&first->signal->stats_lock, flags); + } + do { if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) continue; @@ -264,7 +267,7 @@ static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, * Accounting subsytems can also add calls here to modify * fields of taskstats. */ - + put_task_struct(first); return 0; } -- cgit v0.10.2 From 05d5bcd60e8202e5c7b28cf61186043a4d612623 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:50 -0700 Subject: [PATCH] bacct_add_tsk: fix unsafe and wrong parent/group_leader dereference 1. ts = timespec_sub(uptime, current->group_leader->start_time); It is possible that current != tsk. Probably it was supposed to be 'tsk->group_leader->start_time. But why we are reading group_leader's start_time ? This accounting is per thread, not per procees, I changed this to 'tsk->start_time. Please corect me. 2. stats->ac_ppid = (tsk->parent) ? tsk->parent->pid : 0; tsk->parent never == NULL, and it is unsafe to dereference it. Both the task and it's parent may exit after the caller unlocks tasklist_lock, the memory could be unmapped (DEBUG_SLAB). (And we should use ->real_parent->tgid in fact). Q: I don't understand the 'if (thread_group_leader(tsk))' check. Why it is needed ? Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Acked-by: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/tsacct.c b/kernel/tsacct.c index db44322..65a5036 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -36,7 +36,7 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) /* calculate task elapsed time in timespec */ do_posix_clock_monotonic_gettime(&uptime); - ts = timespec_sub(uptime, current->group_leader->start_time); + ts = timespec_sub(uptime, tsk->start_time); /* rebase elapsed time to usec */ ac_etime = timespec_to_ns(&ts); do_div(ac_etime, NSEC_PER_USEC); @@ -58,7 +58,10 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) stats->ac_uid = tsk->uid; stats->ac_gid = tsk->gid; stats->ac_pid = tsk->pid; - stats->ac_ppid = (tsk->parent) ? tsk->parent->pid : 0; + rcu_read_lock(); + stats->ac_ppid = pid_alive(tsk) ? + rcu_dereference(tsk->real_parent)->tgid : 0; + rcu_read_unlock(); stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC; stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC; stats->ac_minflt = tsk->min_flt; -- cgit v0.10.2 From 093a8e8aecd77b2799934996a55a6838e1e2b8f3 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:51 -0700 Subject: [PATCH] taskstats_tgid_free: fix usage taskstats_tgid_free() is called on copy_process's error path. This is wrong. IF (clone_flags & CLONE_THREAD) We should not clear ->signal->taskstats, current uses it, it probably has a valid accumulated info. ELSE taskstats_tgid_init() set ->signal->taskstats = NULL, there is nothing to free. Move the callsite to __exit_signal(). We don't need any locking, entire thread group is exiting, nobody should have a reference to soon to be released ->signal. Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index 16894b7..a437ca0 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h @@ -49,17 +49,8 @@ static inline void taskstats_tgid_alloc(struct signal_struct *sig) static inline void taskstats_tgid_free(struct signal_struct *sig) { - struct taskstats *stats = NULL; - unsigned long flags; - - spin_lock_irqsave(&sig->stats_lock, flags); - if (sig->stats) { - stats = sig->stats; - sig->stats = NULL; - } - spin_unlock_irqrestore(&sig->stats_lock, flags); - if (stats) - kmem_cache_free(taskstats_cache, stats); + if (sig->stats) + kmem_cache_free(taskstats_cache, sig->stats); } extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); diff --git a/kernel/exit.c b/kernel/exit.c index f250a5e..06de6c4 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -128,6 +128,7 @@ static void __exit_signal(struct task_struct *tsk) flush_sigqueue(&tsk->pending); if (sig) { flush_sigqueue(&sig->shared_pending); + taskstats_tgid_free(sig); __cleanup_signal(sig); } } diff --git a/kernel/fork.c b/kernel/fork.c index 29ebb30..2133266 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -897,7 +897,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts void __cleanup_signal(struct signal_struct *sig) { exit_thread_group_keys(sig); - taskstats_tgid_free(sig); kmem_cache_free(signal_cachep, sig); } -- cgit v0.10.2 From 17b02695b254aa2ef0e53df9c8e6548f86e66a9d Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:52 -0700 Subject: [PATCH] taskstats_tgid_alloc: optimization Every subthread (except first) does unneeded kmem_cache_alloc/kmem_cache_free. Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index a437ca0..6642240 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h @@ -32,6 +32,9 @@ static inline void taskstats_tgid_alloc(struct signal_struct *sig) struct taskstats *stats; unsigned long flags; + if (sig->stats != NULL) + return; + stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); if (!stats) return; -- cgit v0.10.2 From b8534d7bd89df0cd41cd47bcd6733a05ea9a691a Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:53 -0700 Subject: [PATCH] taskstats: kill ->taskstats_lock in favor of ->siglock signal_struct is (mostly) protected by ->sighand->siglock, I think we don't need ->taskstats_lock to protect ->stats. This also allows us to simplify the locking in fill_tgid(). Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/sched.h b/include/linux/sched.h index 6735c1c..eafe4a7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -466,7 +466,6 @@ struct signal_struct { struct pacct_struct pacct; /* per-process accounting information */ #endif #ifdef CONFIG_TASKSTATS - spinlock_t stats_lock; struct taskstats *stats; #endif }; diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index 6642240..6562a20 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h @@ -23,28 +23,26 @@ static inline void taskstats_exit_free(struct taskstats *tidstats) static inline void taskstats_tgid_init(struct signal_struct *sig) { - spin_lock_init(&sig->stats_lock); sig->stats = NULL; } -static inline void taskstats_tgid_alloc(struct signal_struct *sig) +static inline void taskstats_tgid_alloc(struct task_struct *tsk) { + struct signal_struct *sig = tsk->signal; struct taskstats *stats; - unsigned long flags; if (sig->stats != NULL) return; + /* No problem if kmem_cache_zalloc() fails */ stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); - if (!stats) - return; - spin_lock_irqsave(&sig->stats_lock, flags); + spin_lock_irq(&tsk->sighand->siglock); if (!sig->stats) { sig->stats = stats; stats = NULL; } - spin_unlock_irqrestore(&sig->stats_lock, flags); + spin_unlock_irq(&tsk->sighand->siglock); if (stats) kmem_cache_free(taskstats_cache, stats); @@ -59,7 +57,6 @@ static inline void taskstats_tgid_free(struct signal_struct *sig) extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int); extern void taskstats_init_early(void); -extern void taskstats_tgid_alloc(struct signal_struct *); #else static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) {} @@ -71,7 +68,7 @@ static inline void taskstats_exit_send(struct task_struct *tsk, {} static inline void taskstats_tgid_init(struct signal_struct *sig) {} -static inline void taskstats_tgid_alloc(struct signal_struct *sig) +static inline void taskstats_tgid_alloc(struct task_struct *tsk) {} static inline void taskstats_tgid_free(struct signal_struct *sig) {} diff --git a/kernel/fork.c b/kernel/fork.c index 2133266..3da978e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -830,7 +830,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts if (clone_flags & CLONE_THREAD) { atomic_inc(¤t->signal->count); atomic_inc(¤t->signal->live); - taskstats_tgid_alloc(current->signal); + taskstats_tgid_alloc(current); return 0; } sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 9aeee51..b2efda9 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -241,11 +241,11 @@ static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, tsk = first; read_lock(&tasklist_lock); /* Start with stats from dead tasks */ - if (first->signal) { - spin_lock_irqsave(&first->signal->stats_lock, flags); + if (first->sighand) { + spin_lock_irqsave(&first->sighand->siglock, flags); if (first->signal->stats) memcpy(stats, first->signal->stats, sizeof(*stats)); - spin_unlock_irqrestore(&first->signal->stats_lock, flags); + spin_unlock_irqrestore(&first->sighand->siglock, flags); } do { @@ -276,7 +276,7 @@ static void fill_tgid_exit(struct task_struct *tsk) { unsigned long flags; - spin_lock_irqsave(&tsk->signal->stats_lock, flags); + spin_lock_irqsave(&tsk->sighand->siglock, flags); if (!tsk->signal->stats) goto ret; @@ -288,7 +288,7 @@ static void fill_tgid_exit(struct task_struct *tsk) */ delayacct_add_tsk(tsk->signal->stats, tsk); ret: - spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); return; } @@ -464,15 +464,10 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, size_t size; int is_thread_group; struct nlattr *na; - unsigned long flags; if (!family_registered || !tidstats) return; - spin_lock_irqsave(&tsk->signal->stats_lock, flags); - is_thread_group = tsk->signal->stats ? 1 : 0; - spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); - rc = 0; /* * Size includes space for nested attributes @@ -480,6 +475,7 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, size = nla_total_size(sizeof(u32)) + nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); + is_thread_group = (tsk->signal->stats != NULL); if (is_thread_group) size = 2 * size; /* PID + STATS + TGID + STATS */ -- cgit v0.10.2 From a98b6094261c0112e9c455c96995972181bff049 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:54 -0700 Subject: [PATCH] taskstats: don't use tasklist_lock Remove tasklist_lock from taskstats.c. find_task_by_pid() is rcu-safe. ->siglock allows us to traverse subthread without tasklist. Q: delay accounting looks wrong to me. If sub-thread has already called taskstats_exit_send() but didn't call release_task(self) yet it will be accounted twice. The window is big. No? Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index b2efda9..b724aee 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -174,21 +174,19 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) up_write(&listeners->sem); } -static int fill_pid(pid_t pid, struct task_struct *pidtsk, +static int fill_pid(pid_t pid, struct task_struct *tsk, struct taskstats *stats) { int rc = 0; - struct task_struct *tsk = pidtsk; - if (!pidtsk) { - read_lock(&tasklist_lock); + if (!tsk) { + rcu_read_lock(); tsk = find_task_by_pid(pid); - if (!tsk) { - read_unlock(&tasklist_lock); + if (tsk) + get_task_struct(tsk); + rcu_read_unlock(); + if (!tsk) return -ESRCH; - } - get_task_struct(tsk); - read_unlock(&tasklist_lock); } else get_task_struct(tsk); @@ -214,40 +212,28 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk, } -static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, +static int fill_tgid(pid_t tgid, struct task_struct *first, struct taskstats *stats) { - struct task_struct *tsk, *first; + struct task_struct *tsk; unsigned long flags; + int rc = -ESRCH; /* * Add additional stats from live tasks except zombie thread group * leaders who are already counted with the dead tasks */ - first = tgidtsk; - if (!first) { - read_lock(&tasklist_lock); + rcu_read_lock(); + if (!first) first = find_task_by_pid(tgid); - if (!first) { - read_unlock(&tasklist_lock); - return -ESRCH; - } - get_task_struct(first); - read_unlock(&tasklist_lock); - } else - get_task_struct(first); + if (!first || !lock_task_sighand(first, &flags)) + goto out; - tsk = first; - read_lock(&tasklist_lock); - /* Start with stats from dead tasks */ - if (first->sighand) { - spin_lock_irqsave(&first->sighand->siglock, flags); - if (first->signal->stats) - memcpy(stats, first->signal->stats, sizeof(*stats)); - spin_unlock_irqrestore(&first->sighand->siglock, flags); - } + if (first->signal->stats) + memcpy(stats, first->signal->stats, sizeof(*stats)); + tsk = first; do { if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) continue; @@ -260,15 +246,18 @@ static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, delayacct_add_tsk(stats, tsk); } while_each_thread(first, tsk); - read_unlock(&tasklist_lock); - stats->version = TASKSTATS_VERSION; + unlock_task_sighand(first, &flags); + rc = 0; +out: + rcu_read_unlock(); + + stats->version = TASKSTATS_VERSION; /* * Accounting subsytems can also add calls here to modify * fields of taskstats. */ - put_task_struct(first); - return 0; + return rc; } -- cgit v0.10.2 From d7c3f5f231c60d7e6ada5770b536df2b3ec1bd08 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 28 Oct 2006 10:38:54 -0700 Subject: [PATCH] fill_tgid: cleanup delays accounting fill_tgid() should skip not only an already exited group leader. If the task has ->exit_state != 0 it already did exit_notify(), so it also did fill_tgid_exit()->delayacct_add_tsk(->signal->stats) and we should skip it to avoid a double accounting. This patch doesn't close the race completely, but it cleanups the code. Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index b724aee..8adfb80 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -235,7 +235,7 @@ static int fill_tgid(pid_t tgid, struct task_struct *first, tsk = first; do { - if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) + if (tsk->exit_state) continue; /* * Accounting subsystem can call its functions here to -- cgit v0.10.2 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 diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 0b4e224..1429f3a2 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 v0.10.2 From bb1d860551c4307b1a7ee9a21b120319075e987e Mon Sep 17 00:00:00 2001 From: Jim Houston Date: Sat, 28 Oct 2006 10:38:56 -0700 Subject: [PATCH] time_adjust cleared before use I notice that the code which implements adjtime clears the time_adjust value before using it. The attached patch makes the obvious fix. Acked-by: Roman Zippel Signed-off-by: Jim Houston Cc: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 47195fa..3afeaa3 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -161,9 +161,9 @@ void second_overflow(void) time_adjust += MAX_TICKADJ; tick_length -= MAX_TICKADJ_SCALED; } else { - time_adjust = 0; tick_length += (s64)(time_adjust * NSEC_PER_USEC / HZ) << TICK_LENGTH_SHIFT; + time_adjust = 0; } } } -- cgit v0.10.2 From 8fa1d7d3b2c51594c0f3aa151983dd51f605e07d Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Sat, 28 Oct 2006 10:38:57 -0700 Subject: [PATCH] cpu-hotplug: release `workqueue_mutex' properly on CPU hot-remove _cpu_down() acquires `workqueue_mutex' on its process, but doen't release it if __cpu_disable() fails. Signed-off-by: Satoru Takeuchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/cpu.c b/kernel/cpu.c index 27dd3ee..663c920 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -150,18 +150,18 @@ static int _cpu_down(unsigned int cpu) p = __stop_machine_run(take_cpu_down, NULL, cpu); mutex_unlock(&cpu_bitmask_lock); - if (IS_ERR(p)) { + if (IS_ERR(p) || cpu_online(cpu)) { /* CPU didn't die: tell everyone. Can't complain. */ if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, (void *)(long)cpu) == NOTIFY_BAD) BUG(); - err = PTR_ERR(p); - goto out_allowed; - } - - if (cpu_online(cpu)) + if (IS_ERR(p)) { + err = PTR_ERR(p); + goto out_allowed; + } goto out_thread; + } /* Wait for it to sleep (leaving idle task). */ while (!idle_cpu(cpu)) -- cgit v0.10.2 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 diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index ad418ce..e72ab36 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 v0.10.2 From 057647fc47b3a5fbcfa997041db3f483d506603c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 28 Oct 2006 10:38:58 -0700 Subject: [PATCH] workqueue: update kerneldoc This patch (as812) changes the kerneldoc comments explaining the return values from queue_work(), queue_delayed_work(), and queue_delayed_work_on(). The updated comments explain more accurately the meaning of the return code and avoid suggesting that a 0 value means the routine was unsuccessful. Signed-off-by: Alan Stern Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3df9bfc..17c2f03 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -99,7 +99,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, * @wq: workqueue to use * @work: work to queue * - * Returns non-zero if it was successfully added. + * Returns 0 if @work was already on a queue, non-zero otherwise. * * We queue the work to the CPU it was submitted, but there is no * guarantee that it will be processed by that CPU. @@ -138,7 +138,7 @@ static void delayed_work_timer_fn(unsigned long __data) * @work: work to queue * @delay: number of jiffies to wait before queueing * - * Returns non-zero if it was successfully added. + * Returns 0 if @work was already on a queue, non-zero otherwise. */ int fastcall queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) @@ -169,7 +169,7 @@ EXPORT_SYMBOL_GPL(queue_delayed_work); * @work: work to queue * @delay: number of jiffies to wait before queueing * - * Returns non-zero if it was successfully added. + * Returns 0 if @work was already on a queue, non-zero otherwise. */ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) -- cgit v0.10.2 From 0c6cb974636dd29681b03f8eb0ae227decab01fb Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Sat, 28 Oct 2006 10:38:59 -0700 Subject: [PATCH] Calculation fix for memory holes beyong the end of physical memory absent_pages_in_range() made the assumption that users of the arch-independent zone-sizing API would not care about holes beyound the end of physical memory. This was not the case and was "fixed" in a patch called "Account for holes that are outside the range of physical memory". However, when given a range that started before a hole in "real" memory and ended beyond the end of memory, it would get the result wrong. The bug is in mainline but a patch is below. It has been tested successfully on a number of machines and architectures. Additional credit to Keith Mannthey for discovering the problem, helping identify the correct fix and confirming it Worked For Him. Signed-off-by: Mel Gorman Cc: keith mannthey Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ecf853b..b55bb35 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2261,7 +2261,7 @@ unsigned long __init __absent_pages_in_range(int nid, /* Account for ranges past physical memory on this node */ if (range_end_pfn > prev_end_pfn) - hole_pages = range_end_pfn - + hole_pages += range_end_pfn - max(range_start_pfn, prev_end_pfn); return hole_pages; -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index bd7727b..1d447e3 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 v0.10.2 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 diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 81050d3..c95a6c1 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 v0.10.2 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 diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index b351813..dca9f85 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 e46cff3..235d681 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 fd1f691..a92f111 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 v0.10.2 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 diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index d8d0f28..e323983 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 v0.10.2 From 51342d7126342e1f1a40cd96a5798a3cfd6136eb Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 29 Oct 2006 12:51:05 +0000 Subject: [ARM] Add KBUILD_IMAGE target support Add support for KBUILD_IMAGE on ARM. This takes the usual target specifiers (zImage/Image/etc) in the same way that powerpc does (iow, without the arch/arm/boot prefix). Signed-off-by: Russell King diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 2a0b2c8..6f4f8bf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -174,11 +174,13 @@ libs-y := arch/arm/lib/ $(libs-y) # Default target when executing plain make ifeq ($(CONFIG_XIP_KERNEL),y) -all: xipImage +KBUILD_IMAGE := xipImage else -all: zImage +KBUILD_IMAGE := zImage endif +all: $(KBUILD_IMAGE) + boot := arch/arm/boot # Update machine arch and proc symlinks if something which affects -- cgit v0.10.2 From 5211e6e6c671f0d4b1e1a1023384d20227d8ee65 Mon Sep 17 00:00:00 2001 From: Giridhar Pemmasani Date: Sun, 29 Oct 2006 04:46:55 -0800 Subject: [PATCH] Fix GFP_HIGHMEM slab panic As reported by Martin J. Bligh , we let through some non-slab bits to slab allocation through __get_vm_area_node when doing a vmalloc. I haven't been able to reproduce this, although I understand why it happens: vmalloc allocates memory with GFP_KERNEL | __GFP_HIGHMEM and commit 52fd24ca1db3a741f144bbc229beefe044202cac resulted in the same flags are passed down to cache_alloc_refill, causing the BUG. The following patch fixes it. Note that when calling kmalloc_node, I am masking off __GFP_HIGHMEM with GFP_LEVEL_MASK, whereas __vmalloc_area_node does the same with ~(__GFP_HIGHMEM | __GFP_ZERO). IMHO, using GFP_LEVEL_MASK is preferable, but either should fix this problem. Signed-off-by: Giridhar Pemmasani (pgiri@yahoo.com) Cc: Martin J. Bligh Cc: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6d381df..46606c1 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -182,7 +182,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl addr = ALIGN(start, align); size = PAGE_ALIGN(size); - area = kmalloc_node(sizeof(*area), gfp_mask, node); + area = kmalloc_node(sizeof(*area), gfp_mask & GFP_LEVEL_MASK, node); if (unlikely(!area)) return NULL; -- cgit v0.10.2 From 811c9a4b618ffc7de097490f8dc61b43b8464b9c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 29 Oct 2006 14:15:10 +0100 Subject: [ARM] 3913/1: n2100: fix IRQ routing for second ethernet port The second ethernet port on the Thecus n2100 was incorrectly assigned to XINT1 instead of the correct XINT3 (PCI INTB instead of INTD), which caused that port to be non-functional. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index a2c94a4..2499a77 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c @@ -85,7 +85,7 @@ n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) irq = IRQ_IOP32X_XINT0; } else if (PCI_SLOT(dev->devfn) == 2) { /* RTL8110SB #2 */ - irq = IRQ_IOP32X_XINT1; + irq = IRQ_IOP32X_XINT3; } else if (PCI_SLOT(dev->devfn) == 3) { /* Sil3512 */ irq = IRQ_IOP32X_XINT2; -- cgit v0.10.2 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 diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index dea1352..6e8ea91 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 v0.10.2 From d46a3d0d07ba539aea5b0e1ad30e568f0cb03576 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 29 Oct 2006 16:45:58 +0300 Subject: [PATCH] taskstats: fix sk_buff leak 'return genlmsg_cancel()' in taskstats_user_cmd/taskstats_exit_send potentially leaks a skb. Unless we pass 'rep_skb' to the netlink layer we own sk_buff. This means we should always do kfree_skb() on failure. [ Thomas acked and pointed out missing return value in original version ] Signed-off-by: Oleg Nesterov Acked-by: Thomas Graf Cc: Andrew Morton Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 8adfb80..f3c3e9d 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -411,7 +411,7 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) return send_reply(rep_skb, info->snd_pid); nla_put_failure: - return genlmsg_cancel(rep_skb, reply); + rc = genlmsg_cancel(rep_skb, reply); err: nlmsg_free(rep_skb); return rc; @@ -507,7 +507,6 @@ send: nla_put_failure: genlmsg_cancel(rep_skb, reply); - goto ret; err_skb: nlmsg_free(rep_skb); ret: -- cgit v0.10.2 From 3d8334def5cf831d2ed438aae021696a2faa4ddd Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 29 Oct 2006 18:57:16 +0300 Subject: [PATCH] taskstats: fix sk_buff size calculation prepare_reply() adds GENL_HDRLEN to the payload (genlmsg_total_size()), but then it does genlmsg_put()->nlmsg_put(). This means we forget to reserve a room for 'struct nlmsghdr'. Signed-off-by: Oleg Nesterov Cc: Thomas Graf Cc: Andrew Morton Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index f3c3e9d..2039585 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -77,7 +77,8 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, /* * If new attributes are added, please revisit this allocation */ - skb = nlmsg_new(genlmsg_total_size(size), GFP_KERNEL); + size = nlmsg_total_size(genlmsg_total_size(size)); + skb = nlmsg_new(size, GFP_KERNEL); if (!skb) return -ENOMEM; -- cgit v0.10.2 From 5fdb51a10f3ab4320c3170b79d66ce34a6e65a67 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 29 Oct 2006 11:21:51 +0100 Subject: [PATCH] m68k: consolidate initcall sections Commit 61ce1efe6e40233663d27ab8ac9ba9710eebcaad missed the m68k initcall sections. Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Torvalds diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 69d1d3d..d279445 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -54,13 +54,7 @@ SECTIONS __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 65cc39c..2550b4a 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -48,13 +48,7 @@ __init_begin = .; __setup_end = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; __con_initcall_start = .; -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index d8d0f28..e323983 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 v0.10.2 From 9f0f9313cec8c76c89bc8a68653f928fa12fab96 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Sun, 29 Oct 2006 22:38:08 +0100 Subject: [ARM] 3914/1: [Jornada7xx] - Typo Fix in cpu-sa1110.c (b != B) "K4S281632b-1H" should read "K4S281632B-1H" (As it does everywhere else). No more coffe! Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 90a4130..78f4c13 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -83,7 +83,7 @@ static struct sdram_params sdram_tbl[] __initdata = { .refresh = 64000, .cas_latency = 3, }, { /* Samsung K4S281632B-1H */ - .name = "K4S281632b-1H", + .name = "K4S281632B-1H", .rows = 12, .tck = 10, .trp = 20, -- cgit v0.10.2 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 diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index d132fe7..27f90b2 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 v0.10.2 From 89f68225876db7df638de2884b561facb1870239 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 30 Oct 2006 11:47:02 -0600 Subject: jfs: Add splice support This allows the splice() and tee() syscalls to be used with JFS. Signed-off-by: Daniel Drake Signed-off-by: Dave Kleikamp diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 34181b8..aa9132d 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -109,6 +109,8 @@ const struct file_operations jfs_file_operations = { .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .sendfile = generic_file_sendfile, + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, .fsync = jfs_fsync, .release = jfs_release, .ioctl = jfs_ioctl, -- cgit v0.10.2 From 0261d6886eb5822867a5310dc1e4479b940a1942 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 30 Oct 2006 19:07:48 +0100 Subject: [PATCH] CFQ: use irq safe locking in cfq_cic_link() If cfq_set_request() is called for a new process AND a non-fs io request (so that __GFP_WAIT may not be set), cfq_cic_link() may use spin_lock_irq() and spin_unlock_irq() with interrupts already disabled. Fix is to always use irq safe locking in cfq_cic_link() Acked-By: Arjan van de Ven Acked-by: Ingo Molnar Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index d3d7613..5c3da89 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1362,6 +1362,7 @@ cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, struct rb_node **p; struct rb_node *parent; struct cfq_io_context *__cic; + unsigned long flags; void *k; cic->ioc = ioc; @@ -1391,9 +1392,9 @@ restart: rb_link_node(&cic->rb_node, parent, p); rb_insert_color(&cic->rb_node, &ioc->cic_root); - spin_lock_irq(cfqd->queue->queue_lock); + spin_lock_irqsave(cfqd->queue->queue_lock, flags); list_add(&cic->queue_list, &cfqd->cic_list); - spin_unlock_irq(cfqd->queue->queue_lock); + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); } /* -- cgit v0.10.2 From c1b707d253fe918b92882cff1dbd926b47e14fd2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 30 Oct 2006 19:54:23 +0100 Subject: [PATCH] CFQ: bad locking in changed_ioprio() When the ioprio code recently got juggled a bit, a bug was introduced. changed_ioprio() is no longer called with interrupts disabled, so using plain spin_lock() on the queue_lock is a bug. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5c3da89..25c4e7e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1215,11 +1215,12 @@ static inline void changed_ioprio(struct cfq_io_context *cic) { struct cfq_data *cfqd = cic->key; struct cfq_queue *cfqq; + unsigned long flags; if (unlikely(!cfqd)) return; - spin_lock(cfqd->queue->queue_lock); + spin_lock_irqsave(cfqd->queue->queue_lock, flags); cfqq = cic->cfqq[ASYNC]; if (cfqq) { @@ -1236,7 +1237,7 @@ static inline void changed_ioprio(struct cfq_io_context *cic) if (cfqq) cfq_mark_cfqq_prio_changed(cfqq); - spin_unlock(cfqd->queue->queue_lock); + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); } static void cfq_ioc_set_ioprio(struct io_context *ioc) -- cgit v0.10.2 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 diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a625576..08a40f4 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 v0.10.2 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 diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index ff4fa25..711bd15 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 v0.10.2 From 0e2d57fc6e7dabdbfdd4f26c861e7e6c75d5bdcf Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 29 Oct 2006 22:46:34 -0800 Subject: [PATCH] ndiswrapper: don't set the module->taints flags For ndiswrapper, don't set the module->taints flags, just set the kernel global tainted flag. This should allow ndiswrapper to continue to use GPL symbols. Signed-off-by: Randy Dunlap Cc: Florin Malita Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/module.c b/kernel/module.c index 5072a94..f016656 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1718,7 +1718,7 @@ static struct module *load_module(void __user *umod, set_license(mod, get_modinfo(sechdrs, infoindex, "license")); if (strcmp(mod->name, "ndiswrapper") == 0) - add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + add_taint(TAINT_PROPRIETARY_MODULE); if (strcmp(mod->name, "driverloader") == 0) add_taint_module(mod, TAINT_PROPRIETARY_MODULE); -- cgit v0.10.2 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 diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index aca165d..d8d256d 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 v0.10.2 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 diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 845b868..cbc0725 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 01a5a70..a235064 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 b3fa7ed..5a49216 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 2d95ac9..e31f612 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 d586c3d..19c79a0 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 24a1779..582f5ea 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 b0eba39..89a2a9f 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 cf3d20e..4087363 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 b3b9048..e820d00 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 v0.10.2 From f8da1f746588ba997734274b4aadc5ae501fbd88 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 29 Oct 2006 22:46:39 -0800 Subject: [PATCH] cryptocop: double spin_lock_irqsave() Signed-off-by: Alexey Dobriyan Cc: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index ba096eb..2449637 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -2051,7 +2051,6 @@ static void cryptocop_job_queue_close(void) spin_lock_irqsave(&cryptocop_process_lock, process_flags); /* Empty the job queue. */ - spin_lock_irqsave(&cryptocop_process_lock, process_flags); for (i = 0; i < cryptocop_prio_no_prios; i++){ if (!list_empty(&(cryptocop_job_queues[i].jobs))){ list_for_each_safe(node, tmp, &(cryptocop_job_queues[i].jobs)) { -- cgit v0.10.2 From 351edd240d0ba8620789ca9e24f5a38b62157f23 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 29 Oct 2006 22:46:40 -0800 Subject: [PATCH] MTD: fix last kernel-doc warning Fix the last current kernel-doc warning: Warning(/var/linsrc/linux-2619-rc3g5//include/linux/mtd/nand.h:416): No description found for parameter 'write_page' Signed-off-by: Randy Dunlap Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 70420bb..8b3ef41 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -355,7 +355,7 @@ struct nand_buffers { * @priv: [OPTIONAL] pointer to private chip date * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks * (determine if errors are correctable) - * @write_page [REPLACEABLE] High-level page write function + * @write_page: [REPLACEABLE] High-level page write function */ struct nand_chip { -- cgit v0.10.2 From bbb5bbb037812ba36d638014a93134148a568684 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 29 Oct 2006 22:46:40 -0800 Subject: [PATCH] docbook: make a filesystems book Make a filesystems DocBook book/file by moving all filesystems info from kernel-api.tmpl. Will also merge journal-api.tmpl into it soon (with permission from Roger Gammans). Localizes filesystem info and reduces size of the huge (produced) kernel-api output files. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 66e1cf7..3bf5086 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -9,7 +9,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ - kernel-api.xml journal-api.xml lsm.xml usb.xml \ + kernel-api.xml filesystems.xml journal-api.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl new file mode 100644 index 0000000..4785032 --- /dev/null +++ b/Documentation/DocBook/filesystems.tmpl @@ -0,0 +1,101 @@ + + + + + + Linux Filesystems API + + + + This documentation 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 + + + + For more details see the file COPYING in the source + distribution of Linux. + + + + + + + + The Linux VFS + The Filesystem types +!Iinclude/linux/fs.h + + The Directory Cache +!Efs/dcache.c +!Iinclude/linux/dcache.h + + Inode Handling +!Efs/inode.c +!Efs/bad_inode.c + + Registration and Superblocks +!Efs/super.c + + File Locks +!Efs/locks.c +!Ifs/locks.c + + Other Functions +!Efs/mpage.c +!Efs/namei.c +!Efs/buffer.c +!Efs/bio.c +!Efs/seq_file.c +!Efs/filesystems.c +!Efs/fs-writeback.c +!Efs/block_dev.c + + + + + The proc filesystem + + sysctl interface +!Ekernel/sysctl.c + + + proc filesystem interface +!Ifs/proc/base.c + + + + + The Filesystem for Exporting Kernel Objects +!Efs/sysfs/file.c +!Efs/sysfs/symlink.c +!Efs/sysfs/bin.c + + + + The debugfs filesystem + + debugfs interface +!Efs/debugfs/inode.c +!Efs/debugfs/file.c + + + + diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 2b5ac60..a166675 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -182,66 +182,6 @@ X!Ilib/string.c - - The Linux VFS - The Filesystem types -!Iinclude/linux/fs.h - - The Directory Cache -!Efs/dcache.c -!Iinclude/linux/dcache.h - - Inode Handling -!Efs/inode.c -!Efs/bad_inode.c - - Registration and Superblocks -!Efs/super.c - - File Locks -!Efs/locks.c -!Ifs/locks.c - - Other Functions -!Efs/mpage.c -!Efs/namei.c -!Efs/buffer.c -!Efs/bio.c -!Efs/seq_file.c -!Efs/filesystems.c -!Efs/fs-writeback.c -!Efs/block_dev.c - - - - - The proc filesystem - - sysctl interface -!Ekernel/sysctl.c - - - proc filesystem interface -!Ifs/proc/base.c - - - - - The Filesystem for Exporting Kernel Objects -!Efs/sysfs/file.c -!Efs/sysfs/symlink.c -!Efs/sysfs/bin.c - - - - The debugfs filesystem - - debugfs interface -!Efs/debugfs/inode.c -!Efs/debugfs/file.c - - - relay interface support -- cgit v0.10.2 From b428b51ed9a4ff8445ea50769961f948480c1d36 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 29 Oct 2006 22:46:41 -0800 Subject: [PATCH] Fix "Remove the use of _syscallX macros in UML" Fix commit 5f4c6bc1f369f20807a8e753c2308d1629478c61: it spits out warnings about missing syscall prototype (it is in ) and it does not recognize that two uses of _syscallX are to be resolved against kernel headers in the source tree, not against _syscallX; they in fact do not compile and would not work anyway. If _syscallX macros will be removed from the kernel tree altogether, the only reasonable solution for that piece of code is switching to open-coded inline assembly (it's remapping the whole executable from memory, except the page containing this code). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c index 6e945ab..2565320 100644 --- a/arch/um/os-Linux/sys-i386/tls.c +++ b/arch/um/os-Linux/sys-i386/tls.c @@ -1,6 +1,9 @@ #include #include + #include +#include + #include "sysdep/tls.h" #include "user_util.h" diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index a2de258..9f7999f 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "sysdep/tls.h" #include "uml-config.h" diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c index 8e55cd5..1b0ad0e4 100644 --- a/arch/um/sys-i386/unmap.c +++ b/arch/um/sys-i386/unmap.c @@ -5,17 +5,20 @@ #include #include -#include +static int errno; + +static inline _syscall2(int,munmap,void *,start,size_t,len) +static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) int switcheroo(int fd, int prot, void *from, void *to, int size) { - if (syscall(__NR_munmap, to, size) < 0){ + if(munmap(to, size) < 0){ return(-1); } - if (syscall(__NR_mmap2, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ + if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ return(-1); } - if (syscall(__NR_munmap, from, size) < 0){ + if(munmap(from, size) < 0){ return(-1); } return(0); diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c index 57c9286..f4a4bff 100644 --- a/arch/um/sys-x86_64/unmap.c +++ b/arch/um/sys-x86_64/unmap.c @@ -5,17 +5,20 @@ #include #include -#include +static int errno; + +static inline _syscall2(int,munmap,void *,start,size_t,len) +static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) int switcheroo(int fd, int prot, void *from, void *to, int size) { - if (syscall(__NR_munmap, to, size) < 0){ + if(munmap(to, size) < 0){ return(-1); } - if (syscall(__NR_mmap, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ + if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ return(-1); } - if (syscall(__NR_munmap, from, size) < 0){ + if(munmap(from, size) < 0){ return(-1); } return(0); -- cgit v0.10.2 From d45e44d4be60ef508579001792f33753b5cb6d36 Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sun, 29 Oct 2006 22:46:42 -0800 Subject: [PATCH] uml: fix compilation options for USER_OBJS From: Jeff Dike , Paolo Giarrusso Make sure that when compiling USER_OBJS the correct compilation options are passed; since they are compiled with USER_CFLAGS which is derived from CFLAGS, make sure it is a recursively evaluated variable, so that changes to CFLAGS done afterwards the inclusion of arch/$(ARCH)/Makefile are reflected in USER_CFLAGS. For instance, without this patch userspace objects are never compiled with debug info active. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/Makefile b/arch/um/Makefile index c8016a9..5d5ed72 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -64,9 +64,14 @@ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ AFLAGS += $(ARCH_INCLUDE) -USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ - $(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64 +USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ + $(patsubst -I%,,$(CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ + -D_FILE_OFFSET_BITS=64 + +include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) + +#This will adjust *FLAGS accordingly to the platform. +include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common @@ -74,15 +79,11 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ # errnos. # These apply to kernelspace only. -CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ - -Dmktime=kernel_mktime +KERNEL_DEFINES = -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ + -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES) +CFLAGS += $(KERNEL_DEFINES) CFLAGS += $(call cc-option,-fno-unit-at-a-time,) -include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) - -#This will adjust *FLAGS accordingly to the platform. -include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) - # These are needed for clean and mrproper, since in that case .config is not # included; the values here are meaningless diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index b65ca11..c9f1c5b 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -16,7 +16,6 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S ifeq ("$(origin SUBARCH)", "command line") ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") CFLAGS += $(call cc-option,-m32) -USER_CFLAGS += $(call cc-option,-m32) AFLAGS += $(call cc-option,-m32) LINK-y += $(call cc-option,-m32) UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) @@ -25,7 +24,7 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS endif endif -CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) +ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH) # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. include $(srctree)/arch/i386/Makefile.cpu @@ -38,4 +37,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) cflags-y += -ffreestanding CFLAGS += $(cflags-y) -USER_CFLAGS += $(cflags-y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index d278682..69ecea6 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -8,8 +8,8 @@ _extra_flags_ = -fno-builtin -m64 #We #undef __x86_64__ for kernelspace, not for userspace where #it's needed for headers to work! -CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_) -USER_CFLAGS += $(_extra_flags_) +ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__ +CFLAGS += $(_extra_flags_) CHECKFLAGS += -m64 AFLAGS += -m64 -- cgit v0.10.2 From f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 29 Oct 2006 22:46:43 -0800 Subject: [PATCH] xacct_add_tsk: fix pure theoretical ->mm use-after-free Paranoid fix. The task can free its ->mm after the 'if (p->mm)' check. Signed-off-by: Oleg Nesterov Cc: Shailabh Nagar Cc: Balbir Singh Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 65a5036..96f7701 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -80,13 +80,17 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) */ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) { + struct mm_struct *mm; + /* convert pages-jiffies to Mbyte-usec */ stats->coremem = jiffies_to_usecs(p->acct_rss_mem1) * PAGE_SIZE / MB; stats->virtmem = jiffies_to_usecs(p->acct_vm_mem1) * PAGE_SIZE / MB; - if (p->mm) { + mm = get_task_mm(p); + if (mm) { /* adjust to KB unit */ - stats->hiwater_rss = p->mm->hiwater_rss * PAGE_SIZE / KB; - stats->hiwater_vm = p->mm->hiwater_vm * PAGE_SIZE / KB; + stats->hiwater_rss = mm->hiwater_rss * PAGE_SIZE / KB; + stats->hiwater_vm = mm->hiwater_vm * PAGE_SIZE / KB; + mmput(mm); } stats->read_char = p->rchar; stats->write_char = p->wchar; -- cgit v0.10.2 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 diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index e72ab36..9f30688 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 v0.10.2 From d6740df98e12a8e49ef3a699dcc1e2913f22c51b Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Sun, 29 Oct 2006 22:46:45 -0800 Subject: [PATCH] sunrpc: fix refcounting problems in rpc servers A recent patch fixed a problem which would occur when the refcount on an auth_domain reached zero. This problem has not been reported in practice despite existing in two major kernel releases because the refcount can never reach zero. This patch fixes the problems that stop the refcount reaching zero. 1/ We were adding to the refcount when inserting in the hash table, but only removing from the hashtable when the refcount reached zero. Obviously it never would. So don't count the implied reference of being in the hash table. 2/ There are two paths on which a socket can be destroyed. One called svcauth_unix_info_release(). The other didn't. So when the other was taken, we can lose a reference to an ip_map which in-turn holds a reference to an auth_domain So unify the exit paths into svc_sock_put. This highlights the fact that svc_delete_socket has slightly odd semantics - it does not drop a reference but probably should. Fixing this need a bit more thought and testing. Signed-off-by: Neil Brown Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index 8f2320a..0004c1f 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -147,10 +147,8 @@ auth_domain_lookup(char *name, struct auth_domain *new) return hp; } } - if (new) { + if (new) hlist_add_head(&new->hash, head); - kref_get(&new->ref); - } spin_unlock(&auth_domain_lock); return new; } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 96521f1..db0d104 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -300,8 +300,13 @@ static inline void svc_sock_put(struct svc_sock *svsk) { if (atomic_dec_and_test(&svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) { - dprintk("svc: releasing dead socket\n"); - sock_release(svsk->sk_sock); + printk("svc: releasing dead socket\n"); + if (svsk->sk_sock->file) + sockfd_put(svsk->sk_sock); + else + sock_release(svsk->sk_sock); + if (svsk->sk_info_authunix != NULL) + svcauth_unix_info_release(svsk->sk_info_authunix); kfree(svsk); } } @@ -1604,20 +1609,13 @@ svc_delete_socket(struct svc_sock *svsk) if (test_bit(SK_TEMP, &svsk->sk_flags)) serv->sv_tmpcnt--; - if (!atomic_read(&svsk->sk_inuse)) { - spin_unlock_bh(&serv->sv_lock); - if (svsk->sk_sock->file) - sockfd_put(svsk->sk_sock); - else - sock_release(svsk->sk_sock); - if (svsk->sk_info_authunix != NULL) - svcauth_unix_info_release(svsk->sk_info_authunix); - kfree(svsk); - } else { - spin_unlock_bh(&serv->sv_lock); - dprintk(KERN_NOTICE "svc: server socket destroy delayed\n"); - /* svsk->sk_server = NULL; */ - } + /* This atomic_inc should be needed - svc_delete_socket + * should have the semantic of dropping a reference. + * But it doesn't yet.... + */ + atomic_inc(&svsk->sk_inuse); + spin_unlock_bh(&serv->sv_lock); + svc_sock_put(svsk); } /* -- cgit v0.10.2 From 3f4b23e9833f0816b57d07401eac5e184b627fd7 Mon Sep 17 00:00:00 2001 From: Kristian Mueller Date: Sun, 29 Oct 2006 22:46:46 -0800 Subject: [PATCH] APM: URL of APM 1.2 specs has changed APM BIOS Interface Secification can now be found at http://www.microsoft.com/whdc/archive/amp_12.mspx Signed-off-by: Kristian Mueller Acked-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 2af6585..a60358f 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -198,7 +198,7 @@ * (APM) BIOS Interface Specification, Revision 1.2, February 1996. * * [This document is available from Microsoft at: - * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + * http://www.microsoft.com/whdc/archive/amp_12.mspx] */ #include -- cgit v0.10.2 From 202dd450246cd658e298a86dddca5592fcb898cd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 29 Oct 2006 22:57:57 -0800 Subject: [PATCH] fix "sunrpc: fix refcounting problems in rpc servers" - printk should remain dprintk - fix coding-style. Cc: Neil Brown Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index db0d104..64ca1f6 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -299,8 +299,9 @@ void svc_reserve(struct svc_rqst *rqstp, int space) static inline void svc_sock_put(struct svc_sock *svsk) { - if (atomic_dec_and_test(&svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) { - printk("svc: releasing dead socket\n"); + if (atomic_dec_and_test(&svsk->sk_inuse) && + test_bit(SK_DEAD, &svsk->sk_flags)) { + dprintk("svc: releasing dead socket\n"); if (svsk->sk_sock->file) sockfd_put(svsk->sk_sock); else -- cgit v0.10.2 From a7aacdf9ea45bf6139cfd750e558a3dcbc6f16c3 Mon Sep 17 00:00:00 2001 From: Albert Cahalan Date: Sun, 29 Oct 2006 22:26:17 -0500 Subject: [PATCH] fix i386 regparm=3 RT signal handlers on x86_64 The recent change to make x86_64 support i386 binaries compiled with -mregparm=3 only covered signal handlers without SA_SIGINFO. (the 3-arg "real-time" ones) This is useful for klibc at least. Signed-off-by: Albert Cahalan Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index a6ba995..0e0a266 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -579,6 +579,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->rsp = (unsigned long) frame; regs->rip = (unsigned long) ka->sa.sa_handler; + /* Make -mregparm=3 work */ + regs->rax = sig; + regs->rdx = (unsigned long) &frame->info; + regs->rcx = (unsigned long) &frame->uc; + asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); -- cgit v0.10.2 From be609f3546d3dd96afd7df8856a91fa2b8825fbc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 23 Oct 2006 13:22:06 +0100 Subject: [MIPS] Oprofile: fix on non-VSMP / non-SMTC SMP configurations. Signed-off-by: Ralf Baechle diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index dd0aec9..ebce715 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -31,16 +31,18 @@ #define M_COUNTER_OVERFLOW (1UL << 31) #ifdef CONFIG_MIPS_MT_SMP -#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define vpe_id() smp_processor_id() #else -#define WHAT 0 +#define WHAT 0 +#define vpe_id() smp_processor_id() #endif #define __define_perf_accessors(r, n, np) \ \ static inline unsigned int r_c0_ ## r ## n(void) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -55,7 +57,7 @@ static inline unsigned int r_c0_ ## r ## n(void) \ \ static inline void w_c0_ ## r ## n(unsigned int value) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ -- cgit v0.10.2 From 53c1b192ece077e1c3892e6afb453ab6f009af81 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 3 Sep 2006 22:17:10 +0400 Subject: [MIPS] Au1xx0 code sets incorrect mips_hpt_frequency Alchemy CPU counter ticks at the full CPU clock speed. Signed-off-by: Sergei Shtylyov Signed-off-by: Ralf Baechle diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 94f0919..7313ef2 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -231,7 +231,6 @@ wakeup_counter0_set(int ticks) */ unsigned long cal_r4koff(void) { - unsigned long count; unsigned long cpu_speed; unsigned long flags; unsigned long counter; @@ -258,7 +257,7 @@ unsigned long cal_r4koff(void) #if defined(CONFIG_AU1000_USE32K) { - unsigned long start, end; + unsigned long start, end, count; start = au_readl(SYS_RTCREAD); start += 2; @@ -282,7 +281,6 @@ unsigned long cal_r4koff(void) #else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; #endif } else { @@ -291,10 +289,9 @@ unsigned long cal_r4koff(void) * NOTE: some old silicon doesn't allow reading the PLL. */ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; no_au1xxx_32khz = 1; } - mips_hpt_frequency = count; + mips_hpt_frequency = cpu_speed; // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); spin_unlock_irqrestore(&time_lock, flags); -- cgit v0.10.2 From ea3df4ac7d4adad915e2d0431a9407b10617114c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 23 Oct 2006 23:21:21 +0100 Subject: [MIPS] Oprofile: Fix MIPSxx counter number detection. Signed-off-by: Ralf Baechle diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index ebce715..1fb240c 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -220,7 +220,7 @@ static inline int n_counters(void) { int counters = __n_counters(); -#ifndef CONFIG_SMP +#ifdef CONFIG_MIPS_MT_SMP if (current_cpu_data.cputype == CPU_34K) return counters >> 1; #endif -- cgit v0.10.2 From 8cde4a3162fdcccaf0ecbf3c21cdb13df422936d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 26 Oct 2006 14:29:01 +0100 Subject: [MIPS] SMTC: Make 8 the default number of processors. 8 is the next larger power of two of the currently 5 supported TCs. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 14af6cc..9c92b49 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1690,6 +1690,7 @@ config NR_CPUS depends on SMP default "64" if SGI_IP27 default "2" + default "8" if MIPS_MT_SMTC help This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 32 for 32-bit -- cgit v0.10.2 From f0ec69e52989986e861a352099803cbb77ca53ba Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sat, 28 Oct 2006 00:42:24 +0900 Subject: [MIPS] Fix warning about unused definition in c-sb1.c arch/mips/mm/c-sb1.c: In function `sb1_cache_init': arch/mips/mm/c-sb1.c:447: warning: unused variable `handle_vec2_sb1' Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 5537558..f2941b4 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -444,7 +444,6 @@ static __init void probe_cache_sizes(void) void sb1_cache_init(void) { extern char except_vec2_sb1; - extern char handle_vec2_sb1; /* Special cache error handler for SB1 */ set_uncached_handler (0x100, &except_vec2_sb1, 0x80); -- cgit v0.10.2 From 9448b8f6a014f46450ef65d81c0be2ca5a81c867 Mon Sep 17 00:00:00 2001 From: Manish Lachwani Date: Thu, 5 Oct 2006 16:30:44 -0700 Subject: [MIPS] Make SB1 cache flushes not to use on_each_cpu This fixes the start_kernel(): bug: interrupts were enabled early messages. Signed-off-by: Manish Lachwani Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index f2941b4..ea49a77 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -49,6 +49,15 @@ static unsigned short dcache_sets; static unsigned int icache_range_cutoff; static unsigned int dcache_range_cutoff; +static inline void sb1_on_each_cpu(void (*func) (void *info), void *info, + int retry, int wait) +{ + preempt_disable(); + smp_call_function(func, info, retry, wait); + func(info); + preempt_enable(); +} + /* * The dcache is fully coherent to the system, with one * big caveat: the instruction stream. In other words, @@ -226,7 +235,7 @@ static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, args.vma = vma; args.addr = addr; args.pfn = pfn; - on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); } #else void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) @@ -249,7 +258,7 @@ void sb1___flush_cache_all_ipi(void *ignored) static void sb1___flush_cache_all(void) { - on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); + sb1_on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); } #else void sb1___flush_cache_all(void) @@ -299,7 +308,7 @@ void sb1_flush_icache_range(unsigned long start, unsigned long end) args.start = start; args.end = end; - on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); + sb1_on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); } #else void sb1_flush_icache_range(unsigned long start, unsigned long end) @@ -326,7 +335,7 @@ static void sb1_flush_cache_sigtramp_ipi(void *info) static void sb1_flush_cache_sigtramp(unsigned long addr) { - on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); } #else void sb1_flush_cache_sigtramp(unsigned long addr) -- cgit v0.10.2 From 991ea26dcbc2524a054f37911ea375e631cb8891 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 29 Oct 2006 21:07:40 +0000 Subject: [MIPS] Wire up getcpu(2) and epoll_wait(2) syscalls. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 720fac3..a95f37d 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -654,6 +654,8 @@ einval: li v0, -EINVAL sys sys_set_robust_list 2 sys sys_get_robust_list 3 /* 4310 */ sys sys_ni_syscall 0 + sys sys_getcpu 3 + sys sys_epoll_pwait 6 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 3a34f62..8fb0f60 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -469,3 +469,5 @@ sys_call_table: PTR sys_set_robust_list PTR sys_get_robust_list PTR sys_ni_syscall /* 5270 */ + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 67b92a1..0da5ca2 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -395,3 +395,5 @@ EXPORT(sysn32_call_table) PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 2875c4a..b9d00ca 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -517,4 +517,6 @@ sys_call_table: PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list /* 4310 */ PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait .size sys_call_table,.-sys_call_table diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index 30240a4..f1ef98c 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -332,16 +332,18 @@ #define __NR_set_robust_list (__NR_Linux + 309) #define __NR_get_robust_list (__NR_Linux + 310) #define __NR_kexec_load (__NR_Linux + 311) +#define __NR_getcpu (__NR_Linux + 312) +#define __NR_epoll_pwait (__NR_Linux + 313) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 311 +#define __NR_Linux_syscalls 313 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 311 +#define __NR_O32_Linux_syscalls 313 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -620,16 +622,18 @@ #define __NR_set_robust_list (__NR_Linux + 268) #define __NR_get_robust_list (__NR_Linux + 269) #define __NR_kexec_load (__NR_Linux + 270) +#define __NR_getcpu (__NR_Linux + 271) +#define __NR_epoll_pwait (__NR_Linux + 272) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 270 +#define __NR_Linux_syscalls 272 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 270 +#define __NR_64_Linux_syscalls 272 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -912,16 +916,18 @@ #define __NR_set_robust_list (__NR_Linux + 272) #define __NR_get_robust_list (__NR_Linux + 273) #define __NR_kexec_load (__NR_Linux + 274) +#define __NR_getcpu (__NR_Linux + 275) +#define __NR_epoll_pwait (__NR_Linux + 276) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 274 +#define __NR_Linux_syscalls 276 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 274 +#define __NR_N32_Linux_syscalls 276 #ifdef __KERNEL__ -- cgit v0.10.2 From a597a473b422f5a69b1f567f12e04db39fa01f39 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sun, 29 Oct 2006 23:37:40 +0900 Subject: [MIPS] Au1000: Fix warning about unused variable. arch/mips/au1000/common/time.c: In function `mips_timer_interrupt': arch/mips/au1000/common/time.c:82: warning: unused variable `count' Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 7313ef2..6768638 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -82,7 +82,6 @@ unsigned long wtimer; void mips_timer_interrupt(void) { int irq = 63; - unsigned long count; irq_enter(); kstat_this_cpu.irqs[irq]++; -- cgit v0.10.2 From c39c30da2dad1aa3fb61862039634e9480a16fde Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sun, 29 Oct 2006 23:37:55 +0900 Subject: [MIPS] Fix return value of TXX9 SPI interrupt handler Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c index b926e6a..08b20cd 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c @@ -36,14 +36,18 @@ void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on) static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait); -static void txx9_spi_interrupt(int irq, void *dev_id) +static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id) { /* disable rx intr */ tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE; wake_up(&txx9_spi_wait); + + return IRQ_HANDLED; } + static struct irqaction txx9_spi_action = { - txx9_spi_interrupt, 0, 0, "spi", NULL, NULL, + .handler = txx9_spi_interrupt, + .name = "spi", }; void __init txx9_spi_irqinit(int irc_irq) -- cgit v0.10.2 From 6ceb6d3ab2d402cea326320a4143db90a66fd216 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 12:52:16 +0000 Subject: [MIPS] Ocelot G: Fix build error and numerous warnings. The cause of the build errors was a 64-bit kernel being configured in ocelot_g_defconfig without the code being 64-bit proof. Fixed for now by limiting 64-bit selection to SYS_SUPPORTS_64BIT_KERNEL if BROKEN. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 9c92b49..74ba763 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -408,7 +408,7 @@ config MOMENCO_OCELOT_C select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_BIG_ENDIAN help The Ocelot is a MIPS-based Single Board Computer (SBC) made by diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h index fcb8275..95e0534 100644 --- a/arch/mips/momentum/ocelot_g/ocelot_pld.h +++ b/arch/mips/momentum/ocelot_g/ocelot_pld.h @@ -23,8 +23,8 @@ #define OCELOT_REG_INTSET (12) #define OCELOT_REG_INTCLR (13) -#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) -#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) - +#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg) +#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg)) +#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg)) #endif /* __MOMENCO_OCELOT_PLD_H__ */ diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index 56ec470..d288f7b 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -160,6 +161,10 @@ static void __init setup_l3cache(unsigned long size) printk("Done\n"); } +void __init plat_timer_setup(struct irqaction *irq) +{ +} + void __init plat_mem_setup(void) { void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); -- cgit v0.10.2 From 408d3258f99458f2dabcb1aa33918250e4864f00 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 14:19:37 +0000 Subject: [MIPS] EMMA 2 / Markeins: Fix build wreckage due to genirq wreckage. I wonder if the original contributor still cares ... Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index 7c93086..197ed4c 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -97,7 +97,7 @@ void emma2rh_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; - irq_desc[i].handler = &emma2rh_irq_controller; + irq_desc[i].chip = &emma2rh_irq_controller; } emma2rh_irq_base = irq_base; diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index f23ae9f..0b36eb0 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -86,7 +86,7 @@ void emma2rh_sw_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_sw_irq_controller; + irq_desc[i].chip = &emma2rh_sw_irq_controller; } emma2rh_sw_irq_base = irq_base; @@ -166,7 +166,7 @@ void emma2rh_gpio_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_gpio_irq_controller; + irq_desc[i].chip = &emma2rh_gpio_irq_controller; } emma2rh_gpio_irq_base = irq_base; -- cgit v0.10.2 From e30e66becaa237d1753d148703cf8f1301ab27f0 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 14:30:07 +0000 Subject: [MIPS] EMMA 2 / Markeins: Formitting fixes split from actual address fixes. Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c index 15cc61d..0b884a1 100644 --- a/arch/mips/emma2rh/markeins/platform.c +++ b/arch/mips/emma2rh/markeins/platform.c @@ -83,32 +83,29 @@ struct platform_device i2c_emma_devices[] = { #define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST static struct plat_serial8250_port platform_serial_ports[] = { - [0] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR0, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [1] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR1, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [2] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR2, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [3] = { - .flags = 0, + [0] = { + .membase= (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR0, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [1] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR1, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [2] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR2, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [3] = { + .flags = 0, }, }; -- cgit v0.10.2 From 4aad7b726996a2d453d210cd5691730aca087b83 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 14:47:21 +0000 Subject: [MIPS] EMMA 2 / Markeins: Convert to name struct resource initialization. This fixes the wreckage caused by shuffeling the order of struct resource members. Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c index 0b884a1..be13cec 100644 --- a/arch/mips/emma2rh/markeins/platform.c +++ b/arch/mips/emma2rh/markeins/platform.c @@ -44,18 +44,45 @@ #define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */ static struct resource i2c_emma_resources_0[] = { - { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC0, + .end = EMMA2RH_IRQ_PIIC0, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = KSEG1ADDR(EMMA2RH_PIIC0_BASE), + .end = KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), + .flags = 0 + }, }; struct resource i2c_emma_resources_1[] = { - { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC1, + .end = EMMA2RH_IRQ_PIIC1, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = KSEG1ADDR(EMMA2RH_PIIC1_BASE), + .end = KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), + .flags = 0 + }, }; struct resource i2c_emma_resources_2[] = { - { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC2, + .end = EMMA2RH_IRQ_PIIC2, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = KSEG1ADDR(EMMA2RH_PIIC2_BASE), + .end = KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), + .flags = 0 + }, }; struct platform_device i2c_emma_devices[] = { -- cgit v0.10.2 From 77aec99906367276afedf6f5583671de2ff609be Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 14:59:54 +0000 Subject: [MIPS] EMMA 2 / Markeins: struct resource takes physical addresses. Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c index be13cec..1156770 100644 --- a/arch/mips/emma2rh/markeins/platform.c +++ b/arch/mips/emma2rh/markeins/platform.c @@ -51,8 +51,8 @@ static struct resource i2c_emma_resources_0[] = { .flags = IORESOURCE_IRQ }, { .name = NULL, - .start = KSEG1ADDR(EMMA2RH_PIIC0_BASE), - .end = KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), + .start = EMMA2RH_PIIC0_BASE, + .end = EMMA2RH_PIIC0_BASE + 0x1000, .flags = 0 }, }; @@ -65,8 +65,8 @@ struct resource i2c_emma_resources_1[] = { .flags = IORESOURCE_IRQ }, { .name = NULL, - .start = KSEG1ADDR(EMMA2RH_PIIC1_BASE), - .end = KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), + .start = EMMA2RH_PIIC1_BASE, + .end = EMMA2RH_PIIC1_BASE + 0x1000, .flags = 0 }, }; @@ -79,8 +79,8 @@ struct resource i2c_emma_resources_2[] = { .flags = IORESOURCE_IRQ }, { .name = NULL, - .start = KSEG1ADDR(EMMA2RH_PIIC2_BASE), - .end = KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), + .start = EMMA2RH_PIIC2_BASE, + .end = EMMA2RH_PIIC2_BASE + 0x1000, .flags = 0 }, }; -- cgit v0.10.2 From e52331845784daeefb78ab3b13efce51af3255bc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 15:32:27 +0000 Subject: [MIPS] JMR3927: Fixup another victim of the irq pt_regs cleanup. Signed-off-by: Ralf Baechle diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 39a0243..de4a238 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -288,6 +288,8 @@ static void tx_branch_likely_bug_fixup(void) static void jmr3927_spurious(void) { + struct pt_regs * regs = get_irq_regs(); + #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND tx_branch_likely_bug_fixup(); #endif @@ -297,6 +299,7 @@ static void jmr3927_spurious(void) asmlinkage void plat_irq_dispatch(void) { + struct pt_regs * regs = get_irq_regs(); int irq; #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND -- cgit v0.10.2 From 21e9ac7b2dd96dfca997313bae6d9a8f642635c7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 21:38:22 +0000 Subject: [MIPS] MIPS doesn't need compat_sys_getdents. Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index f1ef98c..ec56aa5 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -1195,6 +1195,7 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \ #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */ +#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM -- cgit v0.10.2 From 7ca85ba752e521f1b5ead1f3b91c562cc3910c7b Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 30 Oct 2006 21:42:57 +0000 Subject: [CIFS] Fix readdir breakage when blocksize set too small Do not treat filldir running out of space as an error that needs to be returned. Fixes Redhat bugzilla bug # 211070 Signed-off-by: Steve French diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b5b0a2a..ed18c39 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -896,6 +896,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, tmp_inode->i_ino,obj_type); if(rc) { cFYI(1,("filldir rc = %d",rc)); + /* we can not return filldir errors to the caller + since they are "normal" when the stat blocksize + is too small - we return remapped error instead */ + rc = -EOVERFLOW; } dput(tmp_dentry); @@ -1074,6 +1078,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) we want to check for that here? */ rc = cifs_filldir(current_entry, file, filldir, direntry, tmp_buf, max_len); + if(rc == -EOVERFLOW) { + rc = 0; + break; + } + file->f_pos++; if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) { -- cgit v0.10.2 From 4b952a9b0877dbe8f0f69b2747abe79e3bbd2865 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 30 Oct 2006 21:46:13 +0000 Subject: [CIFS] Allow null user connections Some servers are configured to only allow null user mounts for guest access. Allow nul user (anonymous) mounts e.g. mount -t cifs //server/share /mnt -o username= Signed-off-by: Steve French diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 1eb9a2e..50afab8 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,6 +1,9 @@ Version 1.46 ------------ Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. +Allow null user to be specified on mount ("username="). Do not return +EINVAL on readdir when filldir fails due to overwritten blocksize +(fixes FC problem) Version 1.45 ------------ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4093d53..71f7791 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -822,10 +822,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) } else if (strnicmp(data, "nouser_xattr",12) == 0) { vol->no_xattr = 1; } else if (strnicmp(data, "user", 4) == 0) { - if (!value || !*value) { + if (!value) { printk(KERN_WARNING "CIFS: invalid or missing username\n"); return 1; /* needs_arg; */ + } else if(!*value) { + /* null user, ie anonymous, authentication */ + vol->nullauth = 1; } if (strnlen(value, 200) < 200) { vol->username = value; @@ -1642,6 +1645,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* BB fixme parse for domain name here */ cFYI(1, ("Username: %s ", volume_info.username)); + } else if (volume_info.nullauth) { + cFYI(1,("null user")); } else { cifserror("No username specified"); /* In userspace mount helper we can get user name from alternate -- cgit v0.10.2 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 diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 58b7efb..b5d0d7f 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 v0.10.2 From 201a95afaa324b23188eeec268f6bb0b4b70b710 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Oct 2006 15:26:21 -0700 Subject: [APPLETALK]: Fix potential OOPS in atalk_sendmsg(). atrtr_find() can return NULL, so do not blindly dereference rt->dev before we check for rt being NULL. Signed-off-by: David S. Miller diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 708e2e0..485e35c 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1584,7 +1584,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); - dev = rt->dev; } else { struct atalk_addr at_hint; @@ -1592,7 +1591,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); - dev = rt->dev; } if (!rt) return -ENETUNREACH; -- cgit v0.10.2 From 54489c14c058822f7019648b3718bd3820dee802 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Oct 2006 15:29:47 -0700 Subject: [XFRM] xfrm_user: Fix unaligned accesses. Use memcpy() to move xfrm_address_t objects in and out of netlink messages. The vast majority of xfrm_user was doing this properly, except for copy_from_user_state() and copy_to_user_state(). Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2b2e59d..b43e764 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -323,7 +323,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * x->props.replay_window = p->replay_window; x->props.reqid = p->reqid; x->props.family = p->family; - x->props.saddr = p->saddr; + memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); x->props.flags = p->flags; } @@ -545,7 +545,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) memcpy(&p->lft, &x->lft, sizeof(p->lft)); memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); memcpy(&p->stats, &x->stats, sizeof(p->stats)); - p->saddr = x->props.saddr; + memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr)); p->mode = x->props.mode; p->replay_window = x->props.replay_window; p->reqid = x->props.reqid; -- cgit v0.10.2 From c8884edd078748905552d667857259e5358e1232 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 29 Oct 2006 15:59:41 -0800 Subject: [NET]: Fix segmentation of linear packets skb_segment fails to segment linear packets correctly because it tries to write all linear parts of the original skb into each segment. This will always panic as each segment only contains enough space for one MSS. This was not detected earlier because linear packets should be rare for GSO. In fact it still remains to be seen what exactly created the linear packets that triggered this bug. Basically the only time this should happen is if someone enables GSO emulation on an interface that does not support SG. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3c23760..f735455 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1946,7 +1946,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) do { struct sk_buff *nskb; skb_frag_t *frag; - int hsize, nsize; + int hsize; int k; int size; @@ -1957,11 +1957,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) hsize = skb_headlen(skb) - offset; if (hsize < 0) hsize = 0; - nsize = hsize + doffset; - if (nsize > len + doffset || !sg) - nsize = len + doffset; + if (hsize > len || !sg) + hsize = len; - nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); + nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); if (unlikely(!nskb)) goto err; -- cgit v0.10.2 From 234af4840135342ab295b4e1219fd35c27fdd439 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 29 Oct 2006 16:03:30 -0800 Subject: [DCCP]: fix printk format warnings Fix printk format warnings: build2.out:net/dccp/ccids/ccid2.c:355: warning: long long unsigned int format, u64 arg (arg 3) build2.out:net/dccp/ccids/ccid2.c:360: warning: long long unsigned int format, u64 arg (arg 3) build2.out:net/dccp/ccids/ccid2.c:482: warning: long long unsigned int format, u64 arg (arg 5) build2.out:net/dccp/ccids/ccid2.c:639: warning: long long unsigned int format, u64 arg (arg 3) build2.out:net/dccp/ccids/ccid2.c:639: warning: long long unsigned int format, u64 arg (arg 4) build2.out:net/dccp/ccids/ccid2.c:674: warning: long long unsigned int format, u64 arg (arg 3) build2.out:net/dccp/ccids/ccid2.c:720: warning: long long unsigned int format, u64 arg (arg 3) Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 2fbb84b..162032b 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -352,14 +352,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) #ifdef CONFIG_IP_DCCP_CCID2_DEBUG ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); - ccid2_pr_debug("Sent: seq=%llu\n", seq); + ccid2_pr_debug("Sent: seq=%llu\n", (unsigned long long)seq); do { struct ccid2_seq *seqp = hctx->ccid2hctx_seqt; while (seqp != hctx->ccid2hctx_seqh) { ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", - seqp->ccid2s_seq, seqp->ccid2s_acked, - seqp->ccid2s_sent); + (unsigned long long)seqp->ccid2s_seq, + seqp->ccid2s_acked, seqp->ccid2s_sent); seqp = seqp->ccid2s_next; } } while (0); @@ -480,7 +480,8 @@ static inline void ccid2_new_ack(struct sock *sk, /* first measurement */ if (hctx->ccid2hctx_srtt == -1) { ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", - r, jiffies, seqp->ccid2s_seq); + r, jiffies, + (unsigned long long)seqp->ccid2s_seq); ccid2_change_srtt(hctx, r); hctx->ccid2hctx_rttvar = r >> 1; } else { @@ -636,8 +637,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) u64 ackno_end_rl; dccp_set_seqno(&ackno_end_rl, ackno - rl); - ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno, - ackno_end_rl); + ccid2_pr_debug("ackvec start:%llu end:%llu\n", + (unsigned long long)ackno, + (unsigned long long)ackno_end_rl); /* if the seqno we are analyzing is larger than the * current ackno, then move towards the tail of our * seqnos. @@ -672,7 +674,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) seqp->ccid2s_acked = 1; ccid2_pr_debug("Got ack for %llu\n", - seqp->ccid2s_seq); + (unsigned long long)seqp->ccid2s_seq); ccid2_hc_tx_dec_pipe(sk); } if (seqp == hctx->ccid2hctx_seqt) { @@ -718,7 +720,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) while (1) { if (!seqp->ccid2s_acked) { ccid2_pr_debug("Packet lost: %llu\n", - seqp->ccid2s_seq); + (unsigned long long)seqp->ccid2s_seq); /* XXX need to traverse from tail -> head in * order to detect multiple congestion events in * one ack vector. -- cgit v0.10.2 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 diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 8a7b8fa..31e5cc4 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 v0.10.2 From 28cd7752734563d5b0967b96a6bade7a1dc89c7f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 29 Oct 2006 23:46:42 -0800 Subject: [SCTP]: Always linearise packet on input I was looking at a RHEL5 bug report involving Xen and SCTP (https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=212550). It turns out that SCTP wasn't written to handle skb fragments at all. The absence of any calls to skb_may_pull is testament to that. It just so happens that Xen creates fragmented packets more often than other scenarios (header & data split when going from domU to dom0). That's what caused this bug to show up. Until someone has the time sits down and audits the entire net/sctp directory, here is a conservative and safe solution that simply linearises all packets on input. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/sctp/input.c b/net/sctp/input.c index 64f6301..99c0501 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -135,6 +135,9 @@ int sctp_rcv(struct sk_buff *skb) SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS); + if (skb_linearize(skb)) + goto discard_it; + sh = (struct sctphdr *) skb->h.raw; /* Pull up the IP and SCTP headers. */ -- cgit v0.10.2 From a27b58fed90cc5654e2daf1d292cc5bc61be4dd7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 30 Oct 2006 15:06:12 -0800 Subject: [NET]: fix uaccess handling Signed-off-by: Heiko Carstens Signed-off-by: David S. Miller diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index b430cf2..5c31dea 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -329,7 +329,7 @@ error: return err; } -static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) +static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) { struct iovec *iov; u8 __user *type = NULL; @@ -338,7 +338,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) unsigned int i; if (!msg->msg_iov) - return; + return 0; for (i = 0; i < msg->msg_iovlen; i++) { iov = &msg->msg_iov[i]; @@ -360,8 +360,9 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) code = iov->iov_base; if (type && code) { - get_user(fl->fl_icmp_type, type); - get_user(fl->fl_icmp_code, code); + if (get_user(fl->fl_icmp_type, type) || + get_user(fl->fl_icmp_code, code)) + return -EFAULT; probed = 1; } break; @@ -372,6 +373,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (probed) break; } + return 0; } static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, @@ -480,8 +482,11 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, .proto = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, }; - if (!inet->hdrincl) - raw_probe_proto_opt(&fl, msg); + if (!inet->hdrincl) { + err = raw_probe_proto_opt(&fl, msg); + if (err) + goto done; + } security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d09329c..d6dedc4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -604,7 +604,7 @@ error: return err; } -static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) +static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) { struct iovec *iov; u8 __user *type = NULL; @@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) int i; if (!msg->msg_iov) - return; + return 0; for (i = 0; i < msg->msg_iovlen; i++) { iov = &msg->msg_iov[i]; @@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) code = iov->iov_base; if (type && code) { - get_user(fl->fl_icmp_type, type); - get_user(fl->fl_icmp_code, code); + if (get_user(fl->fl_icmp_type, type) || + get_user(fl->fl_icmp_code, code)) + return -EFAULT; probed = 1; } break; @@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) /* check if type field is readable or not. */ if (iov->iov_len > 2 - len) { u8 __user *p = iov->iov_base; - get_user(fl->fl_mh_type, &p[2 - len]); + if (get_user(fl->fl_mh_type, &p[2 - len])) + return -EFAULT; probed = 1; } else len += iov->iov_len; @@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (probed) break; } + return 0; } static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, @@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, opt = ipv6_fixup_options(&opt_space, opt); fl.proto = proto; - rawv6_probe_proto_opt(&fl, msg); + err = rawv6_probe_proto_opt(&fl, msg); + if (err) + goto out; ipv6_addr_copy(&fl.fl6_dst, daddr); if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d56e0d2..d527c89 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1075,8 +1075,9 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, return -EINVAL; len = sizeof(int); val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0; - put_user(len, optlen); - put_user(val, optval); + if (put_user(len, optlen) || + put_user(val, optval)) + return -EFAULT; err = 0; break; default: -- cgit v0.10.2 From bcd620757d3a4ae78ef0ca41adb5d9e400ed92b6 Mon Sep 17 00:00:00 2001 From: James Morris Date: Mon, 30 Oct 2006 15:08:42 -0800 Subject: [IPV6]: fix lockup via /proc/net/ip6_flowlabel There's a bug in the seqfile handling for /proc/net/ip6_flowlabel, where, after finding a flowlabel, the code will loop forever not finding any further flowlabels, first traversing the rest of the hash bucket then just looping. This patch fixes the problem by breaking after the hash bucket has been traversed. Note that this bug can cause lockups and oopses, and is trivially invoked by an unpriveleged user. Signed-off-by: James Morris Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 1d672b0..062e526 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -587,6 +587,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo while (!fl) { if (++state->bucket <= FL_HASH_MASK) fl = fl_ht[state->bucket]; + else + break; } return fl; } -- cgit v0.10.2 From 844dc7c88046ecd2e52596730d7cc400d6c3ad67 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 30 Oct 2006 15:12:16 -0800 Subject: [NETFILTER]: remove masq/NAT from ip6tables Kconfig help Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 4bc4e5b..d7c45a9c 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -40,7 +40,7 @@ config IP6_NF_QUEUE To compile it as a module, choose M here. If unsure, say N. config IP6_NF_IPTABLES - tristate "IP6 tables support (required for filtering/masq/NAT)" + tristate "IP6 tables support (required for filtering)" depends on NETFILTER_XTABLES help ip6tables is a general, extensible packet identification framework. -- cgit v0.10.2 From 590bdf7fd2292b47c428111cb1360e312eff207e Mon Sep 17 00:00:00 2001 From: Dmitry Mishin Date: Mon, 30 Oct 2006 15:12:55 -0800 Subject: [NETFILTER]: Missed and reordered checks in {arp,ip,ip6}_tables There is a number of issues in parsing user-provided table in translate_table(). Malicious user with CAP_NET_ADMIN may crash system by passing special-crafted table to the *_tables. The first issue is that mark_source_chains() function is called before entry content checks. In case of standard target, mark_source_chains() function uses t->verdict field in order to determine new position. But the check, that this field leads no further, than the table end, is in check_entry(), which is called later, than mark_source_chains(). The second issue, that there is no check that target_offset points inside entry. If so, *_ITERATE_MATCH macro will follow further, than the entry ends. As a result, we'll have oops or memory disclosure. And the third issue, that there is no check that the target is completely inside entry. Results are the same, as in previous issue. Signed-off-by: Dmitry Mishin Acked-by: Kirill Korotaev Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 0849f1c..413c2d0a 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -466,7 +466,13 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i return -EINVAL; } + if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset) + return -EINVAL; + t = arpt_get_target(e); + if (e->target_offset + t->u.target_size > e->next_offset) + return -EINVAL; + target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, t->u.user.revision), "arpt_%s", t->u.user.name); @@ -621,20 +627,18 @@ static int translate_table(const char *name, } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) { - duprintf("Looping hook\n"); - return -ELOOP; - } - /* Finally, each sanity check must pass */ i = 0; ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) { - ARPT_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); - return ret; + if (ret != 0) + goto cleanup; + + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry0)) { + duprintf("Looping hook\n"); + goto cleanup; } /* And one copy for every other CPU */ @@ -643,6 +647,9 @@ static int translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } + return 0; +cleanup: + ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4b90927..e2c7f6e 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -547,12 +547,18 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, return -EINVAL; } + if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset) + return -EINVAL; + j = 0; ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); if (ret != 0) goto cleanup_matches; t = ipt_get_target(e); + ret = -EINVAL; + if (e->target_offset + t->u.target_size > e->next_offset) + goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET, t->u.user.name, t->u.user.revision), @@ -712,19 +718,17 @@ translate_table(const char *name, } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) - return -ELOOP; - /* Finally, each sanity check must pass */ i = 0; ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) { - IPT_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); - return ret; - } + if (ret != 0) + goto cleanup; + + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry0)) + goto cleanup; /* And one copy for every other CPU */ for_each_possible_cpu(i) { @@ -732,6 +736,9 @@ translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } + return 0; +cleanup: + IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } @@ -1463,6 +1470,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, return -EINVAL; } + if (e->target_offset + sizeof(struct compat_xt_entry_target) > + e->next_offset) + return -EINVAL; + off = 0; entry_offset = (void *)e - (void *)base; j = 0; @@ -1472,6 +1483,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, goto cleanup_matches; t = ipt_get_target(e); + ret = -EINVAL; + if (e->target_offset + t->u.target_size > e->next_offset) + goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET, t->u.user.name, t->u.user.revision), diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 53bf977..167c2ea 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -586,12 +586,19 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, return -EINVAL; } + if (e->target_offset + sizeof(struct ip6t_entry_target) > + e->next_offset) + return -EINVAL; + j = 0; ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); if (ret != 0) goto cleanup_matches; t = ip6t_get_target(e); + ret = -EINVAL; + if (e->target_offset + t->u.target_size > e->next_offset) + goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET6, t->u.user.name, t->u.user.revision), @@ -751,19 +758,17 @@ translate_table(const char *name, } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) - return -ELOOP; - /* Finally, each sanity check must pass */ i = 0; ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) { - IP6T_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); - return ret; - } + if (ret != 0) + goto cleanup; + + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry0)) + goto cleanup; /* And one copy for every other CPU */ for_each_possible_cpu(i) { @@ -771,6 +776,9 @@ translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } + return 0; +cleanup: + IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } -- cgit v0.10.2 From ef4512e76679b4f4997f60f93f8a576a0d20c26b Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 30 Oct 2006 15:13:28 -0800 Subject: [NETFILTER]: ip_tables: compat error way cleanup This patch adds forgotten compat_flush_offset() call to error way of translate_compat_table(). May lead to table corruption on the next compat_do_replace(). Signed-off-by: Vasily Averin Acked-by: Dmitry Mishin Acked-by: Kirill Korotaev Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index e2c7f6e..0f4835c 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1725,6 +1725,7 @@ free_newinfo: out: return ret; out_unlock: + compat_flush_offsets(); xt_compat_unlock(AF_INET); goto out; } -- cgit v0.10.2 From c073e3fa8b7f9841aa6451885f135656d455f511 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Mon, 30 Oct 2006 15:13:58 -0800 Subject: [NETFILTER]: nf_conntrack: add missing unlock in get_next_corpse() Add missing unlock in get_next_corpse() in nf_conntrack. It was missed during the removal of listhelp.h . Also remove an unneeded use of nf_ct_tuplehash_to_ctrack() in the same function. Should be applied before 2.6.19 is released. Signed-off-by: Martin Josefsson Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 093b3dd..836541e5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1520,9 +1520,10 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), if (iter(ct, data)) goto found; } + write_unlock_bh(&nf_conntrack_lock); return NULL; found: - atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); + atomic_inc(&ct->ct_general.use); write_unlock_bh(&nf_conntrack_lock); return ct; } -- cgit v0.10.2 From 920b868ae1dfdac77c5e8c97e7067b23680f043e Mon Sep 17 00:00:00 2001 From: Dmitry Mishin Date: Mon, 30 Oct 2006 15:14:27 -0800 Subject: [NETFILTER]: ip_tables: compat code module refcounting fix This patch fixes bug in iptables modules refcounting on compat error way. As we are getting modules in check_compat_entry_size_and_hooks(), in case of later error, we should put them all in translate_compat_table(), not in the compat_copy_entry_from_user() or compat_copy_match_from_user(), as it is now. Signed-off-by: Dmitry Mishin Acked-by: Vasily Averin Acked-by: Kirill Korotaev Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 0f4835c..8a45543 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1527,7 +1527,7 @@ cleanup_matches: static inline int compat_copy_match_from_user(struct ipt_entry_match *m, void **dstptr, compat_uint_t *size, const char *name, - const struct ipt_ip *ip, unsigned int hookmask, int *i) + const struct ipt_ip *ip, unsigned int hookmask) { struct ipt_entry_match *dm; struct ipt_match *match; @@ -1540,22 +1540,13 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m, ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), name, hookmask, ip->proto, ip->invflags & IPT_INV_PROTO); - if (ret) - goto err; - - if (m->u.kernel.match->checkentry + if (!ret && m->u.kernel.match->checkentry && !m->u.kernel.match->checkentry(name, ip, match, dm->data, hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", m->u.kernel.match->name); ret = -EINVAL; - goto err; } - (*i)++; - return 0; - -err: - module_put(m->u.kernel.match->me); return ret; } @@ -1567,19 +1558,18 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, struct ipt_target *target; struct ipt_entry *de; unsigned int origsize; - int ret, h, j; + int ret, h; ret = 0; origsize = *size; de = (struct ipt_entry *)*dstptr; memcpy(de, e, sizeof(struct ipt_entry)); - j = 0; *dstptr += sizeof(struct compat_ipt_entry); ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, - name, &de->ip, de->comefrom, &j); + name, &de->ip, de->comefrom); if (ret) - goto cleanup_matches; + goto err; de->target_offset = e->target_offset - (origsize - *size); t = ipt_get_target(e); target = t->u.kernel.target; @@ -1613,12 +1603,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, goto err; } ret = 0; - return ret; - err: - module_put(t->u.kernel.target->me); -cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, &j); return ret; } @@ -1632,7 +1617,7 @@ translate_compat_table(const char *name, unsigned int *hook_entries, unsigned int *underflows) { - unsigned int i; + unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; unsigned int size; @@ -1650,21 +1635,21 @@ translate_compat_table(const char *name, } duprintf("translate_compat_table: size %u\n", info->size); - i = 0; + j = 0; xt_compat_lock(AF_INET); /* Walk through entries, checking offsets. */ ret = IPT_ENTRY_ITERATE(entry0, total_size, check_compat_entry_size_and_hooks, info, &size, entry0, entry0 + total_size, - hook_entries, underflows, &i, name); + hook_entries, underflows, &j, name); if (ret != 0) goto out_unlock; ret = -EINVAL; - if (i != number) { + if (j != number) { duprintf("translate_compat_table: %u not %u entries\n", - i, number); + j, number); goto out_unlock; } @@ -1723,6 +1708,7 @@ translate_compat_table(const char *name, free_newinfo: xt_free_table_info(newinfo); out: + IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j); return ret; out_unlock: compat_flush_offsets(); -- cgit v0.10.2 From f8687afefcc821fc47c75775eec87731fe3de360 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 30 Oct 2006 15:22:15 -0800 Subject: [NetLabel]: protect the CIPSOv4 socket option from setsockopt() This patch makes two changes to protect applications from either removing or tampering with the CIPSOv4 IP option on a socket. The first is the requirement that applications have the CAP_NET_RAW capability to set an IPOPT_CIPSO option on a socket; this prevents untrusted applications from setting their own CIPSOv4 security attributes on the packets they send. The second change is to SELinux and it prevents applications from setting any IPv4 options when there is an IPOPT_CIPSO option already present on the socket; this prevents applications from removing CIPSOv4 security attributes from the packets they send. Signed-off-by: Paul Moore Signed-off-by: James Morris Signed-off-by: David S. Miller diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index e2077a3..6460233 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1307,7 +1307,8 @@ int cipso_v4_socket_setattr(const struct socket *sock, /* We can't use ip_options_get() directly because it makes a call to * ip_options_get_alloc() which allocates memory with GFP_KERNEL and - * we can't block here. */ + * we won't always have CAP_NET_RAW even though we _always_ want to + * set the IPOPT_CIPSO option. */ opt_len = (buf_len + 3) & ~3; opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); if (opt == NULL) { @@ -1317,11 +1318,9 @@ int cipso_v4_socket_setattr(const struct socket *sock, memcpy(opt->__data, buf, buf_len); opt->optlen = opt_len; opt->is_data = 1; + opt->cipso = sizeof(struct iphdr); kfree(buf); buf = NULL; - ret_val = ip_options_compile(opt, NULL); - if (ret_val != 0) - goto socket_setattr_failure; sk_inet = inet_sk(sk); if (sk_inet->is_icsk) { diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 8dabbfc..9f02917 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -443,7 +443,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) opt->router_alert = optptr - iph; break; case IPOPT_CIPSO: - if (opt->cipso) { + if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) { pp_ptr = optptr; goto error; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e9969a2..8ab5679 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3313,7 +3313,13 @@ static int selinux_socket_getpeername(struct socket *sock) static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) { - return socket_has_perm(current, sock, SOCKET__SETOPT); + int err; + + err = socket_has_perm(current, sock, SOCKET__SETOPT); + if (err) + return err; + + return selinux_netlbl_socket_setsockopt(sock, level, optname); } static int selinux_socket_getsockopt(struct socket *sock, int level, diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h index ecab4bd..9de10cc2 100644 --- a/security/selinux/include/selinux_netlabel.h +++ b/security/selinux/include/selinux_netlabel.h @@ -53,6 +53,9 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, struct sk_security_struct *newssec); int selinux_netlbl_inode_permission(struct inode *inode, int mask); +int selinux_netlbl_socket_setsockopt(struct socket *sock, + int level, + int optname); #else static inline void selinux_netlbl_cache_invalidate(void) { @@ -114,6 +117,13 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode, { return 0; } + +static inline int selinux_netlbl_socket_setsockopt(struct socket *sock, + int level, + int optname) +{ + return 0; +} #endif /* CONFIG_NETLABEL */ #endif diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b1f6fb3..bfe1227 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2682,4 +2682,41 @@ u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) return peer_sid; } + +/** + * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel + * @sock: the socket + * @level: the socket level or protocol + * @optname: the socket option name + * + * Description: + * Check the setsockopt() call and if the user is trying to replace the IP + * options on a socket and a NetLabel is in place for the socket deny the + * access; otherwise allow the access. Returns zero when the access is + * allowed, -EACCES when denied, and other negative values on error. + * + */ +int selinux_netlbl_socket_setsockopt(struct socket *sock, + int level, + int optname) +{ + int rc = 0; + struct inode *inode = SOCK_INODE(sock); + struct sk_security_struct *sksec = sock->sk->sk_security; + struct inode_security_struct *isec = inode->i_security; + struct netlbl_lsm_secattr secattr; + + mutex_lock(&isec->lock); + if (level == IPPROTO_IP && optname == IP_OPTIONS && + sksec->nlbl_state == NLBL_LABELED) { + netlbl_secattr_init(&secattr); + rc = netlbl_socket_getattr(sock, &secattr); + if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) + rc = -EACCES; + netlbl_secattr_destroy(&secattr); + } + mutex_unlock(&isec->lock); + + return rc; +} #endif /* CONFIG_NETLABEL */ -- cgit v0.10.2 From 4f4443088b763ca4ac7521e9b4a881b52c294dec Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 30 Oct 2006 18:54:32 -0800 Subject: [SCTP]: Correctly set IP id for SCTP traffic Make SCTP 1-1 style and peeled-off associations behave like TCP when setting IP id. In both cases, we set the inet_sk(sk)->daddr and initialize inet_sk(sk)->id to a random value. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index fac7674..5b4f82f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -591,7 +591,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk, newinet->dport = htons(asoc->peer.port); newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; newinet->pmtudisc = inet->pmtudisc; - newinet->id = 0; + newinet->id = asoc->next_tsn ^ jiffies; newinet->uc_ttl = -1; newinet->mc_loop = 1; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9f34dec..935bc91 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3372,6 +3372,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, { struct sock *sk = asoc->base.sk; struct socket *sock; + struct inet_sock *inetsk; int err = 0; /* An association cannot be branched off from an already peeled-off @@ -3389,6 +3390,14 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, * asoc to the newsk. */ sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); + + /* Make peeled-off sockets more like 1-1 accepted sockets. + * Set the daddr and initialize id to something more random + */ + inetsk = inet_sk(sock->sk); + inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; + inetsk->id = asoc->next_tsn ^ jiffies; + *sockp = sock; return err; -- cgit v0.10.2 From de76e695a5ce19c121ba7e246b45f258be678a75 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 30 Oct 2006 18:55:11 -0800 Subject: [SCTP]: Remove temporary associations from backlog and hash. Every time SCTP creates a temporary association, the stack hashes it, puts it on a list of endpoint associations and increments the backlog. However, the lifetime of a temporary association is the processing time of a current packet and it's destroyed after that. In fact, we don't really want anyone else finding this association. There is no reason to do this extra work. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 27329ce..ed0445f 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -346,11 +346,18 @@ void sctp_association_free(struct sctp_association *asoc) struct list_head *pos, *temp; int i; - list_del(&asoc->asocs); + /* Only real associations count against the endpoint, so + * don't bother for if this is a temporary association. + */ + if (!asoc->temp) { + list_del(&asoc->asocs); - /* Decrement the backlog value for a TCP-style listening socket. */ - if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) - sk->sk_ack_backlog--; + /* Decrement the backlog value for a TCP-style listening + * socket. + */ + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) + sk->sk_ack_backlog--; + } /* Mark as dead, so other users can know this structure is * going away. diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 35c49ff..9b6b394 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -144,6 +144,13 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep, { struct sock *sk = ep->base.sk; + /* If this is a temporary association, don't bother + * since we'll be removing it shortly and don't + * want anyone to find it anyway. + */ + if (asoc->temp) + return; + /* Now just add it to our list of asocs */ list_add_tail(&asoc->asocs, &ep->asocs); diff --git a/net/sctp/input.c b/net/sctp/input.c index 99c0501..6d82f40 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -771,6 +771,9 @@ static void __sctp_hash_established(struct sctp_association *asoc) /* Add an association to the hash. Local BH-safe. */ void sctp_hash_established(struct sctp_association *asoc) { + if (asoc->temp) + return; + sctp_local_bh_disable(); __sctp_hash_established(asoc); sctp_local_bh_enable(); @@ -804,6 +807,9 @@ static void __sctp_unhash_established(struct sctp_association *asoc) /* Remove association from the hash table. Local BH-safe. */ void sctp_unhash_established(struct sctp_association *asoc) { + if (asoc->temp) + return; + sctp_local_bh_disable(); __sctp_unhash_established(asoc); sctp_local_bh_enable(); -- cgit v0.10.2 From c6817e4c32d8c4118405d2dec30ac1c264349085 Mon Sep 17 00:00:00 2001 From: James Morris Date: Mon, 30 Oct 2006 18:56:06 -0800 Subject: [IPV6]: return EINVAL for invalid address with flowlabel lease request Currently, when an application requests a lease for a flowlabel via the IPV6_FLOWLABEL_MGR socket option, no error is returned if an invalid type of destination address is supplied as part of the request, leading to a silent failure. This patch ensures that EINVAL is returned to the application in this case. Signed-off-by: James Morris Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 062e526..2b45f2d6 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * fl->share = freq->flr_share; addr_type = ipv6_addr_type(&freq->flr_dst); if ((addr_type&IPV6_ADDR_MAPPED) - || addr_type == IPV6_ADDR_ANY) + || addr_type == IPV6_ADDR_ANY) { + err = -EINVAL; goto done; + } ipv6_addr_copy(&fl->dst, &freq->flr_dst); atomic_set(&fl->users, 1); switch (fl->share) { -- cgit v0.10.2 From bcb55165d3d1ae3ec95807d118fd6d5956cd127b Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 30 Oct 2006 16:23:45 -0500 Subject: [PATCH] fix bd_claim_by_kobject error handling This fixes bd_claim_by_kobject to release bdev correctly in case that bd_claim succeeds but following add_bd_holder fails. Signed-off-by: Jun'ichi Nomura Signed-off-by: Linus Torvalds diff --git a/fs/block_dev.c b/fs/block_dev.c index 702b88c..b54b0a1 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -751,8 +751,11 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); res = bd_claim(bdev, holder); - if (res == 0) + if (res == 0) { res = add_bd_holder(bdev, bo); + if (res) + bd_release(bdev); + } if (res) free_bd_holder(bo); mutex_unlock(&bdev->bd_mutex); -- cgit v0.10.2 From df6c0cd9a872ebf2298f5d66d8c789f62dbe35fc Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 30 Oct 2006 16:23:56 -0500 Subject: [PATCH] clean up add_bd_holder() add_bd_holder() is called from bd_claim_by_kobject to put a given struct bd_holder in the list if there is no matching entry. There are 3 possible results of add_bd_holder(): 1. there is no matching entry and add the given one to the list 2. there is matching entry, so just increment reference count of the existing one 3. something failed during its course 1 and 2 are successful cases. But for case 2, someone has to free the unused struct bd_holder. The current code frees it inside of add_bd_holder and returns same value 0 for both cases 1 and 2. However, it's natural and less error-prone if caller frees it since it's allocated by the caller. Signed-off-by: Jun'ichi Nomura Signed-off-by: Linus Torvalds diff --git a/fs/block_dev.c b/fs/block_dev.c index b54b0a1..aaa8301 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -642,16 +642,38 @@ static void free_bd_holder(struct bd_holder *bo) } /** + * find_bd_holder - find matching struct bd_holder from the block device + * + * @bdev: struct block device to be searched + * @bo: target struct bd_holder + * + * Returns matching entry with @bo in @bdev->bd_holder_list. + * If found, increment the reference count and return the pointer. + * If not found, returns NULL. + */ +static int find_bd_holder(struct block_device *bdev, struct bd_holder *bo) +{ + struct bd_holder *tmp; + + list_for_each_entry(tmp, &bdev->bd_holder_list, list) + if (tmp->sdir == bo->sdir) { + tmp->count++; + return tmp; + } + + return NULL; +} + +/** * add_bd_holder - create sysfs symlinks for bd_claim() relationship * * @bdev: block device to be bd_claimed * @bo: preallocated and initialized by alloc_bd_holder() * - * If there is no matching entry with @bo in @bdev->bd_holder_list, - * add @bo to the list, create symlinks. + * Add @bo to @bdev->bd_holder_list, create symlinks. * - * Returns 0 if symlinks are created or already there. - * Returns -ve if something fails and @bo can be freed. + * Returns 0 if symlinks are created. + * Returns -ve if something fails. */ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) { @@ -661,15 +683,6 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) if (!bo) return -EINVAL; - list_for_each_entry(tmp, &bdev->bd_holder_list, list) { - if (tmp->sdir == bo->sdir) { - tmp->count++; - /* We've already done what we need to do here. */ - free_bd_holder(bo); - return 0; - } - } - if (!bd_holder_grab_dirs(bdev, bo)) return -EBUSY; @@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, struct kobject *kobj) { int res; - struct bd_holder *bo; + struct bd_holder *bo, *found; if (!kobj) return -EINVAL; @@ -752,11 +765,15 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); res = bd_claim(bdev, holder); if (res == 0) { - res = add_bd_holder(bdev, bo); - if (res) - bd_release(bdev); + found = find_bd_holder(bdev, bo); + if (found == NULL) { + res = add_bd_holder(bdev, bo); + if (res) + bd_release(bdev); + } } - if (res) + + if (res || found) free_bd_holder(bo); mutex_unlock(&bdev->bd_mutex); -- cgit v0.10.2 From 9001f2850ff92b52d7654379e7b7feb72f78f161 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 29 Oct 2006 16:32:31 -0800 Subject: [SPARC64]: Fix Tomatillo/Schizo IRQ handling. The code in schizo_irq_trans_init() should set irq_data->sync_reg to the location of the SYNC register if this is Tomatillo, and set it to zero otherwise. But that is not what it is doing. As a result, non-Tomatillo systems were trying to access a non-existent register resulting in bus errors at the first PCI interrupt. Thanks to Roland Stigge for the bug report. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index c60efb3..0917c24 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -793,7 +793,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, return virt_irq; } -static void schizo_irq_trans_init(struct device_node *dp) +static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) { struct linux_prom64_registers *regs; struct schizo_irq_data *irq_data; @@ -807,11 +807,24 @@ static void schizo_irq_trans_init(struct device_node *dp) dp->irq_trans->data = irq_data; irq_data->pbm_regs = regs[0].phys_addr; - irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; + if (is_tomatillo) + irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; + else + irq_data->sync_reg = 0UL; irq_data->portid = of_getintprop_default(dp, "portid", 0); irq_data->chip_version = of_getintprop_default(dp, "version#", 0); } +static void schizo_irq_trans_init(struct device_node *dp) +{ + __schizo_irq_trans_init(dp, 0); +} + +static void tomatillo_irq_trans_init(struct device_node *dp) +{ + __schizo_irq_trans_init(dp, 1); +} + static unsigned int pci_sun4v_irq_build(struct device_node *dp, unsigned int devino, void *_data) @@ -1050,8 +1063,8 @@ static struct irq_trans pci_irq_trans_table[] = { { "pci108e,8001", schizo_irq_trans_init }, { "SUNW,schizo+", schizo_irq_trans_init }, { "pci108e,8002", schizo_irq_trans_init }, - { "SUNW,tomatillo", schizo_irq_trans_init }, - { "pci108e,a801", schizo_irq_trans_init }, + { "SUNW,tomatillo", tomatillo_irq_trans_init }, + { "pci108e,a801", tomatillo_irq_trans_init }, { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, }; #endif -- cgit v0.10.2 From 5af47db796cb7e06e9bafb0d75ad98693b55f8b6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 30 Oct 2006 01:10:20 -0800 Subject: [SPARC64]: Add some missing print_symbol() calls. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 68420e2..fe1796c 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -87,6 +87,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p) i + 1, p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc, p->trapstack[i].tt); + print_symbol("TRAPLOG: TPC<%s>\n", p->trapstack[i].tpc); } } @@ -1134,6 +1135,9 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate); + printk("%s" "ERROR(%d): ", + (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id()); + print_symbol("TPC<%s>\n", regs->tpc); printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, @@ -1741,6 +1745,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); + print_symbol(KERN_EMERG "TPC<%s>\n", regs->tpc); panic("Irrecoverable Cheetah+ parity error."); } @@ -1748,6 +1753,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); + print_symbol(KERN_WARNING "TPC<%s>\n", regs->tpc); } struct sun4v_error_entry { @@ -1946,6 +1952,7 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); + print_symbol(KERN_EMERG "SUN4V-ITLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, @@ -1966,6 +1973,7 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); + print_symbol(KERN_EMERG "SUN4V-DTLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, -- cgit v0.10.2 From ae99a78af33f00565a05dbbc6ca9b247fed002c5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 30 Oct 2006 19:37:36 -0800 Subject: Linux 2.6.19-rc4 Not halloween. Not scary. Just a regular -rc release. diff --git a/Makefile b/Makefile index 25b3599..9557619 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc4 NAME=Avast! A bilge rat! # *DOCUMENTATION* -- cgit v0.10.2 From 6887d83d6a537b5002edff7efa1a7c600af0ce26 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 31 Oct 2006 11:44:25 +0900 Subject: sh: Wire up new syscalls. This wires up sys_move_pages, sys_getcpu, and sys_epoll_pwait. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S index 768334e..ca81976 100644 --- a/arch/sh/kernel/syscalls.S +++ b/arch/sh/kernel/syscalls.S @@ -351,3 +351,6 @@ ENTRY(sys_call_table) .long sys_sync_file_range .long sys_tee /* 315 */ .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index f1a0cbc..1c2abde 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -324,8 +324,11 @@ #define __NR_sync_file_range 314 #define __NR_tee 315 #define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 -#define NR_syscalls 317 +#define NR_syscalls 320 #ifdef __KERNEL__ -- cgit v0.10.2 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 diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index fe14883..e399321 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 v0.10.2 From 1f6c526c409ed7ecdd02469c46ab4b4a50ebec45 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 31 Oct 2006 12:33:30 +0900 Subject: sh: Update r7780rp_defconfig. Small defconfig updates for R7780RP, enabling SH-RTC. Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig index 2470364..34e2046 100644 --- a/arch/sh/configs/r7780rp_defconfig +++ b/arch/sh/configs/r7780rp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18 -# Tue Oct 3 11:32:47 2006 +# Linux kernel version: 2.6.19-rc3 +# Tue Oct 31 12:32:06 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -10,6 +10,7 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -178,7 +179,7 @@ CONFIG_MMU=y CONFIG_PAGE_OFFSET=0x80000000 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -CONFIG_32BIT=y +# CONFIG_32BIT is not set CONFIG_VSYSCALL=y CONFIG_HUGETLB_PAGE_SIZE_64K=y # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set @@ -229,9 +230,7 @@ CONFIG_SH_PCLK_FREQ=32000000 # # DMA support # -CONFIG_SH_DMA=y -CONFIG_NR_ONCHIP_DMA_CHANNELS=6 -# CONFIG_NR_DMA_CHANNELS_BOOL is not set +# CONFIG_SH_DMA is not set # # Companion Chips @@ -259,7 +258,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00001000 CONFIG_BOOT_LINK_OFFSET=0x00800000 # CONFIG_UBC_WAKEUP is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="mem=128M console=ttySC0,115200 root=/dev/hda1" +CONFIG_CMDLINE="mem=128M console=ttySC0,115200 root=/dev/sda1" # # Bus options @@ -336,6 +335,7 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -441,76 +441,28 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # -CONFIG_IDE=m -CONFIG_IDE_MAX_HWIFS=4 -CONFIG_BLK_DEV_IDE=m - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -CONFIG_BLK_DEV_IDE_SATA=y -CONFIG_BLK_DEV_IDEDISK=m -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=m -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_BLK_DEV_GENERIC=m -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_AEC62XX=m -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -CONFIG_BLK_DEV_PDC202XX_NEW=m -# CONFIG_BLK_DEV_SVWKS is not set -CONFIG_BLK_DEV_SIIMAGE=m -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set +# CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=m +CONFIG_SCSI=y # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) # -CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -561,6 +513,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -570,7 +523,55 @@ CONFIG_CHR_DEV_SG=m # # Serial ATA (prod) and Parallel ATA (experimental) drivers # -# CONFIG_ATA is not set +CONFIG_ATA=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +CONFIG_SATA_SIL=y +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set # # Multi-device support (RAID and LVM) @@ -840,7 +841,6 @@ CONFIG_HW_RANDOM=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -856,6 +856,7 @@ CONFIG_HW_RANDOM=y # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -868,14 +869,9 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # -# Misc devices -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -959,7 +955,29 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # Real Time Clock # -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_SH=y +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set # # DMA Engine support @@ -984,6 +1002,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -991,6 +1010,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set CONFIG_MINIX_FS=y # CONFIG_ROMFS_FS is not set @@ -1027,7 +1047,8 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y -# CONFIG_TMPFS is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -1159,6 +1180,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_LIST is not set CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set @@ -1178,9 +1200,9 @@ CONFIG_FORCED_INLINING=y # CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set @@ -1191,7 +1213,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set -- cgit v0.10.2 From bd71ab88deab3358241f22ed6c035c427aacc4e7 Mon Sep 17 00:00:00 2001 From: Jamie Lenehan Date: Tue, 31 Oct 2006 12:35:02 +0900 Subject: sh: Fix IPR-IRQ's for IRQ-chip change breakage. The conversion from IPR-IRQ to IRQ-chip resulted in the ipr data being allocated in a local variable in make_ipr_irq - breaking anything using IPR interrupts. This changes all of the callers of make_ipr_irq to allocate a static structure containing the IPR data which is then passed to make_ipr_irq. This removes the need for make_ipr_irq to allocate any additional space for the IPR information. Signed-off-by: Jamie Lenehan Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c index 1d997ff..f7d0e30 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/setup.c +++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c @@ -15,12 +15,16 @@ #include #include -static void __init hs7751rvoip_init_irq(void) -{ +static struct ipr_data hs77501rvoip_ipr_map[] = { #if defined(CONFIG_HS7751RVOIP_CODEC) - make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); + { DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, #endif +}; + +static void __init hs7751rvoip_init_irq(void) +{ + make_ipr_irq(hs77501rvoip_ipr_map, ARRAY_SIZE(hs77501rvoip_ipr_map)); init_hs7751rvoip_IRQ(); } diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c index e57e7af..180810b 100644 --- a/arch/sh/boards/renesas/sh7710voipgw/setup.c +++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c @@ -13,6 +13,51 @@ #include #include +static struct ipr_data sh7710voipgw_ipr_map[] = { + { TIMER2_IRQ, TIMER2_IPR_ADDR, TIMER2_IPR_POS, TIMER2_PRIORITY }, + { WDT_IRQ, WDT_IPR_ADDR, WDT_IPR_POS, WDT_PRIORITY }, + + /* SCIF0 */ + { SCIF0_ERI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, + { SCIF0_RXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, + { SCIF0_BRI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, + { SCIF0_TXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, + + /* DMAC-1 */ + { DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE2_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE3_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + + /* DMAC-2 */ + { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY }, + { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY }, + + /* IPSEC */ + { IPSEC_IRQ, IPSEC_IPR_ADDR, IPSEC_IPR_POS, IPSEC_PRIORITY }, + + /* EDMAC */ + { EDMAC0_IRQ, EDMAC0_IPR_ADDR, EDMAC0_IPR_POS, EDMAC0_PRIORITY }, + { EDMAC1_IRQ, EDMAC1_IPR_ADDR, EDMAC1_IPR_POS, EDMAC1_PRIORITY }, + { EDMAC2_IRQ, EDMAC2_IPR_ADDR, EDMAC2_IPR_POS, EDMAC2_PRIORITY }, + + /* SIOF0 */ + { SIOF0_ERI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { SIOF0_TXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { SIOF0_RXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { SIOF0_CCI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + + /* SIOF1 */ + { SIOF1_ERI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, SIOF1_PRIORITY }, + { SIOF1_TXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, SIOF1_PRIORITY }, + { SIOF1_RXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, SIOF1_PRIORITY }, + { SIOF1_CCI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, SIOF1_PRIORITY }, + + /* SLIC IRQ's */ + { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, + { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, +}; + /* * Initialize IRQ setting */ @@ -37,65 +82,7 @@ static void __init sh7710voipgw_init_irq(void) */ ctrl_outw(0x2aa, INTC_ICR1); - /* Now make IPR interrupts */ - make_ipr_irq(TIMER2_IRQ, TIMER2_IPR_ADDR, - TIMER2_IPR_POS, TIMER2_PRIORITY); - make_ipr_irq(WDT_IRQ, WDT_IPR_ADDR, WDT_IPR_POS, WDT_PRIORITY); - - /* SCIF0 */ - make_ipr_irq(SCIF0_ERI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, - SCIF0_PRIORITY); - make_ipr_irq(SCIF0_RXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, - SCIF0_PRIORITY); - make_ipr_irq(SCIF0_BRI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, - SCIF0_PRIORITY); - make_ipr_irq(SCIF0_TXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, - SCIF0_PRIORITY); - - /* DMAC-1 */ - make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - - /* DMAC-2 */ - make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); - make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); - - /* IPSEC */ - make_ipr_irq(IPSEC_IRQ, IPSEC_IPR_ADDR, IPSEC_IPR_POS, IPSEC_PRIORITY); - - /* EDMAC */ - make_ipr_irq(EDMAC0_IRQ, EDMAC0_IPR_ADDR, EDMAC0_IPR_POS, - EDMAC0_PRIORITY); - make_ipr_irq(EDMAC1_IRQ, EDMAC1_IPR_ADDR, EDMAC1_IPR_POS, - EDMAC1_PRIORITY); - make_ipr_irq(EDMAC2_IRQ, EDMAC2_IPR_ADDR, EDMAC2_IPR_POS, - EDMAC2_PRIORITY); - - /* SIOF0 */ - make_ipr_irq(SIOF0_ERI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, - SIOF0_PRIORITY); - make_ipr_irq(SIOF0_TXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, - SIOF0_PRIORITY); - make_ipr_irq(SIOF0_RXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, - SIOF0_PRIORITY); - make_ipr_irq(SIOF0_CCI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, - SIOF0_PRIORITY); - - /* SIOF1 */ - make_ipr_irq(SIOF1_ERI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, - SIOF1_PRIORITY); - make_ipr_irq(SIOF1_TXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, - SIOF1_PRIORITY); - make_ipr_irq(SIOF1_RXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, - SIOF1_PRIORITY); - make_ipr_irq(SIOF1_CCI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS, - SIOF1_PRIORITY); - - /* SLIC IRQ's */ - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); + make_ipr_irq(sh7710voipgw_ipr_map, ARRAY_SIZE(sh7710voipgw_ipr_map)); } /* diff --git a/arch/sh/boards/se/7300/irq.c b/arch/sh/boards/se/7300/irq.c index ad1034f..1279d77 100644 --- a/arch/sh/boards/se/7300/irq.c +++ b/arch/sh/boards/se/7300/irq.c @@ -13,6 +13,17 @@ #include #include +static struct ipr_data se7300_ipr_map[] = { + /* PC_IRQ[0-3] -> IRQ0 (32) */ + { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, 0x0f - IRQ0_IRQ }, + /* A_IRQ[0-3] -> IRQ1 (33) */ + { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, 0x0f - IRQ1_IRQ }, + { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, +}; + /* * Initialize IRQ setting */ @@ -23,14 +34,7 @@ init_7300se_IRQ(void) ctrl_outw(0xa000, INTC_ICR1); /* IRQ mode; IRQ0,1 enable. */ ctrl_outw(0x0000, PORT_PFCR); /* use F for IRQ[3:0] and SIU. */ - /* PC_IRQ[0-3] -> IRQ0 (32) */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, 0x0f - IRQ0_IRQ); - /* A_IRQ[0-3] -> IRQ1 (33) */ - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, 0x0f - IRQ1_IRQ); - make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + make_ipr_irq(se7300_ipr_map, ARRAY_SIZE(se7300_ipr_map)); ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */ } diff --git a/arch/sh/boards/se/73180/irq.c b/arch/sh/boards/se/73180/irq.c index 2c62b8e..e7200c5 100644 --- a/arch/sh/boards/se/73180/irq.c +++ b/arch/sh/boards/se/73180/irq.c @@ -87,13 +87,38 @@ shmse_irq_demux(int irq) return irq; } +static struct ipr_data se73180_siof0_ipr_map[] = { + { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, +}; +static struct ipr_data se73180_vpu_ipr_map[] = { + { VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8 }, +}; +static struct ipr_data se73180_other_ipr_map[] = { + { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY }, + { IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY }, + + /* VIO interrupt */ + { CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + { BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + { VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + + { LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY }, +}; + /* * Initialize IRQ setting */ void __init init_73180se_IRQ(void) { - make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); + make_ipr_irq(se73180_siof0_ipr_map, ARRAY_SIZE(se73180_siof0_ipr_map)); ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */ ctrl_outw(0x2000, 0xb07fffec); /* mrshpc irq enable */ @@ -101,27 +126,11 @@ init_73180se_IRQ(void) ctrl_outw(2 << ((7 - 5) * 2), INTC_ICR1); /* low-level irq */ make_intreq_irq(10); - make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8); + make_ipr_irq(se73180_vpu_ipr_map, ARRAY_SIZE(se73180_vpu_ipr_map)); ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */ - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); - make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); - make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, - IIC0_PRIORITY); - make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, - IIC0_PRIORITY); - make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); - make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); - make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY); - - /* VIO interrupt */ - make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); - make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); - make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + make_ipr_irq(se73180_other_ipr_map, ARRAY_SIZE(se73180_other_ipr_map)); - make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY); ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */ } diff --git a/arch/sh/boards/se/7343/irq.c b/arch/sh/boards/se/7343/irq.c index 288b62f..360153e 100644 --- a/arch/sh/boards/se/7343/irq.c +++ b/arch/sh/boards/se/7343/irq.c @@ -102,6 +102,51 @@ shmse_irq_demux(int irq) static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade", NULL, NULL}; +static struct ipr_data se7343_irq5_ipr_map[] = { + { IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY }, +}; +static struct ipr_data se7343_siof0_vpu_ipr_map[] = { + { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + { VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8 }, +}; +static struct ipr_data se7343_other_ipr_map[] = { + { DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY }, + { DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY }, + + /* I2C block */ + { IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + { IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY }, + + { IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY }, + { IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY }, + { IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY }, + { IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY }, + + /* SIOF */ + { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY }, + + /* SIU */ + { SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY }, + + /* VIO interrupt */ + { CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + { BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + { VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, + + /*MFI interrupt*/ + + { MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY }, + + /* LCD controller */ + { LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY }, +}; + /* * Initialize IRQ setting */ @@ -138,54 +183,17 @@ init_7343se_IRQ(void) /* Setup all external interrupts to be active low */ ctrl_outw(0xaaaa, INTC_ICR1); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY); + make_ipr_irq(se7343_irq5_ipr_map, ARRAY_SIZE(se7343_irq5_ipr_map)); + setup_irq(IRQ5_IRQ, &irq5); /* Set port control to use IRQ5 */ *(u16 *)0xA4050108 &= ~0xc; - make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); - make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8); + make_ipr_irq(se7343_siof0_vpu_ipr_map, ARRAY_SIZE(se7343_siof0_vpu_ipr_map)); ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */ - make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); - make_ipr_irq(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); - - /* I2C block */ - make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); - make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, - IIC0_PRIORITY); - make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, - IIC0_PRIORITY); - make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); - - make_ipr_irq(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); - make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, - IIC1_PRIORITY); - make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, - IIC1_PRIORITY); - make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); - - /* SIOF */ - make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); + make_ipr_irq(se7343_other_ipr_map, ARRAY_SIZE(se7343_other_ipr_map)); - /* SIU */ - make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY); - - /* VIO interrupt */ - make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); - make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); - make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); - - /*MFI interrupt*/ - - make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY); - - /* LCD controller */ - make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY); ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */ } diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c index cff6700..fcd7cd7 100644 --- a/arch/sh/boards/se/770x/irq.c +++ b/arch/sh/boards/se/770x/irq.c @@ -13,6 +13,48 @@ #include #include +static struct ipr_data se770x_ipr_map[] = { +#if defined(CONFIG_CPU_SUBTYPE_SH7705) + /* This is default value */ + { 0xf-0x2, BCR_ILCRA, 2, 0x2 }, + { 0xf-0xa, BCR_ILCRA, 1, 0xa }, + { 0xf-0x5, BCR_ILCRB, 0, 0x5 }, + { 0xf-0x8, BCR_ILCRC, 1, 0x8 }, + { 0xf-0xc, BCR_ILCRC, 0, 0xc }, + { 0xf-0xe, BCR_ILCRD, 3, 0xe }, + { 0xf-0x3, BCR_ILCRD, 1, 0x3 }, /* LAN */ + { 0xf-0xd, BCR_ILCRE, 2, 0xd }, + { 0xf-0x9, BCR_ILCRE, 1, 0x9 }, + { 0xf-0x1, BCR_ILCRE, 0, 0x1 }, + { 0xf-0xf, BCR_ILCRF, 3, 0xf }, + { 0xf-0xb, BCR_ILCRF, 1, 0xb }, + { 0xf-0x7, BCR_ILCRG, 3, 0x7 }, + { 0xf-0x6, BCR_ILCRG, 2, 0x6 }, + { 0xf-0x4, BCR_ILCRG, 1, 0x4 }, +#else + { 14, BCR_ILCRA, 2, 0x0f-14 }, + { 12, BCR_ILCRA, 1, 0x0f-12 }, + { 8, BCR_ILCRB, 1, 0x0f- 8 }, + { 6, BCR_ILCRC, 3, 0x0f- 6 }, + { 5, BCR_ILCRC, 2, 0x0f- 5 }, + { 4, BCR_ILCRC, 1, 0x0f- 4 }, + { 3, BCR_ILCRC, 0, 0x0f- 3 }, + { 1, BCR_ILCRD, 3, 0x0f- 1 }, + + { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */ + + { 0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */ + { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */ + { 9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */ + { 7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */ + { 2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */ +#endif +}; + /* * Initialize IRQ setting */ @@ -38,42 +80,6 @@ void __init init_se_IRQ(void) ctrl_outw(0, BCR_ILCRE); ctrl_outw(0, BCR_ILCRF); ctrl_outw(0, BCR_ILCRG); - /* This is default value */ - make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2); - make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa); - make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5); - make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8); - make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc); - make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe); - make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */ - make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd); - make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9); - make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1); - make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf); - make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb); - make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7); - make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6); - make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4); -#else - make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); - make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); - make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); - make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); - make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); - make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); - make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); - make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); - - make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - - make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ - make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ - make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ - make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ - - /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ - /* NOTE: #2 and #13 are not used on PC */ - make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ - make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ #endif + make_ipr_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map)); } diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c index c607b0a..e4c63a4 100644 --- a/arch/sh/boards/se/7751/irq.c +++ b/arch/sh/boards/se/7751/irq.c @@ -14,53 +14,50 @@ #include #include -/* - * Initialize IRQ setting - */ -void __init init_7751se_IRQ(void) -{ - +static struct ipr_data se7751_ipr_map[] = { /* Leave old Solution Engine code in for reference. */ #if defined(CONFIG_SH_SOLUTION_ENGINE) - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 0 - * 4: serial 1 - * 5: printer - * 6: floppy - * 8: rtc - * 12: mouse - * 14: ide0 - */ - make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); - make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); - make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); - make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); - make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); - make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); - make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); - make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); - - make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - - make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ - make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ - make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ - make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ - - /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ - /* NOTE: #2 and #13 are not used on PC */ - make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ - make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ - + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + { 14, BCR_ILCRA, 2, 0x0f-14 }, + { 12, BCR_ILCRA, 1, 0x0f-12 }, + { 8, BCR_ILCRB, 1, 0x0f- 8 }, + { 6, BCR_ILCRC, 3, 0x0f- 6 }, + { 5, BCR_ILCRC, 2, 0x0f- 5 }, + { 4, BCR_ILCRC, 1, 0x0f- 4 }, + { 3, BCR_ILCRC, 0, 0x0f- 3 }, + { 1, BCR_ILCRD, 3, 0x0f- 1 }, + + { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */ + + { 0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */ + { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */ + { 9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */ + { 7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */ + { 2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */ #elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) - - make_ipr_irq(13, BCR_ILCRD, 3, 2); - - /* Add additional calls to make_ipr_irq() as drivers are added - * and tested. - */ + { 13, BCR_ILCRD, 3, 2 }, + /* Add additional entries here as drivers are added and tested. */ #endif +}; +/* + * Initialize IRQ setting + */ +void __init init_7751se_IRQ(void) +{ + make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map)); } diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c index 137e2ba..5ad1e19 100644 --- a/arch/sh/boards/sh03/setup.c +++ b/arch/sh/boards/sh03/setup.c @@ -14,14 +14,17 @@ #include #include +static struct ipr_data sh03_ipr_map[] = { + { IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, + { IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, + { IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, + { IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, +}; + static void __init init_sh03_IRQ(void) { ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); - - make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); - make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); - make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); - make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); + make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map)); } extern void *cf_io_base; diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c index 540d0bf..650fb36 100644 --- a/arch/sh/boards/snapgear/setup.c +++ b/arch/sh/boards/snapgear/setup.c @@ -68,6 +68,13 @@ module_init(eraseconfig_init); * IRL3 = crypto */ +static struct ipr_data snapgear_ipr_map[] = { + make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); + make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); + make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); + make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); +}; + static void __init init_snapgear_IRQ(void) { /* enable individual interrupt mode for externals */ @@ -75,10 +82,7 @@ static void __init init_snapgear_IRQ(void) printk("Setup SnapGear IRQ/IPR ...\n"); - make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); - make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); - make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); - make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); + make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map)); } /* diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c index 52b66d8..a6046d9 100644 --- a/arch/sh/boards/titan/setup.c +++ b/arch/sh/boards/titan/setup.c @@ -9,15 +9,19 @@ extern void __init pcibios_init_platform(void); +static struct ipr_data titan_ipr_map[] = { + { TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, + { TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, + { TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, + { TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, +}; + static void __init init_titan_irq(void) { /* enable individual interrupt mode for externals */ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); - make_ipr_irq( TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); /* PCIRQ0 */ - make_ipr_irq( TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); /* PCIRQ1 */ - make_ipr_irq( TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); /* PCIRQ2 */ - make_ipr_irq( TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); /* PCIRQ3 */ + make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); } struct sh_machine_vector mv_titan __initmv = { diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index d8ece20..6607860 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -19,23 +19,34 @@ #include #include "dma-sh.h" -static inline unsigned int get_dmte_irq(unsigned int chan) -{ - unsigned int irq = 0; + +#ifdef CONFIG_CPU_SH4 +static struct ipr_data dmae_ipr_map[] = { + { DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, +}; +#endif +static struct ipr_data dmte_ipr_map[] = { /* * Normally we could just do DMTE0_IRQ + chan outright, though in the * case of the 7751R, the DMTE IRQs for channels > 4 start right above * the SCIF */ - if (chan < 4) { - irq = DMTE0_IRQ + chan; - } else { -#ifdef DMTE4_IRQ - irq = DMTE4_IRQ + chan - 4; -#endif - } + { DMTE0_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, +}; +static inline unsigned int get_dmte_irq(unsigned int chan) +{ + unsigned int irq = 0; + if (chan < ARRAY_SIZE(dmte_ipr_map)) + irq = dmte_ipr_map[chan].irq; return irq; } @@ -258,17 +269,16 @@ static int __init sh_dmac_init(void) int i; #ifdef CONFIG_CPU_SH4 - make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); + make_ipr_irq(dmae_ipr_map, ARRAY_SIZE(dmae_ipr_map)); i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); if (unlikely(i < 0)) return i; #endif - for (i = 0; i < info->nr_channels; i++) { - int irq = get_dmte_irq(i); - - make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - } + i = info->nr_channels; + if (i > ARRAY_SIZE(dmte_ipr_map)) + i = ARRAY_SIZE(dmte_ipr_map); + make_ipr_irq(dmte_ipr_map, i); /* * Initialize DMAOR, and clean up any error flags that may have diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index f799731..a008956 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -23,24 +23,21 @@ #include #include -struct ipr_data { - unsigned int addr; /* Address of Interrupt Priority Register */ - int shift; /* Shifts of the 16-bit data */ - int priority; /* The priority */ -}; static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); + int shift = p->shift*4; /* Set the priority in IPR to 0 */ - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); + ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); } static void enable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); + int shift = p->shift*4; /* Set priority in IPR back to original value */ - ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); + ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); } static struct irq_chip ipr_irq_chip = { @@ -50,67 +47,57 @@ static struct irq_chip ipr_irq_chip = { .mask_ack = disable_ipr_irq, }; -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) { - struct ipr_data ipr_data; - - disable_irq_nosync(irq); - - ipr_data.addr = addr; - ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */ - ipr_data.priority = priority; + int i; - set_irq_chip_and_handler_name(irq, &ipr_irq_chip, + for (i = 0; i < nr_irqs; i++) { + unsigned int irq = table[i].irq; + disable_irq_nosync(irq); + set_irq_chip_and_handler_name(irq, &ipr_irq_chip, handle_level_irq, "level"); - set_irq_chip_data(irq, &ipr_data); - - enable_ipr_irq(irq); + set_irq_chip_data(irq, &table[i]); + enable_ipr_irq(irq); + } } +EXPORT_SYMBOL(make_ipr_irq); -/* XXX: This needs to die a horrible death.. */ -void __init init_IRQ(void) -{ +static struct ipr_data sys_ipr_map[] = { #ifndef CONFIG_CPU_SUBTYPE_SH7780 - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); + { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, + { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, #ifdef RTC_IRQ - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, #endif - #ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, + { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, + { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, #endif - #ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, + { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, + { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, + { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, #endif - #if defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, + { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, + { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, #endif - #ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, + { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, + { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, + { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, #endif - #ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, + { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, + { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, + { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, #endif - #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ defined(CONFIG_CPU_SUBTYPE_SH7706) || \ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) @@ -124,14 +111,19 @@ void __init init_IRQ(void) * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); + { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, + { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, + { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, + { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, + { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, + { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, #endif #endif +}; + +void __init init_IRQ(void) +{ + make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); #ifdef CONFIG_CPU_HAS_PINT_IRQ init_IRQ_pint(); @@ -153,5 +145,3 @@ int ipr_irq_demux(int irq) return irq; } #endif - -EXPORT_SYMBOL(make_ipr_irq); diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c index 17f47b3..f600077 100644 --- a/arch/sh/kernel/cpu/irq/pint.c +++ b/arch/sh/kernel/cpu/irq/pint.c @@ -84,12 +84,16 @@ void make_pint_irq(unsigned int irq) disable_pint_irq(irq); } +static struct ipr_data pint_ipr_map[] = { + { PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY }, + { PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY }, +}; + void __init init_IRQ_pint(void) { int i; - make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); - make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); + make_ipr_irq(pint_ipr_map, ARRAY_SIZE(pint_ipr_map)); enable_irq(PINT0_IRQ); enable_irq(PINT8_IRQ); diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 7596ab8..6cd3e9e 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -327,11 +327,17 @@ extern unsigned short *irq_mask_register; */ void init_IRQ_pint(void); +struct ipr_data { + unsigned int irq; + unsigned int addr; /* Address of Interrupt Priority Register */ + int shift; /* Shifts of the 16-bit data */ + int priority; /* The priority */ +}; + /* * Function for "on chip support modules". */ -extern void make_ipr_irq(unsigned int irq, unsigned int addr, - int pos, int priority); +extern void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs); extern void make_imask_irq(unsigned int irq); #if defined(CONFIG_CPU_SUBTYPE_SH7300) -- cgit v0.10.2 From 4731f2dfd5049b7a2b3b5a7131525f6151855f0d Mon Sep 17 00:00:00 2001 From: Jamie Lenehan Date: Tue, 31 Oct 2006 12:36:35 +0900 Subject: sh: Titan defconfig update. Small defconfig update for titan for 2.6.19-rc3, adding SH-RTC. Signed-off-by: Jamie Lenehan Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 5e81754..41049cf 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18 -# Tue Oct 3 12:59:14 2006 +# Linux kernel version: 2.6.19-rc3 +# Mon Oct 30 18:04:49 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -10,6 +10,7 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -23,7 +24,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_IPC_NS is not set @@ -236,8 +237,8 @@ CONFIG_HZ_250=y CONFIG_HZ=250 # CONFIG_KEXEC is not set # CONFIG_SMP is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set # @@ -247,7 +248,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00001000 CONFIG_BOOT_LINK_OFFSET=0x009e0000 # CONFIG_UBC_WAKEUP is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf" +CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf rw" # # Bus options @@ -334,6 +335,7 @@ CONFIG_INET_XFRM_TUNNEL=y CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=m CONFIG_INET_TCP_DIAG=m # CONFIG_TCP_CONG_ADVANCED is not set @@ -355,9 +357,10 @@ CONFIG_INET6_XFRM_TUNNEL=y CONFIG_INET6_TUNNEL=y CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m CONFIG_IPV6_TUNNEL=y -# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y @@ -714,6 +717,12 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_ATA_OVER_ETH=m # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set @@ -778,9 +787,9 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -1095,7 +1104,6 @@ CONFIG_HW_RANDOM=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -1124,14 +1132,9 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # -# Misc devices -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -1177,9 +1180,9 @@ CONFIG_USB_DEVICEFS=y # USB Host Controller Drivers # CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1235,7 +1238,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -1246,11 +1248,20 @@ CONFIG_USB_STORAGE=y # # USB Network Adapters # -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m CONFIG_USB_MON=y # @@ -1285,6 +1296,7 @@ CONFIG_USB_SERIAL_ARK3116=m # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set # CONFIG_USB_SERIAL_MOS7840 is not set # CONFIG_USB_SERIAL_NAVMAN is not set CONFIG_USB_SERIAL_PL2303=m @@ -1316,6 +1328,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1357,7 +1370,26 @@ CONFIG_USB_SERIAL_PL2303=m # # Real Time Clock # -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_SH=m +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set # # DMA Engine support @@ -1380,8 +1412,12 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT4DEV_FS=m +# CONFIG_EXT4DEV_FS_XATTR is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set CONFIG_REISERFS_FS=m # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set @@ -1393,9 +1429,10 @@ CONFIG_XFS_FS=m # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +CONFIG_ROMFS_FS=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set @@ -1480,7 +1517,12 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1583,9 +1625,10 @@ CONFIG_LOG_BUF_SHIFT=16 # CONFIG_DEBUG_LIST is not set # CONFIG_FRAME_POINTER is not set # CONFIG_FORCED_INLINING is not set +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_SH_STANDARD_BIOS is not set -CONFIG_EARLY_SCIF_CONSOLE=y +# CONFIG_EARLY_SCIF_CONSOLE is not set # CONFIG_EARLY_PRINTK is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set @@ -1605,7 +1648,7 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m @@ -1615,7 +1658,7 @@ CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m -- cgit v0.10.2 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 diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index eb6f98d..9b2041e 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9ae4f3a..d8ca3c1 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index 809da3e..973c4b5 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_alloc.c b/drivers/infiniband/hw/amso1100/c2_alloc.c index 028a60b..0315f99 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 9d7bcc5..05c9154 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 30409e1..030238d 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 030238d..21d9612 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 v0.10.2 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 diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b72c7f6..743247e 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 db1b814..64a721f 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 v0.10.2 From 1b7c2dbc07bf0663a41e3dc838992930019f08fd Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 31 Oct 2006 00:43:44 -0800 Subject: [IPV6]: fix flowlabel seqfile handling There's a bug in the seqfile show operation for flowlabel objects, where each hash chain is traversed cumulatively for each element. The following function is called for each element of each chain: static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) { while(fl) { seq_printf... fl = fl->next; } } Thus, objects can appear mutliple times when reading /proc/net/ip6_flowlabel, as the above is called for each element in the chain. The solution is to remove the while() loop from the above, and traverse each chain exactly once, per the patch below. This also removes the ip6fl_fl_seq_show() function, which does nothing else. Signed-off-by: James Morris Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 2b45f2d6..6d4533b 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -627,9 +627,13 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v) read_unlock_bh(&ip6_fl_lock); } -static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) +static int ip6fl_seq_show(struct seq_file *seq, void *v) { - while(fl) { + if (v == SEQ_START_TOKEN) + seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", + "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); + else { + struct ip6_flowlabel *fl = v; seq_printf(seq, "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", (unsigned)ntohl(fl->label), @@ -640,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) (long)(fl->expires - jiffies)/HZ, NIP6(fl->dst), fl->opt ? fl->opt->opt_nflen : 0); - fl = fl->next; } -} - -static int ip6fl_seq_show(struct seq_file *seq, void *v) -{ - if (v == SEQ_START_TOKEN) - seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", - "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); - else - ip6fl_fl_seq_show(seq, v); return 0; } -- cgit v0.10.2 From 36a561d6a95c4b89ae4845bf91456b4f784b6eec Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 30 Oct 2006 22:07:03 -0800 Subject: [PATCH] find_bd_holder() fix fs/block_dev.c: In function 'find_bd_holder': fs/block_dev.c:666: warning: return makes integer from pointer without a cast fs/block_dev.c:669: warning: return makes integer from pointer without a cast fs/block_dev.c: In function 'add_bd_holder': fs/block_dev.c:685: warning: unused variable 'tmp' fs/block_dev.c: In function 'bd_claim_by_kobject': fs/block_dev.c:773: warning: assignment makes pointer from integer without a cast Acked-by: Jun'ichi Nomura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/block_dev.c b/fs/block_dev.c index aaa8301..36c0e7a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -651,7 +651,8 @@ static void free_bd_holder(struct bd_holder *bo) * If found, increment the reference count and return the pointer. * If not found, returns NULL. */ -static int find_bd_holder(struct block_device *bdev, struct bd_holder *bo) +static struct bd_holder *find_bd_holder(struct block_device *bdev, + struct bd_holder *bo) { struct bd_holder *tmp; @@ -677,7 +678,6 @@ static int find_bd_holder(struct block_device *bdev, struct bd_holder *bo) */ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) { - struct bd_holder *tmp; int ret; if (!bo) -- cgit v0.10.2 From 97d88ac83540f9ba9536326c30db4815c5b9169b Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:03 -0800 Subject: [PATCH] uml ubd driver: allow using up to 16 UBD devices With 256 minors and 16 minors used per each UBD device, we can allow the use of up to 16 UBD devices per UML. Also chnage parse_unit and leave to the caller (which already do it) the check for excess numbers, since this is just supposed to do raw parsing. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index bc458f5..54d2473 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -117,7 +117,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); -#define MAX_DEV (8) +#define MAX_DEV (16) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, @@ -277,7 +277,7 @@ static int parse_unit(char **ptr) return(-1); *ptr = end; } - else if (('a' <= *str) && (*str <= 'h')) { + else if (('a' <= *str) && (*str <= 'z')) { n = *str - 'a'; str++; *ptr = str; -- cgit v0.10.2 From 2a9d32f682b2b4928dcd4680bc99e98a3d096816 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:04 -0800 Subject: [PATCH] uml ubd driver: document some struct fields Add documentation about some fields in struct ubd, whose meaning is non-obvious due to struct names (should change names altogether, I agree). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 54d2473..e104f59 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -150,8 +150,9 @@ static struct gendisk *fake_gendisk[MAX_DEV]; static struct openflags global_openflags = OPEN_FLAGS; struct cow { - /* This is the backing file, actually */ + /* backing file name */ char *file; + /* backing file fd */ int fd; unsigned long *bitmap; unsigned long bitmap_len; @@ -160,6 +161,8 @@ struct cow { }; struct ubd { + /* name (and fd, below) of the file opened for writing, either the + * backing or the cow file. */ char *file; int count; int fd; -- cgit v0.10.2 From 7d314e346d6081e8013a96206e601a48528d8f60 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:05 -0800 Subject: [PATCH] uml ubd driver: var renames Rename the ubd_dev array to ubd_devs and then call any "struct ubd" ubd_dev instead of dev, which doesn't make clear what we're treating (and no, it's not hungarian notation - not any more than calling all vm_area_struct vma or all inodes inode). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index e104f59..761e3f9 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -195,14 +195,14 @@ struct ubd { .cow = DEFAULT_COW, \ } -struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; +struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; static int ubd0_init(void) { - struct ubd *dev = &ubd_dev[0]; + struct ubd *ubd_dev = &ubd_devs[0]; - if(dev->file == NULL) - dev->file = "root_fs"; + if(ubd_dev->file == NULL) + ubd_dev->file = "root_fs"; return(0); } @@ -290,7 +290,7 @@ static int parse_unit(char **ptr) static int ubd_setup_common(char *str, int *index_out) { - struct ubd *dev; + struct ubd *ubd_dev; struct openflags flags = global_openflags; char *backing_file; int n, err, i; @@ -345,8 +345,8 @@ static int ubd_setup_common(char *str, int *index_out) err = 1; spin_lock(&ubd_lock); - dev = &ubd_dev[n]; - if(dev->file != NULL){ + ubd_dev = &ubd_devs[n]; + if(ubd_dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out; } @@ -363,10 +363,10 @@ static int ubd_setup_common(char *str, int *index_out) flags.s = 1; break; case 'd': - dev->no_cow = 1; + ubd_dev->no_cow = 1; break; case 'c': - dev->shared = 1; + ubd_dev->shared = 1; break; case '=': str++; @@ -393,7 +393,7 @@ break_loop: } if(backing_file){ - if(dev->no_cow) + if(ubd_dev->no_cow) printk(KERN_ERR "Can't specify both 'd' and a " "cow file\n"); else { @@ -401,9 +401,9 @@ break_loop: backing_file++; } } - dev->file = str; - dev->cow.file = backing_file; - dev->boot_openflags = flags; + ubd_dev->file = str; + ubd_dev->cow.file = backing_file; + ubd_dev->boot_openflags = flags; out: spin_unlock(&ubd_lock); return(err); @@ -544,83 +544,83 @@ void kill_io_thread(void) __uml_exitcall(kill_io_thread); -static int ubd_file_size(struct ubd *dev, __u64 *size_out) +static int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) { char *file; - file = dev->cow.file ? dev->cow.file : dev->file; + file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; return(os_file_size(file, size_out)); } -static void ubd_close(struct ubd *dev) +static void ubd_close(struct ubd *ubd_dev) { - os_close_file(dev->fd); - if(dev->cow.file == NULL) + os_close_file(ubd_dev->fd); + if(ubd_dev->cow.file == NULL) return; - os_close_file(dev->cow.fd); - vfree(dev->cow.bitmap); - dev->cow.bitmap = NULL; + os_close_file(ubd_dev->cow.fd); + vfree(ubd_dev->cow.bitmap); + ubd_dev->cow.bitmap = NULL; } -static int ubd_open_dev(struct ubd *dev) +static int ubd_open_dev(struct ubd *ubd_dev) { struct openflags flags; char **back_ptr; int err, create_cow, *create_ptr; - dev->openflags = dev->boot_openflags; + ubd_dev->openflags = ubd_dev->boot_openflags; create_cow = 0; - create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; - back_ptr = dev->no_cow ? NULL : &dev->cow.file; - dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, - back_ptr, &dev->cow.bitmap_offset, - &dev->cow.bitmap_len, &dev->cow.data_offset, + create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; + back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; + ubd_dev->fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, + back_ptr, &ubd_dev->cow.bitmap_offset, + &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, create_ptr); - if((dev->fd == -ENOENT) && create_cow){ - dev->fd = create_cow_file(dev->file, dev->cow.file, - dev->openflags, 1 << 9, PAGE_SIZE, - &dev->cow.bitmap_offset, - &dev->cow.bitmap_len, - &dev->cow.data_offset); - if(dev->fd >= 0){ + if((ubd_dev->fd == -ENOENT) && create_cow){ + ubd_dev->fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, + ubd_dev->openflags, 1 << 9, PAGE_SIZE, + &ubd_dev->cow.bitmap_offset, + &ubd_dev->cow.bitmap_len, + &ubd_dev->cow.data_offset); + if(ubd_dev->fd >= 0){ printk(KERN_INFO "Creating \"%s\" as COW file for " - "\"%s\"\n", dev->file, dev->cow.file); + "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); } } - if(dev->fd < 0){ - printk("Failed to open '%s', errno = %d\n", dev->file, - -dev->fd); - return(dev->fd); + if(ubd_dev->fd < 0){ + printk("Failed to open '%s', errno = %d\n", ubd_dev->file, + -ubd_dev->fd); + return(ubd_dev->fd); } - if(dev->cow.file != NULL){ + if(ubd_dev->cow.file != NULL){ err = -ENOMEM; - dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); - if(dev->cow.bitmap == NULL){ + ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); + if(ubd_dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; } flush_tlb_kernel_vm(); - err = read_cow_bitmap(dev->fd, dev->cow.bitmap, - dev->cow.bitmap_offset, - dev->cow.bitmap_len); + err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, + ubd_dev->cow.bitmap_offset, + ubd_dev->cow.bitmap_len); if(err < 0) goto error; - flags = dev->openflags; + flags = ubd_dev->openflags; flags.w = 0; - err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, + err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, NULL, NULL, NULL, NULL); if(err < 0) goto error; - dev->cow.fd = err; + ubd_dev->cow.fd = err; } return(0); error: - os_close_file(dev->fd); + os_close_file(ubd_dev->fd); return(err); } @@ -645,13 +645,13 @@ static int ubd_new_disk(int major, u64 size, int unit, /* sysfs register (not for ide fake devices) */ if (major == MAJOR_NR) { - ubd_dev[unit].pdev.id = unit; - ubd_dev[unit].pdev.name = DRIVER_NAME; - platform_device_register(&ubd_dev[unit].pdev); - disk->driverfs_dev = &ubd_dev[unit].pdev.dev; + ubd_devs[unit].pdev.id = unit; + ubd_devs[unit].pdev.name = DRIVER_NAME; + platform_device_register(&ubd_devs[unit].pdev); + disk->driverfs_dev = &ubd_devs[unit].pdev.dev; } - disk->private_data = &ubd_dev[unit]; + disk->private_data = &ubd_devs[unit]; disk->queue = ubd_queue; add_disk(disk); @@ -663,25 +663,25 @@ static int ubd_new_disk(int major, u64 size, int unit, static int ubd_add(int n) { - struct ubd *dev = &ubd_dev[n]; + struct ubd *ubd_dev = &ubd_devs[n]; int err; err = -ENODEV; - if(dev->file == NULL) + if(ubd_dev->file == NULL) goto out; - err = ubd_file_size(dev, &dev->size); + err = ubd_file_size(ubd_dev, &ubd_dev->size); if(err < 0) goto out; - dev->size = ROUND_BLOCK(dev->size); + ubd_dev->size = ROUND_BLOCK(ubd_dev->size); - err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); + err = ubd_new_disk(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); if(err) goto out; if(fake_major != MAJOR_NR) - ubd_new_disk(fake_major, dev->size, n, + ubd_new_disk(fake_major, ubd_dev->size, n, &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ @@ -713,7 +713,7 @@ static int ubd_config(char *str) spin_lock(&ubd_lock); err = ubd_add(n); if(err) - ubd_dev[n].file = NULL; + ubd_devs[n].file = NULL; spin_unlock(&ubd_lock); return(err); @@ -721,7 +721,7 @@ static int ubd_config(char *str) static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *dev; + struct ubd *ubd_dev; int n, len = 0; n = parse_unit(&name); @@ -730,19 +730,19 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) return(-1); } - dev = &ubd_dev[n]; + ubd_dev = &ubd_devs[n]; spin_lock(&ubd_lock); - if(dev->file == NULL){ + if(ubd_dev->file == NULL){ CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, len, dev->file, 0); + CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); - if(dev->cow.file != NULL){ + if(ubd_dev->cow.file != NULL){ CONFIG_CHUNK(str, size, len, ",", 0); - CONFIG_CHUNK(str, size, len, dev->cow.file, 1); + CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); } else CONFIG_CHUNK(str, size, len, "", 1); @@ -763,7 +763,7 @@ static int ubd_id(char **str, int *start_out, int *end_out) static int ubd_remove(int n) { - struct ubd *dev; + struct ubd *ubd_dev; int err = -ENODEV; spin_lock(&ubd_lock); @@ -771,14 +771,14 @@ static int ubd_remove(int n) if(ubd_gendisk[n] == NULL) goto out; - dev = &ubd_dev[n]; + ubd_dev = &ubd_devs[n]; - if(dev->file == NULL) + if(ubd_dev->file == NULL) goto out; /* you cannot remove a open disk */ err = -EBUSY; - if(dev->count > 0) + if(ubd_dev->count > 0) goto out; del_gendisk(ubd_gendisk[n]); @@ -791,8 +791,8 @@ static int ubd_remove(int n) fake_gendisk[n] = NULL; } - platform_device_unregister(&dev->pdev); - *dev = ((struct ubd) DEFAULT_UBD); + platform_device_unregister(&ubd_dev->pdev); + *ubd_dev = ((struct ubd) DEFAULT_UBD); err = 0; out: spin_unlock(&ubd_lock); @@ -870,7 +870,7 @@ int ubd_driver_init(void){ return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - IRQF_DISABLED, "ubd", ubd_dev); + IRQF_DISABLED, "ubd", ubd_devs); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; @@ -881,24 +881,24 @@ device_initcall(ubd_driver_init); static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; int err = 0; - if(dev->count == 0){ - err = ubd_open_dev(dev); + if(ubd_dev->count == 0){ + err = ubd_open_dev(ubd_dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", - disk->disk_name, dev->file, -err); + disk->disk_name, ubd_dev->file, -err); goto out; } } - dev->count++; - set_disk_ro(disk, !dev->openflags.w); + ubd_dev->count++; + set_disk_ro(disk, !ubd_dev->openflags.w); /* This should no more be needed. And it didn't work anyway to exclude * read-write remounting of filesystems.*/ - /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ - if(--dev->count == 0) ubd_close(dev); + /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ + if(--ubd_dev->count == 0) ubd_close(ubd_dev); err = -EROFS; }*/ out: @@ -908,10 +908,10 @@ static int ubd_open(struct inode *inode, struct file *filp) static int ubd_release(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; - if(--dev->count == 0) - ubd_close(dev); + if(--ubd_dev->count == 0) + ubd_close(ubd_dev); return(0); } @@ -979,12 +979,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; __u64 offset; int len; /* This should be impossible now */ - if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ + if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); end_request(req, 0); @@ -994,8 +994,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) offset = ((__u64) req->sector) << 9; len = req->current_nr_sectors << 9; - io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; - io_req->fds[1] = dev->fd; + io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; + io_req->fds[1] = ubd_dev->fd; io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; @@ -1004,13 +1004,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; - io_req->offsets[1] = dev->cow.data_offset; + io_req->offsets[1] = ubd_dev->cow.data_offset; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - if(dev->cow.file != NULL) - cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, - dev->cow.bitmap_len); + if(ubd_dev->cow.file != NULL) + cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, + ubd_dev->cow.bitmap_len); return(0); } @@ -1048,18 +1048,18 @@ static void do_ubd_request(request_queue_t *q) static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - struct ubd *dev = bdev->bd_disk->private_data; + struct ubd *ubd_dev = bdev->bd_disk->private_data; geo->heads = 128; geo->sectors = 32; - geo->cylinders = dev->size / (128 * 32 * 512); + geo->cylinders = ubd_dev->size / (128 * 32 * 512); return 0; } static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct ubd *dev = inode->i_bdev->bd_disk->private_data; + struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -1069,7 +1069,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, switch (cmd) { struct cdrom_volctrl volume; case HDIO_GET_IDENTITY: - ubd_id.cyls = dev->size / (128 * 32 * 512); + ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); -- cgit v0.10.2 From 5f75a4f887a35b99878fc07ed749a90375194b63 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:06 -0800 Subject: [PATCH] uml ubd driver: give better names to some functions. To rethink locking, I needed to understand well what each function does. While doing this I renamed some: * ubd_close -> ubd_close_dev (since it pairs with ubd_open_dev) * ubd_new_disk -> ubd_disk_register (it handles registration with the block layer - one hopes this makes clearer the difference with ubd_add()) Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 761e3f9..cdd82e8 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -552,7 +552,7 @@ static int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) return(os_file_size(file, size_out)); } -static void ubd_close(struct ubd *ubd_dev) +static void ubd_close_dev(struct ubd *ubd_dev) { os_close_file(ubd_dev->fd); if(ubd_dev->cow.file == NULL) @@ -624,7 +624,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) return(err); } -static int ubd_new_disk(int major, u64 size, int unit, +static int ubd_disk_register(int major, u64 size, int unit, struct gendisk **disk_out) { @@ -676,12 +676,12 @@ static int ubd_add(int n) ubd_dev->size = ROUND_BLOCK(ubd_dev->size); - err = ubd_new_disk(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); + err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); if(err) goto out; if(fake_major != MAJOR_NR) - ubd_new_disk(fake_major, ubd_dev->size, n, + ubd_disk_register(fake_major, ubd_dev->size, n, &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ @@ -898,7 +898,7 @@ static int ubd_open(struct inode *inode, struct file *filp) /* This should no more be needed. And it didn't work anyway to exclude * read-write remounting of filesystems.*/ /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ - if(--ubd_dev->count == 0) ubd_close(ubd_dev); + if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); err = -EROFS; }*/ out: @@ -911,7 +911,7 @@ static int ubd_release(struct inode * inode, struct file * file) struct ubd *ubd_dev = disk->private_data; if(--ubd_dev->count == 0) - ubd_close(ubd_dev); + ubd_close_dev(ubd_dev); return(0); } -- cgit v0.10.2 From d7fb2c3865ca0f95d92e2864c3dc9220789d83f5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:07 -0800 Subject: [PATCH] uml ubd driver: change ubd_lock to be a mutex This lock protects ubd setup and teardown, so is only used in process context; beyond that, during such setup memory allocations must be performed and some generic functions which can sleep must be called (such as add_disk()). So the only correct solution is to make it a mutex instead of a spin_lock. No other change is done - this lock must be acquired in different places but it's done afterwards. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index cdd82e8..a3061ae 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -107,7 +107,8 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) #define DRIVER_NAME "uml-blkdev" static DEFINE_SPINLOCK(ubd_io_lock); -static DEFINE_SPINLOCK(ubd_lock); + +static DEFINE_MUTEX(ubd_lock); static void (*do_ubd)(void); @@ -314,7 +315,7 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; @@ -326,7 +327,7 @@ static int ubd_setup_common(char *str, int *index_out) major); err = 0; out1: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(err); } @@ -343,7 +344,7 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); ubd_dev = &ubd_devs[n]; if(ubd_dev->file != NULL){ @@ -405,7 +406,7 @@ break_loop: ubd_dev->cow.file = backing_file; ubd_dev->boot_openflags = flags; out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(err); } @@ -710,11 +711,11 @@ static int ubd_config(char *str) } if(n == -1) return(0); - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); err = ubd_add(n); if(err) ubd_devs[n].file = NULL; - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(err); } @@ -731,7 +732,7 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) } ubd_dev = &ubd_devs[n]; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); if(ubd_dev->file == NULL){ CONFIG_CHUNK(str, size, len, "", 1); @@ -747,7 +748,7 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) else CONFIG_CHUNK(str, size, len, "", 1); out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(len); } @@ -766,7 +767,7 @@ static int ubd_remove(int n) struct ubd *ubd_dev; int err = -ENODEV; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); if(ubd_gendisk[n] == NULL) goto out; @@ -795,7 +796,7 @@ static int ubd_remove(int n) *ubd_dev = ((struct ubd) DEFAULT_UBD); err = 0; out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return err; } -- cgit v0.10.2 From 33f775eea185e8df7701c4afc2c8fcee85c83282 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:08 -0800 Subject: [PATCH] uml ubd driver: ubd_io_lock usage fixup Add some comments about requirements for ubd_io_lock and expand its use. When an irq signals that the "controller" (i.e. another thread on the host, which does the actual requests and is the only one blocked on I/O on the host) has done some work, we call again the request function ourselves (do_ubd_request). We now do that with ubd_io_lock held - that's useful to protect against concurrent calls to elv_next_request and so on. XXX: Maybe we shouldn't call at all the request function. Input needed on this. Are we supposed to plug and unplug the queue? That code "indirectly" does that by setting a flag, called do_ubd, which makes the request function return (it's a residual of 2.4 block layer interface). Meanwhile, however, merge this patch, which improves things. Cc: Jens Axboe Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index a3061ae..6cd8988 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -106,6 +106,8 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) #define DRIVER_NAME "uml-blkdev" +/* Can be taken in interrupt context, and is passed to the block layer to lock + * the request queue. Kernel side code knows that. */ static DEFINE_SPINLOCK(ubd_io_lock); static DEFINE_MUTEX(ubd_lock); @@ -497,6 +499,8 @@ static void __ubd_finish(struct request *req, int error) end_request(req, 1); } +/* Callable only from interrupt context - otherwise you need to do + * spin_lock_irq()/spin_lock_irqsave() */ static inline void ubd_finish(struct request *req, int error) { spin_lock(&ubd_io_lock); @@ -504,7 +508,7 @@ static inline void ubd_finish(struct request *req, int error) spin_unlock(&ubd_io_lock); } -/* Called without ubd_io_lock held */ +/* Called without ubd_io_lock held, and only in interrupt context. */ static void ubd_handler(void) { struct io_thread_req req; @@ -525,7 +529,9 @@ static void ubd_handler(void) ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); + spin_lock(&ubd_io_lock); do_ubd_request(ubd_queue); + spin_unlock(&ubd_io_lock); } static irqreturn_t ubd_intr(int irq, void *dev) -- cgit v0.10.2 From 2fe30a34a141c2188ff2cdd670d031088d9c5d20 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:09 -0800 Subject: [PATCH] uml ubd driver: convert do_ubd to a boolean variable do_ubd is actually just a boolean variable - the way it is used currently is a leftover from the old 2.4 block layer, but it is still used; its use is suspicious, but removing it would be too intrusive for now and needs more thinking. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 6cd8988..460d669 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -112,7 +112,9 @@ static DEFINE_SPINLOCK(ubd_io_lock); static DEFINE_MUTEX(ubd_lock); -static void (*do_ubd)(void); +/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and + * probably it doesn't make sense even for that. */ +static int do_ubd; static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -508,6 +510,7 @@ static inline void ubd_finish(struct request *req, int error) spin_unlock(&ubd_io_lock); } +/* XXX - move this inside ubd_intr. */ /* Called without ubd_io_lock held, and only in interrupt context. */ static void ubd_handler(void) { @@ -515,7 +518,7 @@ static void ubd_handler(void) struct request *rq = elv_next_request(ubd_queue); int n; - do_ubd = NULL; + do_ubd = 0; intr_count++; n = os_read_file(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ @@ -1043,7 +1046,7 @@ static void do_ubd_request(request_queue_t *q) return; err = prepare_request(req, &io_req); if(!err){ - do_ubd = ubd_handler; + do_ubd = 1; n = os_write_file(thread_fd, (char *) &io_req, sizeof(io_req)); if(n != sizeof(io_req)) -- cgit v0.10.2 From e7f6552f237498c805af9f01aba168b731e0a4ce Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:09 -0800 Subject: [PATCH] uml ubd driver: reformat ubd_config Pure whitespace and style fixes split out from subsequent patch. Some changes (err -> ret) don't make sense now, only later, but I split them out anyway since they cluttered the patch. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 460d669..eed95dc 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -706,27 +706,36 @@ out: static int ubd_config(char *str) { - int n, err; + int n, ret; str = kstrdup(str, GFP_KERNEL); - if(str == NULL){ + if (str == NULL) { printk(KERN_ERR "ubd_config failed to strdup string\n"); - return(1); + ret = 1; + goto out; } - err = ubd_setup_common(str, &n); - if(err){ - kfree(str); - return(-1); + ret = ubd_setup_common(str, &n); + if (ret) { + ret = -1; + goto err_free; + } + if (n == -1) { + ret = 0; + goto out; } - if(n == -1) return(0); mutex_lock(&ubd_lock); - err = ubd_add(n); - if(err) + ret = ubd_add(n); + if (ret) ubd_devs[n].file = NULL; mutex_unlock(&ubd_lock); - return(err); +out: + return ret; + +err_free: + kfree(str); + goto out; } static int ubd_get_config(char *name, char *str, int size, char **error_out) -- cgit v0.10.2 From 84e945e399ce9710a34035ea81eaf5719aa709af Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:10 -0800 Subject: [PATCH] uml ubd driver: use bitfields where possible Use bitfields for boolean fields in ubd data structure. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index eed95dc..3e3bb22 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -174,8 +174,8 @@ struct ubd { __u64 size; struct openflags boot_openflags; struct openflags openflags; - int shared; - int no_cow; + unsigned shared:1; + unsigned no_cow:1; struct cow cow; struct platform_device pdev; }; -- cgit v0.10.2 From 0bf16bffeef65622603af22151156807323d7dc7 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:11 -0800 Subject: [PATCH] uml ubd driver: do not store error codes as ->fd To simplify error handling, make sure fd is saved into ubd_dev->fd only when we are sure it is an fd and not an error code. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 3e3bb22..125a63f 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -578,33 +578,36 @@ static int ubd_open_dev(struct ubd *ubd_dev) struct openflags flags; char **back_ptr; int err, create_cow, *create_ptr; + int fd; ubd_dev->openflags = ubd_dev->boot_openflags; create_cow = 0; create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; - ubd_dev->fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, + + fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, back_ptr, &ubd_dev->cow.bitmap_offset, &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, create_ptr); - if((ubd_dev->fd == -ENOENT) && create_cow){ - ubd_dev->fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, + if((fd == -ENOENT) && create_cow){ + fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, ubd_dev->openflags, 1 << 9, PAGE_SIZE, &ubd_dev->cow.bitmap_offset, &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset); - if(ubd_dev->fd >= 0){ + if(fd >= 0){ printk(KERN_INFO "Creating \"%s\" as COW file for " "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); } } - if(ubd_dev->fd < 0){ + if(fd < 0){ printk("Failed to open '%s', errno = %d\n", ubd_dev->file, - -ubd_dev->fd); - return(ubd_dev->fd); + -fd); + return fd; } + ubd_dev->fd = fd; if(ubd_dev->cow.file != NULL){ err = -ENOMEM; -- cgit v0.10.2 From d8d7c28ec0b50ac57ddc909ae6eca1519473f300 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 30 Oct 2006 22:07:12 -0800 Subject: [PATCH] uml ubd driver: various little changes Fix a small memory leak in ubd_config, and clearify the confusion which lead to it. Then, some little changes not affecting operations - * move init functions together, * add a comment about a potential problem in case of some evolution in the block layer, * mark all initcalls as static __init functions * mark an used once little function as inline * document that mconsole methods are all called in process context (was triggered when checking ubd mconsole methods). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 125a63f..49c047b 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -202,17 +202,6 @@ struct ubd { struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; -static int ubd0_init(void) -{ - struct ubd *ubd_dev = &ubd_devs[0]; - - if(ubd_dev->file == NULL) - ubd_dev->file = "root_fs"; - return(0); -} - -__initcall(ubd0_init); - /* Only changed by fake_ide_setup which is a setup */ static int fake_ide = 0; static struct proc_dir_entry *proc_ide_root = NULL; @@ -293,6 +282,10 @@ static int parse_unit(char **ptr) return(n); } +/* If *index_out == -1 at exit, the passed option was a general one; + * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it + * should not be freed on exit. + */ static int ubd_setup_common(char *str, int *index_out) { struct ubd *ubd_dev; @@ -480,8 +473,9 @@ int thread_fd = -1; /* Changed by ubd_handler, which is serialized because interrupts only * happen on CPU 0. + * XXX: currently unused. */ -int intr_count = 0; +static int intr_count = 0; /* call ubd_finish if you need to serialize */ static void __ubd_finish(struct request *req, int error) @@ -554,7 +548,7 @@ void kill_io_thread(void) __uml_exitcall(kill_io_thread); -static int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) +static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) { char *file; @@ -724,7 +718,7 @@ static int ubd_config(char *str) } if (n == -1) { ret = 0; - goto out; + goto err_free; } mutex_lock(&ubd_lock); @@ -821,6 +815,7 @@ out: return err; } +/* All these are called by mconsole in process context and without ubd-specific locks. */ static struct mc_device ubd_mc = { .name = "ubd", .config = ubd_config, @@ -829,7 +824,7 @@ static struct mc_device ubd_mc = { .remove = ubd_remove, }; -static int ubd_mc_init(void) +static int __init ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); return 0; @@ -837,13 +832,24 @@ static int ubd_mc_init(void) __initcall(ubd_mc_init); +static int __init ubd0_init(void) +{ + struct ubd *ubd_dev = &ubd_devs[0]; + + if(ubd_dev->file == NULL) + ubd_dev->file = "root_fs"; + return(0); +} + +__initcall(ubd0_init); + static struct platform_driver ubd_driver = { .driver = { .name = DRIVER_NAME, }, }; -int ubd_init(void) +static int __init ubd_init(void) { int i; @@ -871,7 +877,7 @@ int ubd_init(void) late_initcall(ubd_init); -int ubd_driver_init(void){ +static int __init ubd_driver_init(void){ unsigned long stack; int err; @@ -1378,8 +1384,8 @@ void do_io(struct io_thread_req *req) */ int kernel_fd = -1; -/* Only changed by the io thread */ -int io_count = 0; +/* Only changed by the io thread. XXX: currently unused. */ +static int io_count = 0; int io_thread(void *arg) { diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h index d0b6901..1ea6d928 100644 --- a/arch/um/include/mconsole_kern.h +++ b/arch/um/include/mconsole_kern.h @@ -14,6 +14,7 @@ struct mconsole_entry { struct mc_request request; }; +/* All these methods are called in process context. */ struct mc_device { struct list_head list; char *name; diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index 9882342..b919535 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -176,7 +176,6 @@ struct { int signal_index[32]; int nsignals = 0; int debug_trace = 0; -extern int io_nsignals, io_count, intr_count; extern void signal_usr1(int sig); -- cgit v0.10.2 From d1480c56feb2a894fd47fb399999a5b320c3e103 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 30 Oct 2006 22:07:13 -0800 Subject: [PATCH] uml: add _text definition to linker scripts kallsyms now refers to addresses as '_text + 0xADDRESS', rather than just '0xADDRESS', so we need to define _text. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 68ed24d..e36f92b 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -14,6 +14,7 @@ SECTIONS * is remapped.*/ __binary_start = .; . = ALIGN(4096); /* Init code and data */ + _text = .; _stext = .; __init_begin = .; .init.text : { diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 8eca47a..f630127 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -25,6 +25,7 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ #endif + _text = .; _stext = .; __init_begin = .; .init.text : { -- cgit v0.10.2 From 525fdb6cc929b515ad7e0be40fd023cff8660ed8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 30 Oct 2006 22:07:14 -0800 Subject: [PATCH] uml: add INITCALLS This is the UML piece of the INITCALLS tidying. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S index 1010153..f045451 100644 --- a/include/asm-um/common.lds.S +++ b/include/asm-um/common.lds.S @@ -42,13 +42,7 @@ __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; -- cgit v0.10.2 From 4a279ff1ea1cf325775ada983035123fcdc8e986 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 30 Oct 2006 22:07:15 -0800 Subject: [PATCH] taskstats: fix sub-threads accounting If there are no listeners, taskstats_exit_send() just returns because taskstats_exit_alloc() didn't allocate *tidstats. This is wrong, each sub-thread should do fill_tgid_exit() on exit, otherwise its ->delays is not recorded in ->signal->stats and lost. Q: We don't send TASKSTATS_TYPE_AGGR_TGID when single-threaded process exits. Is it good? How can the listener figure out that it was actually a process exit, not sub-thread? Signed-off-by: Oleg Nesterov Cc: Balbir Singh Acked-by: Shailabh Nagar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 2039585..f45c5e7 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -455,10 +455,9 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, int is_thread_group; struct nlattr *na; - if (!family_registered || !tidstats) + if (!family_registered) return; - rc = 0; /* * Size includes space for nested attributes */ @@ -466,8 +465,15 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); is_thread_group = (tsk->signal->stats != NULL); - if (is_thread_group) - size = 2 * size; /* PID + STATS + TGID + STATS */ + if (is_thread_group) { + /* PID + STATS + TGID + STATS */ + size = 2 * size; + /* fill the tsk->signal->stats structure */ + fill_tgid_exit(tsk); + } + + if (!tidstats) + return; rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); if (rc < 0) @@ -487,11 +493,8 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, goto send; /* - * tsk has/had a thread group so fill the tsk->signal->stats structure * Doesn't matter if tsk is the leader or the last group member leaving */ - - fill_tgid_exit(tsk); if (!group_dead) goto send; -- cgit v0.10.2 From e5d9cbde6ce0001e49994df5fcdcbeff8be8037b Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:16 -0800 Subject: [PATCH] eCryptfs: Clean up crypto initialization Clean up the crypto initialization code; let the crypto API take care of the key size checks. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index ed35a9712..82e7d02 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1573,35 +1573,26 @@ out: /** * ecryptfs_process_cipher - Perform cipher initialization. - * @tfm: Crypto context set by this function * @key_tfm: Crypto context for key material, set by this function - * @cipher_name: Name of the cipher. - * @key_size: Size of the key in bytes. + * @cipher_name: Name of the cipher + * @key_size: Size of the key in bytes * * Returns zero on success. Any crypto_tfm structs allocated here * should be released by other functions, such as on a superblock put * event, regardless of whether this function succeeds for fails. */ int -ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, - char *cipher_name, size_t key_size) +ecryptfs_process_cipher(struct crypto_tfm **key_tfm, char *cipher_name, + size_t *key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; int rc; - *tfm = *key_tfm = NULL; - if (key_size > ECRYPTFS_MAX_KEY_BYTES) { + *key_tfm = NULL; + if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { rc = -EINVAL; printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum " - "allowable is [%d]\n", key_size, ECRYPTFS_MAX_KEY_BYTES); - goto out; - } - *tfm = crypto_alloc_tfm(cipher_name, (ECRYPTFS_DEFAULT_CHAINING_MODE - | CRYPTO_TFM_REQ_WEAK_KEY)); - if (!(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]\n", cipher_name); + "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); goto out; } *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY); @@ -1611,46 +1602,13 @@ ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, "[%s]\n", cipher_name); goto out; } - if (key_size < crypto_tfm_alg_min_keysize(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; minimum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*tfm)); - goto out; - } - if (key_size < crypto_tfm_alg_min_keysize(*key_tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; minimum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); - goto out; - } - if (key_size > crypto_tfm_alg_max_keysize(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; maximum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*tfm)); - goto out; - } - if (key_size > crypto_tfm_alg_max_keysize(*key_tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; maximum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); - goto out; - } - get_random_bytes(dummy_key, key_size); - rc = crypto_cipher_setkey(*tfm, dummy_key, key_size); - if (rc) { - printk(KERN_ERR "Error attempting to set key of size [%Zd] for " - "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); - rc = -EINVAL; - goto out; - } - rc = crypto_cipher_setkey(*key_tfm, dummy_key, key_size); + if (*key_size == 0) + *key_size = crypto_tfm_alg_max_keysize(*key_tfm); + get_random_bytes(dummy_key, *key_size); + rc = crypto_cipher_setkey(*key_tfm, dummy_key, *key_size); if (rc) { printk(KERN_ERR "Error attempting to set key of size [%Zd] for " - "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); + "cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc); rc = -EINVAL; goto out; } diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 872c995..4112df9 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -473,8 +473,8 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *src, struct dentry *ecryptfs_dentry); int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); int -ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, - char *cipher_name, size_t key_size); +ecryptfs_process_cipher(struct crypto_tfm **key_tfm, char *cipher_name, + size_t *key_size); int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); int ecryptfs_inode_set(struct inode *inode, void *lower_inode); void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ba45478..bc706d3 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -493,19 +493,16 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, goto out; } } - if (password_s_ptr->session_key_encryption_key_bytes - < crypto_tfm_alg_min_keysize(tfm)) { - printk(KERN_WARNING "Session key encryption key is [%d] bytes; " - "minimum keysize for selected cipher is [%d] bytes.\n", - password_s_ptr->session_key_encryption_key_bytes, - crypto_tfm_alg_min_keysize(tfm)); - rc = -EINVAL; - goto out; - } if (tfm_mutex) mutex_lock(tfm_mutex); - crypto_cipher_setkey(tfm, password_s_ptr->session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_cipher_setkey(tfm, + password_s_ptr->session_key_encryption_key, + crypt_stat->key_size); + if (rc < 0) { + printk(KERN_ERR "Error setting key for crypto context\n"); + rc = -EINVAL; + goto out_free_tfm; + } /* TODO: virt_to_scatterlist */ encrypted_session_key = (char *)__get_free_page(GFP_KERNEL); if (!encrypted_session_key) { diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 5938a23..a65f486 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -208,7 +208,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) char *cipher_name_dst; char *cipher_name_src; char *cipher_key_bytes_src; - struct crypto_tfm *tmp_tfm; int cipher_name_len; if (!options) { @@ -305,20 +304,12 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) = '\0'; } if (!cipher_key_bytes_set) { - mount_crypt_stat->global_default_cipher_key_size = - ECRYPTFS_DEFAULT_KEY_BYTES; - ecryptfs_printk(KERN_DEBUG, "Cipher key size was not " - "specified. Defaulting to [%d]\n", - mount_crypt_stat-> - global_default_cipher_key_size); + mount_crypt_stat->global_default_cipher_key_size = 0; } rc = ecryptfs_process_cipher( - &tmp_tfm, &mount_crypt_stat->global_key_tfm, mount_crypt_stat->global_default_cipher_name, - mount_crypt_stat->global_default_cipher_key_size); - if (tmp_tfm) - crypto_free_tfm(tmp_tfm); + &mount_crypt_stat->global_default_cipher_key_size); if (rc) { printk(KERN_ERR "Error attempting to initialize cipher [%s] " "with key size [%Zd] bytes; rc = [%d]\n", -- cgit v0.10.2 From 565d9724b8ce49b530287de34aa17f45f21624d5 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:17 -0800 Subject: [PATCH] eCryptfs: Hash code to new crypto API Update eCryptfs hash code to the new kernel crypto API. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 82e7d02..f14c5a3 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -94,25 +94,31 @@ static int ecryptfs_calculate_md5(char *dst, struct ecryptfs_crypt_stat *crypt_stat, char *src, int len) { - int rc = 0; struct scatterlist sg; + struct hash_desc desc = { + .tfm = crypt_stat->hash_tfm, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; - mutex_lock(&crypt_stat->cs_md5_tfm_mutex); + mutex_lock(&crypt_stat->cs_hash_tfm_mutex); sg_init_one(&sg, (u8 *)src, len); - if (!crypt_stat->md5_tfm) { - crypt_stat->md5_tfm = - crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); - if (!crypt_stat->md5_tfm) { - rc = -ENOMEM; + if (!desc.tfm) { + desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); ecryptfs_printk(KERN_ERR, "Error attempting to " - "allocate crypto context\n"); + "allocate crypto context; rc = [%d]\n", + rc); goto out; } + crypt_stat->hash_tfm = desc.tfm; } - crypto_digest_init(crypt_stat->md5_tfm); - crypto_digest_update(crypt_stat->md5_tfm, &sg, 1); - crypto_digest_final(crypt_stat->md5_tfm, dst); - mutex_unlock(&crypt_stat->cs_md5_tfm_mutex); + crypto_hash_init(&desc); + crypto_hash_update(&desc, &sg, len); + crypto_hash_final(&desc, dst); + mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); out: return rc; } @@ -178,7 +184,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); mutex_init(&crypt_stat->cs_mutex); mutex_init(&crypt_stat->cs_tfm_mutex); - mutex_init(&crypt_stat->cs_md5_tfm_mutex); + mutex_init(&crypt_stat->cs_hash_tfm_mutex); ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); } @@ -192,8 +198,8 @@ void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { if (crypt_stat->tfm) crypto_free_tfm(crypt_stat->tfm); - if (crypt_stat->md5_tfm) - crypto_free_tfm(crypt_stat->md5_tfm); + if (crypt_stat->hash_tfm) + crypto_free_hash(crypt_stat->hash_tfm); memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); } diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 4112df9..840aa01 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -175,6 +175,7 @@ ecryptfs_get_key_payload_data(struct key *key) #define ECRYPTFS_DEFAULT_CIPHER "aes" #define ECRYPTFS_DEFAULT_KEY_BYTES 16 #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC +#define ECRYPTFS_DEFAULT_HASH "md5" #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED #define MD5_DIGEST_SIZE 16 @@ -205,14 +206,14 @@ struct ecryptfs_crypt_stat { unsigned int extent_mask; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct crypto_tfm *tfm; - struct crypto_tfm *md5_tfm; /* Crypto context for generating - * the initialization vectors */ + struct crypto_hash *hash_tfm; /* Crypto context for generating + * the initialization vectors */ unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX]; struct mutex cs_tfm_mutex; - struct mutex cs_md5_tfm_mutex; + struct mutex cs_hash_tfm_mutex; struct mutex cs_mutex; }; -- cgit v0.10.2 From 8bba066f4e3854755a303cee37ea37bd080a46b3 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:18 -0800 Subject: [PATCH] eCryptfs: Cipher code to new crypto API Update cipher block encryption code to the new crypto API. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index f14c5a3..2a1b6aa 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -123,6 +123,28 @@ out: return rc; } +int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, + char *cipher_name, + char *chaining_modifier) +{ + int cipher_name_len = strlen(cipher_name); + int chaining_modifier_len = strlen(chaining_modifier); + int algified_name_len; + int rc; + + algified_name_len = (chaining_modifier_len + cipher_name_len + 3); + (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); + if (!(algified_name)) { + rc = -ENOMEM; + goto out; + } + snprintf((*algified_name), algified_name_len, "%s(%s)", + chaining_modifier, cipher_name); + rc = 0; +out: + return rc; +} + /** * ecryptfs_derive_iv * @iv: destination for the derived iv vale @@ -197,7 +219,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { if (crypt_stat->tfm) - crypto_free_tfm(crypt_stat->tfm); + crypto_free_blkcipher(crypt_stat->tfm); if (crypt_stat->hash_tfm) crypto_free_hash(crypt_stat->hash_tfm); memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); @@ -209,7 +231,7 @@ void ecryptfs_destruct_mount_crypt_stat( if (mount_crypt_stat->global_auth_tok_key) key_put(mount_crypt_stat->global_auth_tok_key); if (mount_crypt_stat->global_key_tfm) - crypto_free_tfm(mount_crypt_stat->global_key_tfm); + crypto_free_blkcipher(mount_crypt_stat->global_key_tfm); memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); } @@ -275,6 +297,11 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { + struct blkcipher_desc desc = { + .tfm = crypt_stat->tfm, + .info = iv, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; int rc = 0; BUG_ON(!crypt_stat || !crypt_stat->tfm @@ -288,8 +315,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, } /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -298,7 +325,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); - crypto_cipher_encrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, iv); + crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); mutex_unlock(&crypt_stat->cs_tfm_mutex); out: return rc; @@ -681,12 +708,17 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { + struct blkcipher_desc desc = { + .tfm = crypt_stat->tfm, + .info = iv, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; int rc = 0; /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -695,8 +727,7 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); - rc = crypto_cipher_decrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, - iv); + rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); mutex_unlock(&crypt_stat->cs_tfm_mutex); if (rc) { ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", @@ -765,6 +796,7 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, */ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) { + char *full_alg_name; int rc = -EINVAL; if (!crypt_stat->cipher) { @@ -781,16 +813,24 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) goto out; } mutex_lock(&crypt_stat->cs_tfm_mutex); - crypt_stat->tfm = crypto_alloc_tfm(crypt_stat->cipher, - ECRYPTFS_DEFAULT_CHAINING_MODE - | CRYPTO_TFM_REQ_WEAK_KEY); - mutex_unlock(&crypt_stat->cs_tfm_mutex); + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, "cbc"); + if (rc) + goto out; + crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); if (!crypt_stat->tfm) { ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " "Error initializing cipher [%s]\n", crypt_stat->cipher); + mutex_unlock(&crypt_stat->cs_tfm_mutex); goto out; } + crypto_blkcipher_set_flags(crypt_stat->tfm, + (ECRYPTFS_DEFAULT_CHAINING_MODE + | CRYPTO_TFM_REQ_WEAK_KEY)); + mutex_unlock(&crypt_stat->cs_tfm_mutex); rc = 0; out: return rc; @@ -1588,10 +1628,11 @@ out: * event, regardless of whether this function succeeds for fails. */ int -ecryptfs_process_cipher(struct crypto_tfm **key_tfm, char *cipher_name, +ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, size_t *key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; + char *full_alg_name; int rc; *key_tfm = NULL; @@ -1601,17 +1642,26 @@ ecryptfs_process_cipher(struct crypto_tfm **key_tfm, char *cipher_name, "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); goto out; } - *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY); - if (!(*key_tfm)) { - rc = -EINVAL; + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, + "ecb"); + if (rc) + goto out; + *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(*key_tfm)) { + rc = PTR_ERR(*key_tfm); printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]\n", cipher_name); + "[%s]; rc = [%d]\n", cipher_name, rc); goto out; } - if (*key_size == 0) - *key_size = crypto_tfm_alg_max_keysize(*key_tfm); + crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); + if (*key_size == 0) { + struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); + + *key_size = alg->max_keysize; + } get_random_bytes(dummy_key, *key_size); - rc = crypto_cipher_setkey(*key_tfm, dummy_key, *key_size); + rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); if (rc) { printk(KERN_ERR "Error attempting to set key of size [%Zd] for " "cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 840aa01..199fcda 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -205,7 +205,7 @@ struct ecryptfs_crypt_stat { size_t extent_shift; unsigned int extent_mask; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct crypto_tfm *tfm; + struct crypto_blkcipher *tfm; struct crypto_hash *hash_tfm; /* Crypto context for generating * the initialization vectors */ unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; @@ -245,7 +245,7 @@ struct ecryptfs_mount_crypt_stat { struct ecryptfs_auth_tok *global_auth_tok; struct key *global_auth_tok_key; size_t global_default_cipher_key_size; - struct crypto_tfm *global_key_tfm; + struct crypto_blkcipher *global_key_tfm; struct mutex global_key_tfm_mutex; unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; @@ -426,6 +426,9 @@ void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_destruct_mount_crypt_stat( struct ecryptfs_mount_crypt_stat *mount_crypt_stat); int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); +int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, + char *cipher_name, + char *chaining_modifier); int ecryptfs_write_inode_size_to_header(struct file *lower_file, struct inode *lower_inode, struct inode *inode); @@ -474,7 +477,7 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *src, struct dentry *ecryptfs_dentry); int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); int -ecryptfs_process_cipher(struct crypto_tfm **key_tfm, char *cipher_name, +ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, size_t *key_size); int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); int ecryptfs_inode_set(struct inode *inode, void *lower_inode); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index bc706d3..c3746f5 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -458,14 +458,16 @@ out: static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat) { - int rc = 0; struct ecryptfs_password *password_s_ptr; - struct crypto_tfm *tfm = NULL; struct scatterlist src_sg[2], dst_sg[2]; struct mutex *tfm_mutex = NULL; /* TODO: Use virt_to_scatterlist for these */ char *encrypted_session_key; char *session_key; + struct blkcipher_desc desc = { + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; password_s_ptr = &auth_tok->token.password; if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, @@ -482,22 +484,32 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; } else { - tfm = crypto_alloc_tfm(crypt_stat->cipher, - CRYPTO_TFM_REQ_WEAK_KEY); - if (!tfm) { - printk(KERN_ERR "Error allocating crypto context\n"); - rc = -ENOMEM; + char *full_alg_name; + + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, + "ecb"); + if (rc) + goto out; + desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); + printk(KERN_ERR "Error allocating crypto context; " + "rc = [%d]\n", rc); goto out; } + crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); } if (tfm_mutex) mutex_lock(tfm_mutex); - rc = crypto_cipher_setkey(tfm, - password_s_ptr->session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(desc.tfm, + password_s_ptr->session_key_encryption_key, + crypt_stat->key_size); if (rc < 0) { printk(KERN_ERR "Error setting key for crypto context\n"); rc = -EINVAL; @@ -528,9 +540,12 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; dst_sg[0].length = auth_tok->session_key.encrypted_key_size; - /* TODO: Handle error condition */ - crypto_cipher_decrypt(tfm, dst_sg, src_sg, - auth_tok->session_key.encrypted_key_size); + rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, + auth_tok->session_key.encrypted_key_size); + if (rc) { + printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); + goto out_free_memory; + } auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; memcpy(auth_tok->session_key.decrypted_key, session_key, @@ -543,6 +558,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (ecryptfs_verbosity > 0) ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size); +out_free_memory: memset(encrypted_session_key, 0, PAGE_CACHE_SIZE); free_page((unsigned long)encrypted_session_key); memset(session_key, 0, PAGE_CACHE_SIZE); @@ -551,7 +567,7 @@ out_free_tfm: if (tfm_mutex) mutex_unlock(tfm_mutex); else - crypto_free_tfm(tfm); + crypto_free_blkcipher(desc.tfm); out: return rc; } @@ -800,19 +816,21 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_key_record *key_rec, size_t *packet_size) { - int rc = 0; - size_t i; size_t signature_is_valid = 0; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; struct scatterlist dest_sg[2]; struct scatterlist src_sg[2]; - struct crypto_tfm *tfm = NULL; struct mutex *tfm_mutex = NULL; size_t key_rec_size; size_t packet_size_length; size_t cipher_code; + struct blkcipher_desc desc = { + .tfm = NULL, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; (*packet_size) = 0; /* Check for a valid signature on the auth_tok */ @@ -879,33 +897,48 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; - } else - tfm = crypto_alloc_tfm(crypt_stat->cipher, 0); - if (!tfm) { - ecryptfs_printk(KERN_ERR, "Could not initialize crypto " - "context for cipher [%s]\n", - crypt_stat->cipher); - rc = -EINVAL; - goto out; + } else { + char *full_alg_name; + + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, + "ecb"); + if (rc) + goto out; + desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); + ecryptfs_printk(KERN_ERR, "Could not initialize crypto " + "context for cipher [%s]; rc = [%d]\n", + crypt_stat->cipher, rc); + goto out; + } + crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); } if (tfm_mutex) mutex_lock(tfm_mutex); - rc = crypto_cipher_setkey(tfm, session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, + crypt_stat->key_size); if (rc < 0) { if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_ERR, "Error setting key for crypto " - "context\n"); + "context; rc = [%d]\n", rc); goto out; } rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", crypt_stat->key_size); - crypto_cipher_encrypt(tfm, dest_sg, src_sg, - (*key_rec).enc_key_size); + rc = crypto_blkcipher_encrypt(&desc, dest_sg, src_sg, + (*key_rec).enc_key_size); + if (rc) { + printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); + goto out; + } if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); @@ -968,8 +1001,8 @@ encrypted_session_key_set: (*key_rec).enc_key_size); (*packet_size) += (*key_rec).enc_key_size; out: - if (tfm && !tfm_mutex) - crypto_free_tfm(tfm); + if (desc.tfm && !tfm_mutex) + crypto_free_blkcipher(desc.tfm); if (rc) (*packet_size) = 0; return rc; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index a65f486..a78d87d 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -315,6 +315,8 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) "with key size [%Zd] bytes; rc = [%d]\n", mount_crypt_stat->global_default_cipher_name, mount_crypt_stat->global_default_cipher_key_size, rc); + mount_crypt_stat->global_key_tfm = NULL; + mount_crypt_stat->global_auth_tok_key = NULL; rc = -EINVAL; goto out; } -- cgit v0.10.2 From 7ff1d74f5670329ac4b5959a675f8698ba95be20 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:19 -0800 Subject: [PATCH] eCryptfs: Consolidate lower dentry_open's Opens on lower dentry objects happen in several places in eCryptfs, and they all involve the same steps (dget, mntget, dentry_open). This patch consolidates the lower open events into a single function call. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 2a1b6aa..f49f105 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1191,28 +1191,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) int ecryptfs_read_header_region(char *data, struct dentry *dentry, struct vfsmount *mnt) { - struct file *file; + struct file *lower_file; mm_segment_t oldfs; int rc; - mnt = mntget(mnt); - file = dentry_open(dentry, mnt, O_RDONLY); - if (IS_ERR(file)) { - ecryptfs_printk(KERN_DEBUG, "Error opening file to " - "read header region\n"); - mntput(mnt); - rc = PTR_ERR(file); + if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt, + O_RDONLY))) { + printk(KERN_ERR + "Error opening lower_file to read header region\n"); goto out; } - file->f_pos = 0; + lower_file->f_pos = 0; oldfs = get_fs(); set_fs(get_ds()); /* For releases 0.1 and 0.2, all of the header information * fits in the first data extent-sized region. */ - rc = file->f_op->read(file, (char __user *)data, - ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos); + rc = lower_file->f_op->read(lower_file, (char __user *)data, + ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos); set_fs(oldfs); - fput(file); + if ((rc = ecryptfs_close_lower_file(lower_file))) { + printk(KERN_ERR "Error closing lower_file\n"); + goto out; + } rc = 0; out: return rc; diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 199fcda..f992533 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -482,5 +482,9 @@ ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); int ecryptfs_inode_set(struct inode *inode, void *lower_inode); void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); +int ecryptfs_open_lower_file(struct file **lower_file, + struct dentry *lower_dentry, + struct vfsmount *lower_mnt, int flags); +int ecryptfs_close_lower_file(struct file *lower_file); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c8550c9..a92ef05 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -198,6 +198,33 @@ retry: struct kmem_cache *ecryptfs_file_info_cache; +int ecryptfs_open_lower_file(struct file **lower_file, + struct dentry *lower_dentry, + struct vfsmount *lower_mnt, int flags) +{ + int rc = 0; + + dget(lower_dentry); + mntget(lower_mnt); + *lower_file = dentry_open(lower_dentry, lower_mnt, flags); + if (IS_ERR(*lower_file)) { + printk(KERN_ERR "Error opening lower file for lower_dentry " + "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n", + lower_dentry, lower_mnt, flags); + rc = PTR_ERR(*lower_file); + *lower_file = NULL; + goto out; + } +out: + return rc; +} + +int ecryptfs_close_lower_file(struct file *lower_file) +{ + fput(lower_file); + return 0; +} + /** * ecryptfs_open * @inode: inode speciying file to open @@ -244,19 +271,15 @@ static int ecryptfs_open(struct inode *inode, struct file *file) ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); - /* This mntget & dget is undone via fput when the file is released */ - dget(lower_dentry); lower_flags = file->f_flags; if ((lower_flags & O_ACCMODE) == O_WRONLY) lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; if (file->f_flags & O_APPEND) lower_flags &= ~O_APPEND; lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); - mntget(lower_mnt); /* Corresponding fput() in ecryptfs_release() */ - lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags); - if (IS_ERR(lower_file)) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + lower_flags))) { ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); goto out_puts; } @@ -341,11 +364,16 @@ static int ecryptfs_release(struct inode *inode, struct file *file) struct file *lower_file = ecryptfs_file_to_lower(file); struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); struct inode *lower_inode = ecryptfs_inode_to_lower(inode); + int rc; - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) { + printk(KERN_ERR "Error closing lower_file\n"); + goto out; + } inode->i_blocks = lower_inode->i_blocks; kmem_cache_free(ecryptfs_file_info_cache, file_info); - return 0; +out: + return rc; } static int diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index efdd2b7..2f2c6cf 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -231,7 +231,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) int lower_flags; struct ecryptfs_crypt_stat *crypt_stat; struct dentry *lower_dentry; - struct dentry *tlower_dentry = NULL; struct file *lower_file; struct inode *inode, *lower_inode; struct vfsmount *lower_mnt; @@ -241,30 +240,19 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) lower_dentry->d_name.name); inode = ecryptfs_dentry->d_inode; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - tlower_dentry = dget(lower_dentry); - if (!tlower_dentry) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry\n"); - goto out; - } lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; #if BITS_PER_LONG != 32 lower_flags |= O_LARGEFILE; #endif lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); - mntget(lower_mnt); /* Corresponding fput() at end of this function */ - lower_file = dentry_open(tlower_dentry, lower_mnt, lower_flags); - if (IS_ERR(lower_file)) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + lower_flags))) { ecryptfs_printk(KERN_ERR, "Error opening dentry; rc = [%i]\n", rc); goto out; } - /* fput(lower_file) should handle the puts if we do this */ - lower_file->f_dentry = tlower_dentry; - lower_file->f_vfsmnt = lower_mnt; - lower_inode = tlower_dentry->d_inode; + lower_inode = lower_dentry->d_inode; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); @@ -285,7 +273,8 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) } rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode); out_fput: - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) + printk(KERN_ERR "Error closing lower_file\n"); out: return rc; } @@ -832,12 +821,11 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) } lower_dentry = ecryptfs_dentry_to_lower(dentry); /* This dget & mntget is released through fput at out_fput: */ - dget(lower_dentry); lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - mntget(lower_mnt); - lower_file = dentry_open(lower_dentry, lower_mnt, O_RDWR); - if (unlikely(IS_ERR(lower_file))) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + O_RDWR))) { + ecryptfs_printk(KERN_ERR, + "Error opening dentry; rc = [%i]\n", rc); goto out_free; } ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file); @@ -879,7 +867,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) = CURRENT_TIME; mark_inode_dirty_sync(inode); out_fput: - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) + printk(KERN_ERR "Error closing lower_file\n"); out_free: if (ecryptfs_file_to_private(&fake_ecryptfs_file)) kmem_cache_free(ecryptfs_file_info_cache, -- cgit v0.10.2 From 316bb95e8ed0ddcd767e8aa54264b6c6190f150c Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:20 -0800 Subject: [PATCH] eCryptfs: Remove ecryptfs_umount_begin There is no point to calling the lower umount_begin when the eCryptfs umount_begin is called. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index c337c04..825757a 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -138,23 +138,6 @@ static void ecryptfs_clear_inode(struct inode *inode) } /** - * ecryptfs_umount_begin - * - * Called in do_umount(). - */ -static void ecryptfs_umount_begin(struct vfsmount *vfsmnt, int flags) -{ - struct vfsmount *lower_mnt = - ecryptfs_dentry_to_lower_mnt(vfsmnt->mnt_sb->s_root); - struct super_block *lower_sb; - - mntput(lower_mnt); - lower_sb = lower_mnt->mnt_sb; - if (lower_sb->s_op->umount_begin) - lower_sb->s_op->umount_begin(lower_mnt, flags); -} - -/** * ecryptfs_show_options * * Prints the directory we are currently mounted over. @@ -193,6 +176,5 @@ struct super_operations ecryptfs_sops = { .statfs = ecryptfs_statfs, .remount_fs = NULL, .clear_inode = ecryptfs_clear_inode, - .umount_begin = ecryptfs_umount_begin, .show_options = ecryptfs_show_options }; -- cgit v0.10.2 From 45ec4ababe999cb95f9c0cad03b2689cb0b77a2b Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Mon, 30 Oct 2006 22:07:20 -0800 Subject: [PATCH] eCryptfs: Fix handling of lower d_count Fix the use of dget/dput calls to balance out on the lower filesystem. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index f0d2a43..0b9992a 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -24,6 +24,7 @@ #include #include +#include #include "ecryptfs_kernel.h" /** @@ -76,8 +77,13 @@ static void ecryptfs_d_release(struct dentry *dentry) if (ecryptfs_dentry_to_private(dentry)) kmem_cache_free(ecryptfs_dentry_info_cache, ecryptfs_dentry_to_private(dentry)); - if (lower_dentry) + if (lower_dentry) { + struct vfsmount *lower_mnt = + ecryptfs_dentry_to_lower_mnt(dentry); + + mntput(lower_mnt); dput(lower_dentry); + } return; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 2f2c6cf..ff4865d 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -325,7 +325,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, struct dentry *lower_dir_dentry; struct dentry *lower_dentry; struct vfsmount *lower_mnt; - struct dentry *tlower_dentry = NULL; char *encoded_name; unsigned int encoded_namelen; struct ecryptfs_crypt_stat *crypt_stat = NULL; @@ -336,27 +335,32 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); dentry->d_op = &ecryptfs_dops; if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) - || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) - goto out_drop; + || (dentry->d_name.len == 2 + && !strcmp(dentry->d_name.name, ".."))) { + d_drop(dentry); + goto out; + } encoded_namelen = ecryptfs_encode_filename(crypt_stat, dentry->d_name.name, dentry->d_name.len, &encoded_name); if (encoded_namelen < 0) { rc = encoded_namelen; - goto out_drop; + d_drop(dentry); + goto out; } ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " "= [%d]\n", encoded_name, encoded_namelen); lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, encoded_namelen - 1); kfree(encoded_name); - lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); if (IS_ERR(lower_dentry)) { ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); rc = PTR_ERR(lower_dentry); - goto out_drop; + d_drop(dentry); + goto out; } + lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" "d_name.name = [%s]\n", lower_dentry, lower_dentry->d_name.name); @@ -397,12 +401,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, "as we *think* we are about to unlink\n"); goto out; } - tlower_dentry = dget(lower_dentry); - if (!tlower_dentry || IS_ERR(tlower_dentry)) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n"); - goto out_dput; - } /* Released in this function */ page_virt = (char *)kmem_cache_alloc(ecryptfs_header_cache_2, @@ -414,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, goto out_dput; } memset(page_virt, 0, PAGE_CACHE_SIZE); - rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); + rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) ecryptfs_set_default_sizes(crypt_stat); @@ -437,9 +435,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, out_dput: dput(lower_dentry); - if (tlower_dentry) - dput(tlower_dentry); -out_drop: d_drop(dentry); out: return ERR_PTR(rc); @@ -475,8 +470,8 @@ out_lock: unlock_dir(lower_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); - if (!new_dentry->d_inode) - d_drop(new_dentry); + d_drop(new_dentry); + d_drop(old_dentry); return rc; } @@ -565,41 +560,24 @@ out: static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { - int rc = 0; - struct dentry *tdentry = NULL; struct dentry *lower_dentry; - struct dentry *tlower_dentry = NULL; struct dentry *lower_dir_dentry; + int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); - if (!(tdentry = dget(dentry))) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n", - dentry); - goto out; - } + dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); - if (!(tlower_dentry = dget(lower_dentry))) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry " - "[%p]\n", lower_dentry); - goto out; - } + dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - if (!rc) { - d_delete(tlower_dentry); - tlower_dentry = NULL; - } + dput(lower_dentry); + if (!rc) + d_delete(lower_dentry); ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); -out: - if (tdentry) - dput(tdentry); - if (tlower_dentry) - dput(tlower_dentry); + dput(dentry); return rc; } -- cgit v0.10.2 From 5ddfe9691c91a244e8d1be597b6428fcefd58103 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Oct 2006 22:07:21 -0800 Subject: [PATCH] md: check bio address after mapping through partitions. Partitions are not limited to live within a device. So we should range check after partition mapping. Note that 'maxsector' was being used for two different things. I have split off the second usage into 'old_sector' so that maxsector can be still be used for it's primary usage later in the function. Cc: Jens Axboe Signed-off-by: Neil Brown Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 1360665..c7b1dac 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2999,6 +2999,7 @@ void generic_make_request(struct bio *bio) { request_queue_t *q; sector_t maxsector; + sector_t old_sector; int ret, nr_sectors = bio_sectors(bio); dev_t old_dev; @@ -3027,7 +3028,7 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ - maxsector = -1; + old_sector = -1; old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3061,15 +3062,30 @@ end_io: */ blk_partition_remap(bio); - if (maxsector != -1) + if (old_sector != -1) blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, - maxsector); + old_sector); blk_add_trace_bio(q, bio, BLK_TA_QUEUE); - maxsector = bio->bi_sector; + old_sector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev; + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; + + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - partitions are not checked + * to make sure they are within the size of the + * whole device. + */ + handle_bad_sector(bio); + goto end_io; + } + } + ret = q->make_request_fn(q, bio); } while (ret); } -- cgit v0.10.2 From 5fccbf61be2a7f32d2002b04afca4c5009612a58 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Oct 2006 14:21:55 +0100 Subject: [PATCH] CFQ: request <-> request merging rr_list fixup In very rare circumstances would we be pruning a merged request and at the same time delete the implicated cfqq from the rr_list, and not readd it when the merged request got added. This could cause io stalls until that process issued io again. Fix it up by putting the rr_list add handling into cfq_add_rq_rb(), identical to how pruning is handled in cfq_del_rq_rb(). This fixes a hang reproducible with fsx-linux. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 25c4e7e..1d9c3c7 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -456,6 +456,9 @@ static void cfq_add_rq_rb(struct request *rq) */ while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL) cfq_dispatch_insert(cfqd->queue, __alias); + + if (!cfq_cfqq_on_rr(cfqq)) + cfq_add_cfqq_rr(cfqd, cfqq); } static inline void @@ -1652,9 +1655,6 @@ static void cfq_insert_request(request_queue_t *q, struct request *rq) cfq_add_rq_rb(rq); - if (!cfq_cfqq_on_rr(cfqq)) - cfq_add_cfqq_rr(cfqd, cfqq); - list_add_tail(&rq->queuelist, &cfqq->fifo); cfq_rq_enqueued(cfqd, cfqq, rq); -- cgit v0.10.2 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 diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig index 08a07f0..69cbff3 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 99a94d7..768df72 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 v0.10.2 From 0887fa5158fe7da4a46ae526d313ae636440deae Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 11:52:03 +0000 Subject: [MIPS] TX4927: Remove indent error message that somehow ended in the code. Signed-off-by: Ralf Baechle diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c index 4658b2a..941c441 100644 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -112,8 +112,6 @@ void print_cp0(char *key, int num, char *name, u32 val) return; } -indent: Standard input:25: Error:Unexpected end of file - void dump_cp0(char *key) { -- cgit v0.10.2 From e8f05de54055e90e6d58e45866f84ecdb0b48acd Mon Sep 17 00:00:00 2001 From: Manish Lachwani Date: Sat, 22 Jan 2005 09:23:38 -0800 Subject: [MIPS] Add missing file for support of backplane on TX4927 based board Signed-off-by: Manish Lachwani Signed-off-by: Ralf Baechle diff --git a/arch/mips/tx4927/common/smsc_fdc37m81x.c b/arch/mips/tx4927/common/smsc_fdc37m81x.c new file mode 100644 index 0000000..33f517b --- /dev/null +++ b/arch/mips/tx4927/common/smsc_fdc37m81x.c @@ -0,0 +1,172 @@ +/* + * Interface for smsc fdc48m81x Super IO chip + * + * Author: MontaVista Software, Inc. source@mvista.com + * + * 2001-2003 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Copyright 2004 (c) MontaVista Software, Inc. + */ +#include +#include +#include +#include + +#define DEBUG + +/* Common Registers */ +#define SMSC_FDC37M81X_CONFIG_INDEX 0x00 +#define SMSC_FDC37M81X_CONFIG_DATA 0x01 +#define SMSC_FDC37M81X_CONF 0x02 +#define SMSC_FDC37M81X_INDEX 0x03 +#define SMSC_FDC37M81X_DNUM 0x07 +#define SMSC_FDC37M81X_DID 0x20 +#define SMSC_FDC37M81X_DREV 0x21 +#define SMSC_FDC37M81X_PCNT 0x22 +#define SMSC_FDC37M81X_PMGT 0x23 +#define SMSC_FDC37M81X_OSC 0x24 +#define SMSC_FDC37M81X_CONFPA0 0x26 +#define SMSC_FDC37M81X_CONFPA1 0x27 +#define SMSC_FDC37M81X_TEST4 0x2B +#define SMSC_FDC37M81X_TEST5 0x2C +#define SMSC_FDC37M81X_TEST1 0x2D +#define SMSC_FDC37M81X_TEST2 0x2E +#define SMSC_FDC37M81X_TEST3 0x2F + +/* Logical device numbers */ +#define SMSC_FDC37M81X_FDD 0x00 +#define SMSC_FDC37M81X_SERIAL1 0x04 +#define SMSC_FDC37M81X_SERIAL2 0x05 +#define SMSC_FDC37M81X_KBD 0x07 + +/* Logical device Config Registers */ +#define SMSC_FDC37M81X_ACTIVE 0x30 +#define SMSC_FDC37M81X_BASEADDR0 0x60 +#define SMSC_FDC37M81X_BASEADDR1 0x61 +#define SMSC_FDC37M81X_INT 0x70 +#define SMSC_FDC37M81X_INT2 0x72 +#define SMSC_FDC37M81X_MODE 0xF0 + +/* Chip Config Values */ +#define SMSC_FDC37M81X_CONFIG_ENTER 0x55 +#define SMSC_FDC37M81X_CONFIG_EXIT 0xaa +#define SMSC_FDC37M81X_CHIP_ID 0x4d + +static unsigned long g_smsc_fdc37m81x_base = 0; + +static inline unsigned char smsc_fdc37m81x_rd(unsigned char index) +{ + outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + + return inb(g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); +} + +static inline void smsc_dc37m81x_wr(unsigned char index, unsigned char data) +{ + outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + outb(data, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); +} + +void smsc_fdc37m81x_config_beg(void) +{ + if (g_smsc_fdc37m81x_base) { + outb(SMSC_FDC37M81X_CONFIG_ENTER, + g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + } +} + +void smsc_fdc37m81x_config_end(void) +{ + if (g_smsc_fdc37m81x_base) + outb(SMSC_FDC37M81X_CONFIG_EXIT, + g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); +} + +u8 smsc_fdc37m81x_config_get(u8 reg) +{ + u8 val = 0; + + if (g_smsc_fdc37m81x_base) + val = smsc_fdc37m81x_rd(reg); + + return val; +} + +void smsc_fdc37m81x_config_set(u8 reg, u8 val) +{ + if (g_smsc_fdc37m81x_base) + smsc_dc37m81x_wr(reg, val); +} + +unsigned long __init smsc_fdc37m81x_init(unsigned long port) +{ + const int field = sizeof(unsigned long) * 2; + u8 chip_id; + + if (g_smsc_fdc37m81x_base) + printk("smsc_fdc37m81x_init() stepping on old base=0x%0*lx\n", + field, g_smsc_fdc37m81x_base); + + g_smsc_fdc37m81x_base = port; + + smsc_fdc37m81x_config_beg(); + + chip_id = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DID); + if (chip_id == SMSC_FDC37M81X_CHIP_ID) + smsc_fdc37m81x_config_end(); + else { + printk("smsc_fdc37m81x_init() unknow chip id 0x%02x\n", + chip_id); + g_smsc_fdc37m81x_base = 0; + } + + return g_smsc_fdc37m81x_base; +} + +#ifdef DEBUG +void smsc_fdc37m81x_config_dump_one(char *key, u8 dev, u8 reg) +{ + printk("%s: dev=0x%02x reg=0x%02x val=0x%02x\n", key, dev, reg, + smsc_fdc37m81x_rd(reg)); +} + +void smsc_fdc37m81x_config_dump(void) +{ + u8 orig; + char *fname = "smsc_fdc37m81x_config_dump()"; + + smsc_fdc37m81x_config_beg(); + + orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM); + + printk("%s: common\n", fname); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DNUM); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DID); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DREV); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_PCNT); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_PMGT); + + printk("%s: keyboard\n", fname); + smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, SMSC_FDC37M81X_KBD); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_ACTIVE); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_INT); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_INT2); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_LDCR_F0); + + smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, orig); + + smsc_fdc37m81x_config_end(); +} +#endif -- cgit v0.10.2 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 diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c index b4b010a..6fce60a 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 377ae0d..919172db 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 4873dc6..7db3c8a 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 v0.10.2 From 38384c8bd82474bf74ea68e4e44aaa14504deb07 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Tue, 31 Oct 2006 13:38:44 +0900 Subject: [MIPS] Yosemite: fix uninitialized variable in titan_i2c_xfer() Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c index 416da22..85b14c7 100644 --- a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c +++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c @@ -74,7 +74,7 @@ static int titan_i2c_poll(void) int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command * cmd, int size, unsigned int *addr) { - int loop = 0, bytes, i; + int loop, bytes = 0, i; unsigned int *write_data, data, *read_data; unsigned long reg_val, val; -- cgit v0.10.2 From 3ab0f40f333007eb31dc1e08f578ec224c7d71c2 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Tue, 31 Oct 2006 13:44:38 +0900 Subject: [MIPS] Fix warning of printk format in mips_srs_init() arch/mips/kernel/traps.c:1115: warning: int format, long unsigned int arg (arg 2) Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index cce8313..9fda1b8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1111,7 +1111,7 @@ static struct shadow_registers { static void mips_srs_init(void) { shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1; - printk(KERN_INFO "%d MIPSR2 register sets available\n", + printk(KERN_INFO "%ld MIPSR2 register sets available\n", shadow_registers.sr_supported); shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ } -- cgit v0.10.2 From 781b0f8d4f9c90137ea32771346ab49f0e5319b3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 18:25:10 +0000 Subject: [MIPS] VSMP: Fix initialization ordering bug. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 3b5f3b6..06b29fa 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -140,15 +140,88 @@ static struct irqaction irq_call = { .name = "IPI_call" }; +static void __init smp_copy_vpe_config(void) +{ + write_vpe_c0_status( + (read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0); + + /* set config to be the same as vpe0, particularly kseg0 coherency alg */ + write_vpe_c0_config( read_c0_config()); + + /* make sure there are no software interrupts pending */ + write_vpe_c0_cause(0); + + /* Propagate Config7 */ + write_vpe_c0_config7(read_c0_config7()); +} + +static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0, + unsigned int ncpu) +{ + if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) + return ncpu; + + /* Deactivate all but VPE 0 */ + if (tc != 0) { + unsigned long tmp = read_vpe_c0_vpeconf0(); + + tmp &= ~VPECONF0_VPA; + + /* master VPE */ + tmp |= VPECONF0_MVP; + write_vpe_c0_vpeconf0(tmp); + + /* Record this as available CPU */ + cpu_set(tc, phys_cpu_present_map); + __cpu_number_map[tc] = ++ncpu; + __cpu_logical_map[ncpu] = tc; + } + + /* Disable multi-threading with TC's */ + write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); + + if (tc != 0) + smp_copy_vpe_config(); + + return ncpu; +} + +static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) +{ + unsigned long tmp; + + if (!tc) + return; + + /* bind a TC to each VPE, May as well put all excess TC's + on the last VPE */ + if (tc >= (((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1)) + write_tc_c0_tcbind(read_tc_c0_tcbind() | ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)); + else { + write_tc_c0_tcbind(read_tc_c0_tcbind() | tc); + + /* and set XTC */ + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (tc << VPECONF0_XTC_SHIFT)); + } + + tmp = read_tc_c0_tcstatus(); + + /* mark not allocated and not dynamically allocatable */ + tmp &= ~(TCSTATUS_A | TCSTATUS_DA); + tmp |= TCSTATUS_IXMT; /* interrupt exempt */ + write_tc_c0_tcstatus(tmp); + + write_tc_c0_tchalt(TCHALT_H); +} + /* * Common setup before any secondaries are started * Make sure all CPU's are in a sensible state before we boot any of the * secondarys */ -void plat_smp_setup(void) +void __init plat_smp_setup(void) { - unsigned long val; - int i, num; + unsigned int mvpconf0, ntc, tc, ncpu = 0; #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ @@ -167,75 +240,16 @@ void plat_smp_setup(void) /* Put MVPE's into 'configuration state' */ set_c0_mvpcontrol(MVPCONTROL_VPC); - val = read_c0_mvpconf0(); + mvpconf0 = read_c0_mvpconf0(); + ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; /* we'll always have more TC's than VPE's, so loop setting everything to a sensible state */ - for (i = 0, num = 0; i <= ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT); i++) { - settc(i); - - /* VPE's */ - if (i <= ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) { - - /* deactivate all but vpe0 */ - if (i != 0) { - unsigned long tmp = read_vpe_c0_vpeconf0(); - - tmp &= ~VPECONF0_VPA; - - /* master VPE */ - tmp |= VPECONF0_MVP; - write_vpe_c0_vpeconf0(tmp); - - /* Record this as available CPU */ - cpu_set(i, phys_cpu_present_map); - __cpu_number_map[i] = ++num; - __cpu_logical_map[num] = i; - } - - /* disable multi-threading with TC's */ - write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); - - if (i != 0) { - write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0); + for (tc = 0; tc <= ntc; tc++) { + settc(tc); - /* set config to be the same as vpe0, particularly kseg0 coherency alg */ - write_vpe_c0_config( read_c0_config()); - - /* make sure there are no software interrupts pending */ - write_vpe_c0_cause(0); - - /* Propagate Config7 */ - write_vpe_c0_config7(read_c0_config7()); - } - - } - - /* TC's */ - - if (i != 0) { - unsigned long tmp; - - /* bind a TC to each VPE, May as well put all excess TC's - on the last VPE */ - if ( i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1) ) - write_tc_c0_tcbind(read_tc_c0_tcbind() | ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) ); - else { - write_tc_c0_tcbind( read_tc_c0_tcbind() | i); - - /* and set XTC */ - write_vpe_c0_vpeconf0( read_vpe_c0_vpeconf0() | (i << VPECONF0_XTC_SHIFT)); - } - - tmp = read_tc_c0_tcstatus(); - - /* mark not allocated and not dynamically allocatable */ - tmp &= ~(TCSTATUS_A | TCSTATUS_DA); - tmp |= TCSTATUS_IXMT; /* interrupt exempt */ - write_tc_c0_tcstatus(tmp); - - write_tc_c0_tchalt(TCHALT_H); - } + smp_tc_init(tc, mvpconf0); + ncpu = smp_vpe_init(tc, mvpconf0, ncpu); } /* Release config state */ @@ -243,7 +257,7 @@ void plat_smp_setup(void) /* We'll wait until starting the secondaries before starting MVPE */ - printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); + printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); } void __init plat_prepare_cpus(unsigned int max_cpus) -- cgit v0.10.2 From e79f55a8c7aaae5a33e8c2b29682ec8e603b5434 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 19:53:15 +0000 Subject: [MIPS] Flags must be unsigned long. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index c079e2a..6597067 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -208,7 +208,7 @@ static unsigned int __init estimate_cpu_frequency(void) count = 6000000; #endif #if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) - unsigned int flags; + unsigned long flags; local_irq_save(flags); -- cgit v0.10.2 From 70e46f48cb5933119712ee27945309a4bfc98282 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 18:33:09 +0000 Subject: [MIPS] VSMP: Synchronize cp0 counters on bootup. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 06b29fa..2ac19a6c 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -153,6 +153,8 @@ static void __init smp_copy_vpe_config(void) /* Propagate Config7 */ write_vpe_c0_config7(read_c0_config7()); + + write_vpe_c0_count(read_c0_count()); } static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0, diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 6597067..d817c60 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -209,6 +209,7 @@ static unsigned int __init estimate_cpu_frequency(void) #endif #if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) unsigned long flags; + unsigned int start; local_irq_save(flags); @@ -217,13 +218,13 @@ static unsigned int __init estimate_cpu_frequency(void) while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); /* Start r4k counter. */ - write_c0_count(0); + start = read_c0_count(); /* Read counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - count = read_c0_count(); + count = read_c0_count() - start; /* restore interrupts */ local_irq_restore(flags); diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h index f637ce7..3e9468f 100644 --- a/include/asm-mips/mipsmtregs.h +++ b/include/asm-mips/mipsmtregs.h @@ -352,6 +352,8 @@ do { \ #define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val) #define read_vpe_c0_vpeconf0() mftc0(1, 2) #define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val) +#define read_vpe_c0_count() mftc0(9, 0) +#define write_vpe_c0_count(val) mttc0(9, 0, val) #define read_vpe_c0_status() mftc0(12, 0) #define write_vpe_c0_status(val) mttc0(12, 0, val) #define read_vpe_c0_cause() mftc0(13, 0) -- cgit v0.10.2 From 16b7b2ac0148e839da86af8747b6fa4aad43a9b7 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 24 Oct 2006 00:21:27 +0900 Subject: [MIPS] Fixup migration to GENERIC_TIME Since we already moved to GENERIC_TIME, we should implement alternatives of old do_gettimeoffset routines to get sub-jiffies resolution from gettimeofday(). This patch includes: * MIPS clocksource support (based on works by Manish Lachwani). * remove unused gettimeoffset routines and related codes. * remove unised 64bit do_div64_32(). * simplify mips_hpt_init. (no argument needed, __init tag) * simplify c0_hpt_timer_init. (no need to write to c0_count) * remove some hpt_init routines. * mips_hpt_mask variable to specify bitmask of hpt value. * convert jmr3927_do_gettimeoffset to jmr3927_hpt_read. * convert ip27_do_gettimeoffset to ip27_hpt_read. * convert bcm1480_do_gettimeoffset to bcm1480_hpt_read. * simplify sb1250 hpt functions. (no need to subtract and shift) Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/Documentation/mips/time.README b/Documentation/mips/time.README index e1304b6..a4ce603 100644 --- a/Documentation/mips/time.README +++ b/Documentation/mips/time.README @@ -38,19 +38,14 @@ The new time code provide the following services: a) Implements functions required by Linux common code: time_init - do_gettimeofday - do_settimeofday b) provides an abstraction of RTC and null RTC implementation as default. extern unsigned long (*rtc_get_time)(void); extern int (*rtc_set_time)(unsigned long); - c) a set of gettimeoffset functions for different CPUs and different - needs. - - d) high-level and low-level timer interrupt routines where the timer - interrupt source may or may not be the CPU timer. The high-level - routine is dispatched through do_IRQ() while the low-level is + c) high-level and low-level timer interrupt routines where the timer + interrupt source may or may not be the CPU timer. The high-level + routine is dispatched through do_IRQ() while the low-level is dispatched in assemably code (usually int-handler.S) @@ -73,8 +68,7 @@ the following functions or values: c) (optional) board-specific RTC routines. d) (optional) mips_hpt_frequency - It must be definied if the board - is using CPU counter for timer interrupt or it is using fixed rate - gettimeoffset(). + is using CPU counter for timer interrupt. PORTING GUIDE @@ -89,16 +83,6 @@ Step 1: decide how you like to implement the time services. If the answer is no, you need a timer to provide the timer interrupt at 100 HZ speed. - You cannot use the fast gettimeoffset functions, i.e., - - unsigned long fixed_rate_gettimeoffset(void); - unsigned long calibrate_div32_gettimeoffset(void); - unsigned long calibrate_div64_gettimeoffset(void); - - You can use null_gettimeoffset() will gives the same time resolution as - jiffy. Or you can implement your own gettimeoffset (probably based on - some ad hoc hardware on your machine.) - c) The following sub steps assume your CPU has counter register. Do you plan to use the CPU counter register as the timer interrupt or use an exnternal timer? @@ -123,8 +107,8 @@ Step 3: implement rtc routines, board_time_init() and plat_timer_setup() board_time_init() - a) (optional) set up RTC routines, b) (optional) calibrate and set the mips_hpt_frequency - (only needed if you intended to use fixed_rate_gettimeoffset - or use cpu counter as timer interrupt source) + (only needed if you intended to use cpu counter as timer interrupt + source) plat_timer_setup() - a) (optional) over-write any choices made above by time_init(). @@ -154,8 +138,8 @@ for some of the functions in time.c. For example, you may define your own timer interrupt routine, which does some of its own processing and then calls timer_interrupt(). -You can also over-ride any of the built-in functions (gettimeoffset, -RTC routines and/or timer interrupt routine). +You can also over-ride any of the built-in functions (RTC routines +and/or timer interrupt routine). PORTING NOTES FOR SMP @@ -187,10 +171,3 @@ You need to decide on your timer interrupt sources. You can also do the low-level version of those interrupt routines, following similar dispatching routes described above. - -Note about do_gettimeoffset(): - - It is very likely the CPU counter registers are not sync'ed up in a SMP box. - Therefore you cannot really use the many of the existing routines that - are based on CPU counter. You should wirte your own gettimeoffset rouinte - if you want intra-jiffy resolution. diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 6768638..fa1c62f 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -53,9 +53,6 @@ static unsigned long r4k_cur; /* What counter should be at next timer irq */ int no_au1xxx_32khz; extern int allow_au1k_wait; /* default off for CP0 Counter */ -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi = 0, timerlo = 0; - #ifdef CONFIG_PM #if HZ < 100 || HZ > 1000 #error "unsupported HZ value! Must be in [100,1000]" @@ -90,10 +87,6 @@ void mips_timer_interrupt(void) goto null; do { - count = read_c0_count(); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - kstat_this_cpu.irqs[irq]++; do_timer(1); #ifndef CONFIG_SMP @@ -297,88 +290,6 @@ unsigned long cal_r4koff(void) return (cpu_speed / HZ); } -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff) - -static unsigned long -div64_32(unsigned long v1, unsigned long v2, unsigned long v3) -{ - unsigned long r0; - do_div64_32(r0, v1, v2, v3); - return r0; -} - -static unsigned long do_fast_cp0_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long r0; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - r0 = div64_32(timerhi, timerlo, tmp); - quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - : "=r" (res) - : "r" (count), "r" (quotient) - : "hi", "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -#ifdef CONFIG_PM -static unsigned long do_fast_pm_gettimeoffset(void) -{ - unsigned long pc0; - unsigned long offset; - - pc0 = au_readl(SYS_TOYREAD); - au_sync(); - offset = pc0 - last_pc0; - if (offset > 2*MATCH20_INC) { - printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", - (unsigned)offset, (unsigned)last_pc0, - (unsigned)last_match20, (unsigned)pc0); - } - offset = (unsigned long)((offset * 305) / 10); - return offset; -} -#endif - void __init plat_timer_setup(struct irqaction *irq) { unsigned int est_freq; @@ -416,7 +327,6 @@ void __init plat_timer_setup(struct irqaction *irq) unsigned int c0_status; printk("WARNING: no 32KHz clock found.\n"); - do_gettimeoffset = do_fast_cp0_gettimeoffset; /* Ensure we get CPO_COUNTER interrupts. */ @@ -441,19 +351,11 @@ void __init plat_timer_setup(struct irqaction *irq) while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); startup_match20_interrupt(counter0_irq); - do_gettimeoffset = do_fast_pm_gettimeoffset; - /* We can use the real 'wait' instruction. */ allow_au1k_wait = 1; } -#else - /* We have to do this here instead of in timer_init because - * the generic code in arch/mips/kernel/time.c will write - * over our function pointer. - */ - do_gettimeoffset = do_fast_cp0_gettimeoffset; #endif } diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 4cf0c06..69e424e 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -160,11 +160,6 @@ static unsigned int dec_ioasic_hpt_read(void) return ioasic_read(IO_REG_FCTR); } -static void dec_ioasic_hpt_init(unsigned int count) -{ - ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count); -} - void __init dec_time_init(void) { @@ -174,11 +169,9 @@ void __init dec_time_init(void) mips_timer_state = dec_timer_state; mips_timer_ack = dec_timer_ack; - if (!cpu_has_counter && IOASIC) { + if (!cpu_has_counter && IOASIC) /* For pre-R4k systems we use the I/O ASIC's counter. */ mips_hpt_read = dec_ioasic_hpt_read; - mips_hpt_init = dec_ioasic_hpt_init; - } /* Set up the rate of periodic DS1287 interrupts. */ CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 0254340..16e5dfe 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -170,12 +170,20 @@ static void jmr3927_machine_power_off(void) while (1); } +static unsigned int jmr3927_hpt_read(void) +{ + /* We assume this function is called xtime_lock held. */ + return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; +} + #define USE_RTC_DS1742 #ifdef USE_RTC_DS1742 extern void rtc_ds1742_init(unsigned long base); #endif static void __init jmr3927_time_init(void) { + mips_hpt_read = jmr3927_hpt_read; + mips_hpt_frequency = JMR3927_TIMER_CLK; #ifdef USE_RTC_DS1742 if (jmr3927_have_nvram()) { rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR); @@ -183,12 +191,8 @@ static void __init jmr3927_time_init(void) #endif } -unsigned long jmr3927_do_gettimeoffset(void); - void __init plat_timer_setup(struct irqaction *irq) { - do_gettimeoffset = jmr3927_do_gettimeoffset; - jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; @@ -200,34 +204,6 @@ void __init plat_timer_setup(struct irqaction *irq) #define USECS_PER_JIFFY (1000000/HZ) -unsigned long jmr3927_do_gettimeoffset(void) -{ - unsigned long count; - unsigned long res = 0; - - /* MUST read TRR before TISR. */ - count = jmr3927_tmrptr->trr; - - if (jmr3927_tmrptr->tisr & TXx927_TMTISR_TIIS) { - /* timer interrupt is pending. use Max value. */ - res = USECS_PER_JIFFY - 1; - } else { - /* convert to usec */ - /* res = count / (JMR3927_TIMER_CLK / 1000000); */ - res = (count << 7) / ((JMR3927_TIMER_CLK << 7) / 1000000); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - } - - return res; -} - - //#undef DO_WRITE_THROUGH #define DO_WRITE_THROUGH #define DO_ENABLE_CACHE diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index debe86c..e535f86 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -11,6 +11,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include #include #include #include @@ -67,15 +68,9 @@ int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time; int (*rtc_mips_set_mmss)(unsigned long); -/* usecs per counter cycle, shifted to left by 32 bits */ -static unsigned int sll32_usecs_per_cycle; - /* how many counter cycles in a jiffy */ static unsigned long cycles_per_jiffy __read_mostly; -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi, timerlo; - /* expirelo is the count value for next CPU timer interrupt */ static unsigned int expirelo; @@ -93,7 +88,7 @@ static unsigned int null_hpt_read(void) return 0; } -static void null_hpt_init(unsigned int count) +static void __init null_hpt_init(void) { /* nothing */ } @@ -128,186 +123,18 @@ static unsigned int c0_hpt_read(void) return read_c0_count(); } -/* For use solely as a high precision timer. */ -static void c0_hpt_init(unsigned int count) -{ - write_c0_count(read_c0_count() - count); -} - /* For use both as a high precision timer and an interrupt source. */ -static void c0_hpt_timer_init(unsigned int count) +static void __init c0_hpt_timer_init(void) { - count = read_c0_count() - count; - expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy; - write_c0_count(expirelo - cycles_per_jiffy); + expirelo = read_c0_count() + cycles_per_jiffy; write_c0_compare(expirelo); - write_c0_count(count); } int (*mips_timer_state)(void); void (*mips_timer_ack)(void); unsigned int (*mips_hpt_read)(void); -void (*mips_hpt_init)(unsigned int); - -/* - * Gettimeoffset routines. These routines returns the time duration - * since last timer interrupt in usecs. - * - * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. - * Otherwise use calibrate_gettimeoffset() - * - * If the CPU does not have the counter register, you can either supply - * your own gettimeoffset() routine, or use null_gettimeoffset(), which - * gives the same resolution as HZ. - */ - -static unsigned long null_gettimeoffset(void) -{ - return 0; -} - - -/* The function pointer to one of the gettimeoffset funcs. */ -unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; - - -static unsigned long fixed_rate_gettimeoffset(void) -{ - u32 count; - unsigned long res; - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (sll32_usecs_per_cycle) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - - -/* - * Cached "1/(clocks per usec) * 2^32" value. - * It has to be recalculated once each jiffy. - */ -static unsigned long cached_quotient; - -/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ -static unsigned long last_jiffies; - -/* - * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej. - */ -static unsigned long calibrate_div32_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - unsigned long r0; - do_div64_32(r0, timerhi, timerlo, tmp); - do_div64_32(quotient, USECS_PER_JIFFY, - USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (quotient) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - -static unsigned long calibrate_div64_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies) { - unsigned long r0; - __asm__(".set push\n\t" - ".set mips3\n\t" - "lwu %0,%3\n\t" - "dsll32 %1,%2,0\n\t" - "or %1,%1,%0\n\t" - "ddivu $0,%1,%4\n\t" - "mflo %1\n\t" - "dsll32 %0,%5,0\n\t" - "or %0,%0,%6\n\t" - "ddivu $0,%0,%1\n\t" - "mflo %0\n\t" - ".set pop" - : "=&r" (quotient), "=&r" (r0) - : "r" (timerhi), "m" (timerlo), - "r" (tmp), "r" (USECS_PER_JIFFY), - "r" (USECS_PER_JIFFY_FRAC) - : "hi", "lo", GCC_REG_ACCUM); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (quotient) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - +void (*mips_hpt_init)(void) __initdata = null_hpt_init; +unsigned int mips_hpt_mask = 0xffffffff; /* last time when xtime and rtc are sync'ed up */ static long last_rtc_update; @@ -334,18 +161,10 @@ void local_timer_interrupt(int irq, void *dev_id) */ irqreturn_t timer_interrupt(int irq, void *dev_id) { - unsigned long j; - unsigned int count; - write_seqlock(&xtime_lock); - count = mips_hpt_read(); mips_timer_ack(); - /* Update timerhi/timerlo for intra-jiffy calibration. */ - timerhi += count < timerlo; /* Wrap around */ - timerlo = count; - /* * call the generic timer interrupt handling */ @@ -368,47 +187,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) } } - /* - * If jiffies has overflown in this timer_interrupt, we must - * update the timer[hi]/[lo] to make fast gettimeoffset funcs - * quotient calc still valid. -arca - * - * The first timer interrupt comes late as interrupts are - * enabled long after timers are initialized. Therefore the - * high precision timer is fast, leading to wrong gettimeoffset() - * calculations. We deal with it by setting it based on the - * number of its ticks between the second and the third interrupt. - * That is still somewhat imprecise, but it's a good estimate. - * --macro - */ - j = jiffies; - if (j < 4) { - static unsigned int prev_count; - static int hpt_initialized; - - switch (j) { - case 0: - timerhi = timerlo = 0; - mips_hpt_init(count); - break; - case 2: - prev_count = count; - break; - case 3: - if (!hpt_initialized) { - unsigned int c3 = 3 * (count - prev_count); - - timerhi = 0; - timerlo = c3; - mips_hpt_init(count - c3); - hpt_initialized = 1; - } - break; - default: - break; - } - } - write_sequnlock(&xtime_lock); /* @@ -476,12 +254,11 @@ asmlinkage void ll_local_timer_interrupt(int irq) * 1) board_time_init() - * a) (optional) set up RTC routines, * b) (optional) calibrate and set the mips_hpt_frequency - * (only needed if you intended to use fixed_rate_gettimeoffset - * or use cpu counter as timer interrupt source) + * (only needed if you intended to use cpu counter as timer interrupt + * source) * 2) setup xtime based on rtc_mips_get_time(). - * 3) choose a appropriate gettimeoffset routine. - * 4) calculate a couple of cached variables for later usage - * 5) plat_timer_setup() - + * 3) calculate a couple of cached variables for later usage + * 4) plat_timer_setup() - * a) (optional) over-write any choices made above by time_init(). * b) machine specific code should setup the timer irqaction. * c) enable the timer interrupt @@ -533,13 +310,48 @@ static unsigned int __init calibrate_hpt(void) } while (--i); hpt_end = mips_hpt_read(); - hpt_count = hpt_end - hpt_start; + hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; hz = HZ; frequency = (u64)hpt_count * (u64)hz; return frequency >> log_2_loops; } +static cycle_t read_mips_hpt(void) +{ + return (cycle_t)mips_hpt_read(); +} + +static struct clocksource clocksource_mips = { + .name = "MIPS", + .read = read_mips_hpt, + .is_continuous = 1, +}; + +static void __init init_mips_clocksource(void) +{ + u64 temp; + u32 shift; + + if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) + return; + + /* Calclate a somewhat reasonable rating value */ + clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; + /* Find a shift value */ + for (shift = 32; shift > 0; shift--) { + temp = (u64) NSEC_PER_SEC << shift; + do_div(temp, mips_hpt_frequency); + if ((temp >> 32) == 0) + break; + } + clocksource_mips.shift = shift; + clocksource_mips.mult = (u32)temp; + clocksource_mips.mask = mips_hpt_mask; + + clocksource_register(&clocksource_mips); +} + void __init time_init(void) { if (board_time_init) @@ -555,41 +367,21 @@ void __init time_init(void) -xtime.tv_sec, -xtime.tv_nsec); /* Choose appropriate high precision timer routines. */ - if (!cpu_has_counter && !mips_hpt_read) { + if (!cpu_has_counter && !mips_hpt_read) /* No high precision timer -- sorry. */ mips_hpt_read = null_hpt_read; - mips_hpt_init = null_hpt_init; - } else if (!mips_hpt_frequency && !mips_timer_state) { + else if (!mips_hpt_frequency && !mips_timer_state) { /* A high precision timer of unknown frequency. */ - if (!mips_hpt_read) { + if (!mips_hpt_read) /* No external high precision timer -- use R4k. */ mips_hpt_read = c0_hpt_read; - mips_hpt_init = c0_hpt_init; - } - - if (cpu_has_mips32r1 || cpu_has_mips32r2 || - (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) - /* - * We need to calibrate the counter but we don't have - * 64-bit division. - */ - do_gettimeoffset = calibrate_div32_gettimeoffset; - else - /* - * We need to calibrate the counter but we *do* have - * 64-bit division. - */ - do_gettimeoffset = calibrate_div64_gettimeoffset; } else { /* We know counter frequency. Or we can get it. */ if (!mips_hpt_read) { /* No external high precision timer -- use R4k. */ mips_hpt_read = c0_hpt_read; - if (mips_timer_state) - mips_hpt_init = c0_hpt_init; - else { + if (!mips_timer_state) { /* No external timer interrupt -- use R4k. */ mips_hpt_init = c0_hpt_timer_init; mips_timer_ack = c0_timer_ack; @@ -598,16 +390,9 @@ void __init time_init(void) if (!mips_hpt_frequency) mips_hpt_frequency = calibrate_hpt(); - do_gettimeoffset = fixed_rate_gettimeoffset; - /* Calculate cache parameters. */ cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; - /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ - do_div64_32(sll32_usecs_per_cycle, - 1000000, mips_hpt_frequency / 2, - mips_hpt_frequency); - /* Report the high precision timer rate for a reference. */ printk("Using %u.%03u MHz high precision timer.\n", ((mips_hpt_frequency + 500) / 1000) / 1000, @@ -619,7 +404,7 @@ void __init time_init(void) mips_timer_ack = null_timer_ack; /* This sets up the high precision timer for the first interrupt. */ - mips_hpt_init(mips_hpt_read()); + mips_hpt_init(); /* * Call board specific timer interrupt setup. @@ -633,6 +418,8 @@ void __init time_init(void) * is not invoked accidentally. */ plat_timer_setup(&timer_irqaction); + + init_mips_clocksource(); } #define FEBRUARY 2 diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c index 0af655b..65c440e 100644 --- a/arch/mips/philips/pnx8550/common/time.c +++ b/arch/mips/philips/pnx8550/common/time.c @@ -41,8 +41,8 @@ extern unsigned int mips_hpt_frequency; * 1) board_time_init() - * a) (optional) set up RTC routines, * b) (optional) calibrate and set the mips_hpt_frequency - * (only needed if you intended to use fixed_rate_gettimeoffset - * or use cpu counter as timer interrupt source) + * (only needed if you intended to use cpu counter as timer interrupt + * source) */ void pnx8550_time_init(void) diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 65fa3a2..3cc0436 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -3,9 +3,7 @@ #include #include - -extern unsigned int (*mips_hpt_read)(void); -extern void (*mips_hpt_init)(unsigned int); +#include #define LAUNCHSTACK_SIZE 256 @@ -101,7 +99,7 @@ void prom_cpus_done(void) */ void prom_init_secondary(void) { - mips_hpt_init(mips_hpt_read()); + mips_hpt_init(); set_c0_status(ST0_CO | ST0_IE | ST0_IM); } diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 4e870fc..c965705 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -134,13 +134,6 @@ again: irq_exit(); } -unsigned long ip27_do_gettimeoffset(void) -{ - unsigned long ct_cur1; - ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY; - return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000; -} - /* Includes for ioc3_init(). */ #include #include @@ -248,12 +241,17 @@ void __init plat_timer_setup(struct irqaction *irq) setup_irq(irqno, &rt_irqaction); } +static unsigned int ip27_hpt_read(void) +{ + return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); +} + void __init ip27_time_init(void) { + mips_hpt_read = ip27_hpt_read; + mips_hpt_frequency = CYCLES_PER_SEC; xtime.tv_sec = get_m48t35_time(); xtime.tv_nsec = 0; - - do_gettimeoffset = ip27_do_gettimeoffset; } void __init cpu_time_init(void) diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index bf12af4..e136bde 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -47,6 +47,12 @@ #define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 #define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 +#ifdef CONFIG_SIMULATION +#define BCM1480_HPT_VALUE 50000 +#else +#define BCM1480_HPT_VALUE 1000000 +#endif + extern int bcm1480_steal_irq(int irq); void bcm1480_time_init(void) @@ -59,11 +65,6 @@ void bcm1480_time_init(void) BUG(); } - if (!cpu) { - /* Use our own gettimeoffset() routine */ - do_gettimeoffset = bcm1480_gettimeoffset; - } - bcm1480_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ @@ -74,11 +75,7 @@ void bcm1480_time_init(void) /* Disable the timer and set up the count */ __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); __raw_writeq( -#ifndef CONFIG_SIMULATION - 1000000/HZ -#else - 50000/HZ -#endif + BCM1480_HPT_VALUE/HZ , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); /* Set the timer running */ @@ -122,16 +119,16 @@ void bcm1480_timer_interrupt(void) } } -/* - * We use our own do_gettimeoffset() instead of the generic one, - * because the generic one does not work for SMP case. - * In addition, since we use general timer 0 for system time, - * we can get accurate intra-jiffy offset without calibration. - */ -unsigned long bcm1480_gettimeoffset(void) +static unsigned int bcm1480_hpt_read(void) { + /* We assume this function is called xtime_lock held. */ unsigned long count = __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); + return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count; +} - return 1000000/HZ - count; +void __init bcm1480_hpt_setup(void) +{ + mips_hpt_read = bcm1480_hpt_read; + mips_hpt_frequency = BCM1480_HPT_VALUE; } diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index 0ccf179..bcb74f2 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -47,15 +47,11 @@ #define SB1250_HPT_NUM 3 #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ -#define SB1250_HPT_SHIFT ((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH) extern int sb1250_steal_irq(int irq); static unsigned int sb1250_hpt_read(void); -static void sb1250_hpt_init(unsigned int); - -static unsigned int hpt_offset; void __init sb1250_hpt_setup(void) { @@ -69,13 +65,9 @@ void __init sb1250_hpt_setup(void) __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); - /* - * we need to fill 32 bits, so just use the upper 23 bits and pretend - * the timer is going 512Mhz instead of 1Mhz - */ - mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT; - mips_hpt_init = sb1250_hpt_init; + mips_hpt_frequency = V_SCD_TIMER_FREQ; mips_hpt_read = sb1250_hpt_read; + mips_hpt_mask = M_SCD_TIMER_INIT; } } @@ -149,11 +141,7 @@ void sb1250_timer_interrupt(void) /* * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over - * again. There's no easy way to set to a specific value so store init value - * in hpt_offset and subtract each time. - * - * Note: Timer isn't full 32bits so shift it into the upper part making - * it appear to run at a higher frequency. + * again. */ static unsigned int sb1250_hpt_read(void) { @@ -161,13 +149,5 @@ static unsigned int sb1250_hpt_read(void) count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); - count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT; - - return count - hpt_offset; -} - -static void sb1250_hpt_init(unsigned int count) -{ - hpt_offset = count; - return; + return SB1250_HPT_VALUE - count; } diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h index 5f7dcf5..d107832 100644 --- a/include/asm-mips/div64.h +++ b/include/asm-mips/div64.h @@ -83,27 +83,6 @@ #if (_MIPS_SZLONG == 64) /* - * Don't use this one in new code - */ -#define do_div64_32(res, high, low, base) ({ \ - unsigned int __quot, __mod; \ - unsigned long __div; \ - unsigned int __low, __high, __base; \ - \ - __high = (high); \ - __low = (low); \ - __div = __high; \ - __div = __div << 32 | __low; \ - __base = (base); \ - \ - __mod = __div % __base; \ - __div = __div / __base; \ - \ - __quot = __div; \ - (res) = __quot; \ - __mod; }) - -/* * Hey, we're already 64-bit, no * need to play games.. */ diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h index b09e16c..2ba6988 100644 --- a/include/asm-mips/sibyte/sb1250.h +++ b/include/asm-mips/sibyte/sb1250.h @@ -51,8 +51,8 @@ extern void sb1250_mask_irq(int cpu, int irq); extern void sb1250_unmask_irq(int cpu, int irq); extern void sb1250_smp_finish(void); +extern void bcm1480_hpt_setup(void); extern void bcm1480_time_init(void); -extern unsigned long bcm1480_gettimeoffset(void); extern void bcm1480_mask_irq(int cpu, int irq); extern void bcm1480_unmask_irq(int cpu, int irq); extern void bcm1480_smp_finish(void); diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 28512ba..625acd3 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -48,7 +48,8 @@ extern void (*mips_timer_ack)(void); * If mips_hpt_read is NULL, an R4k-compatible timer setup is attempted. */ extern unsigned int (*mips_hpt_read)(void); -extern void (*mips_hpt_init)(unsigned int); +extern void (*mips_hpt_init)(void); +extern unsigned int mips_hpt_mask; /* * to_tm() converts system time back to (year, mon, day, hour, min, sec). @@ -58,13 +59,6 @@ extern void (*mips_hpt_init)(unsigned int); extern void to_tm(unsigned long tim, struct rtc_time *tm); /* - * do_gettimeoffset(). By default, this func pointer points to - * do_null_gettimeoffset(), which leads to the same resolution as HZ. - * Higher resolution versions are available, which give ~1us resolution. - */ -extern unsigned long (*do_gettimeoffset)(void); - -/* * high-level timer interrupt routines. */ extern irqreturn_t timer_interrupt(int irq, void *dev_id); -- cgit v0.10.2 From 5ee7737379b1d7f0c977c0f1661fbaf01a8d4721 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 27 Oct 2006 19:49:53 +0900 Subject: [IA64] cpu-hotplug: Fixing confliction between CPU hot-add and IPI Signed-off-by: Kenji Kaneshige Acked-by: Satoru Takeuchi Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 657ac99..2763e79 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -328,10 +328,14 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait) { struct call_data_struct data; - int cpus = num_online_cpus()-1; + int cpus; - if (!cpus) + spin_lock(&call_lock); + cpus = num_online_cpus() - 1; + if (!cpus) { + spin_unlock(&call_lock); return 0; + } /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); @@ -343,8 +347,6 @@ smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wai if (wait) atomic_set(&data.finished, 0); - spin_lock(&call_lock); - call_data = &data; mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */ send_IPI_allbutself(IPI_CALL_FUNC); -- cgit v0.10.2 From 264b0f99308436deaee38bab99e586612d012fc1 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Wed, 25 Oct 2006 17:59:47 -0500 Subject: [IA64] MCA recovery: Montecito support The information in MCA records is filled in slightly differently on Montecito than on Madison/McKinley. Usually, the cache check and bus check target identifiers have the same address. On Montecito the cache check and bus check target identifiers can be different if a corrected error (ie SBE or unconsumed poison data) was encountered and then an uncorrected error (ie DBE) was consumed. In that case, the cache check target identifier is the physical address of the DBE (that caused the MCA to surface) while the bus check target identifier is the physical address of the SBE. This patch correctly finds the target identifier that triggered the MCA. If there are multiple valid cache target identifiers in the same error record then use the one with the lowest cache level. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index a45009d..afc1403 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -435,6 +435,50 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, } /** + * get_target_identifier - Get the valid Cache or Bus check target identifier. + * @peidx: pointer of index of processor error section + * + * Return value: + * target address on Success / 0 on Failue + */ +static u64 +get_target_identifier(peidx_table_t *peidx) +{ + u64 target_address = 0; + sal_log_mod_error_info_t *smei; + pal_cache_check_info_t *pcci; + int i, level = 9; + + /* + * Look through the cache checks for a valid target identifier + * If more than one valid target identifier, return the one + * with the lowest cache level. + */ + for (i = 0; i < peidx_cache_check_num(peidx); i++) { + smei = (sal_log_mod_error_info_t *)peidx_cache_check(peidx, i); + if (smei->valid.target_identifier && smei->target_identifier) { + pcci = (pal_cache_check_info_t *)&(smei->check_info); + if (!target_address || (pcci->level < level)) { + target_address = smei->target_identifier; + level = pcci->level; + continue; + } + } + } + if (target_address) + return target_address; + + /* + * Look at the bus check for a valid target identifier + */ + smei = peidx_bus_check(peidx, 0); + if (smei && smei->valid.target_identifier) + return smei->target_identifier; + + return 0; +} + +/** * recover_from_read_error - Try to recover the errors which type are "read"s. * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section @@ -450,13 +494,14 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { - sal_log_mod_error_info_t *smei; + u64 target_identifier; pal_min_state_area_t *pmsa; struct ia64_psr *psr1, *psr2; ia64_fptr_t *mca_hdlr_bh = (ia64_fptr_t*)mca_handler_bhhook; /* Is target address valid? */ - if (!pbci->tv) + target_identifier = get_target_identifier(peidx); + if (!target_identifier) return fatal_mca("target address not valid"); /* @@ -487,32 +532,28 @@ recover_from_read_error(slidx_table_t *slidx, pmsa = sos->pal_min_state; if (psr1->cpl != 0 || ((psr2->cpl != 0) && mca_recover_range(pmsa->pmsa_iip))) { - smei = peidx_bus_check(peidx, 0); - if (smei->valid.target_identifier) { - /* - * setup for resume to bottom half of MCA, - * "mca_handler_bhhook" - */ - /* pass to bhhook as argument (gr8, ...) */ - pmsa->pmsa_gr[8-1] = smei->target_identifier; - pmsa->pmsa_gr[9-1] = pmsa->pmsa_iip; - pmsa->pmsa_gr[10-1] = pmsa->pmsa_ipsr; - /* set interrupted return address (but no use) */ - pmsa->pmsa_br0 = pmsa->pmsa_iip; - /* change resume address to bottom half */ - pmsa->pmsa_iip = mca_hdlr_bh->fp; - pmsa->pmsa_gr[1-1] = mca_hdlr_bh->gp; - /* set cpl with kernel mode */ - psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr; - psr2->cpl = 0; - psr2->ri = 0; - psr2->bn = 1; - psr2->i = 0; - - return mca_recovered("user memory corruption. " + /* + * setup for resume to bottom half of MCA, + * "mca_handler_bhhook" + */ + /* pass to bhhook as argument (gr8, ...) */ + pmsa->pmsa_gr[8-1] = target_identifier; + pmsa->pmsa_gr[9-1] = pmsa->pmsa_iip; + pmsa->pmsa_gr[10-1] = pmsa->pmsa_ipsr; + /* set interrupted return address (but no use) */ + pmsa->pmsa_br0 = pmsa->pmsa_iip; + /* change resume address to bottom half */ + pmsa->pmsa_iip = mca_hdlr_bh->fp; + pmsa->pmsa_gr[1-1] = mca_hdlr_bh->gp; + /* set cpl with kernel mode */ + psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr; + psr2->cpl = 0; + psr2->ri = 0; + psr2->bn = 1; + psr2->i = 0; + + return mca_recovered("user memory corruption. " "kill affected process - recovered."); - } - } return fatal_mca("kernel context not recovered, iip 0x%lx\n", -- cgit v0.10.2 From fa1d19e5d9a94120f31e5783ab44758f46892d94 Mon Sep 17 00:00:00 2001 From: Troy Heber Date: Wed, 25 Oct 2006 14:46:15 -0600 Subject: [IA64] move SAL_CACHE_FLUSH check later in boot The check to see if the firmware drops interrupts during a SAL_CACHE_FLUSH is done to early in the boot. SAL_CACHE_FLUSH expects to be able to make PAL calls in virtual mode, on some cell based machines a fault occurs causing a MCA. This patch moves the check after mmu_context_init so the TLB and VHPT are properly setup. Signed-off-by Troy Heber Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 642fdc7..20bad78 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -223,12 +223,13 @@ static void __init sal_desc_ap_wakeup(void *p) { } */ static int sal_cache_flush_drops_interrupts; -static void __init +void __init check_sal_cache_flush (void) { unsigned long flags; int cpu; - u64 vector; + u64 vector, cache_type = 3; + struct ia64_sal_retval isrv; cpu = get_cpu(); local_irq_save(flags); @@ -243,7 +244,10 @@ check_sal_cache_flush (void) while (!ia64_get_irr(IA64_TIMER_VECTOR)) cpu_relax(); - ia64_sal_cache_flush(3); + SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); + + if (isrv.status) + printk(KERN_ERR "SAL_CAL_FLUSH failed with %ld\n", isrv.status); if (ia64_get_irr(IA64_TIMER_VECTOR)) { vector = ia64_get_ivr(); @@ -331,7 +335,6 @@ ia64_sal_init (struct ia64_sal_systab *systab) p += SAL_DESC_SIZE(*p); } - check_sal_cache_flush(); } int diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c4caa80..d10404a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -457,6 +457,8 @@ setup_arch (char **cmdline_p) cpu_init(); /* initialize the bootstrap CPU */ mmu_context_init(); /* initialize context_id bitmap */ + check_sal_cache_flush(); + #ifdef CONFIG_ACPI acpi_boot_init(); #endif diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 0b210ab..d000689 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -659,6 +659,7 @@ ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, } extern s64 ia64_sal_cache_flush (u64 cache_type); +extern void __init check_sal_cache_flush (void); /* Initialize all the processor and platform level instruction and data caches */ static inline s64 -- cgit v0.10.2 From 024e4f2c5175a482c234cf67ed22368d770bf78f Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Wed, 18 Oct 2006 15:36:49 +1000 Subject: [IA64] Correct definition of handle_IPI The declaration of handle_IPI in arch/ia64/kernel/smp.c was changed but not the definition of this function. Remove struct pt_regs from handle_IPI(). Signed-off-by: Keith Owens Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 2763e79..6ab95ce 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -108,7 +108,7 @@ cpu_die(void) } irqreturn_t -handle_IPI (int irq, void *dev_id, struct pt_regs *regs) +handle_IPI (int irq, void *dev_id) { int this_cpu = get_cpu(); unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation); -- cgit v0.10.2 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 diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 127561c..2fc8b2a 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 v0.10.2 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 diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 2fc8b2a..90d77ec 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 v0.10.2 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 diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 90d77ec..8ebd68e 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 v0.10.2 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 diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c index 4f75696..cb7dbb6 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 d6ba41c..33afea3 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 v0.10.2 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 diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index dcf46ad..5c322df 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 v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e38846e..28c17d1 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 v0.10.2 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 diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index fdbb0d7..806081b 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 v0.10.2 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 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index eb7d44d..4538c99 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 v0.10.2 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 diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index a231ab7..33569ec 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 v0.10.2 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 diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index be8a66e..3b4c478 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 e7e4149..b294903 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 95efdb5..53171f6 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 ef8874b..0441876 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 v0.10.2 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 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 53171f6..16616f5 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 v0.10.2 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 diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 0738f52..9d1235b 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 v0.10.2 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 diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 5250187..4fad8d2 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 v0.10.2 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 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 83728a9..a8fd0c3 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 a5ecb71..0ed263b 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 b03d5a3..abd2deb 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 v0.10.2 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 diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 4fad8d2..8385387 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 v0.10.2 From aec41a0d02342fc9e3b6bb278eae50fa29f04d1f Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Wed, 18 Oct 2006 19:34:40 +0200 Subject: [PATCH] ieee80211: don't flood log with errors The "ieee80211: Workaround malformed 802.11 frames from AP" patch (see http://kernel.org/git/?p=linux/kernel/git/linville/wireless-2.6.git;a=commit;h=f09fc44d8c25f22c4d985bb93857338ed02feac6 ) fixes the problem with some buggy APs but also converts debug message into an error one. This floods the log with errors when you are near such AP (you get a message for every beacon). This patch reverts the error message back to the debug one. Signed-off-by: Jiri Benc Signed-off-by: John W. Linville diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 7707041..2759312 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -1078,12 +1078,12 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element while (length >= sizeof(*info_element)) { if (sizeof(*info_element) + info_element->len > length) { - IEEE80211_ERROR("Info elem: parse failed: " - "info_element->len + 2 > left : " - "info_element->len+2=%zd left=%d, id=%d.\n", - info_element->len + - sizeof(*info_element), - length, info_element->id); + IEEE80211_DEBUG_MGMT("Info elem: parse failed: " + "info_element->len + 2 > left : " + "info_element->len+2=%zd left=%d, id=%d.\n", + info_element->len + + sizeof(*info_element), + length, info_element->id); /* We stop processing but don't return an error here * because some misbehaviour APs break this rule. ie. * Orinoco AP1000. */ -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 6dfa041..bc81b13 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a94c6d8..65edb56 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 2ddbec6..7d383a2 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 d3716cf..811e14a 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 v0.10.2 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 diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 995fcef..93f21aa 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 bad0e98..9a40bbe 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 v0.10.2 From e0da0daee14862e0a5c49f2059641a8deb27eca2 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 27 Oct 2006 14:31:07 -0500 Subject: [POWERPC] Fix rmb() for e500-based machines it The e500 core generates an illegal instruction exception when it tries to execute the lwsync instruction, which we currently use for rmb(). This fixes it by using the LWSYNC macro, which turns into a plain sync on 32-bit machines. Signed-off-by: Andrew Fleming Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 4362759..f7b1227 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -25,8 +25,8 @@ * * We have to use the sync instructions for mb(), since lwsync doesn't * order loads with respect to previous stores. Lwsync is fine for - * rmb(), though. Note that lwsync is interpreted as sync by - * 32-bit and older 64-bit CPUs. + * rmb(), though. Note that rmb() actually uses a sync on 32-bit + * architectures. * * For wmb(), we use sync since wmb is used in drivers to order * stores to system memory with respect to writes to the device. @@ -34,7 +34,7 @@ * SMP since it is only used to order updates to system memory. */ #define mb() __asm__ __volatile__ ("sync" : : : "memory") -#define rmb() __asm__ __volatile__ ("lwsync" : : : "memory") +#define rmb() __asm__ __volatile__ (__stringify(LWSYNC) : : : "memory") #define wmb() __asm__ __volatile__ ("sync" : : : "memory") #define read_barrier_depends() do { } while(0) -- cgit v0.10.2 From dd6c89f686bdb2a5de72fab636fc839e5a0add6d Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 27 Oct 2006 15:06:32 -0500 Subject: [POWERPC] Fix oprofile support for e500 in arch/powerpc Fixed a compile error in building the 85xx support with oprofile, and in the process cleaned up some issues with the fsl_booke performance monitor code. * Reorganized FSL Book-E performance monitoring code so that the 7450 wouldn't be built if the e500 was, and cleaned it up so it was more self-contained. * Added a cpu_setup function for FSL Book-E. The original cpu_setup function prototype had no arguments, assuming that the reg_setup function would copy the required information into variables which represented the registers. This was silly for e500, since it has 1 register per counter (rather than 3 for all counters), so the code has been restructured to have cpu_setup take the current counter config array as an argument, with op_powerpc_setup() invoking op_powerpc_cpu_setup() through on_each_cpu(), and op_powerpc_cpu_setup() invoking the model-specific cpu_setup function with an argument. The argument is ignored on all other platforms at present. * Fixed a confusing line where a trinary operator only had two arguments Signed-off-by: Andrew Fleming Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8b133af..7af23c4 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o obj32-$(CONFIG_MODULES) += module_32.o -obj-$(CONFIG_E500) += perfmon_fsl_booke.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c deleted file mode 100644 index e0dcf2b..0000000 --- a/arch/powerpc/kernel/perfmon_fsl_booke.c +++ /dev/null @@ -1,221 +0,0 @@ -/* arch/powerpc/kernel/perfmon_fsl_booke.c - * Freescale Book-E Performance Monitor code - * - * Author: Andy Fleming - * Copyright (c) 2004 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 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static inline u32 get_pmlca(int ctr); -static inline void set_pmlca(int ctr, u32 pmlca); - -static inline u32 get_pmlca(int ctr) -{ - u32 pmlca; - - switch (ctr) { - case 0: - pmlca = mfpmr(PMRN_PMLCA0); - break; - case 1: - pmlca = mfpmr(PMRN_PMLCA1); - break; - case 2: - pmlca = mfpmr(PMRN_PMLCA2); - break; - case 3: - pmlca = mfpmr(PMRN_PMLCA3); - break; - default: - panic("Bad ctr number\n"); - } - - return pmlca; -} - -static inline void set_pmlca(int ctr, u32 pmlca) -{ - switch (ctr) { - case 0: - mtpmr(PMRN_PMLCA0, pmlca); - break; - case 1: - mtpmr(PMRN_PMLCA1, pmlca); - break; - case 2: - mtpmr(PMRN_PMLCA2, pmlca); - break; - case 3: - mtpmr(PMRN_PMLCA3, pmlca); - break; - default: - panic("Bad ctr number\n"); - } -} - -void init_pmc_stop(int ctr) -{ - u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | - PMLCA_FCM1 | PMLCA_FCM0); - u32 pmlcb = 0; - - switch (ctr) { - case 0: - mtpmr(PMRN_PMLCA0, pmlca); - mtpmr(PMRN_PMLCB0, pmlcb); - break; - case 1: - mtpmr(PMRN_PMLCA1, pmlca); - mtpmr(PMRN_PMLCB1, pmlcb); - break; - case 2: - mtpmr(PMRN_PMLCA2, pmlca); - mtpmr(PMRN_PMLCB2, pmlcb); - break; - case 3: - mtpmr(PMRN_PMLCA3, pmlca); - mtpmr(PMRN_PMLCB3, pmlcb); - break; - default: - panic("Bad ctr number!\n"); - } -} - -void set_pmc_event(int ctr, int event) -{ - u32 pmlca; - - pmlca = get_pmlca(ctr); - - pmlca = (pmlca & ~PMLCA_EVENT_MASK) | - ((event << PMLCA_EVENT_SHIFT) & - PMLCA_EVENT_MASK); - - set_pmlca(ctr, pmlca); -} - -void set_pmc_user_kernel(int ctr, int user, int kernel) -{ - u32 pmlca; - - pmlca = get_pmlca(ctr); - - if(user) - pmlca &= ~PMLCA_FCU; - else - pmlca |= PMLCA_FCU; - - if(kernel) - pmlca &= ~PMLCA_FCS; - else - pmlca |= PMLCA_FCS; - - set_pmlca(ctr, pmlca); -} - -void set_pmc_marked(int ctr, int mark0, int mark1) -{ - u32 pmlca = get_pmlca(ctr); - - if(mark0) - pmlca &= ~PMLCA_FCM0; - else - pmlca |= PMLCA_FCM0; - - if(mark1) - pmlca &= ~PMLCA_FCM1; - else - pmlca |= PMLCA_FCM1; - - set_pmlca(ctr, pmlca); -} - -void pmc_start_ctr(int ctr, int enable) -{ - u32 pmlca = get_pmlca(ctr); - - pmlca &= ~PMLCA_FC; - - if (enable) - pmlca |= PMLCA_CE; - else - pmlca &= ~PMLCA_CE; - - set_pmlca(ctr, pmlca); -} - -void pmc_start_ctrs(int enable) -{ - u32 pmgc0 = mfpmr(PMRN_PMGC0); - - pmgc0 &= ~PMGC0_FAC; - pmgc0 |= PMGC0_FCECE; - - if (enable) - pmgc0 |= PMGC0_PMIE; - else - pmgc0 &= ~PMGC0_PMIE; - - mtpmr(PMRN_PMGC0, pmgc0); -} - -void pmc_stop_ctrs(void) -{ - u32 pmgc0 = mfpmr(PMRN_PMGC0); - - pmgc0 |= PMGC0_FAC; - - pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); - - mtpmr(PMRN_PMGC0, pmgc0); -} - -void dump_pmcs(void) -{ - printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); - printk("pmc\t\tpmlca\t\tpmlcb\n"); - printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), - mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); - printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), - mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); - printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), - mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); - printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), - mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); -} - -EXPORT_SYMBOL(init_pmc_stop); -EXPORT_SYMBOL(set_pmc_event); -EXPORT_SYMBOL(set_pmc_user_kernel); -EXPORT_SYMBOL(set_pmc_marked); -EXPORT_SYMBOL(pmc_start_ctr); -EXPORT_SYMBOL(pmc_start_ctrs); -EXPORT_SYMBOL(pmc_stop_ctrs); -EXPORT_SYMBOL(dump_pmcs); diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c index a0a2efa..3d8f6f4 100644 --- a/arch/powerpc/kernel/pmc.c +++ b/arch/powerpc/kernel/pmc.c @@ -71,7 +71,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq) } pmc_owner_caller = __builtin_return_address(0); - perf_irq = new_perf_irq ? : dummy_perf; + perf_irq = new_perf_irq ? new_perf_irq : dummy_perf; out: spin_unlock(&pmc_owner_lock); diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 3145d61..0b5df9c 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -13,4 +13,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o -oprofile-$(CONFIG_PPC32) += op_model_7450.o +oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index fd0bbbe..63bbef3 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -34,6 +34,11 @@ static void op_handle_interrupt(struct pt_regs *regs) model->handle_interrupt(regs, ctr); } +static void op_powerpc_cpu_setup(void *dummy) +{ + model->cpu_setup(ctr); +} + static int op_powerpc_setup(void) { int err; @@ -47,7 +52,7 @@ static int op_powerpc_setup(void) model->reg_setup(ctr, &sys, model->num_counters); /* Configure the registers on all cpus. */ - on_each_cpu(model->cpu_setup, NULL, 0, 1); + on_each_cpu(op_powerpc_cpu_setup, NULL, 0, 1); return 0; } @@ -142,7 +147,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case PPC_OPROFILE_POWER4: model = &op_model_power4; break; -#else +#endif +#ifdef CONFIG_6xx case PPC_OPROFILE_G4: model = &op_model_7450; break; diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c index d8ee3ae..f481c0e 100644 --- a/arch/powerpc/oprofile/op_model_7450.c +++ b/arch/powerpc/oprofile/op_model_7450.c @@ -81,7 +81,7 @@ static void pmc_stop_ctrs(void) /* Configures the counters on this CPU based on the global * settings */ -static void fsl7450_cpu_setup(void *unused) +static void fsl7450_cpu_setup(struct op_counter_config *ctr) { /* freeze all counters */ pmc_stop_ctrs(); diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index e29dede..0b3c31f 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c @@ -32,42 +32,152 @@ static unsigned long reset_value[OP_MAX_COUNTER]; static int num_counters; static int oprofile_running; -static inline unsigned int ctr_read(unsigned int i) +static void init_pmc_stop(int ctr) { - switch(i) { - case 0: - return mfpmr(PMRN_PMC0); - case 1: - return mfpmr(PMRN_PMC1); - case 2: - return mfpmr(PMRN_PMC2); - case 3: - return mfpmr(PMRN_PMC3); - default: - return 0; - } -} + u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | + PMLCA_FCM1 | PMLCA_FCM0); + u32 pmlcb = 0; -static inline void ctr_write(unsigned int i, unsigned int val) -{ - switch(i) { + switch (ctr) { case 0: - mtpmr(PMRN_PMC0, val); + mtpmr(PMRN_PMLCA0, pmlca); + mtpmr(PMRN_PMLCB0, pmlcb); break; case 1: - mtpmr(PMRN_PMC1, val); + mtpmr(PMRN_PMLCA1, pmlca); + mtpmr(PMRN_PMLCB1, pmlcb); break; case 2: - mtpmr(PMRN_PMC2, val); + mtpmr(PMRN_PMLCA2, pmlca); + mtpmr(PMRN_PMLCB2, pmlcb); break; case 3: - mtpmr(PMRN_PMC3, val); + mtpmr(PMRN_PMLCA3, pmlca); + mtpmr(PMRN_PMLCB3, pmlcb); break; default: - break; + panic("Bad ctr number!\n"); } } +static void set_pmc_event(int ctr, int event) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + pmlca = (pmlca & ~PMLCA_EVENT_MASK) | + ((event << PMLCA_EVENT_SHIFT) & + PMLCA_EVENT_MASK); + + set_pmlca(ctr, pmlca); +} + +static void set_pmc_user_kernel(int ctr, int user, int kernel) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + if(user) + pmlca &= ~PMLCA_FCU; + else + pmlca |= PMLCA_FCU; + + if(kernel) + pmlca &= ~PMLCA_FCS; + else + pmlca |= PMLCA_FCS; + + set_pmlca(ctr, pmlca); +} + +static void set_pmc_marked(int ctr, int mark0, int mark1) +{ + u32 pmlca = get_pmlca(ctr); + + if(mark0) + pmlca &= ~PMLCA_FCM0; + else + pmlca |= PMLCA_FCM0; + + if(mark1) + pmlca &= ~PMLCA_FCM1; + else + pmlca |= PMLCA_FCM1; + + set_pmlca(ctr, pmlca); +} + +static void pmc_start_ctr(int ctr, int enable) +{ + u32 pmlca = get_pmlca(ctr); + + pmlca &= ~PMLCA_FC; + + if (enable) + pmlca |= PMLCA_CE; + else + pmlca &= ~PMLCA_CE; + + set_pmlca(ctr, pmlca); +} + +static void pmc_start_ctrs(int enable) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 &= ~PMGC0_FAC; + pmgc0 |= PMGC0_FCECE; + + if (enable) + pmgc0 |= PMGC0_PMIE; + else + pmgc0 &= ~PMGC0_PMIE; + + mtpmr(PMRN_PMGC0, pmgc0); +} + +static void pmc_stop_ctrs(void) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 |= PMGC0_FAC; + + pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); + + mtpmr(PMRN_PMGC0, pmgc0); +} + +static void dump_pmcs(void) +{ + printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); + printk("pmc\t\tpmlca\t\tpmlcb\n"); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), + mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), + mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), + mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), + mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); +} + +static void fsl_booke_cpu_setup(struct op_counter_config *ctr) +{ + int i; + + /* freeze all counters */ + pmc_stop_ctrs(); + + for (i = 0;i < num_counters;i++) { + init_pmc_stop(i); + + set_pmc_event(i, ctr[i].event); + + set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); + } +} static void fsl_booke_reg_setup(struct op_counter_config *ctr, struct op_system_config *sys, @@ -77,23 +187,14 @@ static void fsl_booke_reg_setup(struct op_counter_config *ctr, num_counters = num_ctrs; - /* freeze all counters */ - pmc_stop_ctrs(); - /* Our counters count up, and "count" refers to * how much before the next interrupt, and we interrupt * on overflow. So we calculate the starting value * which will give us "count" until overflow. * Then we set the events on the enabled counters */ - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; - init_pmc_stop(i); - - set_pmc_event(i, ctr[i].event); - - set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); - } } static void fsl_booke_start(struct op_counter_config *ctr) @@ -105,8 +206,8 @@ static void fsl_booke_start(struct op_counter_config *ctr) for (i = 0; i < num_counters; ++i) { if (ctr[i].enabled) { ctr_write(i, reset_value[i]); - /* Set Each enabled counterd to only - * count when the Mark bit is not set */ + /* Set each enabled counter to only + * count when the Mark bit is *not* set */ set_pmc_marked(i, 1, 0); pmc_start_ctr(i, 1); } else { @@ -177,6 +278,7 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, struct op_powerpc_model op_model_fsl_booke = { .reg_setup = fsl_booke_reg_setup, + .cpu_setup = fsl_booke_cpu_setup, .start = fsl_booke_start, .stop = fsl_booke_stop, .handle_interrupt = fsl_booke_handle_interrupt, diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 6a927ef..356709d 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -82,7 +82,7 @@ static inline int mmcra_must_set_sample(void) return 0; } -static void power4_cpu_setup(void *unused) +static void power4_cpu_setup(struct op_counter_config *ctr) { unsigned int mmcr0 = mmcr0_val; unsigned long mmcra = mmcra_val; diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c index 042f8f4..19c5ee0 100644 --- a/arch/powerpc/oprofile/op_model_rs64.c +++ b/arch/powerpc/oprofile/op_model_rs64.c @@ -102,7 +102,7 @@ static void rs64_reg_setup(struct op_counter_config *ctr, /* XXX setup user and kernel profiling */ } -static void rs64_cpu_setup(void *unused) +static void rs64_cpu_setup(struct op_counter_config *ctr) { unsigned int mmcr0; diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 5b33994..07a10e5 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h @@ -42,7 +42,7 @@ struct op_powerpc_model { void (*reg_setup) (struct op_counter_config *, struct op_system_config *, int num_counters); - void (*cpu_setup) (void *); + void (*cpu_setup) (struct op_counter_config *); void (*start) (struct op_counter_config *); void (*stop) (void); void (*handle_interrupt) (struct pt_regs *, @@ -121,7 +121,90 @@ static inline void ctr_write(unsigned int i, unsigned int val) break; } } -#endif /* !CONFIG_FSL_BOOKE */ +#else /* CONFIG_FSL_BOOKE */ +static inline u32 get_pmlca(int ctr) +{ + u32 pmlca; + + switch (ctr) { + case 0: + pmlca = mfpmr(PMRN_PMLCA0); + break; + case 1: + pmlca = mfpmr(PMRN_PMLCA1); + break; + case 2: + pmlca = mfpmr(PMRN_PMLCA2); + break; + case 3: + pmlca = mfpmr(PMRN_PMLCA3); + break; + default: + panic("Bad ctr number\n"); + } + + return pmlca; +} + +static inline void set_pmlca(int ctr, u32 pmlca) +{ + switch (ctr) { + case 0: + mtpmr(PMRN_PMLCA0, pmlca); + break; + case 1: + mtpmr(PMRN_PMLCA1, pmlca); + break; + case 2: + mtpmr(PMRN_PMLCA2, pmlca); + break; + case 3: + mtpmr(PMRN_PMLCA3, pmlca); + break; + default: + panic("Bad ctr number\n"); + } +} + +static inline unsigned int ctr_read(unsigned int i) +{ + switch(i) { + case 0: + return mfpmr(PMRN_PMC0); + case 1: + return mfpmr(PMRN_PMC1); + case 2: + return mfpmr(PMRN_PMC2); + case 3: + return mfpmr(PMRN_PMC3); + default: + return 0; + } +} + +static inline void ctr_write(unsigned int i, unsigned int val) +{ + switch(i) { + case 0: + mtpmr(PMRN_PMC0, val); + break; + case 1: + mtpmr(PMRN_PMC1, val); + break; + case 2: + mtpmr(PMRN_PMC2, val); + break; + case 3: + mtpmr(PMRN_PMC3, val); + break; + default: + break; + } +} + + +#endif /* CONFIG_FSL_BOOKE */ + extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth); diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h index 07d6a42..8588be6 100644 --- a/include/asm-powerpc/pmc.h +++ b/include/asm-powerpc/pmc.h @@ -32,18 +32,5 @@ void release_pmc_hardware(void); void power4_enable_pmcs(void); #endif -#ifdef CONFIG_FSL_BOOKE -void init_pmc_stop(int ctr); -void set_pmc_event(int ctr, int event); -void set_pmc_user_kernel(int ctr, int user, int kernel); -void set_pmc_marked(int ctr, int mark0, int mark1); -void pmc_start_ctr(int ctr, int enable); -void pmc_start_ctrs(int enable); -void pmc_stop_ctrs(void); -void dump_pmcs(void); - -extern struct op_powerpc_model op_model_fsl_booke; -#endif - #endif /* __KERNEL__ */ #endif /* _POWERPC_PMC_H */ -- cgit v0.10.2 From 5d2efba64b231a1733c4048d1708d77e07f26426 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 30 Oct 2006 16:15:59 +1100 Subject: [POWERPC] Use 4kB iommu pages even on 64kB-page systems The 10Gigabit ethernet device drivers appear to be able to chew up all 256MB of TCE mappings on pSeries systems, as evidenced by numerous error messages: iommu_alloc failed, tbl c0000000010d5c48 vaddr c0000000d875eff0 npages 1 Some experimentation indicates that this is essentially because one 1500 byte ethernet MTU gets mapped as a 64K DMA region when the large 64K pages are enabled. Thus, it doesn't take much to exhaust all of the available DMA mappings for a high-speed card. This patch changes the iommu allocator to work with its own unique, distinct page size. Although the patch is long, its actually quite simple: it just #defines a distinct IOMMU_PAGE_SIZE and then uses this in all the places that matter. As a side effect, it also dramatically improves network performance on platforms with H-calls on iommu translation inserts/removes (since we no longer call it 16 times for a 1500 bytes packet when the iommu HW is still 4k). In the future, we might want to make the IOMMU_PAGE_SIZE a variable in the iommu_table instance, thus allowing support for different HW page sizes in the iommu itself. Signed-off-by: Linas Vepstas Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Acked-by: Stephen Rothwell Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index f88a2a6..ba6b725 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -47,6 +47,17 @@ static int novmerge = 0; static int novmerge = 1; #endif +static inline unsigned long iommu_num_pages(unsigned long vaddr, + unsigned long slen) +{ + unsigned long npages; + + npages = IOMMU_PAGE_ALIGN(vaddr + slen) - (vaddr & IOMMU_PAGE_MASK); + npages >>= IOMMU_PAGE_SHIFT; + + return npages; +} + static int __init setup_iommu(char *str) { if (!strcmp(str, "novmerge")) @@ -178,10 +189,10 @@ static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, } entry += tbl->it_offset; /* Offset into real TCE table */ - ret = entry << PAGE_SHIFT; /* Set the return dma address */ + ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */ /* Put the TCEs in the HW table */ - ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK, + ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK, direction); @@ -203,7 +214,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, unsigned long entry, free_entry; unsigned long i; - entry = dma_addr >> PAGE_SHIFT; + entry = dma_addr >> IOMMU_PAGE_SHIFT; free_entry = entry - tbl->it_offset; if (((free_entry + npages) > tbl->it_size) || @@ -270,7 +281,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, /* Init first segment length for backout at failure */ outs->dma_length = 0; - DBG("mapping %d elements:\n", nelems); + DBG("sg mapping %d elements:\n", nelems); spin_lock_irqsave(&(tbl->it_lock), flags); @@ -285,9 +296,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, } /* Allocate iommu entries for that segment */ vaddr = (unsigned long)page_address(s->page) + s->offset; - npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0); + npages = iommu_num_pages(vaddr, slen); + entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0); DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); @@ -301,14 +311,14 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, /* Convert entry to a dma_addr_t */ entry += tbl->it_offset; - dma_addr = entry << PAGE_SHIFT; - dma_addr |= s->offset; + dma_addr = entry << IOMMU_PAGE_SHIFT; + dma_addr |= (s->offset & ~IOMMU_PAGE_MASK); - DBG(" - %lx pages, entry: %lx, dma_addr: %lx\n", + DBG(" - %lu pages, entry: %lx, dma_addr: %lx\n", npages, entry, dma_addr); /* Insert into HW table */ - ppc_md.tce_build(tbl, entry, npages, vaddr & PAGE_MASK, direction); + ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction); /* If we are in an open segment, try merging */ if (segstart != s) { @@ -323,7 +333,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, DBG(" can't merge, new segment.\n"); } else { outs->dma_length += s->length; - DBG(" merged, new len: %lx\n", outs->dma_length); + DBG(" merged, new len: %ux\n", outs->dma_length); } } @@ -367,9 +377,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, if (s->dma_length != 0) { unsigned long vaddr, npages; - vaddr = s->dma_address & PAGE_MASK; - npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) - >> PAGE_SHIFT; + vaddr = s->dma_address & IOMMU_PAGE_MASK; + npages = iommu_num_pages(s->dma_address, s->dma_length); __iommu_free(tbl, vaddr, npages); s->dma_address = DMA_ERROR_CODE; s->dma_length = 0; @@ -398,8 +407,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, if (sglist->dma_length == 0) break; - npages = (PAGE_ALIGN(dma_handle + sglist->dma_length) - - (dma_handle & PAGE_MASK)) >> PAGE_SHIFT; + npages = iommu_num_pages(dma_handle,sglist->dma_length); __iommu_free(tbl, dma_handle, npages); sglist++; } @@ -532,12 +540,11 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, BUG_ON(direction == DMA_NONE); uaddr = (unsigned long)vaddr; - npages = PAGE_ALIGN(uaddr + size) - (uaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; + npages = iommu_num_pages(uaddr, size); if (tbl) { dma_handle = iommu_alloc(tbl, vaddr, npages, direction, - mask >> PAGE_SHIFT, 0); + mask >> IOMMU_PAGE_SHIFT, 0); if (dma_handle == DMA_ERROR_CODE) { if (printk_ratelimit()) { printk(KERN_INFO "iommu_alloc failed, " @@ -545,7 +552,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, tbl, vaddr, npages); } } else - dma_handle |= (uaddr & ~PAGE_MASK); + dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); } return dma_handle; @@ -554,11 +561,14 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { + unsigned int npages; + BUG_ON(direction == DMA_NONE); - if (tbl) - iommu_free(tbl, dma_handle, (PAGE_ALIGN(dma_handle + size) - - (dma_handle & PAGE_MASK)) >> PAGE_SHIFT); + if (tbl) { + npages = iommu_num_pages(dma_handle, size); + iommu_free(tbl, dma_handle, npages); + } } /* Allocates a contiguous real buffer and creates mappings over it. @@ -570,11 +580,11 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, { void *ret = NULL; dma_addr_t mapping; - unsigned int npages, order; + unsigned int order; + unsigned int nio_pages, io_order; struct page *page; size = PAGE_ALIGN(size); - npages = size >> PAGE_SHIFT; order = get_order(size); /* @@ -598,8 +608,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, memset(ret, 0, size); /* Set up tces to cover the allocated range */ - mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, - mask >> PAGE_SHIFT, order); + nio_pages = size >> IOMMU_PAGE_SHIFT; + io_order = get_iommu_order(size); + mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL, + mask >> IOMMU_PAGE_SHIFT, io_order); if (mapping == DMA_ERROR_CODE) { free_pages((unsigned long)ret, order); return NULL; @@ -611,12 +623,13 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, void iommu_free_coherent(struct iommu_table *tbl, size_t size, void *vaddr, dma_addr_t dma_handle) { - unsigned int npages; - if (tbl) { + unsigned int nio_pages; + + size = PAGE_ALIGN(size); + nio_pages = size >> IOMMU_PAGE_SHIFT; + iommu_free(tbl, dma_handle, nio_pages); size = PAGE_ALIGN(size); - npages = size >> PAGE_SHIFT; - iommu_free(tbl, dma_handle, npages); free_pages((unsigned long)vaddr, get_order(size)); } } diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb87e71..ed00787 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -92,9 +92,9 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) &tbl->it_index, &offset, &size); /* TCE table size - measured in tce entries */ - tbl->it_size = size >> PAGE_SHIFT; + tbl->it_size = size >> IOMMU_PAGE_SHIFT; /* offset for VIO should always be 0 */ - tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; tbl->it_busno = 0; tbl->it_type = TCE_VB; diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index f4cbbcf..218817d 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -43,9 +43,6 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, u64 rc; u64 tce, rpn; - index <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - while (npages--) { rpn = virt_to_abs(uaddr) >> TCE_SHIFT; tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; @@ -75,9 +72,6 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) { u64 rc; - npages <<= TCE_PAGE_FACTOR; - index <<= TCE_PAGE_FACTOR; - while (npages--) { rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); if (rc) @@ -136,10 +130,9 @@ void iommu_table_getparms_iSeries(unsigned long busno, panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); /* itc_size is in pages worth of table, it_size is in # of entries */ - tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / - TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR; + tbl->it_size = (parms->itc_size * TCE_PAGE_SIZE) / TCE_ENTRY_SIZE; tbl->it_busno = parms->itc_busno; - tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; + tbl->it_offset = parms->itc_offset; tbl->it_index = parms->itc_index; tbl->it_blocksize = 1; tbl->it_type = virtbus ? TCE_VB : TCE_PCI; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index d24ba54..556c279 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -57,9 +57,6 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index, u64 *tcep; u64 rpn; - index <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - proto_tce = TCE_PCI_READ; // Read allowed if (direction != DMA_TO_DEVICE) @@ -82,9 +79,6 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) { u64 *tcep; - npages <<= TCE_PAGE_FACTOR; - index <<= TCE_PAGE_FACTOR; - tcep = ((u64 *)tbl->it_base) + index; while (npages--) @@ -95,7 +89,6 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) { u64 *tcep; - index <<= TCE_PAGE_FACTOR; tcep = ((u64 *)tbl->it_base) + index; return *tcep; @@ -109,9 +102,6 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, u64 proto_tce, tce; u64 rpn; - tcenum <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) @@ -146,7 +136,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, u64 rpn; long l, limit; - if (TCE_PAGE_FACTOR == 0 && npages == 1) + if (npages == 1) return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction); @@ -164,9 +154,6 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, __get_cpu_var(tce_page) = tcep; } - tcenum <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) @@ -207,9 +194,6 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages { u64 rc; - tcenum <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - while (npages--) { rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0); @@ -229,9 +213,6 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n { u64 rc; - tcenum <<= TCE_PAGE_FACTOR; - npages <<= TCE_PAGE_FACTOR; - rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages); if (rc && printk_ratelimit()) { @@ -248,7 +229,6 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) u64 rc; unsigned long tce_ret; - tcenum <<= TCE_PAGE_FACTOR; rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret); if (rc && printk_ratelimit()) { @@ -289,7 +269,7 @@ static void iommu_table_setparms(struct pci_controller *phb, tbl->it_busno = phb->bus->number; /* Units of tce entries */ - tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; + tbl->it_offset = phb->dma_window_base_cur >> IOMMU_PAGE_SHIFT; /* Test if we are going over 2GB of DMA space */ if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { @@ -300,7 +280,7 @@ static void iommu_table_setparms(struct pci_controller *phb, phb->dma_window_base_cur += phb->dma_window_size; /* Set the tce table size - measured in entries */ - tbl->it_size = phb->dma_window_size >> PAGE_SHIFT; + tbl->it_size = phb->dma_window_size >> IOMMU_PAGE_SHIFT; tbl->it_index = 0; tbl->it_blocksize = 16; @@ -325,8 +305,8 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, tbl->it_base = 0; tbl->it_blocksize = 16; tbl->it_type = TCE_PCI; - tbl->it_offset = offset >> PAGE_SHIFT; - tbl->it_size = size >> PAGE_SHIFT; + tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; + tbl->it_size = size >> IOMMU_PAGE_SHIFT; } static void iommu_bus_setup_pSeries(struct pci_bus *bus) @@ -522,8 +502,6 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) const void *dma_window = NULL; struct pci_dn *pci; - DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); - /* dev setup for LPAR is a little tricky, since the device tree might * contain the dma-window properties per-device and not neccesarily * for the bus. So we need to search upwards in the tree until we @@ -532,6 +510,9 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) */ dn = pci_device_to_OF_node(dev); + DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", + dev, pci_name(dev), dn->full_name); + for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { dma_window = get_property(pdn, "ibm,dma-window", NULL); diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h index 1c8817c..ff202ed 100644 --- a/arch/powerpc/sysdev/dart.h +++ b/arch/powerpc/sysdev/dart.h @@ -72,7 +72,6 @@ #define DART_PAGE_SHIFT 12 #define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT) -#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT) #endif /* _POWERPC_SYSDEV_DART_H */ diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 03b4477..572b784 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -156,9 +156,6 @@ static void dart_build(struct iommu_table *tbl, long index, DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); - index <<= DART_PAGE_FACTOR; - npages <<= DART_PAGE_FACTOR; - dp = ((unsigned int*)tbl->it_base) + index; /* On U3, all memory is contigous, so we can move this @@ -199,9 +196,6 @@ static void dart_free(struct iommu_table *tbl, long index, long npages) DBG("dart: free at: %lx, %lx\n", index, npages); - index <<= DART_PAGE_FACTOR; - npages <<= DART_PAGE_FACTOR; - dp = ((unsigned int *)tbl->it_base) + index; while (npages--) @@ -281,7 +275,7 @@ static void iommu_table_dart_setup(void) iommu_table_dart.it_busno = 0; iommu_table_dart.it_offset = 0; /* it_size is in number of entries */ - iommu_table_dart.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR; + iommu_table_dart.it_size = dart_tablesize / sizeof(u32); /* Initialize the common IOMMU code */ iommu_table_dart.it_base = (unsigned long)dart_vbase; diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index a5e9864..39fad68 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -22,17 +22,35 @@ #define _ASM_IOMMU_H #ifdef __KERNEL__ -#include +#include #include #include #include +#include +#include + +#define IOMMU_PAGE_SHIFT 12 +#define IOMMU_PAGE_SIZE (ASM_CONST(1) << IOMMU_PAGE_SHIFT) +#define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1)) +#define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) + +#ifndef __ASSEMBLY__ + +/* Pure 2^n version of get_order */ +static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) +{ + return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1; +} + +#endif /* __ASSEMBLY__ */ + /* * IOMAP_MAX_ORDER defines the largest contiguous block * of dma space we can get. IOMAP_MAX_ORDER = 13 * allows up to 2**12 pages (4096 * 4096) = 16 MB */ -#define IOMAP_MAX_ORDER 13 +#define IOMAP_MAX_ORDER 13 struct iommu_table { unsigned long it_busno; /* Bus number this table belongs to */ diff --git a/include/asm-powerpc/tce.h b/include/asm-powerpc/tce.h index c9483ad..f663634 100644 --- a/include/asm-powerpc/tce.h +++ b/include/asm-powerpc/tce.h @@ -22,6 +22,8 @@ #define _ASM_POWERPC_TCE_H #ifdef __KERNEL__ +#include + /* * Tces come in two formats, one for the virtual bus and a different * format for PCI @@ -33,7 +35,6 @@ #define TCE_SHIFT 12 #define TCE_PAGE_SIZE (1 << TCE_SHIFT) -#define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT) #define TCE_ENTRY_SIZE 8 /* each TCE is 64 bits */ -- cgit v0.10.2 From 302439d2167e0f1e01a6480ac40c06063f4e16a1 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 31 Oct 2006 17:53:42 +0800 Subject: [POWERPC] qe_lib: qe_issue_cmd writes wrong value to CECDR Changed qe_issue_cmd() to write cmd_input to the CECDR unmodified. It was treating cmd_input as a virtual address and tried to convert it to a physical address. Signed-off-by: Timur Tabi Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 2bae632..e422322 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -122,8 +122,7 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) mcn_shift = QE_CR_MCN_NORMAL_SHIFT; } - out_be32(&qe_immr->cp.cecdr, - immrbar_virt_to_phys((void *)cmd_input)); + out_be32(&qe_immr->cp.cecdr, cmd_input); out_be32(&qe_immr->cp.cecr, (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32) mcn_protocol << mcn_shift)); -- cgit v0.10.2 From 5fe8e8b88e68e517637e3f8287f1fee89e2d9252 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 31 Oct 2006 18:39:31 +0000 Subject: [POWERPC] Make current preempt-safe Repeated -j20 kernel builds on a G5 Quad running an SMP PREEMPT kernel would often collapse within a day, some exec failing with "Bad address". In each case examined, load_elf_binary was doing a kernel_read, but generic_file_aio_read's access_ok saw current->thread.fs.seg as USER_DS instead of KERNEL_DS. objdump of filemap.o shows gcc 4.1.0 emitting "mr r5,r13 ... ld r9,416(r5)" here for get_paca()->__current, instead of the expected and much more usual "ld r9,416(r13)"; I've seen other gcc4s do the same, but perhaps not gcc3s. So, if the task is preempted and rescheduled on a different cpu in between the mr and the ld, r5 will be looking at a different paca_struct from the one it's now on, pick up the wrong __current, and perhaps the wrong seg. Presumably much worse could happen elsewhere, though that split is rare. Other architectures appear to be safe (x86_64's read_pda is more limiting than get_paca), but ppc64 needs to force "current" into one instruction. Signed-off-by: Hugh Dickins Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/current.h b/include/asm-powerpc/current.h index 1938d6ab..b8708ae 100644 --- a/include/asm-powerpc/current.h +++ b/include/asm-powerpc/current.h @@ -14,7 +14,17 @@ struct task_struct; #ifdef __powerpc64__ #include -#define current (get_paca()->__current) +static inline struct task_struct *get_current(void) +{ + struct task_struct *task; + + __asm__ __volatile__("ld %0,%1(13)" + : "=r" (task) + : "i" (offsetof(struct paca_struct, __current))); + + return task; +} +#define current get_current() #else -- cgit v0.10.2 From 96268889ee369b36203b7a06e8aabb197270216e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 31 Oct 2006 18:40:39 +0000 Subject: [POWERPC] Make high hugepage areas preempt safe Checking source for other get_paca()->field preemption dangers found that open_high_hpage_areas does a structure copy into its paca while preemption is enabled: unsafe however gcc accomplishes it. Just remove that copy: it's done safely afterwards by on_each_cpu, as in open_low_hpage_areas. Signed-off-by: Hugh Dickins Acked-by: David Gibson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 5615acc..fd68b74 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -480,9 +480,6 @@ static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas) mm->context.high_htlb_areas |= newareas; - /* update the paca copy of the context struct */ - get_paca()->context = mm->context; - /* the context change must make it to memory before the flush, * so that further SLB misses do the right thing. */ mb(); -- cgit v0.10.2 From 292f86f005e3867277b2126c2399eea3e773a4fc Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 31 Oct 2006 18:41:51 +0000 Subject: [POWERPC] Make mmiowb's io_sync preempt safe If mmiowb() is always used prior to releasing spinlock as Doc suggests, then it's safe against preemption; but I'm not convinced that's always the case. If preemption occurs between sync and get_paca()->io_sync = 0, I believe there's no problem. But in the unlikely event that gcc does the store relative to another register than r13 (as it did with current), then there's a small danger of setting another cpu's io_sync to 0, after it had just set it to 1. Rewrite ppc64 mmiowb to prevent that. The remaining io_sync assignments in io.h all get_paca()->io_sync = 1, which is harmless even if preempted to the wrong cpu (the context switch itself syncs); and those in spinlock.h are while preemption is disabled. Signed-off-by: Hugh Dickins Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 3baff8b..c2c5f14 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -163,8 +163,11 @@ extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); static inline void mmiowb(void) { - __asm__ __volatile__ ("sync" : : : "memory"); - get_paca()->io_sync = 0; + unsigned long tmp; + + __asm__ __volatile__("sync; li %0,0; stb %0,%1(13)" + : "=&r" (tmp) : "i" (offsetof(struct paca_struct, io_sync)) + : "memory"); } /* -- cgit v0.10.2 From 0d69a052d4d7c4085706b9ac0d1bd28ff90c9fca Mon Sep 17 00:00:00 2001 From: "Gui,Jian" Date: Wed, 1 Nov 2006 10:50:15 +0800 Subject: [POWERPC] Disallow kprobes on emulate_step and branch_taken On powerpc, probing on emulate_step function will crash 2.6.18.1 when it is triggered. When kprobe is triggered, emulate_step() is on its kernel path and will cause recursive kprobe fault. And branch_taken() is called in emulate_step(). This disallows kprobes on both of them. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 9590ba7..7e8ded0 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ #include +#include #include #include #include @@ -25,7 +26,7 @@ extern char system_call_common[]; /* * Determine whether a conditional branch instruction would branch. */ -static int branch_taken(unsigned int instr, struct pt_regs *regs) +static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) { unsigned int bo = (instr >> 21) & 0x1f; unsigned int bi; @@ -51,7 +52,7 @@ static int branch_taken(unsigned int instr, struct pt_regs *regs) * or -1 if the instruction is one that should not be stepped, * such as an rfid, or a mtmsrd that would clear MSR_RI. */ -int emulate_step(struct pt_regs *regs, unsigned int instr) +int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) { unsigned int opcode, rd; unsigned long int imm; -- cgit v0.10.2 From 4393c4f6788cee65095dd838cfeca6edefbfeb52 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 1 Nov 2006 15:11:39 +1100 Subject: [POWERPC] Make alignment exception always check exception table The alignment exception used to only check the exception table for -EFAULT, not for other errors. That opens an oops window if we can coerce the kernel into getting an alignment exception for other reasons in what would normally be a user-protected accessor, which can be done via some of the futex ops. This fixes it by always checking the exception tables. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 5ed4c2c..c66b477 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -843,7 +843,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed = 0; + int sig, code, fixed = 0; /* we don't implement logging of alignment exceptions */ if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) @@ -857,14 +857,16 @@ void alignment_exception(struct pt_regs *regs) /* Operand address was bad */ if (fixed == -EFAULT) { - if (user_mode(regs)) - _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); - else - /* Search exception table */ - bad_page_fault(regs, regs->dar, SIGSEGV); - return; + sig = SIGSEGV; + code = SEGV_ACCERR; + } else { + sig = SIGBUS; + code = BUS_ADRALN; } - _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); + if (user_mode(regs)) + _exception(sig, regs, code, regs->dar); + else + bad_page_fault(regs, regs->dar, sig); } void StackOverflow(struct pt_regs *regs) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index aafc8e8..9661a91 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -708,7 +708,7 @@ void single_step_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed; + int sig, code, fixed = 0; fixed = fix_alignment(regs); if (fixed == 1) { @@ -717,14 +717,16 @@ void alignment_exception(struct pt_regs *regs) return; } if (fixed == -EFAULT) { - /* fixed == -EFAULT means the operand address was bad */ - if (user_mode(regs)) - _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); - else - bad_page_fault(regs, regs->dar, SIGSEGV); - return; + sig = SIGSEGV; + code = SEGV_ACCERR; + } else { + sig = SIGBUS; + code = BUS_ADRALN; } - _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); + if (user_mode(regs)) + _exception(sig, regs, code, regs->dar); + else + bad_page_fault(regs, regs->dar, sig); } void StackOverflow(struct pt_regs *regs) -- cgit v0.10.2 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 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cef2e70..988f8bb 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 v0.10.2 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 diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 323b607..d65ebfd 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 v0.10.2 From 130fe05dbc0114609cfef9815c0c5580b42decfa Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 1 Nov 2006 09:11:00 -0800 Subject: i386: clean up io-apic accesses This is preparation for fixing the ordering of the accesses that got broken by the commit cf4c6a2f27f5db810b69dcb1da7f194489e8ff88 when factoring out the "common" io apic routing entry accesses. Move the accessor function (that were only used by io_apic.c) out of a header file, and use proper memory-mapped accesses rather than making up our own "volatile" pointers. Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 350192d..eb10bd5 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -91,6 +91,46 @@ static struct irq_pin_list { int apic, pin, next; } irq_2_pin[PIN_MAP_SIZE]; +struct io_apic { + unsigned int index; + unsigned int unused[3]; + unsigned int data; +}; + +static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) +{ + return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx) + + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK); +} + +static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + return readl(&io_apic->data); +} + +static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + writel(value, &io_apic->data); +} + +/* + * Re-write a value: to be used for read-modify-write + * cycles where the read already set up the index register. + * + * Older SiS APIC requires we rewrite the index register + */ +static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) +{ + volatile struct io_apic *io_apic = io_apic_base(apic); + if (sis_apic_bug) + writel(reg, &io_apic->index); + writel(value, &io_apic->data); +} + union entry_union { struct { u32 w1, w2; }; struct IO_APIC_route_entry entry; diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h index 276ea7e..059a9ff 100644 --- a/include/asm-i386/io_apic.h +++ b/include/asm-i386/io_apic.h @@ -12,10 +12,6 @@ #ifdef CONFIG_X86_IO_APIC -#define IO_APIC_BASE(idx) \ - ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ - + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK))) - /* * The structure of the IO-APIC: */ @@ -119,31 +115,8 @@ extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* non-0 if default (table-less) MP configuration */ extern int mpc_default_type; -static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -{ - *IO_APIC_BASE(apic) = reg; - return *(IO_APIC_BASE(apic)+4); -} - -static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) -{ - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = value; -} - -/* - * Re-write a value: to be used for read-modify-write - * cycles where the read already set up the index register. - * - * Older SiS APIC requires we rewrite the index regiser - */ +/* Older SiS APIC requires we rewrite the index register */ extern int sis_apic_bug; -static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) -{ - if (sis_apic_bug) - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = value; -} /* 1 if "noapic" boot option passed */ extern int skip_ioapic_setup; -- cgit v0.10.2 From 242954b5aa8e5ec84f46a84637daf08ee4247c6e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 24 Oct 2006 02:29:01 +0100 Subject: [MIPS] 16K & 64K page size fixes Derived from Peter Watkins 's work. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index e9ce5b3..ff88b06 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -22,7 +22,7 @@ #define offset(string, ptr, member) \ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) #define constant(string, member) \ - __asm__("\n@@@" string "%x0" : : "ri" (member)) + __asm__("\n@@@" string "%X0" : : "ri" (member)) #define size(string, size) \ __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) #define linefeed text("") diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 8c6db0f..ddc1b71 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -189,7 +189,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point MTC0 zero, CP0_CONTEXT # clear context register PTR_LA $28, init_thread_union - PTR_ADDIU sp, $28, _THREAD_SIZE - 32 + PTR_LI sp, _THREAD_SIZE - 32 + PTR_ADDU sp, $28 set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index d5c8b82..cc566cf 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -85,7 +85,12 @@ move $28, a2 cpu_restore_nonscratch a1 +#if (_THREAD_SIZE - 32) < 0x10000 PTR_ADDIU t0, $28, _THREAD_SIZE - 32 +#else + PTR_LI t0, _THREAD_SIZE - 32 + PTR_ADDU t0, $28 +#endif set_saved_sp t0, t1, t2 #ifdef CONFIG_MIPS_MT_SMTC /* Read-modify-writes of Status must be atomic on a VPE */ diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 25ed333..79f0317 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -50,6 +50,16 @@ SECTIONS /* writeable */ .data : { /* Data */ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ + /* + * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which + * limits the maximum alignment to at most 32kB and results in the following + * warning: + * + * CC arch/mips/kernel/init_task.o + * arch/mips/kernel/init_task.c:30: warning: alignment of â€init_thread_union’ + * is greater than maximum object file alignment. Using 32768 + */ + . = ALIGN(_PAGE_SIZE); *(.data.init_task) *(.data) diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c index be8261b..594df1a 100644 --- a/arch/mips/lib-64/dump_tlb.c +++ b/arch/mips/lib-64/dump_tlb.c @@ -149,7 +149,7 @@ void dump_list_process(struct task_struct *t, void *address) printk("Addr == %08lx\n", addr); printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); - page_dir = pgd_offset(t->mm, 0); + page_dir = pgd_offset(t->mm, 0UL); printk("page_dir == %016lx\n", (unsigned long) page_dir); pgd = pgd_offset(t->mm, addr); @@ -184,13 +184,13 @@ void dump_list_current(void *address) dump_list_process(current, address); } -unsigned int vtop(void *address) +unsigned long vtop(void *address) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned int addr, paddr; + unsigned long addr, paddr; addr = (unsigned long) address; pgd = pgd_offset(current->mm, addr); diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index be80c5d..eeed944 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -176,7 +176,7 @@ unsigned long __init prom_free_prom_memory(void) if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; - addr = boot_mem_map.map[i].addr; + addr = PAGE_ALIGN(boot_mem_map.map[i].addr); while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index b7c7492..d41fc58 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c @@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(unsigned long offset) emit_instruction(mi); } +static inline void build_addiu_a2(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; + mi.i_format.rs = 6; /* $a2 */ + mi.i_format.rt = 6; /* $a2 */ + mi.i_format.simmediate = offset; + + emit_instruction(mi); +} + static inline void build_addiu_a1(unsigned long offset) { union mips_instruction mi; @@ -333,6 +347,7 @@ static inline void build_jr_ra(void) void __init build_clear_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) &clear_page_array; instruction_pending = 0; @@ -369,7 +384,12 @@ void __init build_clear_page(void) } } - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ @@ -420,12 +440,18 @@ dest = label(); void __init build_copy_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) ©_page_array; store_offset = load_offset = 0; instruction_pending = 0; - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 6f8b25c..fec318a 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -102,7 +102,7 @@ enum opcode { insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, - insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, + insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, @@ -145,6 +145,7 @@ static __initdata struct insn insn_table[] = { { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, + { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE }, { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, { insn_j, M(j_op,0,0,0,0,0), JIMM }, @@ -385,6 +386,7 @@ I_u2u1u3(_dsll); I_u2u1u3(_dsll32); I_u2u1u3(_dsra); I_u2u1u3(_dsrl); +I_u2u1u3(_dsrl32); I_u3u1u2(_dsubu); I_0(_eret); I_u1(_j); @@ -996,7 +998,12 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, #endif l_vmalloc_done(l, *p); - i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ + + if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */ + i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); + else + i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32); + i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ @@ -1073,7 +1080,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) static __init void build_adjust_context(u32 **p, unsigned int ctx) { - unsigned int shift = 4 - (PTE_T_LOG2 + 1); + unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); switch (current_cpu_data.cputype) { diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h index e3038a4..838eb31 100644 --- a/include/asm-mips/asm.h +++ b/include/asm-mips/asm.h @@ -344,6 +344,7 @@ symbol = value #define PTR_L lw #define PTR_S sw #define PTR_LA la +#define PTR_LI li #define PTR_SLL sll #define PTR_SLLV sllv #define PTR_SRL srl @@ -368,6 +369,7 @@ symbol = value #define PTR_L ld #define PTR_S sd #define PTR_LA dla +#define PTR_LI dli #define PTR_SLL dsll #define PTR_SLLV dsllv #define PTR_SRL dsrl diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h index 582c1fe..af121c6 100644 --- a/include/asm-mips/pgalloc.h +++ b/include/asm-mips/pgalloc.h @@ -48,7 +48,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER); if (ret) { - init = pgd_offset(&init_mm, 0); + init = pgd_offset(&init_mm, 0UL); pgd_init((unsigned long)ret); memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h index d05fb6f..7e73203 100644 --- a/include/asm-mips/pgtable-64.h +++ b/include/asm-mips/pgtable-64.h @@ -174,7 +174,7 @@ static inline void pud_clear(pud_t *pudp) #define __pmd_offset(address) pmd_index(address) /* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(address) pgd_offset(&init_mm, 0) +#define pgd_offset_k(address) pgd_offset(&init_mm, 0UL) #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -- cgit v0.10.2 From cb56837ea5f15fa5279fd490f292134c3a92e5de Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 22:49:04 +0000 Subject: [MIPS] SMTC: Fix crash if # of TC's > # of VPE's after pt_regs irq cleanup. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 417c08a..f10b6a1 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -83,7 +83,10 @@ FEXPORT(syscall_exit) FEXPORT(restore_all) # restore full frame #ifdef CONFIG_MIPS_MT_SMTC /* Detect and execute deferred IPI "interrupts" */ + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) jal deferred_smtc_ipi + LONG_S s0, TI_REGS($28) /* Re-arm any temporarily masked interrupts not explicitly "acked" */ mfc0 v0, CP0_TCSTATUS ori v1, v0, TCSTATUS_IXMT diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S index 1cb9441..921207c 100644 --- a/arch/mips/kernel/smtc-asm.S +++ b/arch/mips/kernel/smtc-asm.S @@ -101,7 +101,9 @@ FEXPORT(__smtc_ipi_vector) lw t0,PT_PADSLOT5(sp) /* Argument from sender passed in stack pad slot 4 */ lw a0,PT_PADSLOT4(sp) - PTR_LA ra, _ret_from_irq + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) + PTR_LA ra, ret_from_irq jr t0 /* @@ -119,7 +121,10 @@ LEAF(self_ipi) subu t1,sp,PT_SIZE sw ra,PT_EPC(t1) sw a0,PT_PADSLOT4(t1) + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) la t2,ipi_decode + LONG_S s0, TI_REGS($28) sw t2,PT_PADSLOT5(t1) /* Save pre-disable value of TCStatus */ sw t0,PT_TCSTATUS(t1) -- cgit v0.10.2 From 64c590b7a62ae1272fe4afd7b915de314591f35e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 1 Nov 2006 00:22:00 +0000 Subject: [MIPS] SMTC: Synchronize cp0 counters on bootup. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index cc1f747..3b78caf 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -476,6 +476,7 @@ void mipsmt_prepare_cpus(void) write_vpe_c0_compare(0); /* Propagate Config7 */ write_vpe_c0_config7(read_c0_config7()); + write_vpe_c0_count(read_c0_count()); } /* enable multi-threading within VPE */ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); -- cgit v0.10.2 From 67cac1eba7eee92e2b25c1e8e4737968dc7c8522 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Nov 2006 18:55:22 +0900 Subject: [MIPS] Fix warning in mips-boards generic PCI arch/mips/mips-boards/generic/pci.c: In function `mips_pcibios_init': arch/mips/mips-boards/generic/pci.c:227: warning: comparison of distinct pointer types lacks a cast arch/mips/mips-boards/generic/pci.c:228: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index 9337f6c..3192a14 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -90,7 +90,7 @@ static struct pci_controller msc_controller = { void __init mips_pcibios_init(void) { struct pci_controller *controller; - unsigned long start, end, map, start1, end1, map1, map2, map3, mask; + resource_size_t start, end, map, start1, end1, map1, map2, map3, mask; switch (mips_revision_corid) { case MIPS_REVISION_CORID_QED_RM5261: -- cgit v0.10.2 From f9dadfa71bc594df09044da61d1c72701121d802 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 1 Nov 2006 10:05:35 -0800 Subject: i386: write IO APIC irq routing entries in correct order Since the "mask" bit is in the low word, when we write a new entry, we need to write the high word first, before we potentially unmask it. The exception is when we actually want to mask the interrupt, in which case we want to write the low word first to make sure that the high word doesn't change while the interrupt routing is still active. Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index eb10bd5..507983c 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -147,12 +147,34 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) return eu.entry; } +/* + * When we write a new IO APIC routing entry, we need to write the high + * word first! If the mask bit in the low word is clear, we will enable + * the interrupt, and we need to make sure the entry is fully populated + * before that happens. + */ static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { unsigned long flags; union entry_union eu; eu.entry = e; spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(apic, 0x11 + 2*pin, eu.w2); + io_apic_write(apic, 0x10 + 2*pin, eu.w1); + spin_unlock_irqrestore(&ioapic_lock, flags); +} + +/* + * When we mask an IO APIC routing entry, we need to write the low + * word first, in order to set the mask bit before we change the + * high bits! + */ +static void ioapic_mask_entry(int apic, int pin) +{ + unsigned long flags; + union entry_union eu = { .entry.mask = 1 }; + + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x10 + 2*pin, eu.w1); io_apic_write(apic, 0x11 + 2*pin, eu.w2); spin_unlock_irqrestore(&ioapic_lock, flags); @@ -274,9 +296,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) /* * Disable it in the IO-APIC irq-routing table: */ - memset(&entry, 0, sizeof(entry)); - entry.mask = 1; - ioapic_write_entry(apic, pin, entry); + ioapic_mask_entry(apic, pin); } static void clear_IO_APIC (void) -- cgit v0.10.2 From 3ccfc65c5004e5fe5cfbffe43b8acc686680b53e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 2 Nov 2006 09:44:37 +1100 Subject: [PATCH] powerpc: Eliminate "exceeds stub group size" linker warning It turns out that the linker warnings on 64-bit powerpc about "section blah exceeds stub group size" were being triggered by conditional branches in head_64.S branching to global symbols, whether in head_64.S or in other files. This eliminates the warnings by making some global symbols in head_64.S no longer global, and by rearranging some branches. Signed-off-by: Paul Mackerras [ Yee-haa. Maybe I'll notice newly introduced real warnings now - Linus ] Signed-off-by: Linus Torvalds diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 291e362..e720729 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -487,7 +487,7 @@ BEGIN_FTR_SECTION rlwimi r13,r12,16,0x20 mfcr r12 cmpwi r13,0x2c - beq .do_stab_bolted_pSeries + beq do_stab_bolted_pSeries mtcrf 0x80,r12 mfspr r12,SPRN_SPRG2 END_FTR_SECTION_IFCLR(CPU_FTR_SLB) @@ -600,7 +600,7 @@ system_call_pSeries: STD_EXCEPTION_PSERIES(., performance_monitor) .align 7 -_GLOBAL(do_stab_bolted_pSeries) +do_stab_bolted_pSeries: mtcrf 0x80,r12 mfspr r12,SPRN_SPRG2 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) @@ -1046,7 +1046,7 @@ slb_miss_fault: li r5,0 std r4,_DAR(r1) std r5,_DSISR(r1) - b .handle_page_fault + b handle_page_fault unrecov_user_slb: EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) @@ -1174,12 +1174,13 @@ program_check_common: .globl fp_unavailable_common fp_unavailable_common: EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) - bne .load_up_fpu /* if from user, just load it up */ + bne 1f /* if from user, just load it up */ bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ENABLE_INTS bl .kernel_fp_unavailable_exception BUG_OPCODE +1: b .load_up_fpu .align 7 .globl altivec_unavailable_common @@ -1279,10 +1280,10 @@ _GLOBAL(do_hash_page) std r4,_DSISR(r1) andis. r0,r4,0xa450 /* weird error? */ - bne- .handle_page_fault /* if not, try to insert a HPTE */ + bne- handle_page_fault /* if not, try to insert a HPTE */ BEGIN_FTR_SECTION andis. r0,r4,0x0020 /* Is it a segment table fault? */ - bne- .do_ste_alloc /* If so handle it */ + bne- do_ste_alloc /* If so handle it */ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) /* @@ -1324,7 +1325,7 @@ BEGIN_FW_FTR_SECTION * because ret_from_except_lite will check for and handle pending * interrupts if necessary. */ - beq .ret_from_except_lite + beq 13f /* For a hash failure, we don't bother re-enabling interrupts */ ble- 12f @@ -1346,14 +1347,14 @@ BEGIN_FW_FTR_SECTION END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) /* Here we have a page fault that hash_page can't handle. */ -_GLOBAL(handle_page_fault) +handle_page_fault: ENABLE_INTS 11: ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD bl .do_page_fault cmpdi r3,0 - beq+ .ret_from_except_lite + beq+ 13f bl .save_nvgprs mr r5,r3 addi r3,r1,STACK_FRAME_OVERHEAD @@ -1370,12 +1371,14 @@ _GLOBAL(handle_page_fault) bl .low_hash_fault b .ret_from_except +13: b .ret_from_except_lite + /* here we have a segment miss */ -_GLOBAL(do_ste_alloc) +do_ste_alloc: bl .ste_allocate /* try to insert stab entry */ cmpdi r3,0 - beq+ fast_exception_return - b .handle_page_fault + bne- handle_page_fault + b fast_exception_return /* * r13 points to the PACA, r9 contains the saved CR, -- cgit v0.10.2 From d55b4c631e89a008e80b003e5aa4291d9ec800ac Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 31 Oct 2006 16:59:35 -0800 Subject: [TIPC] net/tipc/port.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: David S. Miller diff --git a/net/tipc/port.c b/net/tipc/port.c index c1a1a76..b7f3199 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -1136,11 +1136,12 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) int res = -EINVAL; p_ptr = tipc_port_lock(ref); + if (!p_ptr) + return -EINVAL; + dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " "lower = %u, upper = %u\n", ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); - if (!p_ptr) - return -EINVAL; if (p_ptr->publ.connected) goto exit; if (seq->lower > seq->upper) -- cgit v0.10.2 From b1736a71404b3961f061c795a81210aa7f945fc0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 31 Oct 2006 17:31:33 -0800 Subject: [TCP]: Set default congestion control when no sysctl. The setting of the default congestion control was buried in the sysctl code so it would not be done properly if SYSCTL was not enabled. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index e82a5be..15061b3 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -129,13 +129,6 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, return ret; } -static int __init tcp_congestion_default(void) -{ - return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG); -} - -late_initcall(tcp_congestion_default); - ctl_table ipv4_table[] = { { .ctl_name = NET_IPV4_TCP_TIMESTAMPS, diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index af0aca1..1e2982f 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -131,6 +131,14 @@ int tcp_set_default_congestion_control(const char *name) return ret; } +/* Set default value from kernel configuration at bootup */ +static int __init tcp_congestion_default(void) +{ + return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG); +} +late_initcall(tcp_congestion_default); + + /* Get current default congestion control */ void tcp_get_default_congestion_control(char *name) { -- cgit v0.10.2 From 5b1225454f7891970cb5ba87c8ef24edb1fa6c3a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 1 Nov 2006 15:28:58 -0800 Subject: [IPV6]: File the fingerprints off ah6->spi/esp6->spi In theory these are opaque 32bit values. However, we end up allocating them sequentially in host-endian and stick unchanged on the wire. Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 7af227b..7931e4f 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -135,7 +135,7 @@ u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) x6spi = __xfrm6_tunnel_spi_lookup(saddr); spi = x6spi ? x6spi->spi : 0; read_unlock_bh(&xfrm6_tunnel_spi_lock); - return spi; + return htonl(spi); } EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); @@ -210,7 +210,7 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) spi = __xfrm6_tunnel_alloc_spi(saddr); write_unlock_bh(&xfrm6_tunnel_spi_lock); - return spi; + return htonl(spi); } EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); -- cgit v0.10.2 From c7fed9d75074f7c243ec8ff2c55d04de2839a6f6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 1 Nov 2006 16:30:39 -0800 Subject: [SPARC64]: Fix futex_atomic_cmpxchg_inatomic implementation. I copied the logic from ll/sc arch implementations, but that was wrong and makes no sense at all. Just do a straight compare-exchange instruction, just like x86. Based upon bug reports from Dennis Gilmore and Fabio Massimo. Signed-off-by: David S. Miller diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h index dee4020..7392fc4 100644 --- a/include/asm-sparc64/futex.h +++ b/include/asm-sparc64/futex.h @@ -87,24 +87,22 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { __asm__ __volatile__( - "\n1: lduwa [%2] %%asi, %0\n" - "2: casa [%2] %%asi, %0, %1\n" - "3:\n" + "\n1: casa [%3] %%asi, %2, %0\n" + "2:\n" " .section .fixup,#alloc,#execinstr\n" " .align 4\n" - "4: ba 3b\n" - " mov %3, %0\n" + "3: ba 2b\n" + " mov %4, %0\n" " .previous\n" " .section __ex_table,\"a\"\n" " .align 4\n" - " .word 1b, 4b\n" - " .word 2b, 4b\n" + " .word 1b, 3b\n" " .previous\n" - : "=&r" (oldval) - : "r" (newval), "r" (uaddr), "i" (-EFAULT) + : "=r" (newval) + : "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT) : "memory"); - return oldval; + return newval; } #endif /* !(_SPARC64_FUTEX_H) */ -- cgit v0.10.2 From 6f5b7ef6b5816dc497094048d7d8a270004602d6 Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Wed, 1 Nov 2006 18:07:27 -0800 Subject: [NETFILTER]: silence a warning in ebtables net/bridge/netfilter/ebtables.c: In function 'ebt_dev_check': net/bridge/netfilter/ebtables.c:89: warning: initialization discards qualifiers from pointer target type So make the char* a const char * and the warning is gone. Signed-off-by: Meelis Roos Signed-off-by: David S. Miller diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 3df55b2..9f85666 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -86,7 +86,7 @@ static inline int ebt_do_match (struct ebt_entry_match *m, static inline int ebt_dev_check(char *entry, const struct net_device *device) { int i = 0; - char *devname = device->name; + const char *devname = device->name; if (*entry == '\0') return 0; -- cgit v0.10.2 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 diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 8385387..720174d 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 v0.10.2 From 8e87d4dc159148f04f515bc072df22a2c089e7f2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 2 Nov 2006 03:45:24 +0000 Subject: [CIFS] report rename failure when target file is locked by Windows Fixes Samba bugzilla bug # 4182 Rename by handle failures (retry after rename by path) were not being returned back. Signed-off-by: Steve French diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 50afab8..0b3c37e 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -3,7 +3,9 @@ Version 1.46 Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. Allow null user to be specified on mount ("username="). Do not return EINVAL on readdir when filldir fails due to overwritten blocksize -(fixes FC problem) +(fixes FC problem). Return error in rename 2nd attempt retry (ie report +if rename by handle also fails, after rename by path fails, we were +not reporting whether the retry worked or not). Version 1.45 ------------ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35d54bb..dffe295 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -885,10 +885,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); if (info_buf_source != NULL) { info_buf_target = info_buf_source + 1; - rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, - info_buf_source, cifs_sb_source->local_nls, - cifs_sb_source->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + if (pTcon->ses->capabilities & CAP_UNIX) + rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, + info_buf_source, + cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + /* else rc is still EEXIST so will fall through to + unlink the target and retry rename */ if (rc == 0) { rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, info_buf_target, @@ -937,7 +941,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, cifs_sb_source->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { - CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, + rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, cifs_sb_source->local_nls, cifs_sb_source->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -- cgit v0.10.2 From d572b87946f8c598b3cad86a7913862dd48daadb Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 2 Nov 2006 10:50:40 -0600 Subject: JFS: Remove redundant xattr permission checking The vfs handles most permissions for setting and retrieving xattrs. This patch removes a redundant and wrong check so that it won't override the correct behavior which is being fixed in the vfs. Signed-off-by: Dave Kleikamp diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 4c7985e..b753ba2 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -756,6 +756,11 @@ static int can_set_system_xattr(struct inode *inode, const char *name, return -EOPNOTSUPP; } +/* + * Most of the permission checking is done by xattr_permission in the vfs. + * The local file system is responsible for handling the system.* namespace. + * We also need to verify that this is a namespace that we recognize. + */ static int can_set_xattr(struct inode *inode, const char *name, const void *value, size_t value_len) { @@ -771,10 +776,6 @@ static int can_set_xattr(struct inode *inode, const char *name, strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) return -EOPNOTSUPP; - if (!S_ISREG(inode->i_mode) && - (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX)) - return -EPERM; - return 0; } -- cgit v0.10.2 From 8427829711b35e0e62668618cec577f65c102935 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 2 Nov 2006 02:00:02 +0000 Subject: Revert "[MIPS] Make SPARSEMEM selectable on QEMU." This reverts commit 31473747bd441719f9f6a07385684dce547533e0. Another amazing example of patch(1) messing up - lmo changeset 66e8560d11d02bcadc261498471831a6375ad046 was merged twice to kernel.org and ended up doing this rubbish job. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 74ba763..76f1cea 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -427,7 +427,6 @@ config MOMENCO_OCELOT_G select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN - select ARCH_SPARSEMEM_ENABLE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -1633,9 +1632,6 @@ config ARCH_DISCONTIGMEM_ENABLE config ARCH_SPARSEMEM_ENABLE bool - -config ARCH_SPARSEMEM_ENABLE - bool select SPARSEMEM_STATIC config NUMA -- cgit v0.10.2 From 8a88ca8f7fd15d06e53a848c6b3558ed9973327c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 2 Nov 2006 17:23:33 +0000 Subject: [MIPS] Fix merge screwup by patch(1) Patch happily applied an Ocelot G patch to Ocelot C when merging linux-mips.org changeset 91ee9a801e65d2981dfe327d2519c7fc6ab02e6b into kernel.org as 6ceb6d3ab2d402cea326320a4143db90a66fd216. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 76f1cea..848089ec 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -408,7 +408,7 @@ config MOMENCO_OCELOT_C select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if BROKEN + select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN help The Ocelot is a MIPS-based Single Board Computer (SBC) made by @@ -425,7 +425,7 @@ config MOMENCO_OCELOT_G select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_BIG_ENDIAN help The Ocelot is a MIPS-based Single Board Computer (SBC) made by -- cgit v0.10.2 From 1a5c5de1b64ec510a6ab6994702c295db00b9acc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 2 Nov 2006 17:23:33 +0000 Subject: [MIPS] IP27: Allow SMP ;-) Another changeset messed up by patch. When lmo commit 4ef893e0515e8bf336dfbd200884f244869fbb43 was merged to kernel.org as e73ea273ef87a04ff59fc368fa33333dca275dde patch happily applied the IP27 segment to IP22. f63f36c18b11e166d0f362ac04dbcd7e6ea23f9e did fix the effects partially - and with a wrong log message. Now fixed for real (tm). Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 848089ec..1443024 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -559,6 +559,7 @@ config SGI_IP27 select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_SMP help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y -- cgit v0.10.2 From 9ba126cfbf505f4d5b39ed294cedd241321c7a91 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 13 Oct 2006 11:22:52 +0100 Subject: [MIPS] Fix warning about init_initrd() call if !CONFIG_BLK_DEV_INITRD. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index fdbb508..8f6e896 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -223,7 +223,11 @@ disable: #else /* !CONFIG_BLK_DEV_INITRD */ -#define init_initrd() 0 +static unsigned long __init init_initrd(void) +{ + return 0; +} + #define finalize_initrd() do {} while (0) #endif -- cgit v0.10.2 From 8b922a851731037b2f1e1669e9b1a0baff3ab5dc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 30 Oct 2006 12:48:04 +0000 Subject: [MIPS] Ocelot G: Fix : "CURRENTLY_UNUSED" is not defined warning. CC arch/mips/momentum/ocelot_g/gt-irq.o arch/mips/momentum/ocelot_g/gt-irq.c:30:5: warning: "CURRENTLY_UNUSED" is not defined arch/mips/momentum/ocelot_g/gt-irq.c:199:5: warning: "CURRENTLY_UNUSED" is not defined Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c index 7b5cc66..e5576bd 100644 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ b/arch/mips/momentum/ocelot_g/gt-irq.c @@ -27,7 +27,7 @@ unsigned long bus_clock; * be handled and ack'ed differently than other MIPS interrupts. */ -#if CURRENTLY_UNUSED +#if 0 struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); @@ -95,7 +95,7 @@ int disable_galileo_irq(int int_cause, int bit_num) return 0; return 1; } -#endif /* UNUSED */ +#endif /* 0 */ /* * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. @@ -196,7 +196,7 @@ void gt64240_time_init(void) void gt64240_irq_init(void) { -#if CURRENTLY_UNUSED +#if 0 int i, j; /* Reset irq handlers pointers to NULL */ @@ -208,5 +208,5 @@ void gt64240_irq_init(void) irq_handlers[i][j].data = NULL; } } -#endif +#endif /* 0 */ } -- cgit v0.10.2 From 904880e717c5466041485ca6d6e8c6c1ef06d0fd Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 13 Oct 2006 11:32:50 +0100 Subject: [MIPS] Don't use R10000 llsc workaround version for all llsc-full processors. Found and original patch by bile@landofbile.com. Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index dcb4701..3056fee 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -392,7 +392,7 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, { __u64 retval; - if (cpu_has_llsc) { + if (cpu_has_llsc && R10000_LLSC_WAR) { __asm__ __volatile__( " .set push \n" " .set noat \n" -- cgit v0.10.2 From 236d333c3c05c179e31f461285c09271256a1381 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 10 Oct 2006 22:13:55 +0900 Subject: [MIPS] Do not use -msym32 option for modules. On 64-bit kernel, modules are loaded into XKSEG for now. While XKSEG address is not a sign-extended 32-bit address, we can not use -msym32 option. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 641aa30..d580d46 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -63,7 +63,9 @@ cflags-y += -mabi=64 ifdef CONFIG_BUILD_ELF64 cflags-y += $(call cc-option,-mno-explicit-relocs) else -cflags-y += $(call cc-option,-msym32) +# -msym32 can not be used for modules since they are loaded into XKSEG +CFLAGS_MODULE += $(call cc-option,-mno-explicit-relocs) +CFLAGS_KERNEL += $(call cc-option,-msym32) endif endif -- cgit v0.10.2 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 diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 60d3fbd..e11187e 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 d8ca3c1..845090b 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 81b62307..c094e50 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 v0.10.2 From 73218187e8650c08d4e4735dbeeeb860f438da7c Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 2 Nov 2006 23:44:24 +0100 Subject: [ARM] 3917/1: Fix dmabounce symbol exports dma_sync_single is no more (and to be removed in 2.7) so this export should be dma_sync_single_for_cpu. Also export dma_sync_single_for_device. Signed-off-by: Kevin Hilman Signed-off-by: Russell King diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 028bdc9..2e635b8 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -662,7 +662,8 @@ EXPORT_SYMBOL(dma_map_single); EXPORT_SYMBOL(dma_unmap_single); EXPORT_SYMBOL(dma_map_sg); EXPORT_SYMBOL(dma_unmap_sg); -EXPORT_SYMBOL(dma_sync_single); +EXPORT_SYMBOL(dma_sync_single_for_cpu); +EXPORT_SYMBOL(dma_sync_single_for_device); EXPORT_SYMBOL(dma_sync_sg); EXPORT_SYMBOL(dmabounce_register_dev); EXPORT_SYMBOL(dmabounce_unregister_dev); -- cgit v0.10.2 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 diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 29234c8..5c47a9e 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 v0.10.2 From 94c52fde553260e86f263448034930abe364faec Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 30 Oct 2006 02:27:45 +0100 Subject: [ARM] 3915/1: S3C2412: Add s3c2410_gpio_getirq() to general gpio.c s3c2410_gpio_getirq() holds for the S3C2412 build, so ensure that it gets built for all the current S3C24XX architectures Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c index db6393c..ba34654 100644 --- a/arch/arm/mach-s3c2410/gpio.c +++ b/arch/arm/mach-s3c2410/gpio.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks * - * S3C2410 GPIO support + * S3C24XX GPIO support * * 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 @@ -163,3 +163,22 @@ unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) } EXPORT_SYMBOL(s3c2410_modify_misccr); + +int s3c2410_gpio_getirq(unsigned int pin) +{ + if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15) + return -1; /* not valid interrupts */ + + if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) + return -1; /* not valid pin */ + + if (pin < S3C2410_GPF4) + return (pin - S3C2410_GPF0) + IRQ_EINT0; + + if (pin < S3C2410_GPG0) + return (pin - S3C2410_GPF4) + IRQ_EINT4; + + return (pin - S3C2410_GPG0) + IRQ_EINT8; +} + +EXPORT_SYMBOL(s3c2410_gpio_getirq); diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c index a2098f6..ec3a276 100644 --- a/arch/arm/mach-s3c2410/s3c2410-gpio.c +++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c @@ -69,22 +69,3 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, } EXPORT_SYMBOL(s3c2410_gpio_irqfilter); - -int s3c2410_gpio_getirq(unsigned int pin) -{ - if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15) - return -1; /* not valid interrupts */ - - if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) - return -1; /* not valid pin */ - - if (pin < S3C2410_GPF4) - return (pin - S3C2410_GPF0) + IRQ_EINT0; - - if (pin < S3C2410_GPG0) - return (pin - S3C2410_GPF4) + IRQ_EINT4; - - return (pin - S3C2410_GPG0) + IRQ_EINT8; -} - -EXPORT_SYMBOL(s3c2410_gpio_getirq); -- cgit v0.10.2 From 8f7f9435e6df0985c877d10259393bdfaac3655f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 27 Oct 2006 05:13:19 +0100 Subject: [ARM] 3912/1: Make PXA270 advertise HWCAP_IWMMXT capability ARM patch 3756/1 added HWCAP_IWMMXT. This patch adds support for broadcasting that info via /proc/cpuinfo and sets it for the CPU features of the PXA270. I've booted 19rc3 on a pxa270 and confirmed that the /proc/cpuinfo shows "iwmmxt" in the Features. Signed-off-by: Paul Gortmaker Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6bbd93d..29efc9f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -357,6 +357,9 @@ static void __init setup_processor(void) #ifndef CONFIG_VFP elf_hwcap &= ~HWCAP_VFP; #endif +#ifndef CONFIG_IWMMXT + elf_hwcap &= ~HWCAP_IWMMXT; +#endif cpu_proc_init(); } @@ -854,6 +857,7 @@ static const char *hwcap_str[] = { "vfp", "edsp", "java", + "iwmmxt", NULL }; diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index e8b377d..2749c1f 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -909,7 +909,7 @@ __pxa270_proc_info: b __xscale_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_IWMMXT .long cpu_pxa270_name .long xscale_processor_functions .long v4wbi_tlb_fns -- cgit v0.10.2 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 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 988f8bb..234197e 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 v0.10.2 From 4fa2eeeac5e13a8579ee45bc172eed690d28fbb7 Mon Sep 17 00:00:00 2001 From: Peer Chen Date: Thu, 2 Nov 2006 18:55:48 -0500 Subject: pci_ids.h: Add NVIDIA PCI ID Signed-off-by: Jeff Garzik diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f3a168f..fa4e1d7 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1213,6 +1213,7 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 #define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 #define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_TT128 0x9128 -- cgit v0.10.2 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 diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 2cc5caa..a263b3f 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 080fa25..aebb8d6f 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 34a37c2..0a86eab 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 v0.10.2 From ecba77f246011344f0b8f46eb25ae01ab4ae282d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=E4rdeman?= 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 diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 2a2e9b4..ac0cecb 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 v0.10.2 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 diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index df8feac..c80c26b 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 97e974d..bb40e90 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 v0.10.2 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 diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index ac0cecb..cd5ec48 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 v0.10.2 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 diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1ba53b5..6b61d9b 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 v0.10.2 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 diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index d9953f7..5297a36 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 v0.10.2 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 diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h index 6dfa839..7e4f95e 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 10286cc..7ac3369 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 bc217dd..9cd64da 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 c9d5ae2..0ca3af4 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 57a1dae..84f9e4f 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 0caac3f..a6d3854 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 0d6fdef..72d4757 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 1916e3e..ea7f78a 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 21ba4a2..cd15f76 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 3f96b48..9950590 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 1fe1dd1..68906ac 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 7112fb4..cf9a150 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 0035c2e..e996408 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 2eb220e..28bc559 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 9397393..13d2251 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 9718be4..add24f0 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 10a5419..8aad840 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 efc54d7..1555870 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 4cf27d3..909cefe 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 cab7ea6..7ee78d7 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 760b80d..69f4515 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 7ef2520..33df949 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 d68ae20..e3da780 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 e28fca0..605ad2d 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 18457ad..ed584a8 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 aae15bd..2d33079 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 83998c0..ad99811 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 8f98033..03a665e 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 f0c9dde..e4a2a32 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 395fed3..d507f89 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 79a9472..0bc0109 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 v0.10.2 From 1447190e39847cc2cc8a826e7061989c83ff4362 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 2 Nov 2006 23:26:55 -0500 Subject: Input: add comments to input_{allocate|free}_device() Hopefully this will stop people from using input_free_device() incorrectly. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/input.c b/drivers/input/input.c index 1c8c8a5..7cf2b4f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -37,7 +37,7 @@ static struct input_handler *input_table[8]; /** * input_event() - report new input event - * @handle: device that generated the event + * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event @@ -900,6 +900,15 @@ struct class input_class = { }; EXPORT_SYMBOL_GPL(input_class); +/** + * input_allocate_device - allocate memory for new input device + * + * Returns prepared struct input_dev or NULL. + * + * NOTE: Use input_free_device() to free devices that have not been + * registered; input_unregister_device() should be used for already + * registered devices. + */ struct input_dev *input_allocate_device(void) { struct input_dev *dev; @@ -919,6 +928,20 @@ struct input_dev *input_allocate_device(void) } EXPORT_SYMBOL(input_allocate_device); +/** + * input_free_device - free memory occupied by input_dev structure + * @dev: input device to free + * + * This function should only be used if input_register_device() + * was not called yet or if it failed. Once device was registered + * use input_unregister_device() and memory will be freed once last + * refrence to the device is dropped. + * + * Device should be allocated by input_allocate_device(). + * + * NOTE: If there are references to the input device then memory + * will not be freed until last reference is dropped. + */ void input_free_device(struct input_dev *dev) { if (dev) { -- cgit v0.10.2 From 6a89bc0004c8d9400439db6167c9887456d5d18d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 2 Nov 2006 23:27:11 -0500 Subject: Input: lightning - return proper error codes from l4_init() Signed-off-by: Akinobu Mita Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c index d65d810..6b4d456 100644 --- a/drivers/input/gameport/lightning.c +++ b/drivers/input/gameport/lightning.c @@ -309,7 +309,7 @@ static int __init l4_init(void) int i, cards = 0; if (!request_region(L4_PORT, 1, "lightning")) - return -1; + return -EBUSY; for (i = 0; i < 2; i++) if (l4_add_card(i) == 0) @@ -319,7 +319,7 @@ static int __init l4_init(void) if (!cards) { release_region(L4_PORT, 1); - return -1; + return -ENODEV; } return 0; -- cgit v0.10.2 From 1ea2a69d54f40ecebf594ce5abfa02d53682df8a Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Thu, 2 Nov 2006 23:27:21 -0500 Subject: Input: serio - rearrange serio_bus initialization Initialize serio_bus structure at compile time instead of at runtime in serio_init(). Signed-off-by: Marton Nemeth Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 211943f..3cb99d4 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -784,12 +784,6 @@ static int serio_driver_remove(struct device *dev) return 0; } -static struct bus_type serio_bus = { - .name = "serio", - .probe = serio_driver_probe, - .remove = serio_driver_remove, -}; - static void serio_add_driver(struct serio_driver *drv) { int error; @@ -946,15 +940,21 @@ irqreturn_t serio_interrupt(struct serio *serio, return ret; } +static struct bus_type serio_bus = { + .name = "serio", + .dev_attrs = serio_device_attrs, + .drv_attrs = serio_driver_attrs, + .match = serio_bus_match, + .uevent = serio_uevent, + .probe = serio_driver_probe, + .remove = serio_driver_remove, + .resume = serio_resume, +}; + static int __init serio_init(void) { int error; - serio_bus.dev_attrs = serio_device_attrs; - serio_bus.drv_attrs = serio_driver_attrs; - serio_bus.match = serio_bus_match; - serio_bus.uevent = serio_uevent; - serio_bus.resume = serio_resume; error = bus_register(&serio_bus); if (error) { printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); -- cgit v0.10.2 From b187dd7b5231bb359f587bf4d276ffd467ebc884 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 2 Nov 2006 23:27:30 -0500 Subject: Input: gameport - rearrange gameport_bus initialization Initialize gameport_bus structure at compile time instead of at runtime in gameport_init(). Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index a0af97e..bba5894 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -730,12 +730,6 @@ static int gameport_driver_remove(struct device *dev) return 0; } -static struct bus_type gameport_bus = { - .name = "gameport", - .probe = gameport_driver_probe, - .remove = gameport_driver_remove, -}; - static void gameport_add_driver(struct gameport_driver *drv) { int error; @@ -781,6 +775,15 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv) return !gameport_drv->ignore; } +static struct bus_type gameport_bus = { + .name = "gameport", + .dev_attrs = gameport_device_attrs, + .drv_attrs = gameport_driver_attrs, + .match = gameport_bus_match, + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, +}; + static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) { mutex_lock(&gameport->drv_mutex); @@ -790,7 +793,6 @@ static void gameport_set_drv(struct gameport *gameport, struct gameport_driver * int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) { - if (gameport->open) { if (gameport->open(gameport, mode)) { return -1; @@ -818,9 +820,6 @@ static int __init gameport_init(void) { int error; - gameport_bus.dev_attrs = gameport_device_attrs; - gameport_bus.drv_attrs = gameport_driver_attrs; - gameport_bus.match = gameport_bus_match; error = bus_register(&gameport_bus); if (error) { printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); -- cgit v0.10.2 From 15e9acb83c299963490b1f12d46498ae257d8f4e Mon Sep 17 00:00:00 2001 From: Greg Chandler Date: Thu, 2 Nov 2006 23:27:38 -0500 Subject: Input: lifebook - add Hitachi Flora-IE 55mi tablet DMI signature This adds another DMI detected touchscreen. It is exactly the same driver as the existing ones, but this allows it to be detected on the Hitachi Flora-IE 55mi tablet. The original Midori drivers are "abeo antiquus". This should allow new life for these machines. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index c57e885..ab924484 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -22,6 +22,12 @@ static struct dmi_system_id lifebook_dmi_table[] = { { + .ident = "FLORA-ie 55mi", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), + }, + }, + { .ident = "LifeBook B", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), -- cgit v0.10.2 From b1b2965057700d6dc9e1f986e8f7743b95ead424 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 23:27:44 -0500 Subject: Input: lifebook - learn about hard tabs Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index ab924484..29542f0 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -21,53 +21,51 @@ #include "lifebook.h" static struct dmi_system_id lifebook_dmi_table[] = { - { - .ident = "FLORA-ie 55mi", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), - }, - }, - { - .ident = "LifeBook B", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), - }, - }, - { - .ident = "Lifebook B", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), - }, - }, - { - .ident = "Lifebook B213x/B2150", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), - }, - }, - { - .ident = "Zephyr", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), - }, - }, - { - .ident = "CF-18", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), - }, - }, - { - .ident = "Lifebook B142", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), - }, - - }, - { } + { + .ident = "FLORA-ie 55mi", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), + }, + }, + { + .ident = "LifeBook B", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), + }, + }, + { + .ident = "Lifebook B", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), + }, + }, + { + .ident = "Lifebook B213x/B2150", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), + }, + }, + { + .ident = "Zephyr", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), + }, + }, + { + .ident = "CF-18", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), + }, + }, + { + .ident = "Lifebook B142", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), + }, + }, + { } }; - static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) { unsigned char *packet = psmouse->packet; -- cgit v0.10.2 From f4e3c711b31cea401b03ce39d4b5f1a30279094c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 2 Nov 2006 23:27:49 -0500 Subject: Input: i8042 - remove unneeded call to i8042_interrupt() Remove call to i8042_interrupt() from i8042_aux_write(). According to Vojtech it may cause problems with older controllers if it is called right after real interrupt. Also it is not needed anymore since we register IRQs early and not waiting for serio ports to be opened. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 7e3141f..d365f22 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -255,25 +255,10 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) static int i8042_aux_write(struct serio *serio, unsigned char c) { struct i8042_port *port = serio->port_data; - int retval; - -/* - * Send the byte out. - */ - - if (port->mux == -1) - retval = i8042_command(&c, I8042_CMD_AUX_SEND); - else - retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux); -/* - * Make sure the interrupt happens and the character is received even - * in the case the IRQ isn't wired, so that we can receive further - * characters later. - */ - - i8042_interrupt(0, NULL); - return retval; + return i8042_command(&c, port->mux == -1 ? + I8042_CMD_AUX_SEND : + I8042_CMD_MUX_SEND + port->mux); } /* -- cgit v0.10.2 From 8dd51650baf0861b0a73acb2c08bb944aa45bc61 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 2 Nov 2006 23:34:09 -0500 Subject: Input: ads7846 - handle errors from sysfs Add sysfs error handling and switch to using attribute groups to simplify it. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index f56d6a0..8f56af8 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -76,6 +76,7 @@ struct ads7846 { char phys[32]; struct spi_device *spi; + struct attribute_group *attr_group; u16 model; u16 vref_delay_usecs; u16 x_plate_ohms; @@ -317,6 +318,48 @@ static ssize_t ads7846_disable_store(struct device *dev, static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); +static struct attribute *ads7846_attributes[] = { + &dev_attr_temp0.attr, + &dev_attr_temp1.attr, + &dev_attr_vbatt.attr, + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7846_attr_group = { + .attrs = ads7846_attributes, +}; + +/* + * ads7843/7845 don't have temperature sensors, and + * use the other sensors a bit differently too + */ + +static struct attribute *ads7843_attributes[] = { + &dev_attr_vbatt.attr, + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7843_attr_group = { + .attrs = ads7843_attributes, +}; + +static struct attribute *ads7845_attributes[] = { + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7845_attr_group = { + .attrs = ads7845_attributes, +}; + /*--------------------------------------------------------------------------*/ /* @@ -788,38 +831,30 @@ static int __devinit ads7846_probe(struct spi_device *spi) (void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); - /* ads7843/7845 don't have temperature sensors, and - * use the other sensors a bit differently too - */ - if (ts->model == 7846) { - device_create_file(&spi->dev, &dev_attr_temp0); - device_create_file(&spi->dev, &dev_attr_temp1); + switch (ts->model) { + case 7846: + ts->attr_group = &ads7846_attr_group; + break; + case 7845: + ts->attr_group = &ads7845_attr_group; + break; + default: + ts->attr_group = &ads7843_attr_group; + break; } - if (ts->model != 7845) - device_create_file(&spi->dev, &dev_attr_vbatt); - device_create_file(&spi->dev, &dev_attr_vaux); - - device_create_file(&spi->dev, &dev_attr_pen_down); - - device_create_file(&spi->dev, &dev_attr_disable); + err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); + if (err) + goto err_free_irq; err = input_register_device(input_dev); if (err) - goto err_remove_attr; + goto err_remove_attr_group; return 0; - err_remove_attr: - device_remove_file(&spi->dev, &dev_attr_disable); - device_remove_file(&spi->dev, &dev_attr_pen_down); - if (ts->model == 7846) { - device_remove_file(&spi->dev, &dev_attr_temp1); - device_remove_file(&spi->dev, &dev_attr_temp0); - } - if (ts->model != 7845) - device_remove_file(&spi->dev, &dev_attr_vbatt); - device_remove_file(&spi->dev, &dev_attr_vaux); - + err_remove_attr_group: + sysfs_remove_group(&spi->dev.kobj, ts->attr_group); + err_free_irq: free_irq(spi->irq, ts); err_free_mem: input_free_device(input_dev); @@ -835,15 +870,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) ads7846_suspend(spi, PMSG_SUSPEND); - device_remove_file(&spi->dev, &dev_attr_disable); - device_remove_file(&spi->dev, &dev_attr_pen_down); - if (ts->model == 7846) { - device_remove_file(&spi->dev, &dev_attr_temp1); - device_remove_file(&spi->dev, &dev_attr_temp0); - } - if (ts->model != 7845) - device_remove_file(&spi->dev, &dev_attr_vbatt); - device_remove_file(&spi->dev, &dev_attr_vaux); + sysfs_remove_group(&spi->dev.kobj, ts->attr_group); free_irq(ts->spi->irq, ts); /* suspend left the IRQ disabled */ -- cgit v0.10.2 From 8ff22ea7d29d99b3dbec08fd541eb406c6775ec1 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 2 Nov 2006 23:59:30 -0500 Subject: Input: trackpoint - handle sysfs errors Also use kzalloc instead of kcalloc since we are allocating single object. Signed-off-by: Jeff Garzik Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ae5871a..9ab5b5e 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -293,6 +293,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char firmware_id; unsigned char button_info; + int error; if (trackpoint_start_protocol(psmouse, &firmware_id)) return -1; @@ -305,7 +306,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) button_info = 0; } - psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); if (!priv) return -1; @@ -318,7 +319,14 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) trackpoint_defaults(priv); trackpoint_sync(psmouse); - sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); + error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); + if (error) { + printk(KERN_ERR + "trackpoint.c: failed to create sysfs attributes, error: %d\n", + error); + kfree(priv); + return -1; + } printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f); -- cgit v0.10.2 From 0fea0e9a9c72dab526447895605fc236c87c2726 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 2 Nov 2006 23:59:40 -0500 Subject: Input: logips2pp - handle sysfs errors Signed-off-by: Jeff Garzik Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 8a4f862..d3ddea2 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -328,6 +328,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) unsigned char model, buttons; const struct ps2pp_info *model_info; int use_ps2pp = 0; + int error; param[0] = 0; ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); @@ -393,8 +394,14 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) psmouse->set_resolution = ps2pp_set_resolution; psmouse->disconnect = ps2pp_disconnect; - device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_smartscroll.dattr); + error = device_create_file(&psmouse->ps2dev.serio->dev, + &psmouse_attr_smartscroll.dattr); + if (error) { + printk(KERN_ERR + "logips2pp.c: failed to create smartscroll " + "sysfs attribute, error: %d\n", error); + return -1; + } } } -- cgit v0.10.2 From 6851ecc6e2fa4a01449a0fec9f4abd9aec43afde Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Nov 2006 23:02:24 -0800 Subject: PCI: Revert "PCI: i386/x86_84: disable PCI resource decode on device disable" This reverts commit 53e4d30dd666d7f83598957ee4a415eefb47c9a6. It was found that it caused unneeded problems (see http://bugzilla.kernel.org/show_bug.cgi?id=7082 for details of one such issue. Signed-off-by: Greg Kroah-Hartman diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 6d5ace8..cdfcf97 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -343,7 +343,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) void pcibios_disable_device (struct pci_dev *dev) { - pcibios_disable_resources(dev); if (pcibios_disable_irq) pcibios_disable_irq(dev); } diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 10154a2..9858029 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -242,15 +242,6 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) return 0; } -void pcibios_disable_resources(struct pci_dev *dev) -{ - u16 cmd; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, cmd); -} - /* * If we set up a device for bus mastering, we need to check the latency * timer as certain crappy BIOSes forget to set it properly. diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index ad065ce..a0a2518 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -43,7 +43,6 @@ extern unsigned int pcibios_max_latency; void pcibios_resource_survey(void); int pcibios_enable_resources(struct pci_dev *, int); -void pcibios_disable_resources(struct pci_dev *); /* pci-pc.c */ -- cgit v0.10.2 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 diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index ecc50db..5f1b9f5 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 v0.10.2 From 984d115bbf2d731ed2264031fe49c1378d730db0 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 3 Nov 2006 01:47:20 +0100 Subject: [ARM] 3918/1: ixp4xx irq-chip rework This is a rework of the ixp4xx irq_chip implementation. The use of two irq_chip structures and potentially switching between them is a violation of the intended use of the IRQ framework. The current implementation does not work with current in-kernel spinlock debugging or lockdep due to lock recursion problems caused by calling set_irq_chip/handler from within the chip's set_irq_type(). This patch goes back to using one irq_chip structure and handling the differences between edge/level, normal/GPIO interrupts inside the ack/mask/unmask routines themselves. Signed-off-by: Kevin Hilman Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index c7513f6..fbe288a 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -86,7 +86,8 @@ enum ixp4xx_irq_type { IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE }; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); +/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */ +static unsigned long long ixp4xx_irq_edge = 0; /* * IRQ -> GPIO mapping table @@ -135,7 +136,11 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) default: return -EINVAL; } - ixp4xx_config_irq(irq, irq_type); + + if (irq_type == IXP4XX_IRQ_EDGE) + ixp4xx_irq_edge |= (1 << irq); + else + ixp4xx_irq_edge &= ~(1 << irq); if (line >= 8) { /* pins 8-15 */ line -= 8; @@ -167,14 +172,6 @@ static void ixp4xx_irq_mask(unsigned int irq) *IXP4XX_ICMR &= ~(1 << irq); } -static void ixp4xx_irq_unmask(unsigned int irq) -{ - if (cpu_is_ixp46x() && irq >= 32) - *IXP4XX_ICMR2 |= (1 << (irq - 32)); - else - *IXP4XX_ICMR |= (1 << irq); -} - static void ixp4xx_irq_ack(unsigned int irq) { int line = (irq < 32) ? irq2gpio[irq] : -1; @@ -187,41 +184,25 @@ static void ixp4xx_irq_ack(unsigned int irq) * Level triggered interrupts on GPIO lines can only be cleared when the * interrupt condition disappears. */ -static void ixp4xx_irq_level_unmask(unsigned int irq) +static void ixp4xx_irq_unmask(unsigned int irq) { - ixp4xx_irq_ack(irq); - ixp4xx_irq_unmask(irq); -} + if (!(ixp4xx_irq_edge & (1 << irq))) + ixp4xx_irq_ack(irq); -static struct irqchip ixp4xx_irq_level_chip = { - .ack = ixp4xx_irq_mask, - .mask = ixp4xx_irq_mask, - .unmask = ixp4xx_irq_level_unmask, - .set_type = ixp4xx_set_irq_type, -}; + if (cpu_is_ixp46x() && irq >= 32) + *IXP4XX_ICMR2 |= (1 << (irq - 32)); + else + *IXP4XX_ICMR |= (1 << irq); +} -static struct irqchip ixp4xx_irq_edge_chip = { +static struct irqchip ixp4xx_irq_chip = { + .name = "IXP4xx", .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_unmask, .set_type = ixp4xx_set_irq_type, }; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) -{ - switch (type) { - case IXP4XX_IRQ_LEVEL: - set_irq_chip(irq, &ixp4xx_irq_level_chip); - set_irq_handler(irq, do_level_IRQ); - break; - case IXP4XX_IRQ_EDGE: - set_irq_chip(irq, &ixp4xx_irq_edge_chip); - set_irq_handler(irq, do_edge_IRQ); - break; - } - set_irq_flags(irq, IRQF_VALID); -} - void __init ixp4xx_init_irq(void) { int i = 0; @@ -241,8 +222,11 @@ void __init ixp4xx_init_irq(void) } /* Default to all level triggered */ - for(i = 0; i < NR_IRQS; i++) - ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL); + for(i = 0; i < NR_IRQS; i++) { + set_irq_chip(i, &ixp4xx_irq_chip); + set_irq_handler(i, do_level_IRQ); + set_irq_flags(i, IRQF_VALID); + } } -- cgit v0.10.2 From 1f4a39319e9226c3b1d5b91a1e4d3559ef8740e4 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Fri, 3 Nov 2006 13:47:39 +0100 Subject: [ARM] 3919/1: Fixed definition of some PXA270 CIF related registers Fixed definition of some CIF registers; see PXA27x Developer\'s Manual. Signed-off-by: Enrico Scholz Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 68731e0..cff752f 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -2242,7 +2242,7 @@ #define CICR1_TBIT (1 << 31) /* Transparency bit */ #define CICR1_RGBT_CONV (0x3 << 30) /* RGBT conversion mask */ -#define CICR1_PPL (0x3f << 15) /* Pixels per line mask */ +#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ #define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ #define CICR1_RGB_F (1 << 11) /* RGB format */ #define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ @@ -2268,7 +2268,7 @@ #define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ #define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock wait count mask */ -#define CICR3_LPF (0x3ff << 0) /* Lines per frame mask */ +#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ #define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ #define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ @@ -2289,8 +2289,8 @@ #define CISR_EOL (1 << 8) /* End of line */ #define CISR_PAR_ERR (1 << 7) /* Parity error */ #define CISR_CQD (1 << 6) /* Camera interface quick disable */ -#define CISR_SOF (1 << 5) /* Start of frame */ -#define CISR_CDD (1 << 4) /* Camera interface disable done */ +#define CISR_CDD (1 << 5) /* Camera interface disable done */ +#define CISR_SOF (1 << 4) /* Start of frame */ #define CISR_EOF (1 << 3) /* End of frame */ #define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ #define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ -- cgit v0.10.2 From d91f75fb761e1e691796287889774cc8690034c1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 3 Nov 2006 18:30:12 +0100 Subject: [ARM] 3920/1: S3C24XX: Remove smdk2410_defconfig Remove the smdk2410_defconifg as it is out of data and has not been touched since 2.6.11. Use the s3c2410_defconfig instead. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/configs/smdk2410_defconfig b/arch/arm/configs/smdk2410_defconfig deleted file mode 100644 index 4d123d3..0000000 --- a/arch/arm/configs/smdk2410_defconfig +++ /dev/null @@ -1,735 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Sun Mar 27 22:42:40 2005 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_IOMAP=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -CONFIG_ARCH_S3C2410=y -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set - -# -# S3C24XX Implementations -# -# CONFIG_ARCH_BAST is not set -# CONFIG_ARCH_H1940 is not set -# CONFIG_MACH_N30 is not set -CONFIG_ARCH_SMDK2410=y -# CONFIG_ARCH_S3C2440 is not set -# CONFIG_MACH_VR1000 is not set -# CONFIG_MACH_RX3715 is not set -# CONFIG_MACH_OTOM is not set -# CONFIG_MACH_NEXCODER_2440 is not set -CONFIG_CPU_S3C2410=y - -# -# S3C2410 Boot -# - -# -# S3C2410 Setup -# -# CONFIG_S3C2410_DMA is not set -CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_32v4=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_TLB_V4WBI=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set - -# -# Bus support -# - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -# CONFIG_PREEMPT is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=1f04 mem=32M" -# CONFIG_XIP_KERNEL is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -# CONFIG_FPE_NWFPE is not set -# CONFIG_FPE_FASTFPE is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set - -# -# Power management options -# -# CONFIG_PM is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_PARTITIONS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_XIP is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_SMC91X is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_S3C2410=y -CONFIG_SERIAL_S3C2410_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_S3C2410_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -CONFIG_FB=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_SOFT_CURSOR=y -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set -CONFIG_FB_VIRTUAL=y - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -# CONFIG_LOGO is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set - -# -# XFS support -# -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_ERRORS is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_DEBUG_S3C2410_PORT=y -CONFIG_DEBUG_S3C2410_UART=0 - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -- cgit v0.10.2 From 73d15da44f34626b4ad18eb4d56e1c2c4aaed578 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 3 Nov 2006 18:33:43 +0100 Subject: [ARM] 3921/1: S3C24XX: remove bast_defconfig Remove the bast_defconfig, as it has not been updated since 2.6.13. The s3c2410_defconfig should be a good replacement. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig deleted file mode 100644 index 4a8564f..0000000 --- a/arch/arm/configs/bast_defconfig +++ /dev/null @@ -1,947 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Sun Mar 27 02:24:16 2005 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_IOMAP=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -CONFIG_ARCH_S3C2410=y -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set - -# -# S3C24XX Implementations -# -CONFIG_ARCH_BAST=y -# CONFIG_ARCH_H1940 is not set -# CONFIG_MACH_N30 is not set -# CONFIG_ARCH_SMDK2410 is not set -# CONFIG_ARCH_S3C2440 is not set -CONFIG_MACH_VR1000=y -# CONFIG_MACH_RX3715 is not set -# CONFIG_MACH_OTOM is not set -# CONFIG_MACH_NEXCODER_2440 is not set -CONFIG_CPU_S3C2410=y - -# -# S3C2410 Boot -# -# CONFIG_S3C2410_BOOT_WATCHDOG is not set - -# -# S3C2410 Setup -# -CONFIG_S3C2410_DMA=y -# CONFIG_S3C2410_DMA_DEBUG is not set -# CONFIG_S3C2410_PM_DEBUG is not set -# CONFIG_S3C2410_PM_CHECK is not set -CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_32v4=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_TLB_V4WBI=y - -# -# Processor Features -# -# CONFIG_ARM_THUMB is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set - -# -# Bus support -# - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -# CONFIG_PREEMPT is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0" -# CONFIG_XIP_KERNEL is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set - -# -# Power management options -# -CONFIG_PM=y -CONFIG_APM=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 -CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -CONFIG_MTD_MAP_BANK_WIDTH_16=y -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_XIP is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set -# CONFIG_MTD_IMPA7 is not set -CONFIG_MTD_BAST=y -CONFIG_MTD_BAST_MAXSIZE=4 - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_NAND_S3C2410=y -# CONFIG_MTD_NAND_S3C2410_DEBUG is not set -# CONFIG_MTD_NAND_S3C2410_HWECC is not set -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set - -# -# Parallel port support -# -CONFIG_PARPORT=y -# CONFIG_PARPORT_PC is not set -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_GSC is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -# CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDE_BAST=y -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_SMC91X is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PARKBD is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=8 -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_S3C2410=y -CONFIG_SERIAL_S3C2410_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_PRINTER=y -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=y -# CONFIG_TIPAR is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -CONFIG_S3C2410_WATCHDOG=y -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_S3C2410_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=m - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=m -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_PARPORT is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -CONFIG_I2C_S3C2410=y -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_PCA_ISA is not set - -# -# Hardware Sensors Chip support -# -CONFIG_I2C_SENSOR=m -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_FSCPOS is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -CONFIG_SENSORS_LM75=m -# CONFIG_SENSORS_LM77 is not set -CONFIG_SENSORS_LM78=m -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -CONFIG_SENSORS_LM85=m -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -CONFIG_SENSORS_EEPROM=m -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -CONFIG_FB=y -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_SOFT_CURSOR is not set -CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set - -# -# XFS support -# -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -# CONFIG_JFFS_PROC_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -# CONFIG_MINIX_SUBPARTITION is not set -CONFIG_SOLARIS_X86_PARTITION=y -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_FS is not set -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_ERRORS is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_DEBUG_S3C2410_PORT=y -CONFIG_DEBUG_S3C2410_UART=0 - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -- cgit v0.10.2 From da86341856befac4e2f4b16965d6f78379dc960a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 3 Nov 2006 18:38:02 +0100 Subject: [ARM] 3922/1: S3C24XX: update s3c2410_defconfig to 2.6.19-rc4 Update the s3c2410_defconfig to 2.6.19-rc4 Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index a832226..c773380 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,9 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18 -# Wed Sep 20 20:27:31 2006 +# Linux kernel version: 2.6.19-rc4 +# Fri Nov 3 17:34:07 2006 # CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y @@ -29,17 +30,20 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y -CONFIG_SYSCTL=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -70,6 +74,7 @@ CONFIG_KMOD=y # # Block layer # +CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # @@ -120,6 +125,7 @@ CONFIG_ARCH_S3C2410=y # # S3C24XX Implementations # +# CONFIG_MACH_AML_M5900 is not set CONFIG_MACH_ANUBIS=y CONFIG_MACH_OSIRIS=y CONFIG_ARCH_BAST=y @@ -178,6 +184,8 @@ CONFIG_CPU_CACHE_V4WT=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y # # Processor Features @@ -251,6 +259,7 @@ CONFIG_BINFMT_AOUT=y CONFIG_PM=y CONFIG_PM_LEGACY=y # CONFIG_PM_DEBUG is not set +# CONFIG_PM_SYSFS_DEPRECATED is not set CONFIG_APM=y # @@ -266,6 +275,7 @@ CONFIG_NET=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -286,10 +296,12 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -377,6 +389,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set # # RAM/ROM/Flash chip drivers @@ -512,6 +525,7 @@ CONFIG_BLK_DEV_IDE_BAST=y # # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set # # Multi-device support (RAID and LVM) @@ -606,6 +620,7 @@ CONFIG_DM9000=y # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -628,6 +643,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set @@ -734,7 +750,6 @@ CONFIG_S3C2410_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set CONFIG_HW_RANDOM=y # CONFIG_NVRAM is not set -CONFIG_S3C2410_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -747,7 +762,6 @@ CONFIG_S3C2410_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -798,6 +812,7 @@ CONFIG_SENSORS_EEPROM=m # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -834,6 +849,7 @@ CONFIG_SENSORS_LM85=m # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VT1211 is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set @@ -845,6 +861,7 @@ CONFIG_SENSORS_LM85=m # # Misc devices # +# CONFIG_TIFM_CORE is not set # # LED devices @@ -863,7 +880,6 @@ CONFIG_SENSORS_LM85=m # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -876,6 +892,7 @@ CONFIG_VIDEO_V4L2=y # CONFIG_FIRMWARE_EDID=y CONFIG_FB=y +# CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y @@ -951,7 +968,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # # may also be needed; see USB_STORAGE Help for more information # -# CONFIG_USB_STORAGE is not set # CONFIG_USB_LIBUSUAL is not set # @@ -1007,6 +1023,7 @@ CONFIG_USB_MON=y # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set @@ -1014,11 +1031,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1051,6 +1069,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1058,6 +1077,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y @@ -1089,6 +1109,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set @@ -1219,6 +1240,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y @@ -1238,9 +1260,10 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FRAME_POINTER=y -# CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y # CONFIG_DEBUG_WAITQ is not set @@ -1262,10 +1285,6 @@ CONFIG_DEBUG_S3C2410_UART=0 # CONFIG_CRYPTO is not set # -# Hardware crypto devices -# - -# # Library routines # # CONFIG_CRC_CCITT is not set -- cgit v0.10.2 From 3f84ada6c173d856b5e06b239931866ed7dd7a16 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 3 Nov 2006 18:47:10 +0100 Subject: [ARM] 3923/1: S3C24XX: update s3c2410_defconfig with new drivers Add the new drivers, such as SPI, LED and RTC core, to the s3c2410_defconfig. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index c773380..0563c14 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.19-rc4 -# Fri Nov 3 17:34:07 2006 +# Fri Nov 3 17:41:31 2006 # CONFIG_ARM=y # CONFIG_GENERIC_TIME is not set @@ -66,7 +66,8 @@ CONFIG_BASE_SMALL=0 # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -431,6 +432,8 @@ CONFIG_MTD_BAST_MAXSIZE=4 # # Self-contained MTD device drivers # +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set @@ -806,8 +809,21 @@ CONFIG_SENSORS_EEPROM=m # # SPI support # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=m +# CONFIG_SPI_BUTTERFLY is not set +CONFIG_SPI_S3C24XX_GPIO=m +CONFIG_SPI_S3C24XX=m + +# +# SPI Protocol Masters +# # # Dallas's 1-wire bus @@ -835,6 +851,7 @@ CONFIG_HWMON_VID=m # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set CONFIG_SENSORS_LM75=m # CONFIG_SENSORS_LM77 is not set CONFIG_SENSORS_LM78=m @@ -866,15 +883,21 @@ CONFIG_SENSORS_LM85=m # # LED devices # -# CONFIG_NEW_LEDS is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m # # LED drivers # +CONFIG_LEDS_S3C24XX=m # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +# CONFIG_LEDS_TRIGGER_IDE_DISK is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=m # # Multimedia devices @@ -1057,7 +1080,37 @@ CONFIG_USB_MON=y # Real Time Clock # CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +CONFIG_RTC_DRV_S3C=y +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_V3020 is not set # # File systems -- cgit v0.10.2 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 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ea16572..69cc8fb 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 37ed8e0..1e0d04f 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 45f44fe..6d42036 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 v0.10.2 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 diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index bbf6532..f95d42c 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 v0.10.2 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 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 69cc8fb..4b5097f 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 v0.10.2 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 diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index 2902742..933cedd 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 v0.10.2 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 diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 809d465..16353b6 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 v0.10.2 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 diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 16353b6..6303970 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 v0.10.2 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 diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 8dc2bac..50436e1 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 6d42036..6daf85c 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 9a6ec1b..2a8dd4c 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 v0.10.2 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 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 66bff18..ba165af 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 v0.10.2 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 diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index 6a12a94..df97e5c 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1e0d04f..bc1ac07 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 v0.10.2 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 diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 454a186..e081836 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 4087363..760b532 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 v0.10.2 From 7bd473fcc217adec000f213e8864bf9a161d57e1 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Thu, 2 Nov 2006 22:06:56 -0800 Subject: [PATCH] eCryptfs: Fix pointer deref I missed a pointer dereference in this kmalloc result check. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index f49f105..136175a 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -134,7 +134,7 @@ int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, algified_name_len = (chaining_modifier_len + cipher_name_len + 3); (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); - if (!(algified_name)) { + if (!(*algified_name)) { rc = -ENOMEM; goto out; } -- cgit v0.10.2 From df66b8552be5fdab5c4b4d53ee08b99388b9bd02 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 22:06:56 -0800 Subject: [PATCH] tidy "md: check bio address after mapping through partitions" Neil's xterms are too wide. Cc: Neil Brown Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index c7b1dac..9eaee66 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3075,11 +3075,12 @@ end_io: if (maxsector) { sector_t sector = bio->bi_sector; - if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + if (maxsector < nr_sectors || + maxsector - nr_sectors < sector) { /* - * This may well happen - partitions are not checked - * to make sure they are within the size of the - * whole device. + * This may well happen - partitions are not + * checked to make sure they are within the size + * of the whole device. */ handle_bad_sector(bio); goto end_io; -- cgit v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index 50ab4a9..d111356 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 v0.10.2 From 87c2b7c045a44f6c1c7af23e64f2b286e6f7130a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 2 Nov 2006 22:06:58 -0800 Subject: [PATCH] sys_pselect7 vs compat_sys_pselect7 uaccess error handling 758333458aa719bfc26ec16eafd4ad3a9e96014d fixes the not checked copy_to_user return value of compat_sys_pselect7. I ran into this too because of an old source tree, but my fix would look quite a bit different to Andi's fix. The reason is that the compat function IMHO should behave the very same as the non-compat function if possible. Since sys_pselect7 does not return -EFAULT in this specific case, change the compat code so it behaves like sys_pselect7. Cc: David Woodhouse Cc: Andi Kleen Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/compat.c b/fs/compat.c index 50624d4..8d0a001 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1835,9 +1835,12 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); - if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) { + if (tsp) { struct compat_timespec rts; + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + rts.tv_sec = timeout / HZ; rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); if (rts.tv_nsec >= NSEC_PER_SEC) { @@ -1846,8 +1849,19 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, } if (compat_timespec_compare(&rts, &ts) >= 0) rts = ts; - if (copy_to_user(tsp, &rts, sizeof(rts))) - ret = -EFAULT; + if (copy_to_user(tsp, &rts, sizeof(rts))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND) + ret = -EINTR; + } } if (ret == -ERESTARTNOHAND) { -- cgit v0.10.2 From c6120938365df9976dc07c536e1c14190ead48e3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 2 Nov 2006 22:07:01 -0800 Subject: [PATCH] update some docbook comments Correct a few comments in kernel-doc Doc and source files. (akpm: note: the patch removes a non-ascii character and might have to be applied by hand..) Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index c65233d..284e7e1 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -17,7 +17,7 @@ are: special place-holders for where the extracted documentation should go. -- scripts/docproc.c +- scripts/basic/docproc.c This is a program for converting SGML template files into SGML files. When a file is referenced it is searched for symbols diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index 4ab6cbf..d6071cb 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c @@ -250,7 +250,7 @@ void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } void extfunc(char * filename) { docfunctions(filename, FUNCTION); } /* - * Document spĺecific function(s) in a file. + * Document specific function(s) in a file. * Call kernel-doc with the following parameters: * kernel-doc -docbook -function function1 [-function function2] */ -- cgit v0.10.2 From 733b72c31efb0d6b29577655939ccfe835381b52 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 2 Nov 2006 22:07:02 -0800 Subject: [PATCH] docbook: merge journal-api into filesystems.tmpl Move journal-api into filesystems.tmpl as a Chapter. Applies on top of the previous docbook: make a filesystems book patch. Remove trailing whitespace from journal-api chapter. Align some of the tags. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 3bf5086..db9499a 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -9,7 +9,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ - kernel-api.xml filesystems.xml journal-api.xml lsm.xml usb.xml \ + kernel-api.xml filesystems.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl index 4785032..39fa2ab 100644 --- a/Documentation/DocBook/filesystems.tmpl +++ b/Documentation/DocBook/filesystems.tmpl @@ -98,4 +98,304 @@ + + + The Linux Journalling API + + + + Roger + Gammans + +
+ rgammans@computer-surgery.co.uk +
+
+
+
+ + + + Stephen + Tweedie + +
+ sct@redhat.com +
+
+
+
+ + + 2002 + Roger Gammans + +
+ + The Linux Journalling API + + + Overview + + Details + +The journalling layer is easy to use. You need to +first of all create a journal_t data structure. There are +two calls to do this dependent on how you decide to allocate the physical +media on which the journal resides. The journal_init_inode() call +is for journals stored in filesystem inodes, or the journal_init_dev() +call can be use for journal stored on a raw device (in a continuous range +of blocks). A journal_t is a typedef for a struct pointer, so when +you are finally finished make sure you call journal_destroy() on it +to free up any used kernel memory. + + + +Once you have got your journal_t object you need to 'mount' or load the journal +file, unless of course you haven't initialised it yet - in which case you +need to call journal_create(). + + + +Most of the time however your journal file will already have been created, but +before you load it you must call journal_wipe() to empty the journal file. +Hang on, you say , what if the filesystem wasn't cleanly umount()'d . Well, it is the +job of the client file system to detect this and skip the call to journal_wipe(). + + + +In either case the next call should be to journal_load() which prepares the +journal file for use. Note that journal_wipe(..,0) calls journal_skip_recovery() +for you if it detects any outstanding transactions in the journal and similarly +journal_load() will call journal_recover() if necessary. +I would advise reading fs/ext3/super.c for examples on this stage. +[RGG: Why is the journal_wipe() call necessary - doesn't this needlessly +complicate the API. Or isn't a good idea for the journal layer to hide +dirty mounts from the client fs] + + + +Now you can go ahead and start modifying the underlying +filesystem. Almost. + + + + +You still need to actually journal your filesystem changes, this +is done by wrapping them into transactions. Additionally you +also need to wrap the modification of each of the buffers +with calls to the journal layer, so it knows what the modifications +you are actually making are. To do this use journal_start() which +returns a transaction handle. + + + +journal_start() +and its counterpart journal_stop(), which indicates the end of a transaction +are nestable calls, so you can reenter a transaction if necessary, +but remember you must call journal_stop() the same number of times as +journal_start() before the transaction is completed (or more accurately +leaves the update phase). Ext3/VFS makes use of this feature to simplify +quota support. + + + +Inside each transaction you need to wrap the modifications to the +individual buffers (blocks). Before you start to modify a buffer you +need to call journal_get_{create,write,undo}_access() as appropriate, +this allows the journalling layer to copy the unmodified data if it +needs to. After all the buffer may be part of a previously uncommitted +transaction. +At this point you are at last ready to modify a buffer, and once +you are have done so you need to call journal_dirty_{meta,}data(). +Or if you've asked for access to a buffer you now know is now longer +required to be pushed back on the device you can call journal_forget() +in much the same way as you might have used bforget() in the past. + + + +A journal_flush() may be called at any time to commit and checkpoint +all your transactions. + + + +Then at umount time , in your put_super() (2.4) or write_super() (2.5) +you can then call journal_destroy() to clean up your in-core journal object. + + + +Unfortunately there a couple of ways the journal layer can cause a deadlock. +The first thing to note is that each task can only have +a single outstanding transaction at any one time, remember nothing +commits until the outermost journal_stop(). This means +you must complete the transaction at the end of each file/inode/address +etc. operation you perform, so that the journalling system isn't re-entered +on another journal. Since transactions can't be nested/batched +across differing journals, and another filesystem other than +yours (say ext3) may be modified in a later syscall. + + + +The second case to bear in mind is that journal_start() can +block if there isn't enough space in the journal for your transaction +(based on the passed nblocks param) - when it blocks it merely(!) needs to +wait for transactions to complete and be committed from other tasks, +so essentially we are waiting for journal_stop(). So to avoid +deadlocks you must treat journal_start/stop() as if they +were semaphores and include them in your semaphore ordering rules to prevent +deadlocks. Note that journal_extend() has similar blocking behaviour to +journal_start() so you can deadlock here just as easily as on journal_start(). + + + +Try to reserve the right number of blocks the first time. ;-). This will +be the maximum number of blocks you are going to touch in this transaction. +I advise having a look at at least ext3_jbd.h to see the basis on which +ext3 uses to make these decisions. + + + +Another wriggle to watch out for is your on-disk block allocation strategy. +why? Because, if you undo a delete, you need to ensure you haven't reused any +of the freed blocks in a later transaction. One simple way of doing this +is make sure any blocks you allocate only have checkpointed transactions +listed against them. Ext3 does this in ext3_test_allocatable(). + + + +Lock is also providing through journal_{un,}lock_updates(), +ext3 uses this when it wants a window with a clean and stable fs for a moment. +eg. + + + + + journal_lock_updates() //stop new stuff happening.. + journal_flush() // checkpoint everything. + ..do stuff on stable fs + journal_unlock_updates() // carry on with filesystem use. + + + +The opportunities for abuse and DOS attacks with this should be obvious, +if you allow unprivileged userspace to trigger codepaths containing these +calls. + + + +A new feature of jbd since 2.5.25 is commit callbacks with the new +journal_callback_set() function you can now ask the journalling layer +to call you back when the transaction is finally committed to disk, so that +you can do some of your own management. The key to this is the journal_callback +struct, this maintains the internal callback information but you can +extend it like this:- + + + struct myfs_callback_s { + //Data structure element required by jbd.. + struct journal_callback for_jbd; + // Stuff for myfs allocated together. + myfs_inode* i_commited; + + } + + + +this would be useful if you needed to know when data was committed to a +particular inode. + + + + + + Summary + +Using the journal is a matter of wrapping the different context changes, +being each mount, each modification (transaction) and each changed buffer +to tell the journalling layer about them. + + + +Here is a some pseudo code to give you an idea of how it works, as +an example. + + + + journal_t* my_jnrl = journal_create(); + journal_init_{dev,inode}(jnrl,...) + if (clean) journal_wipe(); + journal_load(); + + foreach(transaction) { /*transactions must be + completed before + a syscall returns to + userspace*/ + + handle_t * xct=journal_start(my_jnrl); + foreach(bh) { + journal_get_{create,write,undo}_access(xact,bh); + if ( myfs_modify(bh) ) { /* returns true + if makes changes */ + journal_dirty_{meta,}data(xact,bh); + } else { + journal_forget(bh); + } + } + journal_stop(xct); + } + journal_destroy(my_jrnl); + + + + + + + Data Types + + The journalling layer uses typedefs to 'hide' the concrete definitions + of the structures used. As a client of the JBD layer you can + just rely on the using the pointer as a magic cookie of some sort. + + Obviously the hiding is not enforced as this is 'C'. + + Structures +!Iinclude/linux/jbd.h + + + + + Functions + + The functions here are split into two groups those that + affect a journal as a whole, and those which are used to + manage transactions + + Journal Level +!Efs/jbd/journal.c +!Ifs/jbd/recovery.c + + Transasction Level +!Efs/jbd/transaction.c + + + + See also + + + + Journaling the Linux ext2fs Filesystem, LinuxExpo 98, Stephen Tweedie + + + + + + + Ext3 Journalling FileSystem, OLS 2000, Dr. Stephen Tweedie + + + + + +
+ diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl deleted file mode 100644 index 2077f9a..0000000 --- a/Documentation/DocBook/journal-api.tmpl +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - The Linux Journalling API - - - Roger - Gammans - -
- rgammans@computer-surgery.co.uk -
-
-
-
- - - - Stephen - Tweedie - -
- sct@redhat.com -
-
-
-
- - - 2002 - Roger Gammans - - - - - This documentation 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 - - - - For more details see the file COPYING in the source - distribution of Linux. - - -
- - - - - Overview - - Details - -The journalling layer is easy to use. You need to -first of all create a journal_t data structure. There are -two calls to do this dependent on how you decide to allocate the physical -media on which the journal resides. The journal_init_inode() call -is for journals stored in filesystem inodes, or the journal_init_dev() -call can be use for journal stored on a raw device (in a continuous range -of blocks). A journal_t is a typedef for a struct pointer, so when -you are finally finished make sure you call journal_destroy() on it -to free up any used kernel memory. - - - -Once you have got your journal_t object you need to 'mount' or load the journal -file, unless of course you haven't initialised it yet - in which case you -need to call journal_create(). - - - -Most of the time however your journal file will already have been created, but -before you load it you must call journal_wipe() to empty the journal file. -Hang on, you say , what if the filesystem wasn't cleanly umount()'d . Well, it is the -job of the client file system to detect this and skip the call to journal_wipe(). - - - -In either case the next call should be to journal_load() which prepares the -journal file for use. Note that journal_wipe(..,0) calls journal_skip_recovery() -for you if it detects any outstanding transactions in the journal and similarly -journal_load() will call journal_recover() if necessary. -I would advise reading fs/ext3/super.c for examples on this stage. -[RGG: Why is the journal_wipe() call necessary - doesn't this needlessly -complicate the API. Or isn't a good idea for the journal layer to hide -dirty mounts from the client fs] - - - -Now you can go ahead and start modifying the underlying -filesystem. Almost. - - - - - -You still need to actually journal your filesystem changes, this -is done by wrapping them into transactions. Additionally you -also need to wrap the modification of each of the buffers -with calls to the journal layer, so it knows what the modifications -you are actually making are. To do this use journal_start() which -returns a transaction handle. - - - -journal_start() -and its counterpart journal_stop(), which indicates the end of a transaction -are nestable calls, so you can reenter a transaction if necessary, -but remember you must call journal_stop() the same number of times as -journal_start() before the transaction is completed (or more accurately -leaves the update phase). Ext3/VFS makes use of this feature to simplify -quota support. - - - -Inside each transaction you need to wrap the modifications to the -individual buffers (blocks). Before you start to modify a buffer you -need to call journal_get_{create,write,undo}_access() as appropriate, -this allows the journalling layer to copy the unmodified data if it -needs to. After all the buffer may be part of a previously uncommitted -transaction. -At this point you are at last ready to modify a buffer, and once -you are have done so you need to call journal_dirty_{meta,}data(). -Or if you've asked for access to a buffer you now know is now longer -required to be pushed back on the device you can call journal_forget() -in much the same way as you might have used bforget() in the past. - - - -A journal_flush() may be called at any time to commit and checkpoint -all your transactions. - - - -Then at umount time , in your put_super() (2.4) or write_super() (2.5) -you can then call journal_destroy() to clean up your in-core journal object. - - - - -Unfortunately there a couple of ways the journal layer can cause a deadlock. -The first thing to note is that each task can only have -a single outstanding transaction at any one time, remember nothing -commits until the outermost journal_stop(). This means -you must complete the transaction at the end of each file/inode/address -etc. operation you perform, so that the journalling system isn't re-entered -on another journal. Since transactions can't be nested/batched -across differing journals, and another filesystem other than -yours (say ext3) may be modified in a later syscall. - - - -The second case to bear in mind is that journal_start() can -block if there isn't enough space in the journal for your transaction -(based on the passed nblocks param) - when it blocks it merely(!) needs to -wait for transactions to complete and be committed from other tasks, -so essentially we are waiting for journal_stop(). So to avoid -deadlocks you must treat journal_start/stop() as if they -were semaphores and include them in your semaphore ordering rules to prevent -deadlocks. Note that journal_extend() has similar blocking behaviour to -journal_start() so you can deadlock here just as easily as on journal_start(). - - - -Try to reserve the right number of blocks the first time. ;-). This will -be the maximum number of blocks you are going to touch in this transaction. -I advise having a look at at least ext3_jbd.h to see the basis on which -ext3 uses to make these decisions. - - - -Another wriggle to watch out for is your on-disk block allocation strategy. -why? Because, if you undo a delete, you need to ensure you haven't reused any -of the freed blocks in a later transaction. One simple way of doing this -is make sure any blocks you allocate only have checkpointed transactions -listed against them. Ext3 does this in ext3_test_allocatable(). - - - -Lock is also providing through journal_{un,}lock_updates(), -ext3 uses this when it wants a window with a clean and stable fs for a moment. -eg. - - - - - journal_lock_updates() //stop new stuff happening.. - journal_flush() // checkpoint everything. - ..do stuff on stable fs - journal_unlock_updates() // carry on with filesystem use. - - - -The opportunities for abuse and DOS attacks with this should be obvious, -if you allow unprivileged userspace to trigger codepaths containing these -calls. - - - -A new feature of jbd since 2.5.25 is commit callbacks with the new -journal_callback_set() function you can now ask the journalling layer -to call you back when the transaction is finally committed to disk, so that -you can do some of your own management. The key to this is the journal_callback -struct, this maintains the internal callback information but you can -extend it like this:- - - - struct myfs_callback_s { - //Data structure element required by jbd.. - struct journal_callback for_jbd; - // Stuff for myfs allocated together. - myfs_inode* i_commited; - - } - - - -this would be useful if you needed to know when data was committed to a -particular inode. - - - - - -Summary - -Using the journal is a matter of wrapping the different context changes, -being each mount, each modification (transaction) and each changed buffer -to tell the journalling layer about them. - - - -Here is a some pseudo code to give you an idea of how it works, as -an example. - - - - journal_t* my_jnrl = journal_create(); - journal_init_{dev,inode}(jnrl,...) - if (clean) journal_wipe(); - journal_load(); - - foreach(transaction) { /*transactions must be - completed before - a syscall returns to - userspace*/ - - handle_t * xct=journal_start(my_jnrl); - foreach(bh) { - journal_get_{create,write,undo}_access(xact,bh); - if ( myfs_modify(bh) ) { /* returns true - if makes changes */ - journal_dirty_{meta,}data(xact,bh); - } else { - journal_forget(bh); - } - } - journal_stop(xct); - } - journal_destroy(my_jrnl); - - - - - - - Data Types - - The journalling layer uses typedefs to 'hide' the concrete definitions - of the structures used. As a client of the JBD layer you can - just rely on the using the pointer as a magic cookie of some sort. - - Obviously the hiding is not enforced as this is 'C'. - - Structures -!Iinclude/linux/jbd.h - - - - - Functions - - The functions here are split into two groups those that - affect a journal as a whole, and those which are used to - manage transactions - - Journal Level -!Efs/jbd/journal.c -!Ifs/jbd/recovery.c - - Transasction Level -!Efs/jbd/transaction.c - - - - See also - - - - Journaling the Linux ext2fs Filesystem,LinuxExpo 98, Stephen Tweedie - - - - - - - Ext3 Journalling FileSystem , OLS 2000, Dr. Stephen Tweedie - - - - - -
-- cgit v0.10.2 From c7e12b838989b0e432c7a1cdf1e6c6fd936007f6 Mon Sep 17 00:00:00 2001 From: Pavel Emelianov Date: Thu, 2 Nov 2006 22:07:03 -0800 Subject: [PATCH] Fix ipc entries removal Fix two issuses related to ipc_ids->entries freeing. 1. When freeing ipc namespace we need to free entries allocated with ipc_init_ids(). 2. When removing old entries in grow_ary() ipc_rcu_putref() may be called on entries set to &ids->nullentry earlier in ipc_init_ids(). This is almost impossible without namespaces, but with them this situation becomes possible. Found during OpenVZ testing after obvious leaks in beancounters. Signed-off-by: Pavel Emelianov Cc: Kirill Korotaev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/ipc/msg.c b/ipc/msg.c index 5b213d9..600e06f 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -124,6 +124,7 @@ void msg_exit_ns(struct ipc_namespace *ns) } mutex_unlock(&msg_ids(ns).mutex); + ipc_fini_ids(ns->ids[IPC_MSG_IDS]); kfree(ns->ids[IPC_MSG_IDS]); ns->ids[IPC_MSG_IDS] = NULL; } diff --git a/ipc/sem.c b/ipc/sem.c index 0dafcc4..21b3289 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -161,6 +161,7 @@ void sem_exit_ns(struct ipc_namespace *ns) } mutex_unlock(&sem_ids(ns).mutex); + ipc_fini_ids(ns->ids[IPC_SEM_IDS]); kfree(ns->ids[IPC_SEM_IDS]); ns->ids[IPC_SEM_IDS] = NULL; } diff --git a/ipc/shm.c b/ipc/shm.c index bfbd317..d1198dd 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -116,6 +116,7 @@ void shm_exit_ns(struct ipc_namespace *ns) } mutex_unlock(&shm_ids(ns).mutex); + ipc_fini_ids(ns->ids[IPC_SHM_IDS]); kfree(ns->ids[IPC_SHM_IDS]); ns->ids[IPC_SHM_IDS] = NULL; } diff --git a/ipc/util.c b/ipc/util.c index 42479e4..cd8bb14 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -301,7 +301,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize) */ rcu_assign_pointer(ids->entries, new); - ipc_rcu_putref(old); + __ipc_fini_ids(ids, old); return newsize; } diff --git a/ipc/util.h b/ipc/util.h index c8fd6b9..e3aa2c5 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -83,6 +83,18 @@ void* ipc_rcu_alloc(int size); void ipc_rcu_getref(void *ptr); void ipc_rcu_putref(void *ptr); +static inline void __ipc_fini_ids(struct ipc_ids *ids, + struct ipc_id_ary *entries) +{ + if (entries != &ids->nullentry) + ipc_rcu_putref(entries); +} + +static inline void ipc_fini_ids(struct ipc_ids *ids) +{ + __ipc_fini_ids(ids, ids->entries); +} + struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id); struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id); void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp); -- cgit v0.10.2 From 941c7105dc4f4961727acc518e18e00b9a03cbf3 Mon Sep 17 00:00:00 2001 From: nkalmala Date: Thu, 2 Nov 2006 22:07:04 -0800 Subject: [PATCH] mm: un-needed add-store operation wastes a few bytes Un-needed add-store operation wastes a few bytes. 8 bytes wasted with -O2, on a ppc. Signed-off-by: nkalmala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b55bb35..bf2f6cf 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -853,7 +853,7 @@ again: pcp = &zone_pcp(zone, cpu)->pcp[cold]; local_irq_save(flags); if (!pcp->count) { - pcp->count += rmqueue_bulk(zone, 0, + pcp->count = rmqueue_bulk(zone, 0, pcp->batch, &pcp->list); if (unlikely(!pcp->count)) goto failed; -- cgit v0.10.2 From 86f4f0f9ba6e35fbbc409dfc3d8615c1a9822482 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 2 Nov 2006 22:07:05 -0800 Subject: [PATCH] fix UFS superblock alignment issues ufs2 fails to mount on x86_64, claiming bad magic. This is because ufs_super_block_third's fs_un1 member is padded out by 4 bytes for 8-byte alignment, pushing down the rest of the struct. Forcing this to be packed solves it. I took a quick look over other on-disk structures and didn't immediately find other problems. I was able to mount & ls a populated ufs2 filesystem w/ this change. Signed-off-by: Eric Sandeen Cc: Evgeniy Dushistov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index 61eef50..28967ed 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -908,7 +908,7 @@ struct ufs_super_block_third { __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ __fs64 fs_pendingblocks;/* blocks in process of being freed */ __fs32 fs_pendinginodes;/*inodes in process of being freed */ - } fs_u2; + } __attribute__ ((packed)) fs_u2; } fs_un1; union { struct { -- cgit v0.10.2 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 diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index bbdba7b..46a9c35 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 v0.10.2 From 029e332ea717810172e965ec50f942755ad0c58a Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 2 Nov 2006 22:07:06 -0800 Subject: [PATCH] Cleanup read_pages() Current read_pages() assume ->readpages() frees the passed pages. This patch free the pages in ->read_pages(), if those were remaining in the pages_list. So, readpages() just can ignore the remaining pages in pages_list. Signed-off-by: OGAWA Hirofumi Cc: Steven French Cc: Miklos Szeredi Cc: Steven Whitehouse Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/readahead.c b/mm/readahead.c index 1ba736a..23cb61a 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -173,6 +173,8 @@ static int read_pages(struct address_space *mapping, struct file *filp, if (mapping->a_ops->readpages) { ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages); + /* Clean up the remaining pages */ + put_pages_list(pages); goto out; } -- cgit v0.10.2 From 05ac9d4b3d7eac9e8542c83341a0e22d09aecf8f Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 2 Nov 2006 22:07:08 -0800 Subject: [PATCH] cifs: ->readpages() fixes This just ignore the remaining pages, and will fix a forgot put_pages_list(). Signed-off-by: OGAWA Hirofumi Cc: Steven French Cc: Miklos Szeredi Cc: Steven Whitehouse Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 976a691..7e056b9 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1806,13 +1806,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } if ((rc < 0) || (smb_read_data == NULL)) { cFYI(1, ("Read error in readpages: %d", rc)); - /* clean up remaing pages off list */ - while (!list_empty(page_list) && (i < num_pages)) { - page = list_entry(page_list->prev, struct page, - lru); - list_del(&page->lru); - page_cache_release(page); - } break; } else if (bytes_read > 0) { pSMBr = (struct smb_com_read_rsp *)smb_read_data; @@ -1831,13 +1824,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, this case is ok - if we are at server EOF we will hit it on next read */ - /* while (!list_empty(page_list) && (i < num_pages)) { - page = list_entry(page_list->prev, - struct page, list); - list_del(&page->list); - page_cache_release(page); - } - break; */ + /* break; */ } } else { cFYI(1, ("No bytes read (%d) at offset %lld . " @@ -1845,14 +1832,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, bytes_read, offset)); /* BB turn off caching and do new lookup on file size at server? */ - while (!list_empty(page_list) && (i < num_pages)) { - page = list_entry(page_list->prev, struct page, - lru); - list_del(&page->lru); - - /* BB removeme - replace with zero of page? */ - page_cache_release(page); - } break; } if (smb_read_data) { -- cgit v0.10.2 From 2e990021bfc65b1a3778479a9e6b4811f9c1ff0e Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 2 Nov 2006 22:07:09 -0800 Subject: [PATCH] fuse: ->readpages() cleanup This just ignore the remaining pages. Signed-off-by: OGAWA Hirofumi Cc: Steven French Cc: Miklos Szeredi Cc: Steven Whitehouse Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 2bb5ace..763a50d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -397,14 +397,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, err = -EIO; if (is_bad_inode(inode)) - goto clean_pages_up; + goto out; data.file = file; data.inode = inode; data.req = fuse_get_req(fc); err = PTR_ERR(data.req); if (IS_ERR(data.req)) - goto clean_pages_up; + goto out; err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { @@ -413,10 +413,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, else fuse_put_request(fc, data.req); } - return err; - -clean_pages_up: - put_pages_list(pages); +out: return err; } -- cgit v0.10.2 From 7011774db8afca43be466f0f0428434a9edf053e Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 2 Nov 2006 22:07:10 -0800 Subject: [PATCH] gfs2: ->readpages() fixes This just ignore the remaining pages, and remove unneeded unlock_pages(). Signed-off-by: OGAWA Hirofumi Cc: Steven French Cc: Miklos Szeredi Acked-by: Steven Whitehouse Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 8d5963c..015640b 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -337,13 +337,6 @@ out: out_noerror: ret = 0; out_unlock: - /* unlock all pages, we can't do any I/O right now */ - for (page_idx = 0; page_idx < nr_pages; page_idx++) { - struct page *page = list_entry(pages->prev, struct page, lru); - list_del(&page->lru); - unlock_page(page); - page_cache_release(page); - } if (do_unlock) gfs2_holder_uninit(&gh); goto out; -- cgit v0.10.2 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 diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4bde30b..75e9e38 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 v0.10.2 From 7ef55b8a05c02db7c07d81827c69fe8f124e8654 Mon Sep 17 00:00:00 2001 From: Srinivasa Ds Date: Thu, 2 Nov 2006 22:07:12 -0800 Subject: [PATCH] NFS4: fix for recursive locking problem When I was performing some operations on NFS, I got below error on server side. ============================================= [ INFO: possible recursive locking detected ] 2.6.19-prep #1 --------------------------------------------- nfsd4/3525 is trying to acquire lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 but task is already holding lock: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 other info that might help us debug this: 2 locks held by nfsd4/3525: #0: (client_mutex){--..}, at: [] mutex_lock+0x21/0x24 #1: (&inode->i_mutex){--..}, at: [] mutex_lock+0x21/0x24 stack backtrace: [] show_trace_log_lvl+0x58/0x16a [] show_trace+0xd/0x10 [] dump_stack+0x19/0x1b [] __lock_acquire+0x778/0x99c [] lock_acquire+0x4b/0x6d [] __mutex_lock_slowpath+0xbc/0x20a [] mutex_lock+0x21/0x24 [] vfs_rmdir+0x76/0xf8 [] nfsd4_clear_clid_dir+0x2c/0x41 [nfsd] [] nfsd4_remove_clid_dir+0xb1/0xe8 [nfsd] [] laundromat_main+0x9b/0x1c3 [nfsd] [] run_workqueue+0x7a/0xbb [] worker_thread+0xd2/0x107 [] kthread+0xc3/0xf2 [] kernel_thread_helper+0x5/0xb =================================================================== Cause for this problem was,2 successive mutex_lock calls on 2 diffrent inodes ,as shown below static int nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) { int status; /* For now this directory should already be empty, but we empty it of * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); mutex_lock(&dir->d_inode->i_mutex); status = vfs_rmdir(dir->d_inode, dentry); ... int vfs_rmdir(struct inode *dir, struct dentry *dentry) { int error = may_delete(dir, dentry, 1); if (error) return error; if (!dir->i_op || !dir->i_op->rmdir) return -EPERM; DQUOT_INIT(dir); mutex_lock(&dentry->d_inode->i_mutex); ... So I have developed the patch to overcome this problem. Signed-off-by: Srinivasa DS Cc: Neil Brown Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index e9d0770..81b8565 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -274,7 +274,7 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); - mutex_lock(&dir->d_inode->i_mutex); + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); status = vfs_rmdir(dir->d_inode, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status; -- cgit v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e5cfb1f..157fa81 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 v0.10.2 From 7f6b8876c7e66b0d15af134e2a5b87e55514eb6d Mon Sep 17 00:00:00 2001 From: Daniel Yeisley Date: Thu, 2 Nov 2006 22:07:14 -0800 Subject: [PATCH] init_reap_node() initialization fix It looks like there is a bug in init_reap_node() in slab.c that can cause multiple oops's on certain ES7000 configurations. The variable reap_node is defined per cpu, but only initialized on a single CPU. This causes an oops in next_reap_node() when __get_cpu_var(reap_node) returns the wrong value. Fix is below. Signed-off-by: Dan Yeisley Cc: Andi Kleen Acked-by: Christoph Lameter Cc: Pekka Enberg Cc: Manfred Spraul Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index 84c631f..3c4a7e3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -883,7 +883,7 @@ static void init_reap_node(int cpu) if (node == MAX_NUMNODES) node = first_node(node_online_map); - __get_cpu_var(reap_node) = node; + per_cpu(reap_node, cpu) = node; } static void next_reap_node(void) -- cgit v0.10.2 From f46c483357c2d87606bbefb511321e3efd4baae0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 22:07:16 -0800 Subject: [PATCH] Add printk_timed_ratelimit() printk_ratelimit() has global state which makes it not useful for callers which wish to perform ratelimiting at a particular frequency. Add a printk_timed_ratelimit() which utilises caller-provided state storage to permit more flexibility. This function can in fact be used for things other than printk ratelimiting and is perhaps poorly named. Cc: Ulrich Drepper Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 80f39ca..24b6111 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -171,6 +171,8 @@ __attribute_const__ roundup_pow_of_two(unsigned long x) extern int printk_ratelimit(void); extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst); +extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, + unsigned int interval_msec); static inline void console_silent(void) { diff --git a/kernel/printk.c b/kernel/printk.c index f7d427e..6642655 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -1101,3 +1102,23 @@ int printk_ratelimit(void) printk_ratelimit_burst); } EXPORT_SYMBOL(printk_ratelimit); + +/** + * printk_timed_ratelimit - caller-controlled printk ratelimiting + * @caller_jiffies: pointer to caller's state + * @interval_msecs: minimum interval between prints + * + * printk_timed_ratelimit() returns true if more than @interval_msecs + * milliseconds have elapsed since the last time printk_timed_ratelimit() + * returned true. + */ +bool printk_timed_ratelimit(unsigned long *caller_jiffies, + unsigned int interval_msecs) +{ + if (*caller_jiffies == 0 || time_after(jiffies, *caller_jiffies)) { + *caller_jiffies = jiffies + msecs_to_jiffies(interval_msecs); + return true; + } + return false; +} +EXPORT_SYMBOL(printk_timed_ratelimit); -- cgit v0.10.2 From 19c6b6ed3f597a583f58e3fc99256cc01ae8c394 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 22:07:17 -0800 Subject: [PATCH] schedule removal of FUTEX_FD Apparently FUTEX_FD is unfixably racy and nothing uses it (or if it does, it shouldn't). Add a warning printk, give any remaining users six months to migrate off it. Cc: Ulrich Drepper Cc: Ingo Molnar Acked-by: Thomas Gleixner Cc: Rusty Russell Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/futex.c b/kernel/futex.c index b364e00..93ef30b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1507,6 +1507,13 @@ static int futex_fd(u32 __user *uaddr, int signal) struct futex_q *q; struct file *filp; int ret, err; + static unsigned long printk_interval; + + if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) { + printk(KERN_WARNING "Process `%s' used FUTEX_FD, which " + "will be removed from the kernel in June 2007\n", + current->comm); + } ret = -EINVAL; if (!valid_signal(signal)) -- cgit v0.10.2 From 90d53909443b3986569b38ef145f09ea2359af75 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 22:07:18 -0800 Subject: [PATCH] acpi_noirq section fix WARNING: vmlinux - Section mismatch: reference to .init.data:acpi_noirq from .text between 'pcibios_penalize_isa_irq' (at offset 0xc026ffa1) and 'pirq_serverworks_get' Acked-by: "Brown, Len" Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index ab974ff..22e4c466 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -70,7 +70,7 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return #define PREFIX "ACPI: " -int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ +int acpi_noirq; /* skip ACPI IRQ initialization */ int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */ int acpi_ht __initdata = 1; /* enable HT */ -- cgit v0.10.2 From b918f6e62cd46774f9fc0a3fbba6bd10ad85ee14 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 2 Nov 2006 22:07:19 -0800 Subject: [PATCH] swsusp: debugging Add a swsusp debugging mode. This does everything that's needed for a suspend except for actually suspending. So we can look in the log messages and work out a) what code is being slow and b) which drivers are misbehaving. (1) # echo testproc > /sys/power/disk # echo disk > /sys/power/state This should turn off the non-boot CPU, freeze all processes, wait for 5 seconds and then thaw the processes and the CPU. (2) # echo test > /sys/power/disk # echo disk > /sys/power/state This should turn off the non-boot CPU, freeze all processes, shrink memory, suspend all devices, wait for 5 seconds, resume the devices etc. Cc: Pavel Machek Cc: Stefan Seyfried Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power index d882f80..dcff4d0 100644 --- a/Documentation/ABI/testing/sysfs-power +++ b/Documentation/ABI/testing/sysfs-power @@ -21,7 +21,7 @@ Description: these states. What: /sys/power/disk -Date: August 2006 +Date: September 2006 Contact: Rafael J. Wysocki Description: The /sys/power/disk file controls the operating mode of the @@ -39,6 +39,19 @@ Description: 'reboot' - the memory image will be saved by the kernel and the system will be rebooted. + Additionally, /sys/power/disk can be used to turn on one of the + two testing modes of the suspend-to-disk mechanism: 'testproc' + or 'test'. If the suspend-to-disk mechanism is in the + 'testproc' mode, writing 'disk' to /sys/power/state will cause + the kernel to disable nonboot CPUs and freeze tasks, wait for 5 + seconds, unfreeze tasks and enable nonboot CPUs. If it is in + the 'test' mode, writing 'disk' to /sys/power/state will cause + the kernel to disable nonboot CPUs and freeze tasks, shrink + memory, suspend devices, wait for 5 seconds, resume devices, + unfreeze tasks and enable nonboot CPUs. Then, we are able to + look in the log messages and work out, for example, which code + is being slow and which device drivers are misbehaving. + The suspend-to-disk method may be chosen by writing to this file one of the accepted strings: @@ -46,6 +59,8 @@ Description: 'platform' 'shutdown' 'reboot' + 'testproc' + 'test' It will only change to 'firmware' or 'platform' if the system supports that. diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt index a66bec2..74311d7 100644 --- a/Documentation/power/interface.txt +++ b/Documentation/power/interface.txt @@ -30,6 +30,17 @@ testing). The system will support either 'firmware' or 'platform', and that is known a priori. But, the user may choose 'shutdown' or 'reboot' as alternatives. +Additionally, /sys/power/disk can be used to turn on one of the two testing +modes of the suspend-to-disk mechanism: 'testproc' or 'test'. If the +suspend-to-disk mechanism is in the 'testproc' mode, writing 'disk' to +/sys/power/state will cause the kernel to disable nonboot CPUs and freeze +tasks, wait for 5 seconds, unfreeze tasks and enable nonboot CPUs. If it is +in the 'test' mode, writing 'disk' to /sys/power/state will cause the kernel +to disable nonboot CPUs and freeze tasks, shrink memory, suspend devices, wait +for 5 seconds, resume devices, unfreeze tasks and enable nonboot CPUs. Then, +we are able to look in the log messages and work out, for example, which code +is being slow and which device drivers are misbehaving. + Reading from this file will display what the mode is currently set to. Writing to this file will accept one of @@ -37,6 +48,8 @@ to. Writing to this file will accept one of 'platform' 'shutdown' 'reboot' + 'testproc' + 'test' It will only change to 'firmware' or 'platform' if the system supports it. diff --git a/include/linux/pm.h b/include/linux/pm.h index 6b27e07..070394e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -116,7 +116,9 @@ typedef int __bitwise suspend_disk_method_t; #define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2) #define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3) #define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4) -#define PM_DISK_MAX ((__force suspend_disk_method_t) 5) +#define PM_DISK_TEST ((__force suspend_disk_method_t) 5) +#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6) +#define PM_DISK_MAX ((__force suspend_disk_method_t) 7) struct pm_ops { suspend_disk_method_t pm_disk_mode; diff --git a/kernel/power/disk.c b/kernel/power/disk.c index d3a158a..b1fb786 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -71,7 +71,7 @@ static inline void platform_finish(void) static int prepare_processes(void) { - int error; + int error = 0; pm_prepare_console(); @@ -84,6 +84,12 @@ static int prepare_processes(void) goto thaw; } + if (pm_disk_mode == PM_DISK_TESTPROC) { + printk("swsusp debug: Waiting for 5 seconds.\n"); + mdelay(5000); + goto thaw; + } + /* Free memory before shutting down devices. */ if (!(error = swsusp_shrink_memory())) return 0; @@ -120,13 +126,21 @@ int pm_suspend_disk(void) if (error) return error; + if (pm_disk_mode == PM_DISK_TESTPROC) + goto Thaw; + suspend_console(); error = device_suspend(PMSG_FREEZE); if (error) { resume_console(); printk("Some devices failed to suspend\n"); - unprepare_processes(); - return error; + goto Thaw; + } + + if (pm_disk_mode == PM_DISK_TEST) { + printk("swsusp debug: Waiting for 5 seconds.\n"); + mdelay(5000); + goto Done; } pr_debug("PM: snapshotting memory.\n"); @@ -143,16 +157,17 @@ int pm_suspend_disk(void) power_down(pm_disk_mode); else { swsusp_free(); - unprepare_processes(); - return error; + goto Thaw; } - } else + } else { pr_debug("PM: Image restored successfully.\n"); + } swsusp_free(); Done: device_resume(); resume_console(); + Thaw: unprepare_processes(); return error; } @@ -249,6 +264,8 @@ static const char * const pm_disk_modes[] = { [PM_DISK_PLATFORM] = "platform", [PM_DISK_SHUTDOWN] = "shutdown", [PM_DISK_REBOOT] = "reboot", + [PM_DISK_TEST] = "test", + [PM_DISK_TESTPROC] = "testproc", }; /** @@ -303,17 +320,19 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) } } if (mode) { - if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT) + if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT || + mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) { pm_disk_mode = mode; - else { + } else { if (pm_ops && pm_ops->enter && (mode == pm_ops->pm_disk_mode)) pm_disk_mode = mode; else error = -EINVAL; } - } else + } else { error = -EINVAL; + } pr_debug("PM: suspend-to-disk mode set to '%s'\n", pm_disk_modes[mode]); -- cgit v0.10.2 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 diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 146298a..c3c0626 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 v0.10.2 From d2c89a4284ea4ecfba77c6f2d7d6f96d52e801e5 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 2 Nov 2006 22:07:20 -0800 Subject: [PATCH] reiserfs: reset errval after initializing bitmap cache Callers after reiserfs_init_bitmap_cache() expect errval to contain -EINVAL until much later. If a condition fails before errval is reset later, reiserfs_fill_super() will mistakenly return 0, causing an Oops in do_add_mount(). This patch resets errval to -EINVAL after the call. I view this as a temporary fix and real error codes should be used throughout reiserfs_fill_super(). Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 9041802..1724999 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1619,6 +1619,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) "jmacd-8: reiserfs_fill_super: unable to read bitmap"); goto error; } + errval = -EINVAL; #ifdef CONFIG_REISERFS_CHECK SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON"); SWARN(silent, s, "- it is slow mode for debugging."); -- cgit v0.10.2 From 53b173327d283b9bdbfb0c3b6de6f0eb197819d6 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 2 Nov 2006 22:07:22 -0800 Subject: [PATCH] uml: fix I/O hang Fix a UML hang in which everything would just stop until some I/O happened - a ping, someone whacking the keyboard - at which point everything would start up again as though nothing had happened. The cause was gcc reordering some code which absolutely needed to be executed in the order in the source. When unblock_signals switches signals from off to on, it needs to see if any interrupts had happened in the critical section. The interrupt handlers check signals_enabled - if it is zero, then the handler adds a bit to the "pending" bitmask and returns. unblock_signals checks this mask to see if any signals need to be delivered. The crucial part is this: signals_enabled = 1; save_pending = pending; if(save_pending == 0) return; pending = 0; In order to avoid an interrupt arriving between reading pending and setting it to zero, in which case, the record of the interrupt would be erased, signals are enabled. What happened was that gcc reordered this so that 'save_pending = pending' came before 'signals_enabled = 1', creating a one-instruction window within which an interrupt could arrive, set its bit in pending, and have it be immediately erased. When the I/O workload is purely disk-based, the loss of a block device interrupt stops the entire I/O system because the next block request will wait for the current one to finish. Thus the system hangs until something else causes some I/O to arrive, such as a network packet or console input. The fix to this particular problem is a memory barrier between enabling signals and reading the pending signal mask. An xchg would also probably work. Looking over this code for similar problems led me to do a few more things: - make signals_enabled and pending volatile so that they don't get cached in registers - add an mb() to the return paths of block_signals and unblock_signals so that the modification of signals_enabled doesn't get shuffled into the caller in the event that these are inlined in the future. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/sysdep-i386/barrier.h b/arch/um/include/sysdep-i386/barrier.h new file mode 100644 index 0000000..b58d52c --- /dev/null +++ b/arch/um/include/sysdep-i386/barrier.h @@ -0,0 +1,9 @@ +#ifndef __SYSDEP_I386_BARRIER_H +#define __SYSDEP_I386_BARRIER_H + +/* Copied from include/asm-i386 for use by userspace. i386 has the option + * of using mfence, but I'm just using this, which works everywhere, for now. + */ +#define mb() asm volatile("lock; addl $0,0(%esp)") + +#endif diff --git a/arch/um/include/sysdep-x86_64/barrier.h b/arch/um/include/sysdep-x86_64/barrier.h new file mode 100644 index 0000000..7b610be --- /dev/null +++ b/arch/um/include/sysdep-x86_64/barrier.h @@ -0,0 +1,7 @@ +#ifndef __SYSDEP_X86_64_BARRIER_H +#define __SYSDEP_X86_64_BARRIER_H + +/* Copied from include/asm-x86_64 for use by userspace. */ +#define mb() asm volatile("mfence":::"memory") + +#endif diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 6b81739..b897e85 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -15,6 +15,7 @@ #include "user.h" #include "signal_kern.h" #include "sysdep/sigcontext.h" +#include "sysdep/barrier.h" #include "sigcontext.h" #include "mode.h" #include "os.h" @@ -34,8 +35,12 @@ #define SIGALRM_BIT 2 #define SIGALRM_MASK (1 << SIGALRM_BIT) -static int signals_enabled = 1; -static int pending = 0; +/* These are used by both the signal handlers and + * block/unblock_signals. I don't want modifications cached in a + * register - they must go straight to memory. + */ +static volatile int signals_enabled = 1; +static volatile int pending = 0; void sig_handler(int sig, struct sigcontext *sc) { @@ -152,6 +157,12 @@ int change_sig(int signal, int on) void block_signals(void) { signals_enabled = 0; + /* This must return with signals disabled, so this barrier + * ensures that writes are flushed out before the return. + * This might matter if gcc figures out how to inline this and + * decides to shuffle this code into the caller. + */ + mb(); } void unblock_signals(void) @@ -171,9 +182,23 @@ void unblock_signals(void) */ signals_enabled = 1; + /* Setting signals_enabled and reading pending must + * happen in this order. + */ + mb(); + save_pending = pending; - if(save_pending == 0) + if(save_pending == 0){ + /* This must return with signals enabled, so + * this barrier ensures that writes are + * flushed out before the return. This might + * matter if gcc figures out how to inline + * this (unlikely, given its size) and decides + * to shuffle this code into the caller. + */ + mb(); return; + } pending = 0; -- cgit v0.10.2 From 1f6f61649d8c64d7a3a4d143405df9a7bdd4af10 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 2 Nov 2006 22:07:23 -0800 Subject: [PATCH] uml: include tidying In order to get the __NR_* constants, we need sys/syscall.h. linux/unistd.h works as well since it includes syscall.h, however syscall.h is more parsimonious. We were inconsistent in this, and this patch adds syscall.h includes where necessary and removes linux/unistd.h includes where they are not needed. asm/unistd.h also includes the __NR_* constants, but these are not the glibc-sanctioned ones, so this also removes one such inclusion. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 51f0893..c692a19 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index cb9ab54..9b34fe6 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "user.h" #include "sysdep/ptrace.h" diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index 9f7999f..16215b9 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c @@ -1,7 +1,7 @@ #include +#include #include #include -#include #include #include "sysdep/tls.h" #include "uml-config.h" -- cgit v0.10.2 From 3fd593979802f81ff6452596ac61e3840f917589 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 2 Nov 2006 22:07:24 -0800 Subject: [PATCH] Create compat_sys_migrate_pages This is needed on bigendian 64bit architectures. Signed-off-by: Stephen Rothwell Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/compat.h b/include/linux/compat.h index f155319..80b17f4 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -230,5 +230,9 @@ asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); extern int compat_printk(const char *fmt, ...); extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); +asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, + compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, + const compat_ulong_t __user *new_nodes); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/kernel/compat.c b/kernel/compat.c index d4898aa..6952dd0 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -982,4 +982,37 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, } return sys_move_pages(pid, nr_pages, pages, nodes, status, flags); } + +asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, + compat_ulong_t maxnode, + const compat_ulong_t __user *old_nodes, + const compat_ulong_t __user *new_nodes) +{ + unsigned long __user *old = NULL; + unsigned long __user *new = NULL; + nodemask_t tmp_mask; + unsigned long nr_bits; + unsigned long size; + + nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES); + size = ALIGN(nr_bits, BITS_PER_LONG) / 8; + if (old_nodes) { + if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits)) + return -EFAULT; + old = compat_alloc_user_space(new_nodes ? size * 2 : size); + if (new_nodes) + new = old + size / sizeof(unsigned long); + if (copy_to_user(old, nodes_addr(tmp_mask), size)) + return -EFAULT; + } + if (new_nodes) { + if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits)) + return -EFAULT; + if (new == NULL) + new = compat_alloc_user_space(size); + if (copy_to_user(new, nodes_addr(tmp_mask), size)) + return -EFAULT; + } + return sys_migrate_pages(pid, nr_bits + 1, old, new); +} #endif diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 0e53314..d7306d0 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -135,6 +135,7 @@ cond_syscall(sys_madvise); cond_syscall(sys_mremap); cond_syscall(sys_remap_file_pages); cond_syscall(compat_sys_move_pages); +cond_syscall(compat_sys_migrate_pages); /* block-layer dependent */ cond_syscall(sys_bdflush); -- cgit v0.10.2 From 43530d2b04b63ac4bb4ac25deee5f1180ccedc2e Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 2 Nov 2006 22:07:24 -0800 Subject: [PATCH] powerpc: wire up sys_migrate_pages Signed-off-by: Stephen Rothwell Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h index eac85ce..c6a0318 100644 --- a/include/asm-powerpc/systbl.h +++ b/include/asm-powerpc/systbl.h @@ -261,7 +261,7 @@ SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) PPC_SYS_SPU(rtas) OLDSYS(debug_setcontext) SYSCALL(ni_syscall) -SYSCALL(ni_syscall) +COMPAT_SYS(migrate_pages) COMPAT_SYS(mbind) COMPAT_SYS(get_mempolicy) COMPAT_SYS(set_mempolicy) diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 464a48c..b5fe932 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -276,7 +276,7 @@ #define __NR_rtas 255 #define __NR_sys_debug_setcontext 256 /* Number 257 is reserved for vserver */ -/* 258 currently unused */ +#define __NR_migrate_pages 258 #define __NR_mbind 259 #define __NR_get_mempolicy 260 #define __NR_set_mempolicy 261 -- cgit v0.10.2 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 diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 1fadf01..1875877 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 v0.10.2 From 8804023061b3447fbaddbd286d78170ad88d1a43 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 2 Nov 2006 22:07:26 -0800 Subject: [PATCH] fix Documentation/accounting/getdelays.c buf size getdelays reports a "fatal reply error, errno 258". We don't have enough room for multi-threaded exit (PID + TGID). Signed-off-by: Oleg Nesterov Cc: Balbir Singh Cc: Shailabh Nagar Cc: Jay Lan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c index b11792a..bf2b0e2 100644 --- a/Documentation/accounting/getdelays.c +++ b/Documentation/accounting/getdelays.c @@ -49,7 +49,7 @@ __u64 stime, utime; } /* Maximum size of response requested or message sent */ -#define MAX_MSG_SIZE 256 +#define MAX_MSG_SIZE 1024 /* Maximum number of cpus expected to be specified in a cpumask */ #define MAX_CPUS 32 /* Maximum length of pathname to log file */ -- cgit v0.10.2 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 diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 2b0ea8b..753fe0e 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 v0.10.2 From 8ce08464d2c749610a52c4d6c7c11080a7eaaef1 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 2 Nov 2006 22:07:28 -0800 Subject: [PATCH] Fix sys_move_pages when a NULL node list is passed sys_move_pages() uses vmalloc() to allocate an array of structures that is fills with information passed from user mode and then passes to do_stat_pages() (in the case the node list is NULL). do_stat_pages() depends on a marker in the node field of the structure to decide how large the array is and this marker is correctly inserted into the last element of the array. However, vmalloc() doesn't zero the memory it allocates and if the user passes NULL for the node list, then the node fields are not filled in (except for the end marker). If the memory the vmalloc() returned happend to have a word with the marker value in it in just the right place, do_pages_stat will fail to fill the status field of part of the array and we will return (random) kernel data to user mode. Signed-off-by: Stephen Rothwell Cc: Christoph Lameter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/migrate.c b/mm/migrate.c index ba2453f..b4979d4 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -952,7 +952,8 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, goto out; pm[i].node = node; - } + } else + pm[i].node = 0; /* anything to not match MAX_NUMNODES */ } /* End marker */ pm[nr_pages].node = MAX_NUMNODES; -- cgit v0.10.2 From f1f2d8713d16a1e198880bbc716eb24fae09c858 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 2 Nov 2006 22:07:29 -0800 Subject: [PATCH] Fix user.* xattr permission check for sticky dirs The user.* extended attributes are only allowed on regular files and directories. Sticky directories further restrict write access to the owner and privileged users. (See the attr(5) man page for an explanation.) The original check in ext2/ext3 when user.* xattrs were merged was more restrictive than intended, and when the xattr permission checks were moved into the VFS, read access to user.* attributes on sticky directores ended up being denied in addition. Originally-from: Gerard Neil Signed-off-by: Andreas Gruenbacher Cc: Dave Kleikamp Cc: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/xattr.c b/fs/xattr.c index 3956351..0901bdc 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -48,14 +48,21 @@ xattr_permission(struct inode *inode, const char *name, int mask) return 0; /* - * The trusted.* namespace can only accessed by a privilegued user. + * The trusted.* namespace can only be accessed by a privileged user. */ if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); + /* In user.* namespace, only regular files and directories can have + * extended attributes. For sticky directories, only the owner and + * privileged user can write attributes. + */ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { - if (!S_ISREG(inode->i_mode) && - (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) + return -EPERM; + if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && + (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) && + !capable(CAP_FOWNER)) return -EPERM; } -- cgit v0.10.2 From ddac0d39cf437d02fde9795ae57d9c4b4c146de9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Nov 2006 12:49:32 +0100 Subject: [PATCH] splice: fix problem introduced with inode diet After the inode slimming patch that unionised i_pipe/i_bdev/i_cdev, it's no longer enough to check for existance of ->i_pipe to verify that this is a pipe. Original patch from Eric Dumazet Final solution suggested by Linus. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/fs/splice.c b/fs/splice.c index 8d70595..da74583 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1109,6 +1109,19 @@ out_release: EXPORT_SYMBOL(do_splice_direct); /* + * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same + * location, so checking ->i_pipe is not enough to verify that this is a + * pipe. + */ +static inline struct pipe_inode_info *pipe_info(struct inode *inode) +{ + if (S_ISFIFO(inode->i_mode)) + return inode->i_pipe; + + return NULL; +} + +/* * Determine where to splice to/from. */ static long do_splice(struct file *in, loff_t __user *off_in, @@ -1119,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, loff_t offset, *off; long ret; - pipe = in->f_dentry->d_inode->i_pipe; + pipe = pipe_info(in->f_dentry->d_inode); if (pipe) { if (off_in) return -ESPIPE; @@ -1140,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, return ret; } - pipe = out->f_dentry->d_inode->i_pipe; + pipe = pipe_info(out->f_dentry->d_inode); if (pipe) { if (off_out) return -ESPIPE; @@ -1298,7 +1311,7 @@ static int get_iovec_page_array(const struct iovec __user *iov, static long do_vmsplice(struct file *file, const struct iovec __user *iov, unsigned long nr_segs, unsigned int flags) { - struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe; + struct pipe_inode_info *pipe; struct page *pages[PIPE_BUFFERS]; struct partial_page partial[PIPE_BUFFERS]; struct splice_pipe_desc spd = { @@ -1308,7 +1321,8 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov, .ops = &user_page_pipe_buf_ops, }; - if (unlikely(!pipe)) + pipe = pipe_info(file->f_dentry->d_inode); + if (!pipe) return -EBADF; if (unlikely(nr_segs > UIO_MAXIOV)) return -EINVAL; @@ -1535,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, static long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) { - struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe; - struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe; + struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode); + struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode); int ret = -EINVAL; /* -- cgit v0.10.2 From 80491eb90c750fcd7d13830062f27ae9b7cc5f75 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 4 Nov 2006 09:55:00 -0800 Subject: Revert unintentional "volatile" changes in ipc/msg.c Commit 5a06a363ef48444186f18095ae1b932dddbbfa89 ("[PATCH] ipc/msg.c: clean up coding style") breaks fakeroot on Alpha (variously hangs or oopses), according to a report by Falk Hueffner. The fact that the code seems to rely on compiler access ordering through the use of "volatile" is a pretty certain sign that the code has locking problems, and we should fix those properly and then remove the whole "volatile" entirely. But in the meantime, the movement of "volatile" was unintentional, and should be reverted. Cc: Falk Hueffner Cc: Andrew Morton Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds diff --git a/ipc/msg.c b/ipc/msg.c index 600e06f..1266b1d 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -52,7 +52,7 @@ struct msg_receiver { long r_msgtype; long r_maxsize; - volatile struct msg_msg *r_msg; + struct msg_msg *volatile r_msg; }; /* one msg_sender for each sleeping sender */ -- cgit v0.10.2 From 45c18b0bb579b5c1b89f8c99f1b6ffa4c586ba08 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 4 Nov 2006 10:06:02 -0800 Subject: Fix unlikely (but possible) race condition on task->user access There's a possible race condition when doing a "switch_uid()" from one user to another, which could race with another thread doing a signal allocation and looking at the old thread ->user pointer as it is freed. This explains an oops reported by Lukasz Trabinski: http://permalink.gmane.org/gmane.linux.kernel/462241 We fix this by delaying the (reference-counted) freeing of the user structure until the thread signal handler lock has been released, so that we know that the signal allocation has either seen the new value or has properly incremented the reference count of the old one. Race identified by Oleg Nesterov. Cc: Lukasz Trabinski Cc: Oleg Nesterov Cc: Andrew Morton Cc: Ingo Molnar Signed-off-by: Linus Torvalds diff --git a/kernel/user.c b/kernel/user.c index 6408c04..220e586 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -187,6 +187,17 @@ void switch_uid(struct user_struct *new_user) atomic_dec(&old_user->processes); switch_uid_keyring(new_user); current->user = new_user; + + /* + * We need to synchronize with __sigqueue_alloc() + * doing a get_uid(p->user).. If that saw the old + * user value, we need to wait until it has exited + * its critical region before we can free the old + * structure. + */ + smp_mb(); + spin_unlock_wait(¤t->sighand->siglock); + free_uid(old_user); suid_keys(current); } -- cgit v0.10.2 From 10b1fbdb0a0ca91847a534ad26d0bc250c25b74f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 4 Nov 2006 13:03:00 -0800 Subject: Make sure "user->sigpending" count is in sync The previous commit (45c18b0bb579b5c1b89f8c99f1b6ffa4c586ba08, aka "Fix unlikely (but possible) race condition on task->user access") fixed a potential oops due to __sigqueue_alloc() getting its "user" pointer out of sync with switch_user(), and accessing a user pointer that had been de-allocated on another CPU. It still left another (much less serious) problem, where a concurrent __sigqueue_alloc and swich_user could cause sigqueue_alloc to do signal pending reference counting for a _different_ user than the one it then actually ended up using. No oops, but we'd end up with the wrong signal accounting. Another case of Oleg's eagle-eyes picking up the problem. This is trivially fixed by just making sure we load whichever "user" structure we decide to use (it doesn't matter _which_ one we pick, we just need to pick one) just once. Acked-by: Oleg Nesterov Cc: Andrew Morton Cc: Ingo Molnar Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index 7ed8d53..df18c16 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -267,18 +267,25 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, int override_rlimit) { struct sigqueue *q = NULL; + struct user_struct *user; - atomic_inc(&t->user->sigpending); + /* + * In order to avoid problems with "switch_user()", we want to make + * sure that the compiler doesn't re-load "t->user" + */ + user = t->user; + barrier(); + atomic_inc(&user->sigpending); if (override_rlimit || - atomic_read(&t->user->sigpending) <= + atomic_read(&user->sigpending) <= t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) q = kmem_cache_alloc(sigqueue_cachep, flags); if (unlikely(q == NULL)) { - atomic_dec(&t->user->sigpending); + atomic_dec(&user->sigpending); } else { INIT_LIST_HEAD(&q->list); q->flags = 0; - q->user = get_uid(t->user); + q->user = get_uid(user); } return(q); } -- cgit v0.10.2 From e52b29c2a637f6854d71a45646d7283d984a6dad Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Sat, 4 Nov 2006 22:09:08 -0500 Subject: Input: drivers/char/keyboard.c - small cleanup in k_cur() To save a char pointer in the final assembly change to alternate string form. Signed-off-by: Brandon Philips Signed-off-by: Dmitry Torokhov diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 20b6c8b..7a6c1c0 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -710,7 +710,7 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) { - static const char *cur_chars = "BDCA"; + static const char cur_chars[] = "BDCA"; if (up_flag) return; -- cgit v0.10.2 From 41ad5fbabda0c3930136bb40cfc7a0c23013365f Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sat, 4 Nov 2006 22:49:53 -0500 Subject: Input: HID - add a quirk for the Logitech USB Receiver Logitech USB Receiver (046d:c101) has two interfaces. The first one contains fields from HID_UP_KEYBOARD and HID_UP_LED, and the other one contains fields from HID_UP_CONSUMER and HID_UP_LOGIVENDOR. This device is used with multiple wireless Logitech products, including UltraX Media Remote. All fields on both interfaces are either keys or leds. All fields in the first interface are marked as Absolute, while the fields in the second interface are marked as Relative. Marking the keys as relative causes hidinput_hid_event() to send release events right after key press events. The device has EV_REP set, so the userspace expects the device to send repeat events if a key is held down. However, as hidinput_hid_event() sends release events immediately, repeat events are not sent at all. In fact, the userspace has no way of knowing if a key is being held down. Fix this by adding a quirk for 046d:c101 which changes relative keys to absolute ones. Signed-off-by: Anssi Hannula Signed-off-by: Dmitry Torokhov diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6daf85c..6095d9c 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1643,6 +1643,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_AIRCABLE 0x16CA #define USB_DEVICE_ID_AIRCABLE1 0x1502 +#define USB_VENDOR_ID_LOGITECH 0x046d +#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1811,7 +1814,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - + + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, + { 0, 0 } }; diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 9a808a3..c8ce65c 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -564,6 +564,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) goto ignore; + if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && + usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) + field->flags &= ~HID_MAIN_ITEM_RELATIVE; + set_bit(usage->type, input->evbit); while (usage->code <= max && test_and_set_bit(usage->code, bit)) diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 9b50eff..8aa9ec0 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_BAD_RELATIVE_KEYS 0x00008000 /* * This is the global environment of the parser. This information is -- cgit v0.10.2 From 4833ed094097323f5f219820f6ebdc8dd66f501f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:27:06 -0800 Subject: [IPX]: Trivial parts of endianness annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/include/linux/ipx.h b/include/linux/ipx.h index 4f29c60..eb19b4e 100644 --- a/include/linux/ipx.h +++ b/include/linux/ipx.h @@ -7,8 +7,8 @@ struct sockaddr_ipx { sa_family_t sipx_family; - __u16 sipx_port; - __u32 sipx_network; + __be16 sipx_port; + __be32 sipx_network; unsigned char sipx_node[IPX_NODE_LEN]; __u8 sipx_type; unsigned char sipx_zero; /* 16 byte fill */ @@ -23,13 +23,13 @@ struct sockaddr_ipx { #define IPX_CRTITF 1 struct ipx_route_definition { - __u32 ipx_network; - __u32 ipx_router_network; + __be32 ipx_network; + __be32 ipx_router_network; unsigned char ipx_router_node[IPX_NODE_LEN]; }; struct ipx_interface_definition { - __u32 ipx_network; + __be32 ipx_network; unsigned char ipx_device[16]; unsigned char ipx_dlink_type; #define IPX_FRAME_NONE 0 @@ -55,8 +55,8 @@ struct ipx_config_data { */ struct ipx_route_def { - __u32 ipx_network; - __u32 ipx_router_network; + __be32 ipx_network; + __be32 ipx_router_network; #define IPX_ROUTE_NO_ROUTER 0 unsigned char ipx_router_node[IPX_NODE_LEN]; unsigned char ipx_device[16]; diff --git a/include/net/ipx.h b/include/net/ipx.h index 5c0cf33..4a423d2 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -15,9 +15,9 @@ #include struct ipx_address { - __u32 net; + __be32 net; __u8 node[IPX_NODE_LEN]; - __u16 sock; + __be16 sock; }; #define ipx_broadcast_node "\377\377\377\377\377\377" @@ -28,7 +28,7 @@ struct ipx_address { struct ipxhdr { __u16 ipx_checksum __attribute__ ((packed)); #define IPX_NO_CHECKSUM 0xFFFF - __u16 ipx_pktsize __attribute__ ((packed)); + __be16 ipx_pktsize __attribute__ ((packed)); __u8 ipx_tctrl; __u8 ipx_type; #define IPX_TYPE_UNKNOWN 0x00 @@ -48,14 +48,14 @@ static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb) struct ipx_interface { /* IPX address */ - __u32 if_netnum; + __be32 if_netnum; unsigned char if_node[IPX_NODE_LEN]; atomic_t refcnt; /* physical device info */ struct net_device *if_dev; struct datalink_proto *if_dlink; - unsigned short if_dlink_type; + __be16 if_dlink_type; /* socket support */ unsigned short if_sknum; @@ -71,7 +71,7 @@ struct ipx_interface { }; struct ipx_route { - __u32 ir_net; + __be32 ir_net; struct ipx_interface *ir_intrfc; unsigned char ir_routed; unsigned char ir_router_node[IPX_NODE_LEN]; @@ -82,10 +82,10 @@ struct ipx_route { #ifdef __KERNEL__ struct ipx_cb { u8 ipx_tctrl; - u32 ipx_dest_net; - u32 ipx_source_net; + __be32 ipx_dest_net; + __be32 ipx_source_net; struct { - u32 netnum; + __be32 netnum; int index; } last_hop; }; @@ -97,7 +97,7 @@ struct ipx_sock { struct sock sk; struct ipx_address dest_addr; struct ipx_interface *intrfc; - unsigned short port; + __be16 port; #ifdef CONFIG_IPX_INTERN unsigned char node[IPX_NODE_LEN]; #endif @@ -132,7 +132,7 @@ extern struct ipx_interface *ipx_primary_net; extern int ipx_proc_init(void); extern void ipx_proc_exit(void); -extern const char *ipx_frame_name(unsigned short); +extern const char *ipx_frame_name(__be16); extern const char *ipx_device_name(struct ipx_interface *intrfc); static __inline__ void ipxitf_hold(struct ipx_interface *intrfc) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index bef3f61..c272a38a 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -83,13 +83,13 @@ DEFINE_SPINLOCK(ipx_interfaces_lock); struct ipx_interface *ipx_primary_net; struct ipx_interface *ipx_internal_net; -extern int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc, +extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, unsigned char *node); extern void ipxrtr_del_routes(struct ipx_interface *intrfc); extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len, int noblock); extern int ipxrtr_route_skb(struct sk_buff *skb); -extern struct ipx_route *ipxrtr_lookup(__u32 net); +extern struct ipx_route *ipxrtr_lookup(__be32 net); extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg); #undef IPX_REFCNT_DEBUG @@ -177,7 +177,7 @@ static void ipxitf_clear_primary_net(void) } static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, - unsigned short datalink) + __be16 datalink) { struct ipx_interface *i; @@ -190,7 +190,7 @@ out: } static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev, - unsigned short datalink) + __be16 datalink) { struct ipx_interface *i; @@ -202,7 +202,7 @@ static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev, return i; } -struct ipx_interface *ipxitf_find_using_net(__u32 net) +struct ipx_interface *ipxitf_find_using_net(__be32 net) { struct ipx_interface *i; @@ -237,7 +237,7 @@ static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk) /* caller must hold intrfc->if_sklist_lock */ static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc, - unsigned short port) + __be16 port) { struct sock *s; struct hlist_node *node; @@ -252,7 +252,7 @@ found: /* caller must hold a reference to intrfc */ static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc, - unsigned short port) + __be16 port) { struct sock *s; @@ -268,7 +268,7 @@ static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc, #ifdef CONFIG_IPX_INTERN static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, unsigned char *ipx_node, - unsigned short port) + __be16 port) { struct sock *s; struct hlist_node *node; @@ -600,10 +600,10 @@ int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node) /* see if we need to include the netnum in the route list */ if (IPX_SKB_CB(skb)->last_hop.index >= 0) { - u32 *last_hop = (u32 *)(((u8 *) skb->data) + + __be32 *last_hop = (__be32 *)(((u8 *) skb->data) + sizeof(struct ipxhdr) + IPX_SKB_CB(skb)->last_hop.index * - sizeof(u32)); + sizeof(__be32)); *last_hop = IPX_SKB_CB(skb)->last_hop.netnum; IPX_SKB_CB(skb)->last_hop.index = -1; } @@ -772,7 +772,7 @@ static void ipxitf_discover_netnum(struct ipx_interface *intrfc, } else { printk(KERN_WARNING "IPX: Network number collision " "%lx\n %s %s and %s %s\n", - (unsigned long) htonl(cb->ipx_source_net), + (unsigned long) ntohl(cb->ipx_source_net), ipx_device_name(i), ipx_frame_name(i->if_dlink_type), ipx_device_name(intrfc), @@ -812,7 +812,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) int i, rc = -EINVAL; struct ipx_interface *ifcs; char *c; - u32 *l; + __be32 *l; /* Illegal packet - too many hops or too short */ /* We decide to throw it away: no broadcasting, no local processing. @@ -833,7 +833,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) goto out; c = ((u8 *) ipx) + sizeof(struct ipxhdr); - l = (u32 *) c; + l = (__be32 *) c; /* Don't broadcast packet if already seen this net */ for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) @@ -855,7 +855,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) /* That aren't in the list */ if (ifcs == intrfc) continue; - l = (__u32 *) c; + l = (__be32 *) c; /* don't consider the last entry in the packet list, * it is our netnum, and it is not there yet */ for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) @@ -885,8 +885,8 @@ static void ipxitf_insert(struct ipx_interface *intrfc) ipx_primary_net = intrfc; } -static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum, - unsigned short dlink_type, +static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum, + __be16 dlink_type, struct datalink_proto *dlink, unsigned char internal, int ipx_offset) @@ -960,7 +960,7 @@ static __be16 ipx_map_frame_type(unsigned char type) static int ipxitf_create(struct ipx_interface_definition *idef) { struct net_device *dev; - unsigned short dlink_type = 0; + __be16 dlink_type = 0; struct datalink_proto *datalink = NULL; struct ipx_interface *intrfc; int rc; @@ -1073,7 +1073,7 @@ out: static int ipxitf_delete(struct ipx_interface_definition *idef) { struct net_device *dev = NULL; - unsigned short dlink_type = 0; + __be16 dlink_type = 0; struct ipx_interface *intrfc; int rc = 0; @@ -1110,7 +1110,7 @@ out: } static struct ipx_interface *ipxitf_auto_create(struct net_device *dev, - unsigned short dlink_type) + __be16 dlink_type) { struct ipx_interface *intrfc = NULL; struct datalink_proto *datalink; @@ -1122,7 +1122,7 @@ static struct ipx_interface *ipxitf_auto_create(struct net_device *dev, if (dev->addr_len > IPX_NODE_LEN) goto out; - switch (htons(dlink_type)) { + switch (ntohs(dlink_type)) { case ETH_P_IPX: datalink = pEII_datalink; break; case ETH_P_802_2: datalink = p8022_datalink; break; case ETH_P_SNAP: datalink = pSNAP_datalink; break; @@ -1266,7 +1266,7 @@ __u16 ipx_cksum(struct ipxhdr *packet, int length) return ~sum; } -const char *ipx_frame_name(unsigned short frame) +const char *ipx_frame_name(__be16 frame) { char* rc = "None"; @@ -1401,7 +1401,7 @@ out: /* caller must hold a reference to intrfc */ -static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc) +static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) { unsigned short socketNum = intrfc->if_sknum; @@ -1410,7 +1410,7 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc) if (socketNum < IPX_MIN_EPHEMERAL_SOCKET) socketNum = IPX_MIN_EPHEMERAL_SOCKET; - while (__ipxitf_find_socket(intrfc, ntohs(socketNum))) + while (__ipxitf_find_socket(intrfc, htons(socketNum))) if (socketNum > IPX_MAX_EPHEMERAL_SOCKET) socketNum = IPX_MIN_EPHEMERAL_SOCKET; else @@ -1419,7 +1419,7 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc) spin_unlock_bh(&intrfc->if_sklist_lock); intrfc->if_sknum = socketNum; - return ntohs(socketNum); + return htons(socketNum); } static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) @@ -1473,7 +1473,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ipxs->port)) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", - ntohs((int)addr->sipx_port)); + ntohs(addr->sipx_port)); goto out_put; } } else { @@ -1488,7 +1488,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (ipxitf_find_socket(intrfc, addr->sipx_port)) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", - ntohs((int)addr->sipx_port)); + ntohs(addr->sipx_port)); goto out_put; } } @@ -1665,7 +1665,7 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty intrfc = ipxitf_find_using_phys(dev, pt->type); if (!intrfc) { if (ipxcfg_auto_create_interfaces && - ntohl(IPX_SKB_CB(skb)->ipx_dest_net)) { + IPX_SKB_CB(skb)->ipx_dest_net) { intrfc = ipxitf_auto_create(dev, pt->type); if (intrfc) ipxitf_hold(intrfc); diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index 4c0c712..b7463df 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c @@ -260,22 +260,22 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v) ipxs = ipx_sk(s); #ifdef CONFIG_IPX_INTERN seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", - (unsigned long)htonl(ipxs->intrfc->if_netnum), + (unsigned long)ntohl(ipxs->intrfc->if_netnum), ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], - ipxs->node[4], ipxs->node[5], htons(ipxs->port)); + ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); #else - seq_printf(seq, "%08lX:%04X ", (unsigned long) htonl(ipxs->intrfc->if_netnum), - htons(ipxs->port)); + seq_printf(seq, "%08lX:%04X ", (unsigned long) ntohl(ipxs->intrfc->if_netnum), + ntohs(ipxs->port)); #endif /* CONFIG_IPX_INTERN */ if (s->sk_state != TCP_ESTABLISHED) seq_printf(seq, "%-28s", "Not_Connected"); else { seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", - (unsigned long)htonl(ipxs->dest_addr.net), + (unsigned long)ntohl(ipxs->dest_addr.net), ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], - htons(ipxs->dest_addr.sock)); + ntohs(ipxs->dest_addr.sock)); } seq_printf(seq, "%08X %08X %02X %03d\n", diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index a30dbb1..8bfaefa 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c @@ -20,16 +20,16 @@ DEFINE_RWLOCK(ipx_routes_lock); extern struct ipx_interface *ipx_internal_net; extern __u16 ipx_cksum(struct ipxhdr *packet, int length); -extern struct ipx_interface *ipxitf_find_using_net(__u32 net); +extern struct ipx_interface *ipxitf_find_using_net(__be32 net); extern int ipxitf_demux_socket(struct ipx_interface *intrfc, struct sk_buff *skb, int copy); extern int ipxitf_demux_socket(struct ipx_interface *intrfc, struct sk_buff *skb, int copy); extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node); -extern struct ipx_interface *ipxitf_find_using_net(__u32 net); +extern struct ipx_interface *ipxitf_find_using_net(__be32 net); -struct ipx_route *ipxrtr_lookup(__u32 net) +struct ipx_route *ipxrtr_lookup(__be32 net) { struct ipx_route *r; @@ -48,7 +48,7 @@ unlock: /* * Caller must hold a reference to intrfc */ -int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc, +int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, unsigned char *node) { struct ipx_route *rt; @@ -118,7 +118,7 @@ out: return rc; } -static int ipxrtr_delete(__u32 net) +static int ipxrtr_delete(__be32 net) { struct ipx_route *r, *tmp; int rc; -- cgit v0.10.2 From 02e60370d4dac83f22d5ae75d5512bcb9a3f24b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:28:23 -0800 Subject: [IPX]: Annotate and fix IPX checksum Calculation of IPX checksum got buggered about 2.4.0. The old variant mangled the packet; that got fixed, but calculation itself got buggered. Restored the correct logics, fixed a subtle breakage we used to have even back then: if the sum is 0 mod 0xffff, we want to return 0, not 0xffff. The latter has special meaning for IPX (cheksum disabled). Observation (and obvious fix) nicked from history of FreeBSD ipx_cksum.c... Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/include/net/ipx.h b/include/net/ipx.h index 4a423d2..c6b2ee6 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -26,8 +26,8 @@ struct ipx_address { #define IPX_MAX_PPROP_HOPS 8 struct ipxhdr { - __u16 ipx_checksum __attribute__ ((packed)); -#define IPX_NO_CHECKSUM 0xFFFF + __be16 ipx_checksum __attribute__ ((packed)); +#define IPX_NO_CHECKSUM __constant_htons(0xFFFF) __be16 ipx_pktsize __attribute__ ((packed)); __u8 ipx_tctrl; __u8 ipx_type; diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index c272a38a..76c6615 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1234,27 +1234,27 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */ /* This functions should *not* mess with packet contents */ -__u16 ipx_cksum(struct ipxhdr *packet, int length) +__be16 ipx_cksum(struct ipxhdr *packet, int length) { /* * NOTE: sum is a net byte order quantity, which optimizes the * loop. This only works on big and little endian machines. (I * don't know of a machine that isn't.) */ - /* start at ipx_dest - We skip the checksum field and start with - * ipx_type before the loop, not considering ipx_tctrl in the calc */ - __u16 *p = (__u16 *)&packet->ipx_dest; - __u32 i = (length >> 1) - 1; /* Number of complete words */ - __u32 sum = packet->ipx_type << sizeof(packet->ipx_tctrl); - - /* Loop through all complete words except the checksum field, - * ipx_type (accounted above) and ipx_tctrl (not used in the cksum) */ - while (--i) + /* handle the first 3 words separately; checksum should be skipped + * and ipx_tctrl masked out */ + __u16 *p = (__u16 *)packet; + __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff)); + __u32 i = (length >> 1) - 3; /* Number of remaining complete words */ + + /* Loop through them */ + p += 3; + while (i--) sum += *p++; /* Add on the last part word if it exists */ if (packet->ipx_pktsize & htons(1)) - sum += ntohs(0xff00) & *p; + sum += (__force u16)htons(0xff00) & *p; /* Do final fixup */ sum = (sum & 0xffff) + (sum >> 16); @@ -1263,7 +1263,14 @@ __u16 ipx_cksum(struct ipxhdr *packet, int length) if (sum >= 0x10000) sum++; - return ~sum; + /* + * Leave 0 alone; we don't want 0xffff here. Note that we can't get + * here with 0x10000, so this check is the same as ((__u16)sum) + */ + if (sum) + sum = ~sum; + + return (__force __be16)sum; } const char *ipx_frame_name(__be16 frame) diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index 8bfaefa..68560ee 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c @@ -19,7 +19,7 @@ DEFINE_RWLOCK(ipx_routes_lock); extern struct ipx_interface *ipx_internal_net; -extern __u16 ipx_cksum(struct ipxhdr *packet, int length); +extern __be16 ipx_cksum(struct ipxhdr *packet, int length); extern struct ipx_interface *ipxitf_find_using_net(__be32 net); extern int ipxitf_demux_socket(struct ipx_interface *intrfc, struct sk_buff *skb, int copy); @@ -238,7 +238,7 @@ int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, /* Apply checksum. Not allowed on 802.3 links. */ if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023)) - ipx->ipx_checksum = 0xFFFF; + ipx->ipx_checksum = htons(0xFFFF); else ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr)); -- cgit v0.10.2 From 95026cd242bd4188a036f2eba20994113ed5a5d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:55:35 -0800 Subject: [IPV6]: Fix ECN bug on big-endian __constant_htons(2<<4) is not a replacement for htonl(2<<20). Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index d599c6b..7849844 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -48,7 +48,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) #define IP6_ECN_flow_xmit(sk, label) do { \ if (INET_ECN_is_capable(inet_sk(sk)->tos)) \ - (label) |= __constant_htons(INET_ECN_ECT_0 << 4); \ + (label) |= htonl(INET_ECN_ECT_0 << 20); \ } while (0) static inline int IP_ECN_set_ce(struct iphdr *iph) -- cgit v0.10.2 From 7ac00a24f379f8ab9d3c968fea3dc030a45956fd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:58:17 -0800 Subject: [NETFILTER] bug: NFULA_CFG_QTHRESH uses 32bit Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b59d3b2..fca946c 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -896,8 +896,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } if (nfula[NFULA_CFG_QTHRESH-1]) { - u_int32_t qthresh = - *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]); + __be32 qthresh = + *(__be32 *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]); nfulnl_set_qthresh(inst, ntohl(qthresh)); } -- cgit v0.10.2 From d1208b999dd367b72168cc3c7f8d8d2c95143c67 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:58:41 -0800 Subject: [NETFILTER] bug: nfulnl_msg_config_mode ->copy_range is 32bit Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index fca946c..00580a8 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -878,7 +878,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, params = NFA_DATA(nfula[NFULA_CFG_MODE-1]); nfulnl_set_mode(inst, params->copy_mode, - ntohs(params->copy_range)); + ntohl(params->copy_range)); } if (nfula[NFULA_CFG_TIMEOUT-1]) { -- cgit v0.10.2 From febf0a431e42f5a1fdb2b763273700610552ddcc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 00:59:17 -0800 Subject: [NETFILTER] bug: skb->protocol is already net-endian htons() is not needed (and no, it's not misspelled ntohs() - userland expects net-endian here). Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 00580a8..b2bf8f2 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -427,7 +427,7 @@ __build_packet_message(struct nfulnl_instance *inst, nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(inst->group_num); - pmsg.hw_protocol = htons(skb->protocol); + pmsg.hw_protocol = skb->protocol; pmsg.hook = hooknum; NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 8eb2473..6e4ada3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -414,7 +414,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, nfmsg->res_id = htons(queue->queue_num); pmsg.packet_id = htonl(entry->id); - pmsg.hw_protocol = htons(entskb->protocol); + pmsg.hw_protocol = entskb->protocol; pmsg.hook = entinf->hook; NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg); -- cgit v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8e39849..8f059b7 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 v0.10.2 From 0f37c6057414fb68024793966b1dcb6a135cb844 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 3 Nov 2006 03:49:56 -0800 Subject: [PKTGEN]: TCI endianness fixes open-coded variant there works only for little-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/net/core/pktgen.c b/net/core/pktgen.c index dd023fd..733d86d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2304,6 +2304,12 @@ static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) *mpls |= MPLS_STACK_BOTTOM; } +static inline __be16 build_tci(unsigned int id, unsigned int cfi, + unsigned int prio) +{ + return htons(id | (cfi << 12) | (prio << 13)); +} + static struct sk_buff *fill_packet_ipv4(struct net_device *odev, struct pktgen_dev *pkt_dev) { @@ -2353,16 +2359,16 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, if (pkt_dev->vlan_id != 0xffff) { if(pkt_dev->svlan_id != 0xffff) { svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16)); - *svlan_tci = htons(pkt_dev->svlan_id); - *svlan_tci |= pkt_dev->svlan_p << 5; - *svlan_tci |= pkt_dev->svlan_cfi << 4; + *svlan_tci = build_tci(pkt_dev->svlan_id, + pkt_dev->svlan_cfi, + pkt_dev->svlan_p); svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16)); *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q); } vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16)); - *vlan_tci = htons(pkt_dev->vlan_id); - *vlan_tci |= pkt_dev->vlan_p << 5; - *vlan_tci |= pkt_dev->vlan_cfi << 4; + *vlan_tci = build_tci(pkt_dev->vlan_id, + pkt_dev->vlan_cfi, + pkt_dev->vlan_p); vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16)); *vlan_encapsulated_proto = __constant_htons(ETH_P_IP); } @@ -2689,16 +2695,16 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, if (pkt_dev->vlan_id != 0xffff) { if(pkt_dev->svlan_id != 0xffff) { svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16)); - *svlan_tci = htons(pkt_dev->svlan_id); - *svlan_tci |= pkt_dev->svlan_p << 5; - *svlan_tci |= pkt_dev->svlan_cfi << 4; + *svlan_tci = build_tci(pkt_dev->svlan_id, + pkt_dev->svlan_cfi, + pkt_dev->svlan_p); svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16)); *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q); } vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16)); - *vlan_tci = htons(pkt_dev->vlan_id); - *vlan_tci |= pkt_dev->vlan_p << 5; - *vlan_tci |= pkt_dev->vlan_cfi << 4; + *vlan_tci = build_tci(pkt_dev->vlan_id, + pkt_dev->vlan_cfi, + pkt_dev->vlan_p); vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16)); *vlan_encapsulated_proto = __constant_htons(ETH_P_IPV6); } -- cgit v0.10.2 From db38c179a759a9c4722525e8c9f09ac80e372377 Mon Sep 17 00:00:00 2001 From: Larry Woodman Date: Fri, 3 Nov 2006 16:05:45 -0800 Subject: [NET]: __alloc_pages() failures reported due to fragmentation We have seen a couple of __alloc_pages() failures due to fragmentation, there is plenty of free memory but no large order pages available. I think the problem is in sock_alloc_send_pskb(), the gfp_mask includes __GFP_REPEAT but its never used/passed to the page allocator. Shouldnt the gfp_mask be passed to alloc_skb() ? Signed-off-by: Larry Woodman Signed-off-by: David S. Miller diff --git a/net/core/sock.c b/net/core/sock.c index d472db4..ee6cd25 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1160,7 +1160,7 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk, goto failure; if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { - skb = alloc_skb(header_len, sk->sk_allocation); + skb = alloc_skb(header_len, gfp_mask); if (skb) { int npages; int i; -- cgit v0.10.2 From 36f73d0c3b7efa72cd8b89f2d429ff39bc12f15c Mon Sep 17 00:00:00 2001 From: Dmitry Mishin Date: Fri, 3 Nov 2006 16:08:19 -0800 Subject: [IPV6]: Add ndisc_netdev_notifier unregister. If inet6_init() fails later than ndisc_init() call, or IPv6 module is unloaded, ndisc_netdev_notifier call remains in the list and will follows in oops later. Signed-off-by: Dmitry Mishin Signed-off-by: David S. Miller diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 41a8a5f..73eb8c3 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1742,6 +1742,7 @@ int __init ndisc_init(struct net_proto_family *ops) void ndisc_cleanup(void) { + unregister_netdevice_notifier(&ndisc_netdev_notifier); #ifdef CONFIG_SYSCTL neigh_sysctl_unregister(&nd_tbl.parms); #endif -- cgit v0.10.2 From daccff024ffeb21caa2cc479ccc33b2ec50705b1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 5 Nov 2006 15:47:04 -0800 Subject: [IPV6]: Give sit driver an appropriate module alias. It would be nice to keep things working even with this built as a module, it took me some time to realize my IPv6 tunnel was broken because of the missing sit module. This module alias fixes things until distributions have added an appropriate alias to modprobe.conf. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b481a4d..be699f8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -854,3 +854,4 @@ int __init sit_init(void) module_init(sit_init); module_exit(sit_cleanup); MODULE_LICENSE("GPL"); +MODULE_ALIAS("sit0"); -- cgit v0.10.2 From 38c94377a36f70e86665231c9f477e445c806618 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sun, 5 Nov 2006 16:44:06 -0800 Subject: [NETLABEL]: Fix build failure. > the build with the attached .config failed, make ends with: > ... > : undefined reference to `cipso_v4_sock_getattr' > net/built-in.o: In function `netlbl_socket_getattr': ... It looks like I was stupid and made NetLabel depend on CONFIG_NET and not CONFIG_INET, the patch below should fix this by making NetLabel depend on CONFIG_INET and CONFIG_SECURITY. Please review and apply for 2.6.19. Signed-off-by: Paul Moore Signed-off-by: David S. Miller diff --git a/net/Kconfig b/net/Kconfig index a81aca4..67e39ad 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -63,6 +63,7 @@ config INET if INET source "net/ipv4/Kconfig" source "net/ipv6/Kconfig" +source "net/netlabel/Kconfig" endif # if INET @@ -249,8 +250,6 @@ source "net/ieee80211/Kconfig" config WIRELESS_EXT bool -source "net/netlabel/Kconfig" - config FIB_RULES bool diff --git a/net/netlabel/Kconfig b/net/netlabel/Kconfig index 9f7121a..56958c8 100644 --- a/net/netlabel/Kconfig +++ b/net/netlabel/Kconfig @@ -4,7 +4,7 @@ config NETLABEL bool "NetLabel subsystem support" - depends on NET && SECURITY + depends on SECURITY default n ---help--- NetLabel provides support for explicit network packet labeling -- cgit v0.10.2 From 59359ff87700f5e742c96a55da9cf0819984c128 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 5 Nov 2006 16:51:03 -0800 Subject: [SPARC]: Fix robust futex syscalls and wire up migrate_pages. When I added the entries for the robust futex syscall entries, I forgot to bump NR_SYSCALLS. The current situation is error-prone because NR_SYSCALLS lives in entry.S where the system call limit checks are enforced. Move the definition to asm/unistd.h in order to make this mistake much more difficult to make. And wire up sys_migrate_pages since the powerpc folks implemented the compat wrapper for us. Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index a4edff4..831f540 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -32,13 +32,12 @@ #include #include #include +#include #include #define curptr g6 -#define NR_SYSCALLS 300 /* Each OS is different... */ - /* These are just handy. */ #define _SV save %sp, -STACKFRAME_SZ, %sp #define _RS restore diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 10df38e..ea75ca5 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -78,7 +78,7 @@ sys_call_table: /*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 /*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare -/*300*/ .long sys_set_robust_list, sys_get_robust_list +/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -190,6 +190,7 @@ sunos_sys_table: /*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys +/*300*/ .long sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 0aaa35f..6f28bec 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -22,11 +22,10 @@ #include #include #include +#include #define curptr g6 -#define NR_SYSCALLS 300 /* Each OS is different... */ - .text .align 32 diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 419a63f..9a80267 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -79,7 +79,7 @@ sys_call_table32: .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 /*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare -/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list +/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages #endif /* CONFIG_COMPAT */ @@ -149,7 +149,7 @@ sys_call_table: .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 /*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare -/*300*/ .word sys_set_robust_list, sys_get_robust_list +/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -262,5 +262,7 @@ sunos_sys_table: /*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*300*/ .word sunos_nosys, sunos_nosys, sunos_nosys + #endif diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index c7a495a..f7827fa 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -318,12 +318,15 @@ #define __NR_unshare 299 #define __NR_set_robust_list 300 #define __NR_get_robust_list 301 +#define __NR_migrate_pages 302 + +#define NR_SYSCALLS 303 #ifdef __KERNEL__ -/* WARNING: You MAY NOT add syscall numbers larger than 301, since +/* WARNING: You MAY NOT add syscall numbers larger than 302, since * all of the syscall tables in the Sparc kernel are - * sized to have 301 entries (starting at zero). Therefore - * find a free slot in the 0-301 range. + * sized to have 302 entries (starting at zero). Therefore + * find a free slot in the 0-302 range. */ #define _syscall0(type,name) \ diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 124cf07..63669da 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -320,12 +320,16 @@ #define __NR_unshare 299 #define __NR_set_robust_list 300 #define __NR_get_robust_list 301 +#define __NR_migrate_pages 302 + +#define NR_SYSCALLS 303 #ifdef __KERNEL__ -/* WARNING: You MAY NOT add syscall numbers larger than 301, since + +/* WARNING: You MAY NOT add syscall numbers larger than 302, since * all of the syscall tables in the Sparc kernel are - * sized to have 301 entries (starting at zero). Therefore - * find a free slot in the 0-301 range. + * sized to have 302 entries (starting at zero). Therefore + * find a free slot in the 0-302 range. */ #define _syscall0(type,name) \ -- cgit v0.10.2 From 2b03b60e6b8635fffdd15d5d24943950f2bbf96e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 5 Nov 2006 22:39:56 -0500 Subject: Input: keyboards - handle errors when registering input devices Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index 8abdbd0..16583d7 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -190,7 +190,7 @@ static int __init amikbd_init(void) int i, j; if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) - return -EIO; + return -ENODEV; if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) return -EBUSY; @@ -198,8 +198,8 @@ static int __init amikbd_init(void) amikbd_dev = input_allocate_device(); if (!amikbd_dev) { printk(KERN_ERR "amikbd: not enough memory for input device\n"); - release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); - return -ENOMEM; + err = -ENOMEM; + goto fail1; } amikbd_dev->name = "Amiga Keyboard"; @@ -231,10 +231,22 @@ static int __init amikbd_init(void) memcpy(key_maps[i], temp_map, sizeof(temp_map)); } ciaa.cra &= ~0x41; /* serial data in, turn off TA */ - request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt); + if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", + amikbd_interrupt)) { + err = -EBUSY; + goto fail2; + } + + err = input_register_device(amikbd_dev); + if (err) + goto fail3; - input_register_device(amikbd_dev); return 0; + + fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); + fail2: input_free_device(amikbd_dev); + fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); + return err; } static void __exit amikbd_exit(void) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index cbb9366..73c6946 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -939,7 +939,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); dev = input_allocate_device(); if (!atkbd || !dev) - goto fail; + goto fail1; atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); @@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; if (atkbd->write) { if (atkbd_probe(atkbd)) { - serio_close(serio); err = -ENODEV; - goto fail; + goto fail3; } atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); @@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); + err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); + if (err) + goto fail3; atkbd_enable(atkbd); - input_register_device(atkbd->dev); + err = input_register_device(atkbd->dev); + if (err) + goto fail4; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(dev); + fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(dev); kfree(atkbd); return err; } @@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_extra, old_set; if (!atkbd->write) return -EIO; @@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun if (atkbd->extra != value) { /* * Since device's properties will change we need to - * unregister old device. But allocate new one first - * to make sure we have it. + * unregister old device. But allocate and register + * new one first to make sure we have it. */ - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_extra = atkbd->extra; + old_set = atkbd->set; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); atkbd_activate(atkbd); + atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->set = atkbd_select_set(atkbd, old_set, old_extra); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); + } return count; } @@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_scroll; value = simple_strtoul(buf, &rest, 10); if (*rest || value > 1) return -EINVAL; if (atkbd->scroll != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_scroll = atkbd->scroll; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->scroll = value; atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->scroll = old_scroll; + atkbd->dev = old_dev; + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_set, old_extra; if (!atkbd->write) return -EIO; @@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) return -EINVAL; if (atkbd->set != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_extra = atkbd->extra; + old_set = atkbd->set; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); atkbd_activate(atkbd); atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->set = atkbd_select_set(atkbd, old_set, old_extra); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_softrepeat, old_softraw; if (!atkbd->write) return -EIO; @@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t return -EINVAL; if (atkbd->softrepeat != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_softrepeat = atkbd->softrepeat; + old_softraw = atkbd->softraw; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->softrepeat = value; if (atkbd->softrepeat) atkbd->softraw = 1; atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->softrepeat = old_softrepeat; + atkbd->softraw = old_softraw; + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_softraw; value = simple_strtoul(buf, &rest, 10); if (*rest || value > 1) return -EINVAL; if (atkbd->softraw != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_softraw = atkbd->softraw; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->softraw = value; atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->softraw = old_softraw; + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index befdd60..1016c94 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev) { struct corgikbd *corgikbd; struct input_dev *input_dev; - int i; + int i, err = -ENOMEM; corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); input_dev = input_allocate_device(); - if (!corgikbd || !input_dev) { - kfree(corgikbd); - input_free_device(input_dev); - return -ENOMEM; - } + if (!corgikbd || !input_dev) + goto fail; platform_set_drvdata(pdev, corgikbd); @@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) set_bit(SW_TABLET_MODE, input_dev->swbit); set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - input_register_device(corgikbd->input); + err = input_register_device(corgikbd->input); + if (err) + goto fail; mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); @@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev) pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); return 0; + + fail: input_free_device(input_dev); + kfree(corgikbd); + return err; } static int corgikbd_remove(struct platform_device *pdev) diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 708d5a1..0067c1f 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -651,7 +651,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device (); if (!lk || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } lk->serio = serio; @@ -696,15 +696,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) err = serio_open (serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device (lk->dev); + if (err) + goto fail3; - input_register_device (lk->dev); lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); return 0; - fail: serio_set_drvdata (serio, NULL); - input_free_device (input_dev); + fail3: serio_close (serio); + fail2: serio_set_drvdata (serio, NULL); + fail1: input_free_device (input_dev); kfree (lk); return err; } diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 5788dbc..2ade518 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; struct input_dev *input_dev; - int i, ret; + int i, err; locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!locomokbd || !input_dev) { - ret = -ENOMEM; - goto free; + err = -ENOMEM; + goto err_free_mem; } /* try and claim memory region */ if (!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) { - ret = -EBUSY; + err = -EBUSY; printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); - goto free; + goto err_free_mem; } locomokbd->ldev = dev; @@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev) clear_bit(0, input_dev->keybit); /* attempt to get the interrupt */ - ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); - if (ret) { + err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); + if (err) { printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n"); - goto out; + goto err_release_region; } - input_register_device(locomokbd->input); + err = input_register_device(locomokbd->input); + if (err) + goto err_free_irq; return 0; -out: + err_free_irq: + free_irq(dev->irq[0], locomokbd); + err_release_region: release_mem_region((unsigned long) dev->mapbase, dev->length); locomo_set_drvdata(dev, NULL); -free: + err_free_mem: input_free_device(input_dev); kfree(locomokbd); - return ret; + return err; } static int locomokbd_remove(struct locomo_dev *dev) diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index cc6aaf9..99836b3 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c @@ -94,13 +94,13 @@ static int dc_kbd_connect(struct maple_device *dev) struct input_dev *input_dev; unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); int i; + int err; dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!kbd || !input_dev) { - kfree(kbd); - input_free_device(input_dev); - return -ENOMEM; + err = -ENOMEM; + goto fail; } kbd->dev = input_dev; @@ -113,10 +113,16 @@ static int dc_kbd_connect(struct maple_device *dev) set_bit(dc_kbd_keycode[i], input_dev->keybit); clear_bit(0, input_dev->keybit); - input_register_device(kbd->dev); + err = input_register_device(kbd->dev); + if (err) + goto fail; maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD); return 0; + + fail: input_free_device(input_dev); + kfree(kbd); + return err; } diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 9282e4e..33e8139 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!nkbd || !input_dev) - goto fail; + goto fail1; nkbd->serio = serio; nkbd->dev = input_dev; @@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(nkbd->dev); + if (err) + goto fail3; - input_register_device(nkbd->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(nkbd); return err; } diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 28b2748..8a2166c 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev) { struct spitzkbd *spitzkbd; struct input_dev *input_dev; - int i; + int i, err = -ENOMEM; spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); - if (!spitzkbd) - return -ENOMEM; - input_dev = input_allocate_device(); - if (!input_dev) { - kfree(spitzkbd); - return -ENOMEM; - } + if (!spitzkbd || !input_dev) + goto fail; platform_set_drvdata(dev, spitzkbd); strcpy(spitzkbd->phys, "spitzkbd/input0"); @@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) set_bit(SW_TABLET_MODE, input_dev->swbit); set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) + goto fail; mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); @@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev) request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Spitzkbd SWB", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, + request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Spitzkbd HP", spitzkbd); - printk(KERN_INFO "input: Spitz Keyboard Registered\n"); - return 0; + + fail: input_free_device(input_dev); + kfree(spitzkbd); + return err; } static int spitzkbd_remove(struct platform_device *dev) @@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = { .resume = spitzkbd_resume, .driver = { .name = "spitz-keyboard", + .owner = THIS_MODULE, }, }; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index cac4781..d1b62f7 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -243,7 +243,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!sunkbd || !input_dev) - goto fail; + goto fail1; sunkbd->serio = serio; sunkbd->dev = input_dev; @@ -255,11 +255,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; if (sunkbd_initialize(sunkbd) < 0) { - serio_close(serio); - goto fail; + err = -ENODEV; + goto fail3; } snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); @@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) clear_bit(0, input_dev->keybit); sunkbd_enable(sunkbd, 1); - input_register_device(sunkbd->dev); + + err = input_register_device(sunkbd->dev); + if (err) + goto fail4; + return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail4: sunkbd_enable(sunkbd, 0); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(sunkbd); return err; } diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 8c11dc9..b53f716 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!xtkbd || !input_dev) - goto fail; + goto fail1; xtkbd->serio = serio; xtkbd->dev = input_dev; @@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(xtkbd->dev); + if (err) + goto fail3; - input_register_device(xtkbd->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(xtkbd); return err; } -- cgit v0.10.2 From 52c1f5704d7555a16641429b2e7af5d26d7b119a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 5 Nov 2006 22:40:03 -0500 Subject: Input: touchscreens - handle errors when registering input devices Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 66121f6..e294558 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c @@ -175,17 +175,19 @@ static int read_xydata(struct corgi_ts *corgi_ts) static void new_data(struct corgi_ts *corgi_ts) { + struct input_dev *dev = corgi_ts->input; + if (corgi_ts->power_mode != PWR_MODE_ACTIVE) return; if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) return; - input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x); - input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y); - input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0)); - input_sync(corgi_ts->input); + input_report_abs(dev, ABS_X, corgi_ts->tc.x); + input_report_abs(dev, ABS_Y, corgi_ts->tc.y); + input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); + input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); + input_sync(dev); } static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) @@ -219,12 +221,14 @@ 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); } static irqreturn_t ts_interrupt(int irq, void *dev_id) { struct corgi_ts *corgits_data = dev_id; + ts_interrupt_main(corgits_data, 0); return IRQ_HANDLED; } @@ -272,7 +276,7 @@ static int __init corgits_probe(struct platform_device *pdev) corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); input_dev = input_allocate_device(); if (!corgi_ts || !input_dev) - goto fail; + goto fail1; platform_set_drvdata(pdev, corgi_ts); @@ -281,7 +285,7 @@ static int __init corgits_probe(struct platform_device *pdev) if (corgi_ts->irq_gpio < 0) { err = -ENODEV; - goto fail; + goto fail1; } corgi_ts->input = input_dev; @@ -319,10 +323,12 @@ static int __init corgits_probe(struct platform_device *pdev) if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { err = -EBUSY; - goto fail; + goto fail1; } - input_register_device(corgi_ts->input); + err = input_register_device(corgi_ts->input); + if (err) + goto fail2; corgi_ts->power_mode = PWR_MODE_ACTIVE; @@ -331,17 +337,17 @@ static int __init corgits_probe(struct platform_device *pdev) return 0; - fail: input_free_device(input_dev); + fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); + fail1: input_free_device(input_dev); kfree(corgi_ts); return err; - } static int corgits_remove(struct platform_device *pdev) { struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - free_irq(corgi_ts->irq_gpio, NULL); + free_irq(corgi_ts->irq_gpio, corgi_ts); del_timer_sync(&corgi_ts->timer); corgi_ts->machinfo->put_hsync(); input_unregister_device(corgi_ts->input); diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 817c219..44f397f 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -123,7 +123,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device(); if (!gunze || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } gunze->serio = serio; @@ -146,13 +146,17 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(gunze->dev); + if (err) + goto fail3; - input_register_device(gunze->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(gunze); return err; } diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index 58fca31..2490874 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c @@ -76,38 +76,47 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev) static int __init hp680_ts_init(void) { + int err; + hp680_ts_dev = input_allocate_device(); if (!hp680_ts_dev) return -ENOMEM; hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); - hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y); hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN; - hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN; - hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX; - hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX; + input_set_abs_params(hp680_ts_dev, ABS_X, + HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0); + input_set_abs_params(hp680_ts_dev, ABS_Y, + HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0); hp680_ts_dev->name = "HP Jornada touchscreen"; hp680_ts_dev->phys = "hp680_ts/input0"; - input_register_device(hp680_ts_dev); - if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, IRQF_DISABLED, MODNAME, 0) < 0) { printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", HP680_TS_IRQ); - input_unregister_device(hp680_ts_dev); - return -EBUSY; + err = -EBUSY; + goto fail1; } + err = input_register_device(hp680_ts_dev); + if (err) + goto fail2; + return 0; + + fail2: free_irq(HP680_TS_IRQ, NULL); + cancel_delayed_work(&work); + flush_scheduled_work(); + fail1: input_free_device(hp680_ts_dev); + return err; } static void __exit hp680_ts_exit(void) { - free_irq(HP680_TS_IRQ, 0); + free_irq(HP680_TS_IRQ, NULL); cancel_delayed_work(&work); flush_scheduled_work(); input_unregister_device(hp680_ts_dev); diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 4cbcaa6..44140fe 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c @@ -96,15 +96,13 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id) goto end; } - if (~status & MK712_STATUS_TOUCH) - { + if (~status & MK712_STATUS_TOUCH) { debounce = 1; input_report_key(mk712_dev, BTN_TOUCH, 0); goto end; } - if (debounce) - { + if (debounce) { debounce = 0; goto end; } @@ -113,8 +111,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id) input_report_abs(mk712_dev, ABS_X, last_x); input_report_abs(mk712_dev, ABS_Y, last_y); -end: - + end: last_x = inw(mk712_io + MK712_X) & 0x0fff; last_y = inw(mk712_io + MK712_Y) & 0x0fff; input_sync(mk712_dev); @@ -169,13 +166,14 @@ static int __init mk712_init(void) (inw(mk712_io + MK712_STATUS) & 0xf333)) { printk(KERN_WARNING "mk712: device not present\n"); err = -ENODEV; - goto fail; + goto fail1; } - if (!(mk712_dev = input_allocate_device())) { + mk712_dev = input_allocate_device(); + if (!mk712_dev) { printk(KERN_ERR "mk712: not enough memory\n"); err = -ENOMEM; - goto fail; + goto fail1; } mk712_dev->name = "ICS MicroClock MK712 TouchScreen"; @@ -196,13 +194,17 @@ static int __init mk712_init(void) if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) { printk(KERN_WARNING "mk712: unable to get IRQ\n"); err = -EBUSY; - goto fail; + goto fail1; } - input_register_device(mk712_dev); + err = input_register_device(mk712_dev); + if (err) + goto fail2; + return 0; - fail: input_free_device(mk712_dev); + fail2: free_irq(mk712_irq, mk712_dev); + fail1: input_free_device(mk712_dev); release_region(mk712_io, 8); return err; } diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 3b4c616..c66b399 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -137,7 +137,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device(); if (!mtouch || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } mtouch->serio = serio; @@ -160,14 +160,17 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; - input_register_device(mtouch->dev); + err = input_register_device(mtouch->dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(mtouch); return err; } -- cgit v0.10.2 From 127278ce2254c61f1346500374d61e33f74a8729 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 5 Nov 2006 22:40:09 -0500 Subject: Input: joysticks - handle errors when registering input devices Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 704bf70..6279ced 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -521,11 +521,19 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < 2; i++) if (port->adi[i].length > 0) { adi_init_center(port->adi + i); - input_register_device(port->adi[i].dev); + err = input_register_device(port->adi[i].dev); + if (err) + goto fail3; } return 0; + fail3: while (--i >= 0) { + if (port->adi[i].length > 0) { + input_unregister_device(port->adi[i].dev); + port->adi[i].dev = NULL; + } + } fail2: for (i = 0; i < 2; i++) if (port->adi[i].dev) input_free_device(port->adi[i].dev); diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 650acf3..e608691 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -147,7 +147,11 @@ static int __init amijoy_init(void) amijoy_dev[i]->absmax[ABS_X + j] = 1; } - input_register_device(amijoy_dev[i]); + err = input_register_device(amijoy_dev[i]); + if (err) { + input_free_device(amijoy_dev[i]); + goto fail; + } } return 0; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index e9a02db..7ef6845 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -434,6 +434,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i { struct input_dev *input_dev; int i, j, t, v, w, x, y, z; + int error; analog_name(analog); snprintf(analog->phys, sizeof(analog->phys), @@ -505,7 +506,11 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i analog_decode(analog, port->axes, port->initial, port->buttons); - input_register_device(analog->dev); + error = input_register_device(analog->dev); + if (error) { + input_free_device(analog->dev); + return error; + } return 0; } @@ -668,7 +673,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv return 0; fail3: while (--i >= 0) - input_unregister_device(port->analog[i].dev); + if (port->analog[i].mask) + input_unregister_device(port->analog[i].dev); fail2: gameport_close(gameport); fail1: gameport_set_drvdata(gameport, NULL); kfree(port); diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index d5e42eb..034ec39 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -223,12 +223,15 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) for (j = 0; cobra_btn[j]; j++) set_bit(cobra_btn[j], input_dev->keybit); - input_register_device(cobra->dev[i]); + err = input_register_device(cobra->dev[i]); + if (err) + goto fail4; } return 0; - fail3: for (i = 0; i < 2; i++) + fail4: input_free_device(cobra->dev[i]); + fail3: while (--i >= 0) if (cobra->dev[i]) input_unregister_device(cobra->dev[i]); fail2: gameport_close(gameport); diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index e4a699f..bacbab5 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -341,7 +341,9 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; } - input_register_device(gf2k->dev); + err = input_register_device(gf2k->dev); + if (err) + goto fail2; return 0; diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 6243894..8120a9c 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -423,7 +423,10 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags) if (!port->registered) { dbg("New Grip pad in multiport slot %d.\n", slot); - register_slot(slot, grip); + if (register_slot(slot, grip)) { + port->mode = GRIP_MODE_RESET; + port->dirty = 0; + } } return flags; } @@ -585,6 +588,7 @@ static int register_slot(int slot, struct grip_mp *grip) struct grip_port *port = grip->port[slot]; struct input_dev *input_dev; int j, t; + int err; port->dev = input_dev = input_allocate_device(); if (!input_dev) @@ -610,7 +614,12 @@ static int register_slot(int slot, struct grip_mp *grip) if (t > 0) set_bit(t, input_dev->keybit); - input_register_device(port->dev); + err = input_register_device(port->dev); + if (err) { + input_free_device(port->dev); + return err; + } + port->registered = 1; if (port->dirty) /* report initial state, if any */ diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 840ed9b..dbc5d92 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -250,7 +250,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++) set_bit(t, input_dev->keybit); - input_register_device(guillemot->dev); + err = input_register_device(guillemot->dev); + if (err) + goto fail2; return 0; diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 24c684b..706e0ae 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -325,8 +325,8 @@ int iforce_init_device(struct iforce *iforce) if (i == 20) { /* 5 seconds */ printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n"); - input_free_device(input_dev); - return -ENODEV; + error = -ENODEV; + goto fail; } /* @@ -439,10 +439,8 @@ int iforce_init_device(struct iforce *iforce) set_bit(iforce->type->ff[i], input_dev->ffbit); error = input_ff_create(input_dev, ff_effects); - if (error) { - input_free_device(input_dev); - return error; - } + if (error) + goto fail; ff = input_dev->ff; ff->upload = iforce_upload_effect; @@ -455,11 +453,16 @@ int iforce_init_device(struct iforce *iforce) * Register input device. */ - input_register_device(iforce->dev); + error = input_register_device(iforce->dev); + if (error) + goto fail; printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open); return 0; + + fail: input_free_device(input_dev); + return error; } static int __init iforce_init(void) diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index ca08f45..ec4be53 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -141,21 +141,19 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) serio_set_drvdata(serio, iforce); err = serio_open(serio, drv); - if (err) { - serio_set_drvdata(serio, NULL); - kfree(iforce); - return err; - } + if (err) + goto fail1; err = iforce_init_device(iforce); - if (err) { - serio_close(serio); - serio_set_drvdata(serio, NULL); - kfree(iforce); - return -ENODEV; - } + if (err) + goto fail2; return 0; + + fail2: serio_close(serio); + fail1: serio_set_drvdata(serio, NULL); + kfree(iforce); + return err; } static void iforce_serio_disconnect(struct serio *serio) diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index bbfeb9c..fec8b3d 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -283,7 +283,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++) set_bit(t, input_dev->keybit); - input_register_device(interact->dev); + err = input_register_device(interact->dev); + if (err) + goto fail2; return 0; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index e3d1944..d512b0a 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -157,7 +157,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL); input_dev = input_allocate_device(); if (!magellan || !input_dev) - goto fail; + goto fail1; magellan->dev = input_dev; snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys); @@ -183,13 +183,17 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(magellan->dev); + if (err) + goto fail3; - input_register_device(magellan->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(magellan); return err; } diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 2a9808c..9b35973 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -215,7 +215,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceball || !input_dev) - goto fail; + goto fail1; spaceball->dev = input_dev; snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys); @@ -252,13 +252,17 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(spaceball->dev); + if (err) + goto fail3; - input_register_device(spaceball->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(spaceball); return err; } diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index c4db024..ea9d51e 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -172,7 +172,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceorb || !input_dev) - goto fail; + goto fail1; spaceorb->dev = input_dev; snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys); @@ -198,13 +198,17 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(spaceorb->dev); + if (err) + goto fail3; - input_register_device(spaceorb->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(spaceorb); return err; } diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 1ffb032..b51a4a4 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -143,7 +143,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL); input_dev = input_allocate_device(); if (!stinger || !input_dev) - goto fail; + goto fail1; stinger->dev = input_dev; snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys); @@ -168,13 +168,17 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(stinger->dev); + if (err) + goto fail3; - input_register_device(stinger->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(stinger); return err; } diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 49085df..3c1c83e 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -194,7 +194,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL); input_dev = input_allocate_device(); if (!twidjoy || !input_dev) - goto fail; + goto fail1; twidjoy->dev = input_dev; snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys); @@ -221,13 +221,17 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(twidjoy->dev); + if (err) + goto fail3; - input_register_device(twidjoy->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(twidjoy); return err; } diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 35edea1..1e4828b 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -149,7 +149,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL); input_dev = input_allocate_device(); if (!warrior || !input_dev) - goto fail; + goto fail1; warrior->dev = input_dev; snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys); @@ -176,13 +176,17 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(warrior->dev); + if (err) + goto fail3; - input_register_device(warrior->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(warrior); return err; } -- cgit v0.10.2 From 721556150e397f606a3f029736d77a27503f94e2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 5 Nov 2006 22:40:19 -0500 Subject: Input: mice - handle errors when registering input devices Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index 599a7b2..239a0e1 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c @@ -95,10 +95,13 @@ static void amimouse_close(struct input_dev *dev) static int __init amimouse_init(void) { + int err; + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) return -ENODEV; - if (!(amimouse_dev = input_allocate_device())) + amimouse_dev = input_allocate_device(); + if (!amimouse_dev) return -ENOMEM; amimouse_dev->name = "Amiga mouse"; @@ -114,7 +117,11 @@ static int __init amimouse_init(void) amimouse_dev->open = amimouse_open; amimouse_dev->close = amimouse_close; - input_register_device(amimouse_dev); + err = input_register_device(amimouse_dev); + if (err) { + input_free_device(amimouse_dev); + return err; + } return 0; } diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index e1252fa..13dd967 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c @@ -135,6 +135,7 @@ static void inport_close(struct input_dev *dev) static int __init inport_init(void) { unsigned char a, b, c; + int err; if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) { printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE); @@ -145,15 +146,16 @@ static int __init inport_init(void) b = inb(INPORT_SIGNATURE_PORT); c = inb(INPORT_SIGNATURE_PORT); if (a == b || a != c) { - release_region(INPORT_BASE, INPORT_EXTENT); printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); - return -ENODEV; + err = -ENODEV; + goto err_release_region; } - if (!(inport_dev = input_allocate_device())) { + inport_dev = input_allocate_device(); + if (!inport_dev) { printk(KERN_ERR "inport.c: Not enough memory for input device\n"); - release_region(INPORT_BASE, INPORT_EXTENT); - return -ENOMEM; + err = -ENOMEM; + goto err_release_region; } inport_dev->name = INPORT_NAME; @@ -174,9 +176,18 @@ static int __init inport_init(void) outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); outb(INPORT_MODE_BASE, INPORT_DATA_PORT); - input_register_device(inport_dev); + err = input_register_device(inport_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(inport_dev); + err_release_region: + release_region(INPORT_BASE, INPORT_EXTENT); + + return err; } static void __exit inport_exit(void) diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index 8e9c2f3..db20599 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c @@ -124,6 +124,8 @@ static void logibm_close(struct input_dev *dev) static int __init logibm_init(void) { + int err; + if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) { printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE); return -EBUSY; @@ -134,18 +136,19 @@ static int __init logibm_init(void) udelay(100); if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) { - release_region(LOGIBM_BASE, LOGIBM_EXTENT); printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE); - return -ENODEV; + err = -ENODEV; + goto err_release_region; } outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT); outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); - if (!(logibm_dev = input_allocate_device())) { + logibm_dev = input_allocate_device(); + if (!logibm_dev) { printk(KERN_ERR "logibm.c: Not enough memory for input device\n"); - release_region(LOGIBM_BASE, LOGIBM_EXTENT); - return -ENOMEM; + err = -ENOMEM; + goto err_release_region; } logibm_dev->name = "Logitech bus mouse"; @@ -162,9 +165,18 @@ static int __init logibm_init(void) logibm_dev->open = logibm_open; logibm_dev->close = logibm_close; - input_register_device(logibm_dev); + err = input_register_device(logibm_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(logibm_dev); + err_release_region: + release_region(LOGIBM_BASE, LOGIBM_EXTENT); + + return err; } static void __exit logibm_exit(void) diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 8c075aa..f155c1f 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c @@ -108,6 +108,7 @@ static int pc110pad_open(struct input_dev *dev) static int __init pc110pad_init(void) { struct pci_dev *dev; + int err; dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); if (dev) { @@ -124,16 +125,16 @@ static int __init pc110pad_init(void) outb(PC110PAD_OFF, pc110pad_io + 2); if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) { - release_region(pc110pad_io, 4); printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq); - return -EBUSY; + err = -EBUSY; + goto err_release_region; } - if (!(pc110pad_dev = input_allocate_device())) { - free_irq(pc110pad_irq, NULL); - release_region(pc110pad_io, 4); + pc110pad_dev = input_allocate_device(); + if (!pc110pad_dev) { printk(KERN_ERR "pc110pad: Not enough memory.\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_free_irq; } pc110pad_dev->name = "IBM PC110 TouchPad"; @@ -153,9 +154,20 @@ static int __init pc110pad_init(void) pc110pad_dev->open = pc110pad_open; pc110pad_dev->close = pc110pad_close; - input_register_device(pc110pad_dev); + err = input_register_device(pc110pad_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(pc110pad_dev); + err_free_irq: + free_irq(pc110pad_irq, NULL); + err_release_region: + release_region(pc110pad_io, 4); + + return err; } static void __exit pc110pad_exit(void) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 6f9b2c7..9144df6 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1102,7 +1102,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) { struct psmouse *psmouse, *parent = NULL; struct input_dev *input_dev; - int retval = -ENOMEM; + int retval = 0, error = -ENOMEM; mutex_lock(&psmouse_mutex); @@ -1118,7 +1118,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!psmouse || !input_dev) - goto out; + goto err_free; ps2_init(&psmouse->ps2dev, serio); INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); @@ -1129,14 +1129,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) serio_set_drvdata(serio, psmouse); - retval = serio_open(serio, drv); - if (retval) - goto out; + error = serio_open(serio, drv); + if (error) + goto err_clear_drvdata; if (psmouse_probe(psmouse) < 0) { - serio_close(serio); - retval = -ENODEV; - goto out; + error = -ENODEV; + goto err_close_serio; } psmouse->rate = psmouse_rate; @@ -1150,30 +1149,44 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_initialize(psmouse); - input_register_device(psmouse->dev); + error = input_register_device(psmouse->dev); + if (error) + goto err_protocol_disconnect; if (parent && parent->pt_activate) parent->pt_activate(parent); - sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); + error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); + if (error) + goto err_pt_deactivate; psmouse_activate(psmouse); - retval = 0; - -out: - if (retval) { - serio_set_drvdata(serio, NULL); - input_free_device(input_dev); - kfree(psmouse); - } - + out: /* If this is a pass-through port the parent needs to be re-activated */ if (parent) psmouse_activate(parent); mutex_unlock(&psmouse_mutex); return retval; + + err_pt_deactivate: + if (parent && parent->pt_deactivate) + parent->pt_deactivate(parent); + err_protocol_disconnect: + if (psmouse->disconnect) + psmouse->disconnect(psmouse); + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + err_close_serio: + serio_close(serio); + err_clear_drvdata: + serio_set_drvdata(serio, NULL); + err_free: + input_free_device(input_dev); + kfree(psmouse); + + retval = error; + goto out; } @@ -1365,17 +1378,20 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co { struct serio *serio = psmouse->ps2dev.serio; struct psmouse *parent = NULL; - struct input_dev *new_dev; - const struct psmouse_protocol *proto; + struct input_dev *old_dev, *new_dev; + const struct psmouse_protocol *proto, *old_proto; + int error; int retry = 0; - if (!(proto = psmouse_protocol_by_name(buf, count))) + proto = psmouse_protocol_by_name(buf, count); + if (!proto) return -EINVAL; if (psmouse->type == proto->type) return count; - if (!(new_dev = input_allocate_device())) + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; while (serio->child) { @@ -1408,11 +1424,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co parent->pt_deactivate(parent); } + old_dev = psmouse->dev; + old_proto = psmouse_protocol_by_type(psmouse->type); + if (psmouse->disconnect) psmouse->disconnect(psmouse); psmouse_set_state(psmouse, PSMOUSE_IGNORE); - input_unregister_device(psmouse->dev); psmouse->dev = new_dev; psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); @@ -1426,7 +1444,23 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co psmouse_initialize(psmouse); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - input_register_device(psmouse->dev); + error = input_register_device(psmouse->dev); + if (error) { + if (psmouse->disconnect) + psmouse->disconnect(psmouse); + + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + input_free_device(new_dev); + psmouse->dev = old_dev; + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + psmouse_switch_protocol(psmouse, old_proto); + psmouse_initialize(psmouse); + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + + return error; + } + + input_unregister_device(old_dev); if (parent && parent->pt_activate) parent->pt_activate(parent); diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index ea04685..fbdcfd8 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c @@ -66,7 +66,10 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id) static int __init rpcmouse_init(void) { - if (!(rpcmouse_dev = input_allocate_device())) + int err; + + rpcmouse_dev = input_allocate_device(); + if (!rpcmouse_dev) return -ENOMEM; rpcmouse_dev->name = "Acorn RiscPC Mouse"; @@ -85,13 +88,22 @@ static int __init rpcmouse_init(void) if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); - input_free_device(rpcmouse_dev); - return -EBUSY; + err = -EBUSY; + goto err_free_dev; } - input_register_device(rpcmouse_dev); + err = input_register_device(rpcmouse_dev); + if (err) + goto err_free_irq; return 0; + + err_free_irq: + free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); + err_free_dev: + input_free_device(rpcmouse_dev); + + return err; } static void __exit rpcmouse_exit(void) diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 2a272c5..10b51e7 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -246,7 +246,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!sermouse || !input_dev) - goto fail; + goto fail1; sermouse->dev = input_dev; snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys); @@ -275,14 +275,17 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; - input_register_device(sermouse->dev); + err = input_register_device(sermouse->dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(sermouse); return err; } diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index ffdb50e..ffd0d66 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -497,7 +497,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL); input_dev = input_allocate_device (); if (!mouse || !input_dev) - goto fail; + goto fail1; mouse->dev = input_dev; mouse->serio = serio; @@ -527,7 +527,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) err = serio_open (serio, drv); if (err) - goto fail; + goto fail2; /* * Request selftest. Standard packet format and differential @@ -535,12 +535,15 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) */ serio->write (serio, 'T'); /* Test */ - input_register_device (input_dev); + err = input_register_device (input_dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata (serio, NULL); - input_free_device (input_dev); + fail3: serio_close (serio); + fail2: serio_set_drvdata (serio, NULL); + fail1: input_free_device (input_dev); kfree (mouse); return err; } -- cgit v0.10.2 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 diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 3e18623..1615593 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 v0.10.2 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 diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index b40724f..39ad9f7 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 v0.10.2 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 diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 82eb2fb..9f57c2e 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 4538c99..6ad6961 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 0b51a8c..0cfc2bc 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 fa51e3b..919f94b 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 1615593..72ef7bd 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 v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 28c17d1..9cb3ca5 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 v0.10.2 From e9a43850e6a99e335c8120579749389b376bc204 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 30 Oct 2006 09:31:27 +0100 Subject: AVR32: Get rid of board_early_init board_early_init() is left over from some early prototyping work where we had to initialize the SDRAM controller ourselves. This depends on the kernel being loaded into static RAM, which just isn't possible on any commercially available products today. In order to run without a boot loader, we need to create a zImage stub or have the debugger initialize the SDRAM for us (for really low-level debugging) Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 191ab85..272c011 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c @@ -21,15 +21,6 @@ struct tag *bootloader_tags __initdata; struct lcdc_platform_data __initdata atstk1000_fb0_data; -asmlinkage void __init board_early_init(void) -{ - extern void sdram_init(void); - -#ifdef CONFIG_LOADER_STANDALONE - sdram_init(); -#endif -} - void __init board_setup_fbmem(unsigned long fbmem_start, unsigned long fbmem_size) { diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S index 773b7ad..6163bd0 100644 --- a/arch/avr32/kernel/head.S +++ b/arch/avr32/kernel/head.S @@ -30,9 +30,6 @@ kernel_entry: mov r7, 0 #endif - /* Set up the PIO, SDRAM controller, early printk, etc. */ - rcall board_early_init - /* Start the show */ lddpc pc, kernel_start_addr -- cgit v0.10.2 From 168c8fa32ff40d6caf7226a5abf2a0096f3393bf Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 31 Oct 2006 20:01:11 +0100 Subject: AVR32: Fix thinko in generic_find_next_zero_le_bit() The existing implementation of this function seems to be looking for a one although it should be looking for a zero. This causes trouble for the ext2 filesystem, which tends to report -ENOSPC without this patch. Fix this by complementing each word before scanning. Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S index 2b4856f..c6b91de 100644 --- a/arch/avr32/lib/findbit.S +++ b/arch/avr32/lib/findbit.S @@ -136,6 +136,7 @@ ENTRY(generic_find_next_zero_le_bit) /* offset is not word-aligned. Handle the first (32 - r10) bits */ ldswp.w r8, r12[0] sub r12, -4 + com r8 lsr r8, r8, r10 brne .L_found @@ -146,7 +147,7 @@ ENTRY(generic_find_next_zero_le_bit) /* Main loop. offset must be word-aligned */ 1: ldswp.w r8, r12[0] - cp.w r8, 0 + com r8 brne .L_found sub r12, -4 sub r9, 32 -- cgit v0.10.2 From 4b96b1a10cb00c867103b21f0f2a6c91b705db11 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Sun, 5 Nov 2006 23:52:04 -0800 Subject: [PATCH] Fix the spurious unlock_cpu_hotplug false warnings Cpu-hotplug locking has a minor race case caused because of setting the variable "recursive" to NULL *after* releasing the cpu_bitmask_lock in the function unlock_cpu_hotplug,instead of doing so before releasing the cpu_bitmask_lock. This was the cause of most of the recent false spurious lock_cpu_unlock warnings. This should fix the problem reported by Martin Lorenz reported in http://lkml.org/lkml/2006/10/29/127. Thanks to Srinivasa DS for pointing it out. Signed-off-by: Gautham R Shenoy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/cpu.c b/kernel/cpu.c index 663c920..272254f 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -58,8 +58,8 @@ void unlock_cpu_hotplug(void) recursive_depth--; return; } - mutex_unlock(&cpu_bitmask_lock); recursive = NULL; + mutex_unlock(&cpu_bitmask_lock); } EXPORT_SYMBOL_GPL(unlock_cpu_hotplug); -- cgit v0.10.2 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 diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 46a9c35..db9d7df 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 v0.10.2 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 diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index d8d256d..5800bee 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 v0.10.2 From 64efade11cddc4237c1b95ea4ca18af122a7e19e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sun, 5 Nov 2006 23:52:10 -0800 Subject: [PATCH] lockdep: fix delayacct locking bug Make the delayacct lock irqsave; this avoids the possible deadlock where an interrupt is taken while holding the delayacct lock which needs to take the delayacct lock. Signed-off-by: Peter Zijlstra Acked-by: Oleg Nesterov Cc: Balbir Singh Cc: Shailabh Nagar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/delayacct.c b/kernel/delayacct.c index 36752f1..66a0ea4 100644 --- a/kernel/delayacct.c +++ b/kernel/delayacct.c @@ -66,6 +66,7 @@ static void delayacct_end(struct timespec *start, struct timespec *end, { struct timespec ts; s64 ns; + unsigned long flags; do_posix_clock_monotonic_gettime(end); ts = timespec_sub(*end, *start); @@ -73,10 +74,10 @@ static void delayacct_end(struct timespec *start, struct timespec *end, if (ns < 0) return; - spin_lock(¤t->delays->lock); + spin_lock_irqsave(¤t->delays->lock, flags); *total += ns; (*count)++; - spin_unlock(¤t->delays->lock); + spin_unlock_irqrestore(¤t->delays->lock, flags); } void __delayacct_blkio_start(void) @@ -104,6 +105,7 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) s64 tmp; struct timespec ts; unsigned long t1,t2,t3; + unsigned long flags; /* Though tsk->delays accessed later, early exit avoids * unnecessary returning of other data @@ -136,14 +138,14 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */ - spin_lock(&tsk->delays->lock); + spin_lock_irqsave(&tsk->delays->lock, flags); tmp = d->blkio_delay_total + tsk->delays->blkio_delay; d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; tmp = d->swapin_delay_total + tsk->delays->swapin_delay; d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; d->blkio_count += tsk->delays->blkio_count; d->swapin_count += tsk->delays->swapin_count; - spin_unlock(&tsk->delays->lock); + spin_unlock_irqrestore(&tsk->delays->lock, flags); done: return 0; @@ -152,11 +154,12 @@ done: __u64 __delayacct_blkio_ticks(struct task_struct *tsk) { __u64 ret; + unsigned long flags; - spin_lock(&tsk->delays->lock); + spin_lock_irqsave(&tsk->delays->lock, flags); ret = nsec_to_clock_t(tsk->delays->blkio_delay + tsk->delays->swapin_delay); - spin_unlock(&tsk->delays->lock); + spin_unlock_irqrestore(&tsk->delays->lock, flags); return ret; } -- cgit v0.10.2 From 0e009be8a0c2309f3696df70f72ef0075aa34c9c Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 5 Nov 2006 23:52:11 -0800 Subject: [PATCH] Improve the removed sysctl warnings Don't warn about libpthread's access to kernel.version. When it receives -ENOSYS it will read /proc/sys/kernel/version. If anything else shows up print the sysctl number string. Signed-off-by: Eric W. Biederman Cc: Cal Peake Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8bff2c1..0c8e805 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2680,13 +2680,33 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, asmlinkage long sys_sysctl(struct __sysctl_args __user *args) { static int msg_count; + struct __sysctl_args tmp; + int name[CTL_MAXNAME]; + int i; + + /* Read in the sysctl name for better debug message logging */ + if (copy_from_user(&tmp, args, sizeof(tmp))) + return -EFAULT; + if (tmp.nlen <= 0 || tmp.nlen >= CTL_MAXNAME) + return -ENOTDIR; + for (i = 0; i < tmp.nlen; i++) + if (get_user(name[i], tmp.name + i)) + return -EFAULT; + + /* Ignore accesses to kernel.version */ + if ((tmp.nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION)) + goto out; if (msg_count < 5) { msg_count++; printk(KERN_INFO "warning: process `%s' used the removed sysctl " - "system call\n", current->comm); + "system call with ", current->comm); + for (i = 0; i < tmp.nlen; i++) + printk("%d.", name[i]); + printk("\n"); } +out: return -ENOSYS; } -- cgit v0.10.2 From d99f160ac53e51090f015a8f0617cea25f81a191 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 5 Nov 2006 23:52:12 -0800 Subject: [PATCH] sysctl: allow a zero ctl_name in the middle of a sysctl table Since it is becoming clear that there are just enough users of the binary sysctl interface that completely removing the binary interface from the kernel will not be an option for foreseeable future, we need to find a way to address the sysctl maintenance issues. The basic problem is that sysctl requires one central authority to allocate sysctl numbers, or else conflicts and ABI breakage occur. The proc interface to sysctl does not have that problem, as names are not densely allocated. By not terminating a sysctl table until I have neither a ctl_name nor a procname, it becomes simple to add sysctl entries that don't show up in the binary sysctl interface. Which allows people to avoid allocating a binary sysctl value when not needed. I have audited the kernel code and in my reading I have not found a single sysctl table that wasn't terminated by a completely zero filled entry. So this change in behavior should not affect anything. I think this mechanism eases the pain enough that combined with a little disciple we can solve the reoccurring sysctl ABI breakage. Signed-off-by: Eric W. Biederman Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 1b24bd4..c184732 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -961,8 +961,8 @@ extern ctl_handler sysctl_ms_jiffies; /* * Register a set of sysctl names by calling register_sysctl_table * with an initialised array of ctl_table's. An entry with zero - * ctl_name terminates the table. table->de will be set up by the - * registration and need not be initialised in advance. + * ctl_name and NULL procname terminates the table. table->de will be + * set up by the registration and need not be initialised in advance. * * sysctl names can be mirrored automatically under /proc/sys. The * procname supplied controls /proc naming. @@ -973,7 +973,10 @@ extern ctl_handler sysctl_ms_jiffies; * Leaf nodes in the sysctl tree will be represented by a single file * under /proc; non-leaf nodes will be represented by directories. A * null procname disables /proc mirroring at this node. - * + * + * sysctl entries with a zero ctl_name will not be available through + * the binary sysctl interface. + * * sysctl(2) can automatically manage read and write requests through * the sysctl table. The data and maxlen fields of the ctl_table * struct enable minimal validation of the values being written to be diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0c8e805..09e569f4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1315,7 +1315,9 @@ repeat: return -ENOTDIR; if (get_user(n, name)) return -EFAULT; - for ( ; table->ctl_name; table++) { + for ( ; table->ctl_name || table->procname; table++) { + if (!table->ctl_name) + continue; if (n == table->ctl_name || table->ctl_name == CTL_ANY) { int error; if (table->child) { @@ -1532,7 +1534,7 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, int len; mode_t mode; - for (; table->ctl_name; table++) { + for (; table->ctl_name || table->procname; table++) { /* Can't do anything without a proc name. */ if (!table->procname) continue; @@ -1579,7 +1581,7 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root) { struct proc_dir_entry *de; - for (; table->ctl_name; table++) { + for (; table->ctl_name || table->procname; table++) { if (!(de = table->de)) continue; if (de->mode & S_IFDIR) { -- cgit v0.10.2 From 7cc13edc139108bb527b692f0548dce6bc648572 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 5 Nov 2006 23:52:13 -0800 Subject: [PATCH] sysctl: implement CTL_UNNUMBERED This patch takes the CTL_UNNUMBERD concept from NFS and makes it available to all new sysctl users. At the same time the sysctl binary interface maintenance documentation is updated to mention and to describe what is needed to successfully maintain the sysctl binary interface. Signed-off-by: Eric W. Biederman Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 6341392..8ca1808 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -353,9 +353,6 @@ EXPORT_SYMBOL(lockd_down); * Sysctl parameters (same as module parameters, different interface). */ -/* Something that isn't CTL_ANY, CTL_NONE or a value that may clash. */ -#define CTL_UNNUMBERED -2 - static ctl_table nlm_sysctls[] = { { .ctl_name = CTL_UNNUMBERED, diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c index 2fe3403..3ea50ac 100644 --- a/fs/nfs/sysctl.c +++ b/fs/nfs/sysctl.c @@ -18,11 +18,6 @@ static const int nfs_set_port_min = 0; static const int nfs_set_port_max = 65535; static struct ctl_table_header *nfs_callback_sysctl_table; -/* - * Something that isn't CTL_ANY, CTL_NONE or a value that may clash. - * Use the same values as fs/lockd/svc.c - */ -#define CTL_UNNUMBERED -2 static ctl_table nfs_cb_sysctls[] = { #ifdef CONFIG_NFS_V4 diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index c184732..d98562f 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -6,10 +6,17 @@ **************************************************************** **************************************************************** ** + ** WARNING: ** The values in this file are exported to user space via - ** the sysctl() binary interface. However this interface - ** is unstable and deprecated and will be removed in the future. - ** For a stable interface use /proc/sys. + ** the sysctl() binary interface. Do *NOT* change the + ** numbering of any existing values here, and do not change + ** any numbers within any one set of values. If you have to + ** have to redefine an existing interface, use a new number for it. + ** The kernel will then return -ENOTDIR to any application using + ** the old binary interface. + ** + ** For new interfaces unless you really need a binary number + ** please use CTL_UNNUMBERED. ** **************************************************************** **************************************************************** @@ -48,6 +55,7 @@ struct __sysctl_args { #ifdef __KERNEL__ #define CTL_ANY -1 /* Matches any name */ #define CTL_NONE 0 +#define CTL_UNNUMBERED CTL_NONE /* sysctl without a binary number */ #endif enum -- cgit v0.10.2 From 0c7bb31db0e35d4b772fac452b722460ca368acf Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 5 Nov 2006 23:52:13 -0800 Subject: [PATCH] sunrpc: add missing spin_unlock auth_domain_put() forgot to unlock acquired spinlock. Cc: Olaf Kirch Cc: Andy Adamson Cc: J. Bruce Fields Acked-by: Trond Myklebust Signed-off-by: Akinobu Mita Cc: Neil Brown Acked-by: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index 0004c1f..ee9bb15 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -126,6 +126,7 @@ void auth_domain_put(struct auth_domain *dom) if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) { hlist_del(&dom->hash); dom->flavour->domain_release(dom); + spin_unlock(&auth_domain_lock); } } -- cgit v0.10.2 From bcc8bcb1f0cc51c0042497d5de2d79743050e3bb Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 6 Nov 2006 10:49:00 +0100 Subject: [S390] revert add_active_range() usage patch. Commit 7676bef9c183fd573822cac9992927ef596d584c breaks DCSS support on s390. DCSS needs initialized struct pages to work. With the usage of add_active_range() only the struct pages for physically present pages are initialized. This could be fixed if the DCSS driver would initiliaze the struct pages itself, but this doesn't work too. This is because the mem_map array does not include holes after the last present memory area and therefore there is nothing that could be initialized. To fix this and to avoid some dirty hacks revert this patch for now. Will be added later when we move to a virtual mem_map. Cc: Carsten Otte Cc: Adrian Bunk Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 608193c..245b81b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -236,9 +236,6 @@ config WARN_STACK_SIZE This allows you to specify the maximum frame size a function may have without the compiler complaining about it. -config ARCH_POPULATES_NODE_MAP - def_bool y - source "mm/Kconfig" comment "I/O subsystem configuration" diff --git a/arch/s390/defconfig b/arch/s390/defconfig index c313e9a..7cd51e7 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -119,7 +119,6 @@ CONFIG_PACK_STACK=y CONFIG_CHECK_STACK=y CONFIG_STACK_GUARD=256 # CONFIG_WARN_STACK is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 49f2b68..a31abdd 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -70,6 +70,7 @@ struct { #define CHUNK_READ_WRITE 0 #define CHUNK_READ_ONLY 1 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ +unsigned long __initdata zholes_size[MAX_NR_ZONES]; static unsigned long __initdata memory_end; /* @@ -357,6 +358,21 @@ void machine_power_off(void) */ void (*pm_power_off)(void) = machine_power_off; +static void __init +add_memory_hole(unsigned long start, unsigned long end) +{ + unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; + + if (end <= dma_pfn) + zholes_size[ZONE_DMA] += end - start + 1; + else if (start > dma_pfn) + zholes_size[ZONE_NORMAL] += end - start + 1; + else { + zholes_size[ZONE_DMA] += dma_pfn - start + 1; + zholes_size[ZONE_NORMAL] += end - dma_pfn; + } +} + static int __init early_parse_mem(char *p) { memory_end = memparse(p, &p); @@ -478,6 +494,7 @@ setup_memory(void) { unsigned long bootmap_size; unsigned long start_pfn, end_pfn, init_pfn; + unsigned long last_rw_end; int i; /* @@ -533,27 +550,39 @@ setup_memory(void) /* * Register RAM areas with the bootmem allocator. */ + last_rw_end = start_pfn; for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { - unsigned long start_chunk, end_chunk, pfn; + unsigned long start_chunk, end_chunk; if (memory_chunk[i].type != CHUNK_READ_WRITE) continue; - start_chunk = PFN_DOWN(memory_chunk[i].addr); - end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1; - end_chunk = min(end_chunk, end_pfn); - if (start_chunk >= end_chunk) - continue; - add_active_range(0, start_chunk, end_chunk); - pfn = max(start_chunk, start_pfn); - for (; pfn <= end_chunk; pfn++) - page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY); + start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1); + start_chunk >>= PAGE_SHIFT; + end_chunk = (memory_chunk[i].addr + memory_chunk[i].size); + end_chunk >>= PAGE_SHIFT; + if (start_chunk < start_pfn) + start_chunk = start_pfn; + if (end_chunk > end_pfn) + end_chunk = end_pfn; + if (start_chunk < end_chunk) { + /* Initialize storage key for RAM pages */ + for (init_pfn = start_chunk ; init_pfn < end_chunk; + init_pfn++) + page_set_storage_key(init_pfn << PAGE_SHIFT, + PAGE_DEFAULT_KEY); + free_bootmem(start_chunk << PAGE_SHIFT, + (end_chunk - start_chunk) << PAGE_SHIFT); + if (last_rw_end < start_chunk) + add_memory_hole(last_rw_end, start_chunk - 1); + last_rw_end = end_chunk; + } } psw_set_key(PAGE_DEFAULT_KEY); - free_bootmem_with_active_regions(0, max_pfn); - reserve_bootmem(0, PFN_PHYS(start_pfn)); + if (last_rw_end < end_pfn - 1) + add_memory_hole(last_rw_end, end_pfn - 1); /* * Reserve the bootmem bitmap itself as well. We do this in two diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index d998917..e1881c3 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -84,6 +84,7 @@ void show_mem(void) printk("%d pages swap cached\n",cached); } +extern unsigned long __initdata zholes_size[]; /* * paging_init() sets up the page tables */ @@ -100,15 +101,16 @@ void __init paging_init(void) unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; static const int ssm_mask = 0x04000000L; unsigned long ro_start_pfn, ro_end_pfn; - unsigned long max_zone_pfns[MAX_NR_ZONES]; + unsigned long zones_size[MAX_NR_ZONES]; ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); - memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); - max_zone_pfns[ZONE_DMA] = max_low_pfn; - max_zone_pfns[ZONE_NORMAL] = max_low_pfn; - free_area_init_nodes(max_zone_pfns); + memset(zones_size, 0, sizeof(zones_size)); + zones_size[ZONE_DMA] = max_low_pfn; + free_area_init_node(0, &contig_page_data, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, + zholes_size); /* unmap whole virtual address space */ @@ -168,16 +170,26 @@ void __init paging_init(void) unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE; static const int ssm_mask = 0x04000000L; + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long dma_pfn, high_pfn; unsigned long ro_start_pfn, ro_end_pfn; - unsigned long max_zone_pfns[MAX_NR_ZONES]; + memset(zones_size, 0, sizeof(zones_size)); + dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; + high_pfn = max_low_pfn; ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); - memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); - max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); - max_zone_pfns[ZONE_NORMAL] = max_low_pfn; - free_area_init_nodes(max_zone_pfns); + if (dma_pfn > high_pfn) + zones_size[ZONE_DMA] = high_pfn; + else { + zones_size[ZONE_DMA] = dma_pfn; + zones_size[ZONE_NORMAL] = high_pfn - dma_pfn; + } + + /* Initialize mem_map[]. */ + free_area_init_node(0, &contig_page_data, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); /* * map whole physical memory to virtual memory (identity mapping) -- cgit v0.10.2 From c4972f33169e3e1ce06ad00917ddaf2c3b49b36a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 6 Nov 2006 10:49:02 +0100 Subject: [S390] IRQs too early enabled. setup_lowcore() calls ctl_set_bit() which returns withs interrupts enabled. The setup arch code is not supposed to enable interrupts that early. Therefore use the __ctl_set_bit() variant. This fixes the not working lock dependency validator on non 64 bit systems. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index a31abdd..2aa13e8 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -450,7 +450,7 @@ setup_lowcore(void) lc->extended_save_area_addr = (__u32) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); /* enable extended save area */ - ctl_set_bit(14, 29); + __ctl_set_bit(14, 29); } #endif set_prefix((u32)(unsigned long) lc); -- cgit v0.10.2 From bbfd2bf9028a55cb85ff51eb34dc663b7e49ed55 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 6 Nov 2006 14:02:44 +0100 Subject: AVR32: Wire up sys_epoll_pwait Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 7589a9b..890286a 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -100,3 +100,12 @@ __sys_splice: rcall sys_splice sub sp, -4 popm pc + + .global __sys_epoll_pwait + .type __sys_epoll_pwait,@function +__sys_epoll_pwait: + pushm lr + st.w --sp, ARG6 + rcall sys_epoll_pwait + sub sp, -4 + popm pc diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 63b2069..db8f8b5 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -286,4 +286,5 @@ sys_call_table: .long sys_sync_file_range .long sys_tee .long sys_vmsplice + .long __sys_epoll_pwait /* 265 */ .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/include/asm-avr32/unistd.h b/include/asm-avr32/unistd.h index a50e500..56ed1f9 100644 --- a/include/asm-avr32/unistd.h +++ b/include/asm-avr32/unistd.h @@ -280,9 +280,10 @@ #define __NR_sync_file_range 262 #define __NR_tee 263 #define __NR_vmsplice 264 +#define __NR_epoll_pwait 265 #ifdef __KERNEL__ -#define NR_syscalls 265 +#define NR_syscalls 266 #define __ARCH_WANT_IPC_PARSE_VERSION -- cgit v0.10.2 From 6af0f5f83169ef215b4579834ddfb2691e8a7bff Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 6 Nov 2006 14:06:45 +0100 Subject: AVR32: Add missing return instruction in __raw_writesb __raw_writesb ends with a conditional branch, which is obviously wrong. It should return after the last loop terminates. Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/lib/io-readsb.S b/arch/avr32/lib/io-readsb.S index b319d5e..2be5da7 100644 --- a/arch/avr32/lib/io-readsb.S +++ b/arch/avr32/lib/io-readsb.S @@ -45,3 +45,5 @@ __raw_readsb: sub r10, 1 st.b r11++, r8 brne 3b + + retal r12 -- cgit v0.10.2 From eb1dc33aa235b0e44ada6716cda385883c6e6bff Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 28 Oct 2006 03:03:48 +0400 Subject: [GFS2] don't panic needlessly First, SLAB_PANIC is unjustified. Second, all error propagating and backing out is in place. Signed-off-by: Alexey Dobriyan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 21508a1..9889c1e 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -84,8 +84,8 @@ static int __init init_gfs2_fs(void) gfs2_inode_cachep = kmem_cache_create("gfs2_inode", sizeof(struct gfs2_inode), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_PANIC|SLAB_MEM_SPREAD), + 0, SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD, gfs2_init_inode_once, NULL); if (!gfs2_inode_cachep) goto fail; -- cgit v0.10.2 From 4a221953ed121692aa25998451a57c7f4be8b4f6 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 09:57:57 -0500 Subject: [GFS2] Fix incorrect fs sync behaviour. This adds a sync_fs superblock operation for GFS2 and removes the journal flush from write_super in favour of sync_fs where it ought to be. This is more or less identical to the way in which ext3 does this. This bug was pointed out by Russell Cattelan Cc: Russell Cattelan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 06f06f7..b47d959 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -138,16 +138,27 @@ static void gfs2_put_super(struct super_block *sb) } /** - * gfs2_write_super - disk commit all incore transactions - * @sb: the filesystem + * gfs2_write_super + * @sb: the superblock * - * This function is called every time sync(2) is called. - * After this exits, all dirty buffers are synced. */ static void gfs2_write_super(struct super_block *sb) { + sb->s_dirt = 0; +} + +/** + * gfs2_sync_fs - sync the filesystem + * @sb: the superblock + * + * Flushes the log to disk. + */ +static int gfs2_sync_fs(struct super_block *sb, int wait) +{ + sb->s_dirt = 0; gfs2_log_flush(sb->s_fs_info, NULL); + return 0; } /** @@ -452,17 +463,18 @@ static void gfs2_destroy_inode(struct inode *inode) } struct super_operations gfs2_super_ops = { - .alloc_inode = gfs2_alloc_inode, - .destroy_inode = gfs2_destroy_inode, - .write_inode = gfs2_write_inode, - .delete_inode = gfs2_delete_inode, - .put_super = gfs2_put_super, - .write_super = gfs2_write_super, - .write_super_lockfs = gfs2_write_super_lockfs, - .unlockfs = gfs2_unlockfs, - .statfs = gfs2_statfs, - .remount_fs = gfs2_remount_fs, - .clear_inode = gfs2_clear_inode, - .show_options = gfs2_show_options, + .alloc_inode = gfs2_alloc_inode, + .destroy_inode = gfs2_destroy_inode, + .write_inode = gfs2_write_inode, + .delete_inode = gfs2_delete_inode, + .put_super = gfs2_put_super, + .write_super = gfs2_write_super, + .sync_fs = gfs2_sync_fs, + .write_super_lockfs = gfs2_write_super_lockfs, + .unlockfs = gfs2_unlockfs, + .statfs = gfs2_statfs, + .remount_fs = gfs2_remount_fs, + .clear_inode = gfs2_clear_inode, + .show_options = gfs2_show_options, }; -- cgit v0.10.2 From 26d83dedf61d26d85f10bc34b92f4de7660fd746 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 30 Oct 2006 16:59:08 -0500 Subject: [GFS2] Fix OOM error handling Fix the OOM error handling in inode.c where it was possible for a NULL pointer to be dereferenced. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 57c43ac..d470e52 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -157,6 +157,9 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, struct gfs2_glock *io_gl; int error; + if (!inode) + return ERR_PTR(-ENOBUFS); + if (inode->i_state & I_NEW) { struct gfs2_sbd *sdp = GFS2_SB(inode); umode_t mode = DT2IF(type); -- cgit v0.10.2 From ba542e3b92f9ea7c482ae56b68b9122eebc53a39 Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Thu, 2 Nov 2006 14:41:23 +0000 Subject: [DLM] Fix kref_put oops This patch fixes the recounting on the lockspace kobject. Previously the lockspace was freed while userspace could have had a reference to one of its sysfs files, causing an oops in kref_put. Now the lockspace kfree is moved into the kobject release() function Signed-Off-By: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 109333c..499ee11 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -143,6 +143,12 @@ static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr, return a->store ? a->store(ls, buf, len) : len; } +static void lockspace_kobj_release(struct kobject *k) +{ + struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj); + kfree(ls); +} + static struct sysfs_ops dlm_attr_ops = { .show = dlm_attr_show, .store = dlm_attr_store, @@ -151,6 +157,7 @@ static struct sysfs_ops dlm_attr_ops = { static struct kobj_type dlm_ktype = { .default_attrs = dlm_attrs, .sysfs_ops = &dlm_attr_ops, + .release = lockspace_kobj_release, }; static struct kset dlm_kset = { @@ -678,7 +685,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) dlm_clear_members_gone(ls); kfree(ls->ls_node_array); kobject_unregister(&ls->ls_kobj); - kfree(ls); + /* The ls structure will be freed when the kobject is done with */ mutex_lock(&ls_lock); ls_count--; -- cgit v0.10.2 From e2de7f565521a76fbbb927f701c5a1d381c71a93 Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Mon, 6 Nov 2006 08:53:28 +0000 Subject: [DLM] fix oops in kref_put when removing a lockspace Now that the lockspace struct is freed when the last sysfs object is released this patch prevents use of that lockspace by sysfs. We attempt to re-get the lockspace from the lockspace list and fail the request if it has been removed. Signed-Off-By: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 499ee11..f8842ca 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -43,6 +43,10 @@ static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len) ssize_t ret = len; int n = simple_strtol(buf, NULL, 0); + ls = dlm_find_lockspace_local(ls->ls_local_handle); + if (!ls) + return -EINVAL; + switch (n) { case 0: dlm_ls_stop(ls); @@ -53,6 +57,7 @@ static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len) default: ret = -EINVAL; } + dlm_put_lockspace(ls); return ret; } -- cgit v0.10.2 From cca72333e71e348995859b88628c1abcb58b759e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Nov 2006 17:42:47 +0000 Subject: [MIPS] Ocelot C: Fix large number of warnings. Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h index 7228cd1..f0f5581 100644 --- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h +++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h @@ -53,7 +53,9 @@ #define OCELOT_C_REG_INTSET 0xe #define OCELOT_C_REG_INTCLR 0xf -#define OCELOT_FPGA_WRITE(x, y) writeb(x, OCELOT_C_CS0_ADDR + OCELOT_C_REG_##y) -#define OCELOT_FPGA_READ(x) readb(OCELOT_C_CS0_ADDR + OCELOT_C_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif -- cgit v0.10.2 From 9c422e2ad6a1d8bd03e2e9d49e5c63b82165d596 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Nov 2006 17:45:25 +0000 Subject: [MIPS] Ocelot C: fix eth registration after conversion to platform_device Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 9c0c462..0a3ffa3 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,6 @@ #include "ocelot_c_fpga.h" unsigned long marvell_base; -extern unsigned long mv64340_sram_base; unsigned long cpu_clock; /* These functions are used for rebooting or halting the machine*/ @@ -119,7 +119,6 @@ void PMON_v2_setup(void) add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M); marvell_base = 0xfffffffff4000000; - mv64340_sram_base = 0xfffffffffe000000; #else /* marvell and extra space */ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); @@ -129,7 +128,6 @@ void PMON_v2_setup(void) add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); marvell_base = 0xf4000000; - mv64340_sram_base = 0xfe000000; #endif } @@ -365,3 +363,123 @@ static int io_base_ioremap(void) module_init(io_base_ioremap); #endif + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv643xx_eth_platform_data eth0_pd = { + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv643xx_eth_platform_data eth1_pd = { + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif + /* The third port is not wired up on the Ocelot C */ +}; + +int mv643xx_eth_add_pds(void) +{ + int ret; + + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ -- cgit v0.10.2 From 2002d2bde1a9ad10e2521b8b117c11abfbc2ee93 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Nov 2006 17:48:17 +0000 Subject: [MIPS] Ocelot C: Fix warning about missmatching format string. CC arch/mips/momentum/ocelot_c/setup.o arch/mips/momentum/ocelot_c/setup.c: In function 'momenco_time_init': arch/mips/momentum/ocelot_c/setup.c:223: warning: format '%d' expects type 'int', but argument 2 has type 'long unsigned int' Change data type to match format string; a 32-bit type better suits our needs. Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c index 4c50a14..1f67728 100644 --- a/arch/mips/momentum/ocelot_c/prom.c +++ b/arch/mips/momentum/ocelot_c/prom.c @@ -29,7 +29,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; -extern unsigned long cpu_clock; +extern unsigned int cpu_clock; #ifdef CONFIG_MV643XX_ETH extern unsigned char prom_mac_addr_base[6]; diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 0a3ffa3..7832d4e 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -70,7 +70,7 @@ #include "ocelot_c_fpga.h" unsigned long marvell_base; -unsigned long cpu_clock; +unsigned int cpu_clock; /* These functions are used for rebooting or halting the machine*/ extern void momenco_ocelot_restart(char *command); -- cgit v0.10.2 From ad0b365573718a4a83266f98c9a49305c8eaf0b8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Nov 2006 18:06:33 +0000 Subject: [MIPS] Ocelot C: Fix mapping of ioport address range. o Fix warnings o 768MB worth of I/O ports were insane o 64-bit kernels don't need special handling because ioremap does the magic Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 7832d4e..b0e82a0 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -344,25 +344,23 @@ void __init plat_mem_setup(void) } } -#ifndef CONFIG_64BIT -/* This needs to be one of the first initcalls, because no I/O port access - can work before this */ +/* + * This needs to be one of the first initcalls, because no I/O port access + * can work before this + */ static int io_base_ioremap(void) { - /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ - void *io_remap_range = ioremap(0xc0000000, 0x30000000); + void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000); - if (!io_remap_range) { + if (!io_remap_range) panic("Could not ioremap I/O port range"); - } - printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); - set_io_port_base(io_remap_range - 0xc0000000); + + set_io_port_base((unsigned long) io_remap_range); return 0; } module_init(io_base_ioremap); -#endif #if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) -- cgit v0.10.2 From d19f7befe929d400df89699eb51b8d7f4ef1b2d8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 4 Nov 2006 13:02:46 +0000 Subject: [MIPS] Ocelot 3: Fix large number of warnings. Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h index 227e429..5710a90 100644 --- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h +++ b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h @@ -51,7 +51,9 @@ extern unsigned long ocelot_fpga_base; -#define OCELOT_FPGA_WRITE(x, y) writeb(x, ocelot_fpga_base + OCELOT_3_REG_##y) -#define OCELOT_FPGA_READ(x) readb(ocelot_fpga_base + OCELOT_3_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) ocelot_fpga_base + OCELOT_3_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif -- cgit v0.10.2 From d6b861c6402307e30c7df24dcda911df64a5f9d6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 4 Nov 2006 23:26:27 +0000 Subject: [MIPS] SB1: On bootup only flush cache on local CPU. This fixes a warning on bootup warning in smp_call_function. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index ea49a77..d0ddb4a 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -505,5 +505,5 @@ void sb1_cache_init(void) : : "memory"); - flush_cache_all(); + local_sb1___flush_cache_all(); } -- cgit v0.10.2 From 907c51b2d1705b022c3fb65b66cb4e5e09346433 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 5 Nov 2006 01:18:11 +0000 Subject: [MIPS] Ocelot C: Fix MAC address detection after platform_device conversion. Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile index 94802b4..d69161a 100644 --- a/arch/mips/momentum/ocelot_c/Makefile +++ b/arch/mips/momentum/ocelot_c/Makefile @@ -2,7 +2,7 @@ # Makefile for Momentum Computer's Ocelot-C and -CS boards. # -obj-y += cpci-irq.o irq.o prom.o reset.o \ +obj-y += cpci-irq.o irq.o platform.o prom.o reset.o \ setup.o uart-irq.o obj-$(CONFIG_KGDB) += dbg_io.o diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c new file mode 100644 index 0000000..6c495b2 --- /dev/null +++ b/arch/mips/momentum/ocelot_c/platform.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include + +#include "ocelot_c_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif + /* The third port is not wired up on the Ocelot C */ +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c index 1f67728..d0b77e1 100644 --- a/arch/mips/momentum/ocelot_c/prom.c +++ b/arch/mips/momentum/ocelot_c/prom.c @@ -31,10 +31,6 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned int cpu_clock; -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - const char *get_system_type(void) { #ifdef CONFIG_CPU_SR71000 @@ -44,55 +40,6 @@ const char *get_system_type(void) #endif } -#ifdef CONFIG_MV643XX_ETH -static void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -static u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -226,11 +173,6 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_C; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index b0e82a0..0b6b233 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -361,123 +360,3 @@ static int io_base_ioremap(void) } module_init(io_base_ioremap); - -#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) - -static struct resource mv643xx_eth_shared_resources[] = { - [0] = { - .name = "ethernet shared base", - .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, - .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + - MV643XX_ETH_SHARED_REGS_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device mv643xx_eth_shared_device = { - .name = MV643XX_ETH_SHARED_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), - .resource = mv643xx_eth_shared_resources, -}; - -#define MV_SRAM_BASE 0xfe000000UL -#define MV_SRAM_SIZE (256 * 1024) - -#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) -#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) - -#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE -#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) - -#define MV64x60_IRQ_ETH_0 48 -#define MV64x60_IRQ_ETH_1 49 - -#ifdef CONFIG_MV643XX_ETH_0 - -static struct resource mv64x60_eth0_resources[] = { - [0] = { - .name = "eth0 irq", - .start = MV64x60_IRQ_ETH_0, - .end = MV64x60_IRQ_ETH_0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct mv643xx_eth_platform_data eth0_pd = { - .tx_sram_addr = MV_SRAM_BASE_ETH0, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth0_device = { - .name = MV643XX_ETH_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), - .resource = mv64x60_eth0_resources, - .dev = { - .platform_data = ð0_pd, - }, -}; -#endif /* CONFIG_MV643XX_ETH_0 */ - -#ifdef CONFIG_MV643XX_ETH_1 - -static struct resource mv64x60_eth1_resources[] = { - [0] = { - .name = "eth1 irq", - .start = MV64x60_IRQ_ETH_1, - .end = MV64x60_IRQ_ETH_1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct mv643xx_eth_platform_data eth1_pd = { - .tx_sram_addr = MV_SRAM_BASE_ETH1, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth1_device = { - .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), - .resource = mv64x60_eth1_resources, - .dev = { - .platform_data = ð1_pd, - }, -}; -#endif /* CONFIG_MV643XX_ETH_1 */ - -static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { - &mv643xx_eth_shared_device, -#ifdef CONFIG_MV643XX_ETH_0 - ð0_device, -#endif -#ifdef CONFIG_MV643XX_ETH_1 - ð1_device, -#endif - /* The third port is not wired up on the Ocelot C */ -}; - -int mv643xx_eth_add_pds(void) -{ - int ret; - - ret = platform_add_devices(mv643xx_eth_pd_devs, - ARRAY_SIZE(mv643xx_eth_pd_devs)); - - return ret; -} - -device_initcall(mv643xx_eth_add_pds); - -#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ -- cgit v0.10.2 From ff28cbd2804105b144a7054e0302615e1da6749f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 5 Nov 2006 01:18:43 +0000 Subject: [MIPS] Ocelot 3: Fix MAC address detection after platform_device conversion. Signed-off-by: Ralf Baechle diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile index 8bcea64d..d5a090a 100644 --- a/arch/mips/momentum/ocelot_3/Makefile +++ b/arch/mips/momentum/ocelot_3/Makefile @@ -5,4 +5,4 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -obj-y += irq.o prom.o reset.o setup.o +obj-y += irq.o platform.o prom.o reset.o setup.o diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c new file mode 100644 index 0000000..eefe584 --- /dev/null +++ b/arch/mips/momentum/ocelot_3/platform.c @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include + +#include "ocelot_3_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 +#define MV64x60_IRQ_ETH_2 50 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +#ifdef CONFIG_MV643XX_ETH_2 + +static struct resource mv64x60_eth2_resources[] = { + [0] = { + .name = "eth2 irq", + .start = MV64x60_IRQ_ETH_2, + .end = MV64x60_IRQ_ETH_2, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth2_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth2_pd = { + .mac_addr = eth2_mac_addr, +}; + +static struct platform_device eth2_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), + .resource = mv64x60_eth2_resources, + .dev = { + .platform_data = ð2_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_2 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif +#ifdef CONFIG_MV643XX_ETH_2 + ð2_device, +#endif +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif +#ifdef CONFIG_MV643XX_ETH_2 + eth_mac_add(eth2_mac_addr, mac, 2); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c index 296d945..6ce9b7f 100644 --- a/arch/mips/momentum/ocelot_3/prom.c +++ b/arch/mips/momentum/ocelot_3/prom.c @@ -34,64 +34,11 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned long cpu_clock; -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - const char *get_system_type(void) { return "Momentum Ocelot-3"; } -#ifdef CONFIG_MV643XX_ETH -void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -228,11 +175,6 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_3; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index 7d74f8c..ff0829f 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -4,7 +4,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Ocelot-3 board dependent boot routines * - * Copyright (C) 1996, 1997, 01, 05 Ralf Baechle + * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer -- cgit v0.10.2 From 325d08d1a44b601fbf70c259fb61c38d2af7d309 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 6 Nov 2006 13:32:39 +0000 Subject: [MIPS] EV64120: Fix timer initialization for HZ != 100. Signed-off-by: Ralf Baechle diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c index c83ae6a..e6e4832 100644 --- a/arch/mips/gt64120/common/time.c +++ b/arch/mips/gt64120/common/time.c @@ -71,7 +71,7 @@ void gt64120_time_init(void) /* Disable timer first */ GT_WRITE(GT_TC_CONTROL_OFS, 0); /* Load timer value for 100 Hz */ - GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + GT_WRITE(GT_TC3_OFS, Sys_clock / HZ); /* * Create the IRQ structure entry for the timer. Since we're too early -- cgit v0.10.2 From 4a4cf77923eeb3cec40a302656d6ab5ced04ba48 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 6 Nov 2006 17:41:06 +0000 Subject: [MIPS] Make irq number allocator generally available for fixing EV64120. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index dd24434..9b0e49d 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -26,6 +26,48 @@ #include #include +static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; + +int __devinit allocate_irqno(void) +{ + int irq; + +again: + irq = find_first_zero_bit(irq_map, NR_IRQS); + + if (irq >= NR_IRQS) + return -ENOSPC; + + if (test_and_set_bit(irq, irq_map)) + goto again; + + return irq; +} + +EXPORT_SYMBOL_GPL(allocate_irqno); + +/* + * Allocate the 16 legacy interrupts for i8259 devices. This happens early + * in the kernel initialization so treating allocation failure as BUG() is + * ok. + */ +void __init alloc_legacy_irqno(void) +{ + int i; + + for (i = 0; i <= 16; i++) + BUG_ON(test_and_set_bit(i, irq_map)); +} + +void __devinit free_irqno(unsigned int irq) +{ + smp_mb__before_clear_bit(); + clear_bit(irq, irq_map); + smp_mb__after_clear_bit(); +} + +EXPORT_SYMBOL_GPL(free_irqno); + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index f01ba1f..270ecd3 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -354,29 +354,6 @@ static struct irq_chip bridge_irq_type = { .end = end_bridge_irq, }; -static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; - -int allocate_irqno(void) -{ - int irq; - -again: - irq = find_first_zero_bit(irq_map, NR_IRQS); - - if (irq >= NR_IRQS) - return -ENOSPC; - - if (test_and_set_bit(irq, irq_map)) - goto again; - - return irq; -} - -void free_irqno(unsigned int irq) -{ - clear_bit(irq, irq_map); -} - void __devinit register_bridge_irq(unsigned int irq) { irq_desc[irq].status = IRQ_DISABLED; diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index c965705..5e82a26 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -214,8 +214,6 @@ static struct irqaction rt_irqaction = { .name = "timer" }; -extern int allocate_irqno(void); - void __init plat_timer_setup(struct irqaction *irq) { int irqno = allocate_irqno(); diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h index 0ce2a80..35a05ca 100644 --- a/include/asm-mips/irq.h +++ b/include/asm-mips/irq.h @@ -74,4 +74,8 @@ extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, unsigned long hwmask); #endif /* CONFIG_MIPS_MT_SMTC */ +extern int allocate_irqno(void); +extern void alloc_legacy_irqno(void); +extern void free_irqno(unsigned int irq); + #endif /* _ASM_IRQ_H */ -- cgit v0.10.2 From 4e5852f31a22094a19bbc305e42651b6c92f3008 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 6 Nov 2006 18:05:08 +0000 Subject: [MIPS] EV64120: Fix PCI interrupt allocation. Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 3cf0dd4..70cb55b 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o -obj-$(CONFIG_MIPS_EV64120) += fixup-ev64120.o +obj-$(CONFIG_MIPS_EV64120) += pci-ev64120.o obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o diff --git a/arch/mips/pci/fixup-ev64120.c b/arch/mips/pci/fixup-ev64120.c deleted file mode 100644 index 8dbb90d..0000000 --- a/arch/mips/pci/fixup-ev64120.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -int pci_range_ck(unsigned char bus, unsigned char dev) -{ - if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) - return 0; - - return -1; -} - -/* - * After detecting all agents over the PCI , this function is called - * in order to give an interrupt number for each PCI device starting - * from IRQ 20. It does also enables master for each device. - */ -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - unsigned int irq = 20; - struct pci_bus *current_bus = bus; - struct pci_dev *dev; - struct list_head *devices_link; - - list_for_each(devices_link, &(current_bus->devices)) { - dev = pci_dev_b(devices_link); - if (dev != NULL) { - dev->irq = irq++; - - /* Assign an interrupt number for the device */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - pcibios_set_master(dev); - } - } -} diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c new file mode 100644 index 0000000..9cd859e --- /dev/null +++ b/arch/mips/pci/pci-ev64120.c @@ -0,0 +1,21 @@ +#include + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + if (!pin) + return 0; + + irq = allocate_irqno(); + if (irq < 0) + return 0; + + return irq; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} -- cgit v0.10.2 From 73f4388aedade209650ed629ab767d3e2b636f7b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 6 Nov 2006 18:17:35 +0000 Subject: [MIPS] Fix EV64120 and Ocelot builds by providing a plat_timer_setup(). Signed-off-by: Ralf Baechle diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c index e6e4832..c47eeb7 100644 --- a/arch/mips/gt64120/common/time.c +++ b/arch/mips/gt64120/common/time.c @@ -64,7 +64,7 @@ static irqreturn_t gt64120_irq(int irq, void *dev_id) * as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt * handling. */ -void gt64120_time_init(void) +void __init plat_timer_setup(struct irqaction *irq) { static struct irqaction timer; diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c index 91c2d3f..99c8d42 100644 --- a/arch/mips/gt64120/ev64120/setup.c +++ b/arch/mips/gt64120/ev64120/setup.c @@ -68,7 +68,6 @@ unsigned long __init prom_free_prom_memory(void) * Initializes basic routines and structures pointers, memory size (as * given by the bios and saves the command line. */ -extern void gt64120_time_init(void); void __init plat_mem_setup(void) { @@ -76,7 +75,6 @@ void __init plat_mem_setup(void) _machine_halt = galileo_machine_halt; pm_power_off = galileo_machine_power_off; - board_time_init = gt64120_time_init; set_io_port_base(KSEG1); } diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index 0e5bbee..94f94eb 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -70,7 +70,6 @@ extern void momenco_ocelot_restart(char *command); extern void momenco_ocelot_halt(void); extern void momenco_ocelot_power_off(void); -extern void gt64120_time_init(void); extern void momenco_ocelot_irq_setup(void); static char reset_reason; @@ -156,8 +155,6 @@ void __init plat_mem_setup(void) void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; - board_time_init = gt64120_time_init; - _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; pm_power_off = momenco_ocelot_power_off; -- cgit v0.10.2 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 diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 1ec2174..474a4e34 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 8d04752..726ec5e 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 v0.10.2 From 4891d53956abd4ad9d94127c50d931124319a324 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 7 Nov 2006 16:31:16 +0000 Subject: [CIFS] NFS stress test generates flood of "close with pending write" messages Informational/debug message was being logged too often. The error case of logging having to send a close with (presumably stuck on buggy server) pending writes is still logged. Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7e056b9..4b07a8c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -492,10 +492,13 @@ int cifs_close(struct inode *inode, struct file *file) the struct would be in each open file, but this should give enough time to clear the socket */ - cERROR(1,("close with pending writes")); +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1,("close delay, write pending")); +#endif /* DEBUG2 */ msleep(timeout); timeout *= 4; - } + } + cERROR(1,("close with pending writes")); rc = CIFSSMBClose(xid, pTcon, pSMBFile->netfid); } -- cgit v0.10.2 From 5fe14c851efedf95b0e7652a3a7b93ec899d1599 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 7 Nov 2006 19:26:33 +0000 Subject: [CIFS] Explicitly set stat->blksize CIFS may perform I/O over the network in larger chunks than the page size, so it should explicitly set stat->blksize to ensure optimal I/O bandwidth Signed-off-by: Dave Kleikamp Signed-off-by: Steve French diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index dffe295..1ad8c9f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1089,8 +1089,10 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { int err = cifs_revalidate(dentry); - if (!err) + if (!err) { generic_fillattr(dentry->d_inode, stat); + stat->blksize = CIFS_MAX_MSGSIZE; + } return err; } -- cgit v0.10.2 From 6d15cb42fe4f8c07c80c9d49db721fcfe2da0e90 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 6 Nov 2006 19:29:16 +0100 Subject: [ARM] 3926/1: make timer led handle HZ != 100 The timer LED is unusable at HZ=large, since it's got a hard-wired value of 100 ticks per cycle; when HZ=1024 (for example) it's essentially always-on. This patch just makes that be HZ ticks per cycle. Signed-off-by: David Brownell Signed-off-by: Russell King diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 0c5a609..6ff5e3f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -220,10 +220,10 @@ EXPORT_SYMBOL(leds_event); #ifdef CONFIG_LEDS_TIMER static inline void do_leds(void) { - static unsigned int count = 50; + static unsigned int count = HZ/2; if (--count == 0) { - count = 50; + count = HZ/2; leds_event(led_timer); } } -- cgit v0.10.2 From 5e7098275094ec405f2b19285ec0c38aead42d53 Mon Sep 17 00:00:00 2001 From: Ray Lehtiniemi Date: Tue, 7 Nov 2006 03:19:15 +0100 Subject: [ARM] 3927/1: Allow show_mem() to work with holes in memory map. show_mem() was not correctly handling holes in the memory map. It was treating the freed sections of the map as though they contained valid struct page entries. This could cause incorrect debugging output or even a kernel panic. This patch keeps the struct meminfo around after system initialization so that show_mem() can use it when scanning memory. show_mem() now walks over each bank of each online node, rather than assuming that each node contains a single contiguous bank. Signed-off-by: Ray Lehtiniemi Signed-off-by: Russell King diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 22217fe..b5814b4 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -32,40 +32,51 @@ extern unsigned long phys_initrd_start; extern unsigned long phys_initrd_size; /* - * The sole use of this is to pass memory configuration - * data from paging_init to mem_init. + * This is used to pass memory configuration data from paging_init + * to mem_init, and by show_mem() to skip holes in the memory map. */ -static struct meminfo meminfo __initdata = { 0, }; +static struct meminfo meminfo = { 0, }; + +#define for_each_nodebank(iter,mi,no) \ + for (iter = 0; iter < mi->nr_banks; iter++) \ + if (mi->bank[iter].node == no) void show_mem(void) { int free = 0, total = 0, reserved = 0; - int shared = 0, cached = 0, slab = 0, node; + int shared = 0, cached = 0, slab = 0, node, i; + struct meminfo * mi = &meminfo; printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); for_each_online_node(node) { - struct page *page, *end; - - page = NODE_MEM_MAP(node); - end = page + NODE_DATA(node)->node_spanned_pages; - - do { - total++; - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (PageSlab(page)) - slab++; - else if (!page_count(page)) - free++; - else - shared += page_count(page) - 1; - page++; - } while (page < end); + for_each_nodebank (i,mi,node) { + unsigned int pfn1, pfn2; + struct page *page, *end; + + pfn1 = mi->bank[i].start >> PAGE_SHIFT; + pfn2 = (mi->bank[i].size + mi->bank[i].start) >> PAGE_SHIFT; + + page = NODE_MEM_MAP(node) + pfn1; + end = NODE_MEM_MAP(node) + pfn2; + + do { + total++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (PageSlab(page)) + slab++; + else if (!page_count(page)) + free++; + else + shared += page_count(page) - 1; + page++; + } while (page < end); + } } printk("%d pages of RAM\n", total); @@ -76,10 +87,6 @@ void show_mem(void) printk("%d pages swap cached\n", cached); } -#define for_each_nodebank(iter,mi,no) \ - for (iter = 0; iter < mi->nr_banks; iter++) \ - if (mi->bank[iter].node == no) - /* * FIXME: We really want to avoid allocating the bootmap bitmap * over the top of the initrd. Hopefully, this is located towards -- cgit v0.10.2 From 16b7f4dcd340875625714438a812ea06400f9666 Mon Sep 17 00:00:00 2001 From: Jan-Benedict Glaw Date: Tue, 7 Nov 2006 23:50:37 +0100 Subject: Update for the srm_env driver. This patch contains a fix for a bug introduced more than a year ago (not setting *eof) and updates whitespace a bit. Signed-off-by: Jan-Benedict Glaw diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index 990ac61..f7dd081 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -2,7 +2,7 @@ * srm_env.c - Access to SRM environment * variables through linux' procfs * - * Copyright (C) 2001-2002 Jan-Benedict Glaw + * (C) 2001,2002,2006 by Jan-Benedict Glaw * * This driver is at all a modified version of Erik Mouw's * Documentation/DocBook/procfs_example.c, so: thank @@ -21,7 +21,7 @@ * 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, @@ -29,33 +29,6 @@ * */ -/* - * Changelog - * ~~~~~~~~~ - * - * Thu, 22 Aug 2002 15:10:43 +0200 - * - Update Config.help entry. I got a number of emails asking - * me to tell their senders if they could make use of this - * piece of code... So: "SRM is something like BIOS for your - * Alpha" - * - Update code formatting a bit to better conform CodingStyle - * rules. - * - So this is v0.0.5, with no changes (except formatting) - * - * Wed, 22 May 2002 00:11:21 +0200 - * - Fix typo on comment (SRC -> SRM) - * - Call this "Version 0.0.4" - * - * Tue, 9 Apr 2002 18:44:40 +0200 - * - Implement access by variable name and additionally - * by number. This is done by creating two subdirectories - * where one holds all names (like the old directory - * did) and the other holding 256 files named like "0", - * "1" and so on. - * - Call this "Version 0.0.3" - * - */ - #include #include #include @@ -67,7 +40,7 @@ #define BASE_DIR "srm_environment" /* Subdir in /proc/ */ #define NAMED_DIR "named_variables" /* Subdir for known variables */ #define NUMBERED_DIR "numbered_variables" /* Subdir for all variables */ -#define VERSION "0.0.5" /* Module version */ +#define VERSION "0.0.6" /* Module version */ #define NAME "srm_env" /* Module name */ MODULE_AUTHOR("Jan-Benedict Glaw "); @@ -106,7 +79,6 @@ static srm_env_t srm_named_entries[] = { static srm_env_t srm_numbered_entries[256]; - static int srm_env_read(char *page, char **start, off_t off, int count, int *eof, void *data) @@ -115,21 +87,23 @@ srm_env_read(char *page, char **start, off_t off, int count, int *eof, unsigned long ret; srm_env_t *entry; - if(off != 0) - return -EFAULT; + if (off != 0) { + *eof = 1; + return 0; + } entry = (srm_env_t *) data; ret = callback_getenv(entry->id, page, count); - if((ret >> 61) == 0) + if ((ret >> 61) == 0) { nbytes = (int) ret; - else + *eof = 1; + } else nbytes = -EFAULT; return nbytes; } - static int srm_env_write(struct file *file, const char __user *buffer, unsigned long count, void *data) @@ -155,7 +129,7 @@ srm_env_write(struct file *file, const char __user *buffer, unsigned long count, ret1 = callback_setenv(entry->id, buf, count); if ((ret1 >> 61) == 0) { - do + do ret2 = callback_save_env(); while((ret2 >> 61) == 1); res = (int) ret1; @@ -172,14 +146,14 @@ srm_env_cleanup(void) srm_env_t *entry; unsigned long var_num; - if(base_dir) { + if (base_dir) { /* * Remove named entries */ - if(named_dir) { + if (named_dir) { entry = srm_named_entries; - while(entry->name != NULL && entry->id != 0) { - if(entry->proc_entry) { + while (entry->name != NULL && entry->id != 0) { + if (entry->proc_entry) { remove_proc_entry(entry->name, named_dir); entry->proc_entry = NULL; @@ -192,11 +166,11 @@ srm_env_cleanup(void) /* * Remove numbered entries */ - if(numbered_dir) { - for(var_num = 0; var_num <= 255; var_num++) { + if (numbered_dir) { + for (var_num = 0; var_num <= 255; var_num++) { entry = &srm_numbered_entries[var_num]; - if(entry->proc_entry) { + if (entry->proc_entry) { remove_proc_entry(entry->name, numbered_dir); entry->proc_entry = NULL; @@ -212,7 +186,6 @@ srm_env_cleanup(void) return; } - static int __init srm_env_init(void) { @@ -222,7 +195,7 @@ srm_env_init(void) /* * Check system */ - if(!alpha_using_srm) { + if (!alpha_using_srm) { printk(KERN_INFO "%s: This Alpha system doesn't " "know about SRM (or you've booted " "SRM->MILO->Linux, which gets " @@ -233,14 +206,14 @@ srm_env_init(void) /* * Init numbers */ - for(var_num = 0; var_num <= 255; var_num++) + for (var_num = 0; var_num <= 255; var_num++) sprintf(number[var_num], "%ld", var_num); /* * Create base directory */ base_dir = proc_mkdir(BASE_DIR, NULL); - if(base_dir == NULL) { + if (!base_dir) { printk(KERN_ERR "Couldn't create base dir /proc/%s\n", BASE_DIR); goto cleanup; @@ -251,7 +224,7 @@ srm_env_init(void) * Create per-name subdirectory */ named_dir = proc_mkdir(NAMED_DIR, base_dir); - if(named_dir == NULL) { + if (!named_dir) { printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n", BASE_DIR, NAMED_DIR); goto cleanup; @@ -262,7 +235,7 @@ srm_env_init(void) * Create per-number subdirectory */ numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir); - if(numbered_dir == NULL) { + if (!numbered_dir) { printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n", BASE_DIR, NUMBERED_DIR); goto cleanup; @@ -274,10 +247,10 @@ srm_env_init(void) * Create all named nodes */ entry = srm_named_entries; - while(entry->name != NULL && entry->id != 0) { + while (entry->name && entry->id) { entry->proc_entry = create_proc_entry(entry->name, 0644, named_dir); - if(entry->proc_entry == NULL) + if (!entry->proc_entry) goto cleanup; entry->proc_entry->data = (void *) entry; @@ -291,13 +264,13 @@ srm_env_init(void) /* * Create all numbered nodes */ - for(var_num = 0; var_num <= 255; var_num++) { + for (var_num = 0; var_num <= 255; var_num++) { entry = &srm_numbered_entries[var_num]; entry->name = number[var_num]; entry->proc_entry = create_proc_entry(entry->name, 0644, numbered_dir); - if(entry->proc_entry == NULL) + if (!entry->proc_entry) goto cleanup; entry->id = var_num; @@ -318,7 +291,6 @@ cleanup: return -ENOMEM; } - static void __exit srm_env_exit(void) { @@ -328,7 +300,5 @@ srm_env_exit(void) return; } - module_init(srm_env_init); module_exit(srm_env_exit); - -- cgit v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9cb3ca5..6e863aa 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 v0.10.2 From 9e950efa20dc8037c27509666cba6999da9368e8 Mon Sep 17 00:00:00 2001 From: John Heffner Date: Mon, 6 Nov 2006 23:10:51 -0800 Subject: [TCP]: Don't use highmem in tcp hash size calculation. This patch removes consideration of high memory when determining TCP hash table sizes. Taking into account high memory results in tcp_mem values that are too large. Signed-off-by: John Heffner Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 66e9a72..4322318 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2270,7 +2270,7 @@ void __init tcp_init(void) thash_entries, (num_physpages >= 128 * 1024) ? 13 : 15, - HASH_HIGHMEM, + 0, &tcp_hashinfo.ehash_size, NULL, 0); @@ -2286,7 +2286,7 @@ void __init tcp_init(void) tcp_hashinfo.ehash_size, (num_physpages >= 128 * 1024) ? 13 : 15, - HASH_HIGHMEM, + 0, &tcp_hashinfo.bhash_size, NULL, 64 * 1024); -- cgit v0.10.2 From da33e3eb4876c43b78fdc7b7068653239f28714a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 7 Nov 2006 14:54:46 -0800 Subject: [PKT_SCHED] sch_htb: Use hlist_del_init(). Otherwise we can hit paths that (legally) do multiple deletes on the same node and OOPS with the HLIST poison values there instead of NULL. Signed-off-by: David S. Miller diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 9b9c555..4b52fa7 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1284,8 +1284,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) struct htb_class, sibling)); /* note: this delete may happen twice (see htb_delete) */ - if (!hlist_unhashed(&cl->hlist)) - hlist_del(&cl->hlist); + hlist_del_init(&cl->hlist); list_del(&cl->sibling); if (cl->prio_activity) @@ -1333,8 +1332,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) sch_tree_lock(sch); /* delete from hash and active; remainder in destroy_class */ - if (!hlist_unhashed(&cl->hlist)) - hlist_del(&cl->hlist); + hlist_del_init(&cl->hlist); if (cl->prio_activity) htb_deactivate(q, cl); -- cgit v0.10.2 From 8e365eec04c86899fab5db0f49a9c98554069bd0 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Tue, 7 Nov 2006 14:56:19 -0800 Subject: [NETPOLL]: Compute checksum properly in netpoll_send_udp(). Signed-off-by: Chris Lalancette Signed-off-by: David S. Miller diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9308af0..6589adb 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -340,6 +340,12 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) udph->dest = htons(np->remote_port); udph->len = htons(udp_len); udph->check = 0; + udph->check = csum_tcpudp_magic(htonl(np->local_ip), + htonl(np->remote_ip), + udp_len, IPPROTO_UDP, + csum_partial((unsigned char *)udph, udp_len, 0)); + if (udph->check == 0) + udph->check = -1; skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph)); -- cgit v0.10.2 From 25f484a62e41be8020b9a31bf50a792baa58d2d4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 7 Nov 2006 14:57:15 -0800 Subject: [NET]: Set truesize in pskb_copy Since pskb_copy tacks on the non-linear bits from the original skb, it needs to count them in the truesize field of the new skb. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f735455..b8b1063 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -639,6 +639,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) n->csum = skb->csum; n->ip_summed = skb->ip_summed; + n->truesize += skb->data_len; n->data_len = skb->data_len; n->len = skb->len; -- cgit v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8f059b7..06e4f77 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 v0.10.2 From 375d9d71838970030c8e0bf0ac2abcc1a3487df8 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 7 Nov 2006 15:09:17 -0800 Subject: [DECNET]: Endianess fixes (try #2) Here are some fixes to endianess problems spotted by Al Viro. Signed-off-by: Steven Whitehouse Signed-off-by: David S. Miller diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 3456cd3..21f20f2 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -166,7 +166,7 @@ static struct hlist_head *dn_find_list(struct sock *sk) if (scp->addr.sdn_flags & SDF_WILD) return hlist_empty(&dn_wild_sk) ? &dn_wild_sk : NULL; - return &dn_sk_hash[scp->addrloc & DN_SK_HASH_MASK]; + return &dn_sk_hash[dn_ntohs(scp->addrloc) & DN_SK_HASH_MASK]; } /* @@ -180,7 +180,7 @@ static int check_port(__le16 port) if (port == 0) return -1; - sk_for_each(sk, node, &dn_sk_hash[port & DN_SK_HASH_MASK]) { + sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(port) & DN_SK_HASH_MASK]) { struct dn_scp *scp = DN_SK(sk); if (scp->addrloc == port) return -1; @@ -194,12 +194,12 @@ static unsigned short port_alloc(struct sock *sk) static unsigned short port = 0x2000; unsigned short i_port = port; - while(check_port(++port) != 0) { + while(check_port(dn_htons(++port)) != 0) { if (port == i_port) return 0; } - scp->addrloc = port; + scp->addrloc = dn_htons(port); return 1; } @@ -418,7 +418,7 @@ struct sock *dn_find_by_skb(struct sk_buff *skb) struct dn_scp *scp; read_lock(&dn_hash_lock); - sk_for_each(sk, node, &dn_sk_hash[cb->dst_port & DN_SK_HASH_MASK]) { + sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(cb->dst_port) & DN_SK_HASH_MASK]) { scp = DN_SK(sk); if (cb->src != dn_saddr2dn(&scp->peer)) continue; @@ -1016,13 +1016,14 @@ static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc) static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) { - unsigned char *ptr = skb->data; - - opt->opt_optl = *ptr++; - opt->opt_status = 0; - memcpy(opt->opt_data, ptr, opt->opt_optl); - skb_pull(skb, dn_ntohs(opt->opt_optl) + 1); - + unsigned char *ptr = skb->data; + u16 len = *ptr++; /* yes, it's 8bit on the wire */ + + BUG_ON(len > 16); /* we've checked the contents earlier */ + opt->opt_optl = dn_htons(len); + opt->opt_status = 0; + memcpy(opt->opt_data, ptr, len); + skb_pull(skb, len + 1); } static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 72ecc6e..7683d4f 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -360,9 +360,9 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) scp->max_window = decnet_no_fc_max_cwnd; if (skb->len > 0) { - unsigned char dlen = *skb->data; + u16 dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { - scp->conndata_in.opt_optl = dn_htons((__u16)dlen); + scp->conndata_in.opt_optl = dn_htons(dlen); memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen); } } @@ -404,9 +404,9 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb) memset(scp->discdata_in.opt_data, 0, 16); if (skb->len > 0) { - unsigned char dlen = *skb->data; + u16 dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { - scp->discdata_in.opt_optl = dn_htons((__u16)dlen); + scp->discdata_in.opt_optl = dn_htons(dlen); memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen); } } diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index c2e21cd..b342e4e 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -526,7 +526,7 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp) struct nsp_conn_init_msg *msg; __u8 len = (__u8)dn_ntohs(scp->conndata_out.opt_optl); - if ((skb = dn_alloc_skb(sk, 50 + dn_ntohs(scp->conndata_out.opt_optl), gfp)) == NULL) + if ((skb = dn_alloc_skb(sk, 50 + len, gfp)) == NULL) return; msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg)); diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 3e0c882..590e0a7 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -124,8 +124,8 @@ static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) { struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - u16 daddr = fl->fld_dst; - u16 saddr = fl->fld_src; + __le16 daddr = fl->fld_dst; + __le16 saddr = fl->fld_src; if (((saddr ^ r->src) & r->srcmask) || ((daddr ^ r->dst) & r->dstmask)) -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 65edb56..62c2ff8 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 62c2ff8..a1b7838 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 v0.10.2 From 80c218812786f619c9a1ce50d0e7c32c7afde4de Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 7 Nov 2006 18:24:20 -0800 Subject: Linux 2.6.19-rc5 Ok, things are clearly starting to calm down.. Finally. diff --git a/Makefile b/Makefile index 9557619..8484be1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc4 +EXTRAVERSION =-rc5 NAME=Avast! A bilge rat! # *DOCUMENTATION* -- cgit v0.10.2 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 diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index f4455a1..1c7f19a 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 v0.10.2 From de8e7c12430a73654ae3cedbc45428d56c6b777b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Nov 2006 10:09:28 -0800 Subject: Revert "[PATCH] i386: Add MMCFG resources to i386 too" This reverts commit de09bddb9d6f96785be470c832b881e6d72d589f. It tried to reserve the MMCONFIG mmio memory ranges, but since the MMCONFIG information is broken and often bogus (which is why we don't dare use it most of the time _anyway_), it does more harm than good. Cc: Jeff Chua Cc: Adrian Bunk Cc: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index d0c3da3..c6b6d9b 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -154,38 +154,6 @@ static struct pci_raw_ops pci_mmcfg = { .write = pci_mmcfg_write, }; - -static __init void pci_mmcfg_insert_resources(void) -{ -#define PCI_MMCFG_RESOURCE_NAME_LEN 19 - int i; - struct resource *res; - char *names; - unsigned num_buses; - - res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), - pci_mmcfg_config_num, GFP_KERNEL); - - if (!res) { - printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); - return; - } - - names = (void *)&res[pci_mmcfg_config_num]; - for (i = 0; i < pci_mmcfg_config_num; i++, res++) { - num_buses = pci_mmcfg_config[i].end_bus_number - - pci_mmcfg_config[i].start_bus_number + 1; - res->name = names; - snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", - pci_mmcfg_config[i].pci_segment_group_number); - res->start = pci_mmcfg_config[i].base_address; - res->end = res->start + (num_buses << 20) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - insert_resource(&iomem_resource, res); - names += PCI_MMCFG_RESOURCE_NAME_LEN; - } -} - /* K8 systems have some devices (typically in the builtin northbridge) that are only accessible using type1 Normally this can be expressed in the MCFG by not listing them @@ -222,8 +190,6 @@ static __init void unreachable_devices(void) } } - - void __init pci_mmcfg_init(int type) { if ((pci_probe & PCI_PROBE_MMCONF) == 0) @@ -251,5 +217,4 @@ void __init pci_mmcfg_init(int type) pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; unreachable_devices(); - pci_mmcfg_insert_resources(); } -- cgit v0.10.2 From 6c0ffb9d2fd987c79c6cbb81c3f3011c63749b1a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Nov 2006 10:23:03 -0800 Subject: x86-64: clean up io-apic accesses This is just commit 130fe05dbc0114609cfef9815c0c5580b42decfa ported to x86-64, for all the same reasons. It cleans up the IO-APIC accesses in order to then fix the ordering issues. We move the accessor functions (that were only used by io_apic.c) out of a header file, and use proper memory-mapped accesses rather than making up our own "volatile" pointers. Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index fe429e5..96e02d8 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -88,6 +88,52 @@ static struct irq_pin_list { short apic, pin, next; } irq_2_pin[PIN_MAP_SIZE]; +struct io_apic { + unsigned int index; + unsigned int unused[3]; + unsigned int data; +}; + +static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) +{ + return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx) + + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK); +} + +static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + return readl(&io_apic->data); +} + +static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + writel(value, &io_apic->data); +} + +/* + * Re-write a value: to be used for read-modify-write + * cycles where the read already set up the index register. + */ +static inline void io_apic_modify(unsigned int apic, unsigned int value) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(value, &io_apic->data); +} + +/* + * Synchronize the IO-APIC and the CPU by doing + * a dummy read from the IO-APIC + */ +static inline void io_apic_sync(unsigned int apic) +{ + struct io_apic __iomem *io_apic = io_apic_base(apic); + readl(&io_apic->data); +} + #define __DO_ACTION(R, ACTION, FINAL) \ \ { \ diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h index 171ec2d..561ecbf 100644 --- a/include/asm-x86_64/io_apic.h +++ b/include/asm-x86_64/io_apic.h @@ -12,10 +12,6 @@ #define APIC_MISMATCH_DEBUG -#define IO_APIC_BASE(idx) \ - ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ - + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK))) - /* * The structure of the IO-APIC: */ @@ -119,36 +115,6 @@ extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* non-0 if default (table-less) MP configuration */ extern int mpc_default_type; -static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -{ - *IO_APIC_BASE(apic) = reg; - return *(IO_APIC_BASE(apic)+4); -} - -static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) -{ - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = value; -} - -/* - * Re-write a value: to be used for read-modify-write - * cycles where the read already set up the index register. - */ -static inline void io_apic_modify(unsigned int apic, unsigned int value) -{ - *(IO_APIC_BASE(apic)+4) = value; -} - -/* - * Synchronize the IO-APIC and the CPU by doing - * a dummy read from the IO-APIC - */ -static inline void io_apic_sync(unsigned int apic) -{ - (void) *(IO_APIC_BASE(apic)+4); -} - /* 1 if "noapic" boot option passed */ extern int skip_ioapic_setup; -- cgit v0.10.2 From 48797ebd9e8b16fddcd4ef062f792314a6b9219a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Nov 2006 10:27:54 -0800 Subject: x86-64: write IO APIC irq routing entries in correct order This is the x86-64 version of f9dadfa71bc594df09044da61d1c72701121d802 that did the same thing on i386. Since the "mask" bit is in the low word, when we write a new entry, we need to write the high word first, before we potentially unmask it. The exception is when we actually want to mask the interrupt, in which case we want to write the low word first to make sure that the high word doesn't change while the interrupt routing is still active. Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 96e02d8..3b8f9c6 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -172,12 +172,34 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) return eu.entry; } +/* + * When we write a new IO APIC routing entry, we need to write the high + * word first! If the mask bit in the low word is clear, we will enable + * the interrupt, and we need to make sure the entry is fully populated + * before that happens. + */ static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { unsigned long flags; union entry_union eu; eu.entry = e; spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(apic, 0x11 + 2*pin, eu.w2); + io_apic_write(apic, 0x10 + 2*pin, eu.w1); + spin_unlock_irqrestore(&ioapic_lock, flags); +} + +/* + * When we mask an IO APIC routing entry, we need to write the low + * word first, in order to set the mask bit before we change the + * high bits! + */ +static void ioapic_mask_entry(int apic, int pin) +{ + unsigned long flags; + union entry_union eu = { .entry.mask = 1 }; + + spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x10 + 2*pin, eu.w1); io_apic_write(apic, 0x11 + 2*pin, eu.w2); spin_unlock_irqrestore(&ioapic_lock, flags); @@ -302,9 +324,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) /* * Disable it in the IO-APIC irq-routing table: */ - memset(&entry, 0, sizeof(entry)); - entry.mask = 1; - ioapic_write_entry(apic, pin, entry); + ioapic_mask_entry(apic, pin); } static void clear_IO_APIC (void) -- cgit v0.10.2 From 6e659c63998881e8f4a842edbe86ac8c5cdaee41 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 8 Nov 2006 23:10:46 +0000 Subject: [CIFS] Fix mount failure when domain not specified Fixes Samba bugzilla #4176 When users do not specify their domain on mount, 2.6.18 started sending default domain instead of a null domain (which was the only way on some servers to use a default domain). Users of 2.6.18 who did not specify their domain name on mounts to certain common Windows servers that were members of a domain, but not the domain controller, would get mount failures which they did not get in 2.6.18 This fixes that issue and should remove complaints about mount behavior changing. Signed-off-by: Steve French diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index a8a0835..bbdda99 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -90,7 +90,9 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, } */ /* copy user */ if(ses->userName == NULL) { - /* BB what about null user mounts - check that we do this BB */ + /* null user mount */ + *bcc_ptr = 0; + *(bcc_ptr+1) = 0; } else { /* 300 should be long enough for any conceivable user name */ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, 300, nls_cp); @@ -98,10 +100,13 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null termination */ /* copy domain */ - if(ses->domainName == NULL) - bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, - "CIFS_LINUX_DOM", 32, nls_cp); - else + if(ses->domainName == NULL) { + /* Sending null domain better than using a bogus domain name (as + we did briefly in 2.6.18) since server will use its default */ + *bcc_ptr = 0; + *(bcc_ptr+1) = 0; + bytes_ret = 0; + } else bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, 256, nls_cp); bcc_ptr += 2 * bytes_ret; @@ -144,13 +149,11 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, /* copy domain */ - if(ses->domainName == NULL) { - strcpy(bcc_ptr, "CIFS_LINUX_DOM"); - bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */ - } else { + if(ses->domainName != NULL) { strncpy(bcc_ptr, ses->domainName, 256); bcc_ptr += strnlen(ses->domainName, 256); - } + } /* else we will send a null domain name + so the server will default to its own domain */ *bcc_ptr = 0; bcc_ptr++; -- cgit v0.10.2 From d654c673d6394bc26e159b1057b357371b4ce1dc Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 8 Nov 2006 17:44:37 -0800 Subject: [PATCH] Regression in 2.6.19-rc microcode driver If the microcode driver is built in (rather than module) there are some, ehm, interesting effects happening due to the new "call out to userspace" behavior that is introduced.. and which runs too early. The result is a boot hang; which is really nasty. The patch below is a minimally safe patch to fix this regression for 2.6.19 by just not requesting actual microcode updates during early boot. (That is a good idea in general anyway) The "real" fix is a lot more complex given the entire cpu hotplug scenario (during cpu hotplug you normally need to load the microcode as well); but the interactions for that are just really messy at this point; this fix at least makes it work and avoids a full detangle of hotplug. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index c4d0291..23f5984 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -577,7 +577,7 @@ static void microcode_init_cpu(int cpu) set_cpus_allowed(current, cpumask_of_cpu(cpu)); mutex_lock(µcode_mutex); collect_cpu_info(cpu); - if (uci->valid) + if (uci->valid && system_state == SYSTEM_RUNNING) cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); set_cpus_allowed(current, old); -- cgit v0.10.2 From 75b2bd55bd7724c727856fbdf3ab71d2e4287ac8 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 8 Nov 2006 17:44:38 -0800 Subject: [PATCH] A minor fix for set_mb() in Documentation/memory-barriers.txt set_mb() is used by set_current_state() which needs mb(), not wmb(). I think it would be right to assume that set_mb() implies mb(), all arches seem to do just this. Signed-off-by: Oleg Nesterov Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 7f790f6..7751704 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -1016,7 +1016,7 @@ There are some more advanced barrier functions: (*) set_mb(var, value) - This assigns the value to the variable and then inserts at least a write + This assigns the value to the variable and then inserts a full memory barrier after it, depending on the function. It isn't guaranteed to insert anything more than a compiler barrier in a UP compilation. -- cgit v0.10.2 From af85852de0b32d92b14295aa6f5ba3a9ad044cf6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 8 Nov 2006 17:44:39 -0800 Subject: [PATCH] nfsd4: reindent do_open_lookup() Minor rearrangement, cleanup of do_open_lookup(). No change in behavior. Signed-off-by: J. Bruce Fields Acked-by: Neil Brown Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0a7bbdc..4a73f5b 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -106,27 +106,25 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o open->op_fname.len, &open->op_iattr, &resfh, open->op_createmode, (u32 *)open->op_verf.data, &open->op_truncate); - } - else { + } else { status = nfsd_lookup(rqstp, current_fh, open->op_fname.data, open->op_fname.len, &resfh); fh_unlock(current_fh); } + if (status) + goto out; - if (!status) { - set_change_info(&open->op_cinfo, current_fh); + set_change_info(&open->op_cinfo, current_fh); - /* set reply cache */ - fh_dup2(current_fh, &resfh); - open->op_stateowner->so_replay.rp_openfh_len = - resfh.fh_handle.fh_size; - memcpy(open->op_stateowner->so_replay.rp_openfh, - &resfh.fh_handle.fh_base, - resfh.fh_handle.fh_size); + /* set reply cache */ + fh_dup2(current_fh, &resfh); + open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size; + memcpy(open->op_stateowner->so_replay.rp_openfh, + &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size); - status = do_open_permission(rqstp, current_fh, open, MAY_NOP); - } + status = do_open_permission(rqstp, current_fh, open, MAY_NOP); +out: fh_put(&resfh); return status; } -- cgit v0.10.2 From 81ac95c5569d7a60ab5db6c1ccec56c12b3ebcb5 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 8 Nov 2006 17:44:40 -0800 Subject: [PATCH] nfsd4: fix open-create permissions In the case where an open creates the file, we shouldn't be rechecking permissions to open the file; the open succeeds regardless of what the new file's mode bits say. This patch fixes the problem, but only by introducing yet another parameter to nfsd_create_v3. This is ugly. This will be fixed by later patches. Signed-off-by: J. Bruce Fields Acked-by: Neil Brown Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 64db601..7f5bad0 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -258,7 +258,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, /* Now create the file and set attributes */ nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, attr, newfhp, - argp->createmode, argp->verf, NULL); + argp->createmode, argp->verf, NULL, NULL); RETURN_STATUS(nfserr); } diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 4a73f5b..50bc942 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -93,6 +93,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o { struct svc_fh resfh; __be32 status; + int created = 0; fh_init(&resfh, NFS4_FHSIZE); open->op_truncate = 0; @@ -105,7 +106,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, open->op_fname.len, &open->op_iattr, &resfh, open->op_createmode, - (u32 *)open->op_verf.data, &open->op_truncate); + (u32 *)open->op_verf.data, &open->op_truncate, &created); } else { status = nfsd_lookup(rqstp, current_fh, open->op_fname.data, open->op_fname.len, &resfh); @@ -122,7 +123,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o memcpy(open->op_stateowner->so_replay.rp_openfh, &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size); - status = do_open_permission(rqstp, current_fh, open, MAY_NOP); + if (!created) + status = do_open_permission(rqstp, current_fh, open, MAY_NOP); out: fh_put(&resfh); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f21e917..1a7ad8c 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1237,7 +1237,7 @@ __be32 nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, char *fname, int flen, struct iattr *iap, struct svc_fh *resfhp, int createmode, u32 *verifier, - int *truncp) + int *truncp, int *created) { struct dentry *dentry, *dchild = NULL; struct inode *dirp; @@ -1331,6 +1331,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); if (host_err < 0) goto out_nfserr; + if (created) + *created = 1; if (EX_ISSYNC(fhp->fh_export)) { err = nfserrno(nfsd_sync_dir(dentry)); diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index eb23114..edb54c3 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -89,7 +89,7 @@ __be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); __be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, struct svc_fh *res, int createmode, - u32 *verifier, int *truncp); + u32 *verifier, int *truncp, int *created); __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, loff_t, unsigned long); #endif /* CONFIG_NFSD_V3 */ -- cgit v0.10.2 From c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Wed, 8 Nov 2006 17:44:41 -0800 Subject: [PATCH] i386: Force data segment to be 4K aligned o Currently there is no specific alignment restriction in linker script and in some cases it can be placed non 4K aligned addresses. This fails kexec which checks that segment to be loaded is page aligned. o I guess, it does not harm data segment to be 4K aligned. Signed-off-by: Vivek Goyal Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index adc1f23..c6f84a0 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -51,6 +51,7 @@ SECTIONS __tracedata_end = .; /* writeable */ + . = ALIGN(4096); .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ *(.data) CONSTRUCTORS -- cgit v0.10.2 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 diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d13bb15..4510ad8 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 v0.10.2 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 diff --git a/drivers/md/dm.c b/drivers/md/dm.c index b5764a8..fc4f743 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 v0.10.2 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 diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index c5a16c5..6f9fcd4 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 v0.10.2 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 diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 659224c..48a653b 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 v0.10.2 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 diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index fbea454..8d69bcd 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 v0.10.2 From b5b9df697b166948f2770fb65d1b8809637a199b Mon Sep 17 00:00:00 2001 From: Tigran Aivazian Date: Wed, 8 Nov 2006 17:44:46 -0800 Subject: [PATCH] Tigran has moved Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/CREDITS b/CREDITS index 5329ead..606d407 100644 --- a/CREDITS +++ b/CREDITS @@ -45,7 +45,7 @@ S: Longford, Ireland S: Sydney, Australia N: Tigran A. Aivazian -E: tigran@veritas.com +E: tigran@aivazian.fsnet.co.uk W: http://www.moses.uklinux.net/patches D: BFS filesystem D: Intel IA32 CPU microcode update support diff --git a/MAINTAINERS b/MAINTAINERS index d708702..8732dae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -493,7 +493,7 @@ S: Maintained BFS FILE SYSTEM P: Tigran A. Aivazian -M: tigran@veritas.com +M: tigran@aivazian.fsnet.co.uk L: linux-kernel@vger.kernel.org S: Maintained @@ -1513,7 +1513,7 @@ S: Maintained INTEL IA32 MICROCODE UPDATE SUPPORT P: Tigran Aivazian -M: tigran@veritas.com +M: tigran@aivazian.fsnet.co.uk S: Maintained INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT -- cgit v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index d111356..ae50a24 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 v0.10.2 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 diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e14f457..69c3e20 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 v0.10.2 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 diff --git a/drivers/md/md.c b/drivers/md/md.c index ae50a24..8cbf9c9 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 v0.10.2 From 8bdc052eccdc7893d075d3f1f7103594a458c8c4 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 8 Nov 2006 17:44:49 -0800 Subject: [PATCH] kretprobe: fix kretprobe-booster to save regs and set status There are two bugs in the kretprobe-booster. 1) It doesn't make room for gs registers. 2) It doesn't change status of the current kprobe. This status will effect the fault handling. This patch fixes these bugs and, additionally, saves skipped registers for compatibility with the original kretprobe. Signed-off-by: Masami Hiramatsu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index d98e44b..fc79e1e 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -361,8 +361,11 @@ no_kprobe: asm volatile ( ".global kretprobe_trampoline\n" "kretprobe_trampoline: \n" " pushf\n" - /* skip cs, eip, orig_eax, es, ds */ - " subl $20, %esp\n" + /* skip cs, eip, orig_eax */ + " subl $12, %esp\n" + " pushl %gs\n" + " pushl %ds\n" + " pushl %es\n" " pushl %eax\n" " pushl %ebp\n" " pushl %edi\n" @@ -373,10 +376,10 @@ no_kprobe: " movl %esp, %eax\n" " call trampoline_handler\n" /* move eflags to cs */ - " movl 48(%esp), %edx\n" - " movl %edx, 44(%esp)\n" + " movl 52(%esp), %edx\n" + " movl %edx, 48(%esp)\n" /* save true return address on eflags */ - " movl %eax, 48(%esp)\n" + " movl %eax, 52(%esp)\n" " popl %ebx\n" " popl %ecx\n" " popl %edx\n" @@ -384,8 +387,8 @@ no_kprobe: " popl %edi\n" " popl %ebp\n" " popl %eax\n" - /* skip eip, orig_eax, es, ds */ - " addl $16, %esp\n" + /* skip eip, orig_eax, es, ds, gs */ + " addl $20, %esp\n" " popf\n" " ret\n"); } @@ -404,6 +407,10 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs) INIT_HLIST_HEAD(&empty_rp); spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); + /* fixup registers */ + regs->xcs = __KERNEL_CS; + regs->eip = trampoline_address; + regs->orig_eax = 0xffffffff; /* * It is possible to have multiple instances associated with a given @@ -425,6 +432,7 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs) if (ri->rp && ri->rp->handler){ __get_cpu_var(current_kprobe) = &ri->rp->kp; + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; ri->rp->handler(ri, regs); __get_cpu_var(current_kprobe) = NULL; } -- cgit v0.10.2 From 6c33eb39976b67628452ebc791834c7d590e545e Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 8 Nov 2006 17:44:50 -0800 Subject: [PATCH] ia64: select ACPI_NUMA if ACPI When ACPI && NUMA, pxm_to_node is used and it exists in drivers/acpi/numa.c Tony said: The patch makes sense ... if you pick both of "ACPI" and "NUMA", then you need (and should automatically be given) ACPI_NUMA too. The only open question is whether there is a better way of getting there. Perhaps with less configuration options in the first place? We are heading towards a future where so many systems will be NUMA that there would seem to be little benefit in keeping ACPI_NUMA separate from ACPI ... but perhaps we aren't quite there yet. Signed-off-by: KAMEZAWA Hiroyuki Cc: Len Brown Acked-by: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 70f7eb9..1468239 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -341,6 +341,7 @@ config NUMA bool "NUMA support" depends on !IA64_HP_SIM && !FLATMEM default y if IA64_SGI_SN2 + select ACPI_NUMA if ACPI help Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor -- cgit v0.10.2 From 13bb7e37e5081d03643e2bd64f3f5d21f32e7221 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 8 Nov 2006 17:44:51 -0800 Subject: [PATCH] sysctl: Undeprecate sys_sysctl The basic issue is that despite have been deprecated and warned about as a very bad thing in the man pages since its inception there are a few real users of sys_sysctl. It was my assumption that because sysctl had been deprecated for all of 2.6 there would be no user space users by this point, so I initially gave sys_sysctl a very short deprecation period. Now that I know there are a few real users the only sane way to proceed with deprecation is to push the time limit out to a year or two work and work with distributions that have big testing pools like fedora core to find these last remaining users. Which means that the sys_sysctl interface needs to be maintained in the meantime. Since I have provided a technical measure that allows us to add new sysctl entries without reserving more binary numbers I believe that is enough to fix the sys_sysctl binary interface maintenance problems, because there is no longer a need to change the binary interface at all. Since the sys_sysctl implementation needs to stay around for a while and the worst of the maintenance issues that caused us to occasionally break the ABI have been addressed I don't see any advantage in continuing with the removal of sys_sysctl. So instead of merely increasing the deprecation period this patch removes the deprecation of sys_sysctl and modifies the kernel to compile the code in by default. With committing to maintain sys_sysctl we get all of the advantages of a fast interface for anything that needs it. Currently sys_sysctl is about 5x faster than /proc/sys, for the same string data. Signed-off-by: Eric W. Biederman Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 1ac3c74..d52c4aa 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -53,18 +53,6 @@ Who: Mauro Carvalho Chehab --------------------------- -What: sys_sysctl -When: January 2007 -Why: The same information is available through /proc/sys and that is the - interface user space prefers to use. And there do not appear to be - any existing user in user space of sys_sysctl. The additional - maintenance overhead of keeping a set of binary names gets - in the way of doing a good job of maintaining this interface. - -Who: Eric Biederman - ---------------------------- - What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl]) When: November 2005 Files: drivers/pcmcia/: pcmcia_ioctl.c diff --git a/init/Kconfig b/init/Kconfig index c8b2624..176f7e5 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -304,20 +304,19 @@ config UID16 config SYSCTL_SYSCALL bool "Sysctl syscall support" if EMBEDDED - default n + default y select SYSCTL ---help--- - Enable the deprecated sysctl system call. sys_sysctl uses - binary paths that have been found to be a major pain to maintain - and use. The interface in /proc/sys is now the primary and what - everyone uses. + sys_sysctl uses binary paths that have been found challenging + to properly maintain and use. The interface in /proc/sys + using paths with ascii names is now the primary path to this + information. - Nothing has been using the binary sysctl interface for some - time now so nothing should break if you disable sysctl syscall - support, and your kernel will get marginally smaller. + Almost nothing using the binary sysctl interface so if you are + trying to save some space it is probably safe to disable this, + making your kernel marginally smaller. - Unless you have an application that uses the sys_sysctl interface - you should probably say N here. + If unsure say Y here. config KALLSYMS bool "Load all symbols for debugging/kksymoops" if EMBEDDED -- cgit v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 34a4fd1..e55a0d2 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 v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e55a0d2..0b07ca1 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 22f5e2a..4d04d8b 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 v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 157fa81..abc5149 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 v0.10.2 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 diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 507983c..ad84bc2 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 3b8f9c6..41bfc49 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 0e27f24..e346fe3 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 1f15ce2..108f0d9 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 v0.10.2 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 diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index e346fe3..0a8d1cc 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. */ @@ -145,6 +148,21 @@ int ht_create_irq(struct pci_dev *dev, int idx) } /** + * 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 * * This reverses ht_create_irq removing the specified irq from @@ -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 108f0d9..c96ea46 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index b4ffaa7..09a13c1 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 9e4e8d4..e57c7a3 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 a72ab9d..6af8968 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 d9079ee..5652a55 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 06d5020..986b212 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 v0.10.2 From 088406bcf66d6c7fd8a5c04c00aa410ae9077403 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 8 Nov 2006 17:44:59 -0800 Subject: [PATCH] nfsd: fix spurious error return from nfsd_create in async case Commit 6264d69d7df654ca64f625e9409189a0e50734e9 modified the nfsd_create() error handling in such a way that nfsd_create will usually return nfserr_perm even when succesful, if the export has the async export option. This introduced a regression that could cause mkdir() to always return a permissions error, even though the directory in question was actually succesfully created. Signed-off-by: J. Bruce Fields Acked-by: NeilBrown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1a7ad8c..bb4d926 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1177,7 +1177,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, /* * Get the dir op function pointer. */ - err = nfserr_perm; + err = 0; switch (type) { case S_IFREG: host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); -- cgit v0.10.2 From 621da0f8af228525e4b40390e36fbdc44a587cf1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 9 Nov 2006 16:00:06 +1100 Subject: [POWERPC] Make sure initrd and dtb sections get into zImage correctly The "wrapper" script was using the wrong names for the initrd and dtb (device-tree blob) sections. This fixes it, and also ensures the symbols for the start and end of the dtb get defined correctly. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index eab7318..b5fb1fe 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -179,11 +179,11 @@ if [ -z "$cacheit" ]; then fi if [ -n "$initrd" ]; then - addsec $tmp "$initrd" initrd + addsec $tmp "$initrd" $isection fi if [ -n "$dtb" ]; then - addsec $tmp "$dtb" dtb + addsec $tmp "$dtb" .kernel:dtb fi if [ "$platform" != "miboot" ]; then diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4b6bb3f..4be3c64 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -21,6 +21,11 @@ SECTIONS __got2_end = .; } + . = ALIGN(8); + _dtb_start = .; + .kernel:dtb : { *(.kernel:dtb) } + _dtb_end = .; + . = ALIGN(4096); _vmlinux_start = .; .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) } -- cgit v0.10.2 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 diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 3c2d7a3..af7e011 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 7b6aca0..c6c3d18 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 a4cc432..57c5ba4 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 64d2317..9050e93 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 7ee49b5..b15caf1 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 56e4b3b..8451125 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 42281c3..9e715e5 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 v0.10.2 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 diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 30b8014..e34a934 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 v0.10.2 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 diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 5f8c26c..b091a0f 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 e5685be..7901517 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 v0.10.2 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 diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3f8b931..81e3bc7 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 v0.10.2 From eb5d5829b368c5e32f248a70797bee5a414a2ef0 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Thu, 9 Nov 2006 00:34:27 -0500 Subject: Input: psmouse - fix attribute access on 64-bit systems psmouse_show_int_attr() and psmouse_set_int_attr() were accessing unsigned int fields as unsigned long, which gave garbage on x86_64. Signed-off-by: Sergey Vlasov Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 9144df6..58beca9 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1349,14 +1349,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf) { - unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); - return sprintf(buf, "%lu\n", *field); + return sprintf(buf, "%u\n", *field); } static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count) { - unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); unsigned long value; char *rest; @@ -1364,6 +1364,9 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const if (*rest) return -EINVAL; + if ((unsigned int)value != value) + return -EINVAL; + *field = value; return count; -- cgit v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ee8863c..ec8168a 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 v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ec8168a..766bc544 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 v0.10.2 From 8cc05f79d2a4e33d5cb621f36a448d5157f46893 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Tue, 17 Oct 2006 11:16:22 +0100 Subject: [ARM] 3857/2: pnx4008: add devices' registration This patch adds platform devices' registration for the devices which drivers either have been added to the mainline or on the way to. arch/arm/mach-pnx4008/core.c | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) Signed-off-by: Vitaly Wool Signed-off-by: Russell King diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c index 3d73c1e..429c796 100644 --- a/arch/arm/mach-pnx4008/core.c +++ b/arch/arm/mach-pnx4008/core.c @@ -133,10 +133,79 @@ static struct platform_device serial_device = { }, }; +static struct platform_device nand_flash_device = { + .name = "pnx4008-flash", + .id = -1, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = ~(u32) 0; + +static struct resource ohci_resources[] = { + { + .start = IO_ADDRESS(PNX4008_USB_CONFIG_BASE), + .end = IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x100), + .flags = IORESOURCE_MEM, + }, { + .start = USB_HOST_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ohci_device = { + .name = "pnx4008-usb-ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(ohci_resources), + .resource = ohci_resources, +}; + +static struct platform_device sdum_device = { + .name = "pnx4008-sdum", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct platform_device rgbfb_device = { + .name = "pnx4008-rgbfb", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + } +}; + +struct resource watchdog_resources[] = { + { + .start = PNX4008_WDOG_BASE, + .end = PNX4008_WDOG_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device watchdog_device = { + .name = "pnx4008-watchdog", + .id = -1, + .num_resources = ARRAY_SIZE(watchdog_resources), + .resource = watchdog_resources, +}; + static struct platform_device *devices[] __initdata = { &spipnx_1, &spipnx_2, &serial_device, + &ohci_device, + &nand_flash_device, + &sdum_device, + &rgbfb_device, + &watchdog_device, }; -- cgit v0.10.2 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 diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 5eae6ac..e1b618c 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 048cc44..c3ea746 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 319c39d..3720e30 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 024d511..01f5aa9 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 5ca6544..abce676 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 4394123..cf3e50e 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 v0.10.2 From f7b2e8c76b3423a1d2501b9399261e9c9a33e100 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 9 Nov 2006 21:25:37 +0000 Subject: [CIFS] Fix minor problem with previous patch The patch NFS stress test generates flood of "close with pending write was missing an if Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 4b07a8c..2436ed8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -498,7 +498,8 @@ int cifs_close(struct inode *inode, struct file *file) msleep(timeout); timeout *= 4; } - cERROR(1,("close with pending writes")); + if(atomic_read(&pSMBFile->wrtPending)) + cERROR(1,("close with pending writes")); rc = CIFSSMBClose(xid, pTcon, pSMBFile->netfid); } -- cgit v0.10.2 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 diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0a9dbc5..c0b8b33 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 v0.10.2 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 diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2865ebd..5d88621 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 v0.10.2 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 diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index c0b8b33..d0b139c 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 v0.10.2 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 diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2d3baa9..9b25124 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 v0.10.2 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 diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 4bc14ad..4c698a7 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 v0.10.2 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 diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index ac0419e..899e89d 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 v0.10.2 From da413908d5e9ebdd0889a599e80d21d7237021c6 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 9 Nov 2006 20:00:55 -0800 Subject: [IPVS]: Compile fix for annotations in userland. This change makes __beXX available to user-space applications, such as ipvsadm, which include ip_vs.h Signed-Off-By: Simon Horman Signed-off-by: David S. Miller diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 49c717e..903108e 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -7,6 +7,7 @@ #define _IP_VS_H #include /* For __uXX types */ +#include /* For __beXX types in userland */ #define IP_VS_VERSION_CODE 0x010201 #define NVERSION(version) \ -- cgit v0.10.2 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 diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 0abb544..32fd8c8 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 v0.10.2 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 diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index a8f894c..69715e5 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 32fd8c8..7a3b97f 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 95afc37..08e55fd 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 v0.10.2 From ae883cab9457aad0fb3342249e1207873d3b64de Mon Sep 17 00:00:00 2001 From: John Rose Date: Wed, 8 Nov 2006 10:07:30 -0600 Subject: [POWERPC] pseries: Force 4k update_flash block and list sizes The enablement of 64k pages on pseries platforms exposed a bug in the RTAS mechanism for updating firmware. RTAS assumes 4k for flash block and list sizes, and use of any other sizes results in a failure, even though PAPR does not specify any such requirement. This patch changes the rtas_flash module to force the use of 4k memory block and list sizes when preparing and sending a firmware image to RTAS. The rtas_flash function now uses a slab cache of 4k blocks with 4k alignment, rather than get_zeroed_page(), to allocate the memory for the flash blocks and lists. The 4k alignment requirement is specified in PAPR. Signed-off-by: John Rose Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 1442b63..6f6fc97 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -72,6 +72,10 @@ #define VALIDATE_BUF_SIZE 4096 #define RTAS_MSG_MAXLEN 64 +/* Quirk - RTAS requires 4k list length and block size */ +#define RTAS_BLKLIST_LENGTH 4096 +#define RTAS_BLK_SIZE 4096 + struct flash_block { char *data; unsigned long length; @@ -83,7 +87,7 @@ struct flash_block { * into a version/length and translate the pointers * to absolute. */ -#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) +#define FLASH_BLOCKS_PER_NODE ((RTAS_BLKLIST_LENGTH - 16) / sizeof(struct flash_block)) struct flash_block_list { unsigned long num_blocks; struct flash_block_list *next; @@ -96,6 +100,9 @@ struct flash_block_list_header { /* just the header of flash_block_list */ static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; +/* Use slab cache to guarantee 4k alignment */ +static kmem_cache_t *flash_block_cache = NULL; + #define FLASH_BLOCK_LIST_VERSION (1UL) /* Local copy of the flash block list. @@ -153,7 +160,7 @@ static int flash_list_valid(struct flash_block_list *flist) return FLASH_IMG_NULL_DATA; } block_size = f->blocks[i].length; - if (block_size <= 0 || block_size > PAGE_SIZE) { + if (block_size <= 0 || block_size > RTAS_BLK_SIZE) { return FLASH_IMG_BAD_LEN; } image_size += block_size; @@ -177,9 +184,9 @@ static void free_flash_list(struct flash_block_list *f) while (f) { for (i = 0; i < f->num_blocks; i++) - free_page((unsigned long)(f->blocks[i].data)); + kmem_cache_free(flash_block_cache, f->blocks[i].data); next = f->next; - free_page((unsigned long)f); + kmem_cache_free(flash_block_cache, f); f = next; } } @@ -278,6 +285,12 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, return msglen; } +/* constructor for flash_block_cache */ +void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) +{ + memset(ptr, 0, RTAS_BLK_SIZE); +} + /* We could be much more efficient here. But to keep this function * simple we allocate a page to the block list no matter how small the * count is. If the system is low on memory it will be just as well @@ -302,7 +315,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, * proc file */ if (uf->flist == NULL) { - uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); + uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); if (!uf->flist) return -ENOMEM; } @@ -313,21 +326,21 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, next_free = fl->num_blocks; if (next_free == FLASH_BLOCKS_PER_NODE) { /* Need to allocate another block_list */ - fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); + fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); if (!fl->next) return -ENOMEM; fl = fl->next; next_free = 0; } - if (count > PAGE_SIZE) - count = PAGE_SIZE; - p = (char *)get_zeroed_page(GFP_KERNEL); + if (count > RTAS_BLK_SIZE) + count = RTAS_BLK_SIZE; + p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); if (!p) return -ENOMEM; if(copy_from_user(p, buffer, count)) { - free_page((unsigned long)p); + kmem_cache_free(flash_block_cache, p); return -EFAULT; } fl->blocks[next_free].data = p; @@ -791,6 +804,16 @@ int __init rtas_flash_init(void) goto cleanup; rtas_flash_term_hook = rtas_flash_firmware; + + flash_block_cache = kmem_cache_create("rtas_flash_cache", + RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, + rtas_block_ctor, NULL); + if (!flash_block_cache) { + printk(KERN_ERR "%s: failed to create block cache\n", + __FUNCTION__); + rc = -ENOMEM; + goto cleanup; + } return 0; cleanup: @@ -805,6 +828,10 @@ cleanup: void __exit rtas_flash_cleanup(void) { rtas_flash_term_hook = NULL; + + if (flash_block_cache) + kmem_cache_destroy(flash_block_cache); + remove_flash_pde(firmware_flash_pde); remove_flash_pde(firmware_update_pde); remove_flash_pde(validate_pde); -- cgit v0.10.2 From ab56dbddc8a23ff3f4602855aaf0fcb3c814118b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 10 Nov 2006 15:11:20 +1100 Subject: [POWERPC] Fix cell "new style" mapping and add debug This fixes a typo in the "new style" code for mapping SPE resources, which causes it to try to map the same resource 4 times. It also adds some pr_debug's that are useful to track down issues with the firmware when bringinh up new machines. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d0fb959..7aa809d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -655,14 +655,19 @@ static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) for (i=0; i < 3; i++) { ret = of_irq_map_one(np, i, &oirq); - if (ret) + if (ret) { + pr_debug("spu_new: failed to get irq %d\n", i); goto err; - + } ret = -EINVAL; + pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], + oirq.controller->full_name); spu->irqs[i] = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); - if (spu->irqs[i] == NO_IRQ) + if (spu->irqs[i] == NO_IRQ) { + pr_debug("spu_new: failed to map it !\n"); goto err; + } } return 0; @@ -681,7 +686,7 @@ static int spu_map_resource(struct device_node *node, int nr, struct resource resource = { }; int ret; - ret = of_address_to_resource(node, 0, &resource); + ret = of_address_to_resource(node, nr, &resource); if (ret) goto out; @@ -704,22 +709,42 @@ static int __init spu_map_device(struct spu *spu, struct device_node *node) ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, &spu->local_store_phys); - if (ret) + if (ret) { + pr_debug("spu_new: failed to map %s resource 0\n", + node->full_name); goto out; + } ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, &spu->problem_phys); - if (ret) + if (ret) { + pr_debug("spu_new: failed to map %s resource 1\n", + node->full_name); goto out_unmap; + } ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, NULL); - if (ret) + if (ret) { + pr_debug("spu_new: failed to map %s resource 2\n", + node->full_name); goto out_unmap; + } if (!firmware_has_feature(FW_FEATURE_LPAR)) ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, NULL); - if (ret) + if (ret) { + pr_debug("spu_new: failed to map %s resource 3\n", + node->full_name); goto out_unmap; + } + pr_debug("spu_new: %s maps:\n", node->full_name); + pr_debug(" local store : 0x%016lx -> 0x%p\n", + spu->local_store_phys, spu->local_store); + pr_debug(" problem state : 0x%016lx -> 0x%p\n", + spu->problem_phys, spu->problem); + pr_debug(" priv2 : 0x%p\n", spu->priv2); + pr_debug(" priv1 : 0x%p\n", spu->priv1); + return 0; out_unmap: -- cgit v0.10.2 From 36b600f2649e3be49039efe31edeeb64277dbd99 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 2 Nov 2006 21:08:45 -0800 Subject: [POWERPC] cell: set ARCH_SPARSEMEM_DEFAULT in Kconfig The current cell processor support needs sparsemem, so set it as the default memory model. Signed-off-by: Geoff Levand Acked-by: Arnd Bergmann Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2bd9b7f..0673dbe 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -740,7 +740,7 @@ config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y - depends on SMP && PPC_PSERIES + depends on (SMP && PPC_PSERIES) || PPC_CELL config ARCH_POPULATES_NODE_MAP def_bool y -- cgit v0.10.2 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 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c0bbdda..17a4611 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 v0.10.2 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 diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 0dc70c7..aa9dd8f 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 v0.10.2 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 diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 966b563..a03d781 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 v0.10.2 From bb831eb2027c12a740ad4e4ad78f2a0e841ae808 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Fri, 10 Nov 2006 14:57:37 -0800 Subject: [IPVS]: More endianness fixed. - make sure port in FTP data is in network order (in fact it was looking buggy for big endian boxes before Viro's changes) - htonl -> htons for port Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c index 6d398f1..687c1de 100644 --- a/net/ipv4/ipvs/ip_vs_ftp.c +++ b/net/ipv4/ipvs/ip_vs_ftp.c @@ -200,7 +200,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, from = n_cp->vaddr; port = n_cp->vport; sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from), - ntohs(port)&255, (ntohs(port)>>8)&255); + (ntohs(port)>>8)&255, ntohs(port)&255); buf_len = strlen(buf); /* diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index bfe779e..6ff05c3 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -117,7 +117,7 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip, { tcph->check = ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ htonl(0xFFFF), + ip_vs_check_diff(oldport ^ htons(0xFFFF), newport, tcph->check)); } diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 54aa760..691c8b6 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -122,10 +122,10 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, { uhdr->check = ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ htonl(0xFFFF), + ip_vs_check_diff(oldport ^ htons(0xFFFF), newport, uhdr->check)); if (!uhdr->check) - uhdr->check = htonl(0xFFFF); + uhdr->check = -1; } static int @@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = htonl(0xFFFF); + udph->check = -1; IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", pp->name, udph->check, (char*)&(udph->check) - (char*)udph); @@ -228,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = 0xFFFF; + udph->check = -1; (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; } return 1; -- cgit v0.10.2 From 93c189c1148a5e39bcc8f62568f42a77f93477c5 Mon Sep 17 00:00:00 2001 From: Vlad Apostolov Date: Sat, 11 Nov 2006 18:03:49 +1100 Subject: [XFS] 956618: Linux crashes on boot with XFS-DMAPI filesystem when CONFIG_XFS_TRACE is on SGI-PV: 956618 SGI-Modid: xfs-linux-melb:xfs-kern:27196a Signed-off-by: Vlad Apostolov Signed-off-by: Tim Shimmin diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 291948d..b49989b 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -21,22 +21,7 @@ EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char XFS_LINUX := linux-2.6 ifeq ($(CONFIG_XFS_DEBUG),y) - EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG - EXTRA_CFLAGS += -DXFS_BUF_LOCK_TRACKING -endif -ifeq ($(CONFIG_XFS_TRACE),y) - EXTRA_CFLAGS += -DXFS_ALLOC_TRACE - EXTRA_CFLAGS += -DXFS_ATTR_TRACE - EXTRA_CFLAGS += -DXFS_BLI_TRACE - EXTRA_CFLAGS += -DXFS_BMAP_TRACE - EXTRA_CFLAGS += -DXFS_BMBT_TRACE - EXTRA_CFLAGS += -DXFS_DIR2_TRACE - EXTRA_CFLAGS += -DXFS_DQUOT_TRACE - EXTRA_CFLAGS += -DXFS_ILOCK_TRACE - EXTRA_CFLAGS += -DXFS_LOG_TRACE - EXTRA_CFLAGS += -DXFS_RW_TRACE - EXTRA_CFLAGS += -DXFS_BUF_TRACE - EXTRA_CFLAGS += -DXFS_VNODE_TRACE + EXTRA_CFLAGS += -g endif obj-$(CONFIG_XFS_FS) += xfs.o diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index db5f5a3..d338284 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -15,6 +15,7 @@ * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "xfs.h" #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include "xfs_linux.h" STATIC kmem_zone_t *xfs_buf_zone; STATIC kmem_shaker_t xfs_buf_shake; @@ -1406,7 +1406,7 @@ xfs_alloc_bufhash( btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * - sizeof(xfs_bufhash_t), KM_SLEEP); + sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE); for (i = 0; i < (1 << btp->bt_hashshift); i++) { spin_lock_init(&btp->bt_hash[i].bh_lock); INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index c75f683..4363512 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -15,11 +15,9 @@ * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "debug.h" #include "spin.h" -#include -#include -#include static char message[256]; /* keep it off the stack */ static DEFINE_SPINLOCK(xfs_err_lock); diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 1a48dbb..bf0a120 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -17,5 +17,28 @@ */ #ifndef __XFS_H__ #define __XFS_H__ + +#ifdef CONFIG_XFS_DEBUG +#define STATIC +#define DEBUG 1 +#define XFS_BUF_LOCK_TRACKING 1 +/* #define QUOTADEBUG 1 */ +#endif + +#ifdef CONFIG_XFS_TRACE +#define XFS_ALLOC_TRACE 1 +#define XFS_ATTR_TRACE 1 +#define XFS_BLI_TRACE 1 +#define XFS_BMAP_TRACE 1 +#define XFS_BMBT_TRACE 1 +#define XFS_DIR2_TRACE 1 +#define XFS_DQUOT_TRACE 1 +#define XFS_ILOCK_TRACE 1 +#define XFS_LOG_TRACE 1 +#define XFS_RW_TRACE 1 +#define XFS_BUF_TRACE 1 +#define XFS_VNODE_TRACE 1 +#endif + #include #endif /* __XFS_H__ */ -- cgit v0.10.2 From 439b8434792d0b62e32ab1416f214a18a640cc03 Mon Sep 17 00:00:00 2001 From: Tim Shimmin Date: Sat, 11 Nov 2006 18:04:34 +1100 Subject: [XFS] Keep lockdep happy. SGI-PV: 956964 SGI-Modid: xfs-linux-melb:xfs-kern:27200a Signed-off-by: Tim Shimmin Signed-off-by: David Chinner Signed-off-by: Eric Sandeen diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b73d216..1562ac2 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -683,6 +683,7 @@ xfs_ireclaim(xfs_inode_t *ip) /* * Free all memory associated with the inode. */ + xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); xfs_idestroy(ip); } -- cgit v0.10.2 From 70a505285f9859f77e07f7c12371b0d29ecf3d82 Mon Sep 17 00:00:00 2001 From: Vlad Apostolov Date: Sat, 11 Nov 2006 18:04:41 +1100 Subject: [XFS] rename uio_read() to xfs_uio_read() SGI-PV: 957004 SGI-Modid: xfs-linux-melb:xfs-kern:27231a Signed-off-by: Vlad Apostolov Signed-off-by: Tim Shimmin diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c index caefa17..ac8617c 100644 --- a/fs/xfs/support/move.c +++ b/fs/xfs/support/move.c @@ -22,7 +22,7 @@ * as we go. */ int -uio_read(caddr_t src, size_t len, struct uio *uio) +xfs_uio_read(caddr_t src, size_t len, struct uio *uio) { size_t count; diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h index 97a2498..977879c 100644 --- a/fs/xfs/support/move.h +++ b/fs/xfs/support/move.h @@ -65,6 +65,6 @@ struct uio { typedef struct uio uio_t; typedef struct iovec iovec_t; -extern int uio_read (caddr_t, size_t, uio_t *); +extern int xfs_uio_read (caddr_t, size_t, uio_t *); #endif /* __XFS_SUPPORT_MOVE_H__ */ diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 8edbe1a..8e8e527 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -678,7 +678,7 @@ xfs_dir2_put_dirent64_uio( idbp->d_off = pa->cook; idbp->d_name[namelen] = '\0'; memcpy(idbp->d_name, pa->name, namelen); - rval = uio_read((caddr_t)idbp, reclen, uio); + rval = xfs_uio_read((caddr_t)idbp, reclen, uio); pa->done = (rval == 0); return rval; } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 061e2ff..2c79c36 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1013,7 +1013,7 @@ xfs_readlink( pathlen = (int)ip->i_d.di_size; if (ip->i_df.if_flags & XFS_IFINLINE) { - error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); + error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); } else { /* @@ -1044,7 +1044,7 @@ xfs_readlink( byte_cnt = pathlen; pathlen -= byte_cnt; - error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); + error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); xfs_buf_relse (bp); } -- cgit v0.10.2 From 2e2e7bb1fd857b9fc83b0cd77b6b647ebb423301 Mon Sep 17 00:00:00 2001 From: Vlad Apostolov Date: Sat, 11 Nov 2006 18:04:47 +1100 Subject: [XFS] 956664: dm_read_invis() changes i_atime SGI-PV: 956664 SGI-Modid: xfs-linux-melb:xfs-kern:27315a Signed-off-by: Vlad Apostolov Signed-off-by: Sam Vaughan Signed-off-by: Tim Shimmin diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index a74f854..74d09482 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -341,8 +341,11 @@ xfs_open_by_handle( put_unused_fd(new_fd); return -XFS_ERROR(-PTR_ERR(filp)); } - if (inode->i_mode & S_IFREG) + if (inode->i_mode & S_IFREG) { + /* invisible operation should not change atime */ + filp->f_flags |= O_NOATIME; filp->f_op = &xfs_invis_file_operations; + } fd_install(new_fd, filp); return new_fd; -- cgit v0.10.2 From 7a18c386078eaf17ae54595f66c0d64d9c1cb29c Mon Sep 17 00:00:00 2001 From: David Chinner Date: Sat, 11 Nov 2006 18:04:54 +1100 Subject: [XFS] Clean up i_flags and i_flags_lock handling. SGI-PV: 956832 SGI-Modid: xfs-linux-melb:xfs-kern:27358a Signed-off-by: David Chinner Signed-off-by: Nathan Scott Signed-off-by: Tim Shimmin diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 38c4d12..de05abb 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -227,9 +227,7 @@ xfs_initialize_vnode( xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); xfs_set_inodeops(inode); - spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~XFS_INEW; - spin_unlock(&ip->i_flags_lock); + xfs_iflags_clear(ip, XFS_INEW); barrier(); unlock_new_inode(inode); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 1562ac2..4b0c188 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -215,7 +215,7 @@ again: * If INEW is set this inode is being set up * we need to pause and try again. */ - if (ip->i_flags & XFS_INEW) { + if (xfs_iflags_test(ip, XFS_INEW)) { read_unlock(&ih->ih_lock); delay(1); XFS_STATS_INC(xs_ig_frecycle); @@ -230,7 +230,7 @@ again: * on its way out of the system, * we need to pause and try again. */ - if (ip->i_flags & XFS_IRECLAIM) { + if (xfs_iflags_test(ip, XFS_IRECLAIM)) { read_unlock(&ih->ih_lock); delay(1); XFS_STATS_INC(xs_ig_frecycle); @@ -243,9 +243,7 @@ again: XFS_STATS_INC(xs_ig_found); - spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~XFS_IRECLAIMABLE; - spin_unlock(&ip->i_flags_lock); + xfs_iflags_clear(ip, XFS_IRECLAIMABLE); version = ih->ih_version; read_unlock(&ih->ih_lock); xfs_ihash_promote(ih, ip, version); @@ -299,10 +297,7 @@ finish_inode: if (lock_flags != 0) xfs_ilock(ip, lock_flags); - spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~XFS_ISTALE; - spin_unlock(&ip->i_flags_lock); - + xfs_iflags_clear(ip, XFS_ISTALE); vn_trace_exit(vp, "xfs_iget.found", (inst_t *)__return_address); goto return_ip; @@ -371,10 +366,7 @@ finish_inode: ih->ih_next = ip; ip->i_udquot = ip->i_gdquot = NULL; ih->ih_version++; - spin_lock(&ip->i_flags_lock); - ip->i_flags |= XFS_INEW; - spin_unlock(&ip->i_flags_lock); - + xfs_iflags_set(ip, XFS_INEW); write_unlock(&ih->ih_lock); /* @@ -625,7 +617,7 @@ xfs_iput_new(xfs_inode_t *ip, vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); if ((ip->i_d.di_mode == 0)) { - ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE)); + ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); vn_mark_bad(vp); } if (inode->i_state & I_NEW) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c27d7d49..17d2a47 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2193,7 +2193,7 @@ xfs_ifree_cluster( /* Inode not in memory or we found it already, * nothing to do */ - if (!ip || (ip->i_flags & XFS_ISTALE)) { + if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { read_unlock(&ih->ih_lock); continue; } @@ -2215,10 +2215,7 @@ xfs_ifree_cluster( if (ip == free_ip) { if (xfs_iflock_nowait(ip)) { - spin_lock(&ip->i_flags_lock); - ip->i_flags |= XFS_ISTALE; - spin_unlock(&ip->i_flags_lock); - + xfs_iflags_set(ip, XFS_ISTALE); if (xfs_inode_clean(ip)) { xfs_ifunlock(ip); } else { @@ -2231,9 +2228,7 @@ xfs_ifree_cluster( if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { if (xfs_iflock_nowait(ip)) { - spin_lock(&ip->i_flags_lock); - ip->i_flags |= XFS_ISTALE; - spin_unlock(&ip->i_flags_lock); + xfs_iflags_set(ip, XFS_ISTALE); if (xfs_inode_clean(ip)) { xfs_ifunlock(ip); @@ -2263,9 +2258,7 @@ xfs_ifree_cluster( AIL_LOCK(mp,s); iip->ili_flush_lsn = iip->ili_item.li_lsn; AIL_UNLOCK(mp, s); - spin_lock(&iip->ili_inode->i_flags_lock); - iip->ili_inode->i_flags |= XFS_ISTALE; - spin_unlock(&iip->ili_inode->i_flags_lock); + xfs_iflags_set(ip, XFS_ISTALE); pre_flushed++; } lip = lip->li_bio_list; @@ -2764,7 +2757,7 @@ xfs_iunpin( struct inode *inode = NULL; spin_lock(&ip->i_flags_lock); - if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { + if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { bhv_vnode_t *vp = XFS_ITOV_NULL(ip); /* make sync come back and flush this inode */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e96eb08..bc82372 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -305,6 +305,47 @@ typedef struct xfs_inode { #endif } xfs_inode_t; + +/* + * i_flags helper functions + */ +static inline void +__xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) +{ + ip->i_flags |= flags; +} + +static inline void +xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) +{ + spin_lock(&ip->i_flags_lock); + __xfs_iflags_set(ip, flags); + spin_unlock(&ip->i_flags_lock); +} + +static inline void +xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags) +{ + spin_lock(&ip->i_flags_lock); + ip->i_flags &= ~flags; + spin_unlock(&ip->i_flags_lock); +} + +static inline int +__xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) +{ + return (ip->i_flags & flags); +} + +static inline int +xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) +{ + int ret; + spin_lock(&ip->i_flags_lock); + ret = __xfs_iflags_test(ip, flags); + spin_unlock(&ip->i_flags_lock); + return ret; +} #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 2c79c36..4c5d73c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3844,9 +3844,7 @@ xfs_reclaim( XFS_MOUNT_ILOCK(mp); vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); - spin_lock(&ip->i_flags_lock); - ip->i_flags |= XFS_IRECLAIMABLE; - spin_unlock(&ip->i_flags_lock); + xfs_iflags_set(ip, XFS_IRECLAIMABLE); XFS_MOUNT_IUNLOCK(mp); } return 0; @@ -3872,8 +3870,8 @@ xfs_finish_reclaim( */ write_lock(&ih->ih_lock); spin_lock(&ip->i_flags_lock); - if ((ip->i_flags & XFS_IRECLAIM) || - (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) { + if (__xfs_iflags_test(ip, XFS_IRECLAIM) || + (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) { spin_unlock(&ip->i_flags_lock); write_unlock(&ih->ih_lock); if (locked) { @@ -3882,7 +3880,7 @@ xfs_finish_reclaim( } return 1; } - ip->i_flags |= XFS_IRECLAIM; + __xfs_iflags_set(ip, XFS_IRECLAIM); spin_unlock(&ip->i_flags_lock); write_unlock(&ih->ih_lock); -- cgit v0.10.2 From 4c60658e0f4e253cf275f12b7c76bf128515a774 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Sat, 11 Nov 2006 18:05:00 +1100 Subject: [XFS] Prevent a deadlock when xfslogd unpins inodes. The previous fixes for the use after free in xfs_iunpin left a nasty log deadlock when xfslogd unpinned the inode and dropped the last reference to the inode. the ->clear_inode() method can issue transactions, and if the log was full, the transaction could push on the log and get stuck trying to push the inode it was currently unpinning. To fix this, we provide xfs_iunpin a guarantee that it will always have a valid xfs_inode <-> linux inode link or a particular flag will be set on the inode. We then use log forces during lookup to ensure transactions are completed before we recycle the inode. This ensures that xfs_iunpin will never use the linux inode after it is being freed, and any lookup on an inode on the reclaim list will wait until it is safe to attach a new linux inode to the xfs inode. SGI-PV: 956832 SGI-Modid: xfs-linux-melb:xfs-kern:27359a Signed-off-by: David Chinner Signed-off-by: Shailendra Tripathi Signed-off-by: Takenori Nagano Signed-off-by: Tim Shimmin diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 4b0c188..c1c89da 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -237,6 +237,36 @@ again: goto again; } + ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); + + /* + * If lookup is racing with unlink, then we + * should return an error immediately so we + * don't remove it from the reclaim list and + * potentially leak the inode. + */ + if ((ip->i_d.di_mode == 0) && + !(flags & XFS_IGET_CREATE)) { + read_unlock(&ih->ih_lock); + return ENOENT; + } + + /* + * There may be transactions sitting in the + * incore log buffers or being flushed to disk + * at this time. We can't clear the + * XFS_IRECLAIMABLE flag until these + * transactions have hit the disk, otherwise we + * will void the guarantee the flag provides + * xfs_iunpin() + */ + if (xfs_ipincount(ip)) { + read_unlock(&ih->ih_lock); + xfs_log_force(mp, 0, + XFS_LOG_FORCE|XFS_LOG_SYNC); + XFS_STATS_INC(xs_ig_frecycle); + goto again; + } vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 17d2a47..d72c80d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2741,42 +2741,39 @@ xfs_iunpin( { ASSERT(atomic_read(&ip->i_pincount) > 0); - if (atomic_dec_and_test(&ip->i_pincount)) { + if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { + /* - * If the inode is currently being reclaimed, the - * linux inode _and_ the xfs vnode may have been - * freed so we cannot reference either of them safely. - * Hence we should not try to do anything to them - * if the xfs inode is currently in the reclaim - * path. + * If the inode is currently being reclaimed, the link between + * the bhv_vnode and the xfs_inode will be broken after the + * XFS_IRECLAIM* flag is set. Hence, if these flags are not + * set, then we can move forward and mark the linux inode dirty + * knowing that it is still valid as it won't freed until after + * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The + * i_flags_lock is used to synchronise the setting of the + * XFS_IRECLAIM* flags and the breaking of the link, and so we + * can execute atomically w.r.t to reclaim by holding this lock + * here. * - * However, we still need to issue the unpin wakeup - * call as the inode reclaim may be blocked waiting for - * the inode to become unpinned. + * However, we still need to issue the unpin wakeup call as the + * inode reclaim may be blocked waiting for the inode to become + * unpinned. */ - struct inode *inode = NULL; - spin_lock(&ip->i_flags_lock); if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { bhv_vnode_t *vp = XFS_ITOV_NULL(ip); + struct inode *inode = NULL; + + BUG_ON(vp == NULL); + inode = vn_to_inode(vp); + BUG_ON(inode->i_state & I_CLEAR); /* make sync come back and flush this inode */ - if (vp) { - inode = vn_to_inode(vp); - - if (!(inode->i_state & - (I_NEW|I_FREEING|I_CLEAR))) { - inode = igrab(inode); - if (inode) - mark_inode_dirty_sync(inode); - } else - inode = NULL; - } + if (!(inode->i_state & (I_NEW|I_FREEING))) + mark_inode_dirty_sync(inode); } spin_unlock(&ip->i_flags_lock); wake_up(&ip->i_ipin_wait); - if (inode) - iput(inode); } } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 4c5d73c..bda774a 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3827,11 +3827,16 @@ xfs_reclaim( */ xfs_synchronize_atime(ip); - /* If we have nothing to flush with this inode then complete the - * teardown now, otherwise break the link between the xfs inode - * and the linux inode and clean up the xfs inode later. This - * avoids flushing the inode to disk during the delete operation - * itself. + /* + * If we have nothing to flush with this inode then complete the + * teardown now, otherwise break the link between the xfs inode and the + * linux inode and clean up the xfs inode later. This avoids flushing + * the inode to disk during the delete operation itself. + * + * When breaking the link, we need to set the XFS_IRECLAIMABLE flag + * first to ensure that xfs_iunpin() will never see an xfs inode + * that has a linux inode being reclaimed. Synchronisation is provided + * by the i_flags_lock. */ if (!ip->i_update_core && (ip->i_itemp == NULL)) { xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -3840,11 +3845,13 @@ xfs_reclaim( } else { xfs_mount_t *mp = ip->i_mount; - /* Protect sync from us */ + /* Protect sync and unpin from us */ XFS_MOUNT_ILOCK(mp); + spin_lock(&ip->i_flags_lock); + __xfs_iflags_set(ip, XFS_IRECLAIMABLE); vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); + spin_unlock(&ip->i_flags_lock); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); - xfs_iflags_set(ip, XFS_IRECLAIMABLE); XFS_MOUNT_IUNLOCK(mp); } return 0; -- cgit v0.10.2 From 050e714eb2bc662e9df6bf048ce86b4fbdd9bcd3 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Sat, 11 Nov 2006 18:05:06 +1100 Subject: [XFS] Remove KERNEL_VERSION macros from xfs_dmapi.h SGI-PV: 957005 SGI-Modid: xfs-linux-melb:xfs-kern:27398a Signed-off-by: David Chinner Signed-off-by: Michal Piotrowski Signed-off-by: Tim Shimmin diff --git a/fs/xfs/linux-2.6/xfs_dmapi_priv.h b/fs/xfs/linux-2.6/xfs_dmapi_priv.h new file mode 100644 index 0000000..a8b0b16 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_dmapi_priv.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2000-2006 Silicon Graphics, 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. + * + * This program is distributed in the hope that it would 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 the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __XFS_DMAPI_PRIV_H__ +#define __XFS_DMAPI_PRIV_H__ + +/* + * Based on IO_ISDIRECT, decide which i_ flag is set. + */ +#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ + DM_FLAGS_IMUX : 0) +#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) + +#endif /*__XFS_DMAPI_PRIV_H__*/ diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 4e7865a..adc3d25 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -157,27 +157,9 @@ typedef enum { #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ /* - * Based on IO_ISDIRECT, decide which i_ flag is set. + * Pull in platform specific event flags defines */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - DM_FLAGS_IMUX : 0) -#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)) -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX) -#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) -#endif - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - 0 : DM_FLAGS_IMUX) -#define DM_SEM_FLAG_WR (DM_FLAGS_IMUX) -#endif - +#include "xfs_dmapi_priv.h" /* * Macros to turn caller specified delay/block flags into -- cgit v0.10.2 From 6751718932be7325c898e5908daec2ee917afd09 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Nov 2006 22:54:07 +0000 Subject: [ARM] Remove PM_LEGACY=y from selected ARM defconfigs Most ARM defconfigs don't actually need to have PM_LEGACY enabled. Disable it for ATEB9200, Collie, IXP4xx, OMAP H2, S3C2410 and Versatile. Signed-off-by: Russell King diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig index 15e6b0b..3de5c64 100644 --- a/arch/arm/configs/ateb9200_defconfig +++ b/arch/arm/configs/ateb9200_defconfig @@ -217,7 +217,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y -CONFIG_PM_LEGACY=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set # CONFIG_APM is not set diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index 074c47a..a375891 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig @@ -219,7 +219,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y -CONFIG_PM_LEGACY=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set CONFIG_APM=y diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index 4975b91..fac7c3b 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -206,10 +206,8 @@ CONFIG_BINFMT_ELF=y # # Power management options # -CONFIG_PM=y -CONFIG_PM_LEGACY=y -# CONFIG_PM_DEBUG is not set -CONFIG_APM=y +# CONFIG_PM is not set +# CONFIG_APM is not set # # Networking diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig index 05adb0b..b0efd4c 100644 --- a/arch/arm/configs/omap_h2_1610_defconfig +++ b/arch/arm/configs/omap_h2_1610_defconfig @@ -257,7 +257,7 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y -CONFIG_PM_LEGACY=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set # CONFIG_APM is not set diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 0563c14..c0152393 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -258,7 +258,7 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y -CONFIG_PM_LEGACY=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set # CONFIG_PM_SYSFS_DEPRECATED is not set CONFIG_APM=y diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index 96b7a77..f7bf6ef 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -200,7 +200,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y -CONFIG_PM_LEGACY=y +# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set # CONFIG_APM is not set -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index d3e9998..a52ecad 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 e6a9f6f..81abdfa 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 0000000..4150839 --- /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 b6f29cb..7eac922 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 v0.10.2 From 74a9d5f1d140adbeadd5ef319f162903090c3b83 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 3 Nov 2006 09:52:49 +0100 Subject: [PATCH] Remove inclusion of asm/processor.h in via82cxxx.c There is some PPC_CHRP specific code in drivers/ide/pci/via82cxxx.c, so #ifdef on CONFIG_PPC_CHRP instead of CONFIG_PPC_MULTIPLATFORM. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 2af634d..eb7ab11 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -35,7 +35,7 @@ #include #include -#ifdef CONFIG_PPC_MULTIPLATFORM +#ifdef CONFIG_PPC_CHRP #include #endif @@ -442,7 +442,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) hwif->speedproc = &via_set_drive; -#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) +#ifdef CONFIG_PPC_CHRP if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { hwif->irq = hwif->channel ? 15 : 14; } -- cgit v0.10.2 From bfaadcadc9549c7e296e37a0cfe306704e8df739 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:55:57 +0100 Subject: [PATCH] Replace CONFIG_PPC_MULTIPLATFORM with CONFIG_PPC_PMAC in tulip driver Replace CONFIG_PPC_MULTIPLATFORM with CONFIG_PPC_PMAC in drivers/net/tulip/de4x5.c. It is needed for a pmac specific hook but has nothing with to do with PPC_MULTIPLATFORM. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 3f4b640..4b3cd3d 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -473,9 +473,9 @@ #include #include #include -#ifdef CONFIG_PPC_MULTIPLATFORM +#ifdef CONFIG_PPC_PMAC #include -#endif /* CONFIG_PPC_MULTIPLATFORM */ +#endif /* CONFIG_PPC_PMAC */ #include "de4x5.h" @@ -4151,7 +4151,7 @@ get_hw_addr(struct net_device *dev) /* If possible, try to fix a broken card - SMC only so far */ srom_repair(dev, broken); -#ifdef CONFIG_PPC_MULTIPLATFORM +#ifdef CONFIG_PPC_PMAC /* ** If the address starts with 00 a0, we have to bit-reverse ** each byte of the address. @@ -4168,7 +4168,7 @@ get_hw_addr(struct net_device *dev) dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); } } -#endif /* CONFIG_PPC_MULTIPLATFORM */ +#endif /* CONFIG_PPC_PMAC */ /* Test for a bad enet address */ status = test_bad_enet(dev, status); -- cgit v0.10.2 From 2b890bc2ce95e8c141b38ea86100826b46534295 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 6 Nov 2006 11:19:08 +0100 Subject: [PATCH] Remove dead code in iommu.h iommu_setup_pSeries() and iommu_setup_dart() are declared extern but are not implemented, so remove them. Remove ifdef around extern function declaration. Signed-off-by: Sascha Hauer Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index a5e9864..264ed62 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -52,17 +52,9 @@ struct iommu_table { struct scatterlist; struct device_node; -#ifdef CONFIG_PPC_MULTIPLATFORM - -/* Walks all buses and creates iommu tables */ -extern void iommu_setup_pSeries(void); -extern void iommu_setup_dart(void); - /* Frees table for an individual device node */ extern void iommu_free_table(struct device_node *dn); -#endif /* CONFIG_PPC_MULTIPLATFORM */ - /* Initializes an iommu_table based in values set in the passed-in * structure */ -- cgit v0.10.2 From 67764a03193d0246cf9bb491b41806508d415830 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:00 +0100 Subject: [PATCH] Remove unnecessary ifdef in include/asm-powerpc/pci.h Current kernels always have one of CONFIG_PPC_MULTIPLATFORM or CONFIG_PPC32 defined, so remove bogus ifdef. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 46afd29..051694f 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -238,12 +238,10 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, unsigned long size, pgprot_t prot); -#if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32) #define HAVE_ARCH_PCI_RESOURCE_TO_USER extern void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, resource_size_t *start, resource_size_t *end); -#endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */ #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_PCI_H */ -- cgit v0.10.2 From 68e1300a55310a288b87f2a7d6045df0d0f802bc Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:01 +0100 Subject: [PATCH] Remove _machine macro The _machine macro was once used for compatibility with ARCH=ppc drivers. It is unused in current kernels, so remove it. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 6cb6fb1..a26c32e 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -53,10 +53,6 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin; #endif /* CONFIG_PPC_PREP */ -#ifndef CONFIG_PPC_MULTIPLATFORM -#define _machine 0 -#endif /* CONFIG_PPC_MULTIPLATFORM */ - #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ /* -- cgit v0.10.2 From a7a1ed305043961ed06e0ee5e7a4a2cc1250f4b5 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:04 +0100 Subject: [PATCH] Remove occurences of PPC_MULTIPLATFORM in head_64.S Since iSeries is merged to MULTIPLATFORM, there is no way to build a 64bit kernel without MULTIPLATFORM, so PPC_MULTIPLATFORM can be removed in 64bit-only files. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 86e2bdd..ec754c9 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -736,8 +736,6 @@ _STATIC(rtas_restore_regs) #endif /* CONFIG_PPC_RTAS */ -#ifdef CONFIG_PPC_MULTIPLATFORM - _GLOBAL(enter_prom) mflr r0 std r0,16(r1) @@ -822,5 +820,3 @@ _GLOBAL(enter_prom) ld r0,16(r1) mtlr r0 blr - -#endif /* CONFIG_PPC_MULTIPLATFORM */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index d289005..76d1c81 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -72,13 +72,11 @@ .text .globl _stext _stext: -#ifdef CONFIG_PPC_MULTIPLATFORM _GLOBAL(__start) /* NOP this out unconditionally */ BEGIN_FTR_SECTION b .__start_initialization_multiplatform END_FTR_SECTION(0, 1) -#endif /* CONFIG_PPC_MULTIPLATFORM */ /* Catch branch to 0 in real mode */ trap @@ -1643,7 +1641,6 @@ _STATIC(__start_initialization_iSeries) b .start_here_common #endif /* CONFIG_PPC_ISERIES */ -#ifdef CONFIG_PPC_MULTIPLATFORM _STATIC(__mmu_off) mfmsr r3 @@ -1669,13 +1666,11 @@ _STATIC(__mmu_off) * */ _GLOBAL(__start_initialization_multiplatform) -#ifdef CONFIG_PPC_MULTIPLATFORM /* * Are we booted from a PROM Of-type client-interface ? */ cmpldi cr0,r5,0 bne .__boot_from_prom /* yes -> prom */ -#endif /* Save parameters */ mr r31,r3 @@ -1702,7 +1697,6 @@ _GLOBAL(__start_initialization_multiplatform) bl .__mmu_off b .__after_prom_start -#ifdef CONFIG_PPC_MULTIPLATFORM _STATIC(__boot_from_prom) /* Save parameters */ mr r31,r3 @@ -1742,7 +1736,6 @@ _STATIC(__boot_from_prom) bl .prom_init /* We never return */ trap -#endif /* * At this point, r3 contains the physical address we are running at, @@ -1798,8 +1791,6 @@ _STATIC(__after_prom_start) bl .copy_and_flush /* copy the rest */ b .start_here_multiplatform -#endif /* CONFIG_PPC_MULTIPLATFORM */ - /* * Copy routine used to copy the kernel to start at physical address 0 * and flush and invalidate the caches as needed. @@ -1964,7 +1955,6 @@ _GLOBAL(enable_64b_mode) isync blr -#ifdef CONFIG_PPC_MULTIPLATFORM /* * This is where the main kernel code starts. */ @@ -2035,7 +2025,6 @@ _STATIC(start_here_multiplatform) mtspr SPRN_SRR1,r4 rfid b . /* prevent speculative execution */ -#endif /* CONFIG_PPC_MULTIPLATFORM */ /* This is where all platforms converge execution */ _STATIC(start_here_common) -- cgit v0.10.2 From 99a565bab1a41819b9f85c8c069a2f3fc6e27d55 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:06 +0100 Subject: [PATCH] Remove occurences of PPC_MULTIPLATFORM in pci_64.c Since iSeries is merged to MULTIPLATFORM, there is no way to build a 64bit kernel without MULTIPLATFORM, so PPC_MULTIPLATFORM can be removed in 64bit-only files. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9bae8a5..80ae9ea 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -42,11 +42,9 @@ unsigned long pci_probe_only = 1; int pci_assign_all_buses = 0; -#ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); static void phbs_remap_io(void); -#endif /* pci_io_base -- the base address from which io bars are offsets. * This is the lowest I/O base address (so bar values are always positive), @@ -251,7 +249,6 @@ static void __init pcibios_claim_of_setup(void) pcibios_claim_one_bus(b); } -#ifdef CONFIG_PPC_MULTIPLATFORM static u32 get_int_prop(struct device_node *np, const char *name, u32 def) { const u32 *prop; @@ -506,7 +503,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node, pci_scan_child_bus(bus); } EXPORT_SYMBOL(of_scan_pci_bridge); -#endif /* CONFIG_PPC_MULTIPLATFORM */ void __devinit scan_phb(struct pci_controller *hose) { @@ -540,7 +536,7 @@ void __devinit scan_phb(struct pci_controller *hose) } mode = PCI_PROBE_NORMAL; -#ifdef CONFIG_PPC_MULTIPLATFORM + if (node && ppc_md.pci_probe_mode) mode = ppc_md.pci_probe_mode(bus); DBG(" probe mode: %d\n", mode); @@ -548,7 +544,7 @@ void __devinit scan_phb(struct pci_controller *hose) bus->subordinate = hose->last_busno; of_scan_bus(node, bus); } -#endif /* CONFIG_PPC_MULTIPLATFORM */ + if (mode == PCI_PROBE_NORMAL) hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); } @@ -592,11 +588,9 @@ static int __init pcibios_init(void) if (ppc64_isabridge_dev != NULL) printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); -#ifdef CONFIG_PPC_MULTIPLATFORM if (!firmware_has_feature(FW_FEATURE_ISERIES)) /* map in PCI I/O space */ phbs_remap_io(); -#endif printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); @@ -873,8 +867,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) device_create_file(&pdev->dev, &dev_attr_devspec); } -#ifdef CONFIG_PPC_MULTIPLATFORM - #define ISA_SPACE_MASK 0x1 #define ISA_SPACE_IO 0x1 @@ -1343,8 +1335,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) return NULL; } -#endif /* CONFIG_PPC_MULTIPLATFORM */ - unsigned long pci_address_to_pio(phys_addr_t address) { struct pci_controller *hose, *tmp; -- cgit v0.10.2 From fd6e7d2d6a0231ebfa08e1f9a323497ea548da7d Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:10 +0100 Subject: [PATCH] Clean up usage of boot_dev dev_t boot_dev is declared in arch/powerpc/kernel/setup_32.c and in arch/powerpc/kernel/setup_64.c but not used in these files. It is only used in arch/powerpc/platforms/powermac/setup.c, so make it static in this file. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 191d0ab..517ed1b 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE; int have_of = 1; -#ifdef CONFIG_PPC_MULTIPLATFORM -dev_t boot_dev; -#endif /* CONFIG_PPC_MULTIPLATFORM */ - #ifdef CONFIG_VGA_CONSOLE unsigned long vgacon_remap_base; #endif diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index b1b0cda..ae6b67c 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -71,7 +71,6 @@ int have_of = 1; int boot_cpuid = 0; -dev_t boot_dev; u64 ppc64_pft_size; /* Pick defaults since we might want to patch instructions diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 824a618..cb1c342 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -361,7 +361,7 @@ char *bootdevice; void *boot_host; int boot_target; int boot_part; -extern dev_t boot_dev; +static dev_t boot_dev; #ifdef CONFIG_SCSI void __init note_scsi_host(struct device_node *node, void *host) -- cgit v0.10.2 From 2fcd34291b650723091a06e4b51b546961f308a3 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:11 +0100 Subject: [PATCH] Make nvram_64.o a 64bit-only object Make nvram_64.o dependent on 64bit, not on MULTIPLATFORM. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8b133af..82c2238 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -17,7 +17,7 @@ obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o \ paca.o cpu_setup_ppc970.o \ - firmware.o sysfs.o + firmware.o sysfs.o nvram_64.o obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_PPC_970_NAP) += idle_power4.o @@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMEBUS) += ibmebus.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o -obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o -- cgit v0.10.2 From 0f6c95dcabdaa8fdc95b125582bd12625adfbde6 Mon Sep 17 00:00:00 2001 From: Nicolas DET Date: Wed, 8 Nov 2006 17:14:43 +0100 Subject: [PATCH] Add MPC5200 Interrupt Controller support. This adds support for the MPC52xx Interrupt controller for ARCH=powerpc. It includes the main code in arch/powerpc/sysdev/ as well as a header file in include/asm-powerpc. Signed-off-by: Nicolas DET Acked-by: Sylvain Munaut Acked-by: Grant Likely Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index f15af0e..5b87f7b 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ +obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_pic.o ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o diff --git a/arch/powerpc/sysdev/mpc52xx_pic.c b/arch/powerpc/sysdev/mpc52xx_pic.c new file mode 100644 index 0000000..6df51f0 --- /dev/null +++ b/arch/powerpc/sysdev/mpc52xx_pic.c @@ -0,0 +1,538 @@ +/* + * + * Programmable Interrupt Controller functions for the Freescale MPC52xx. + * + * Copyright (C) 2006 bplan GmbH + * + * Based on the code from the 2.4 kernel by + * Dale Farnsworth and Kent Borg. + * + * Copyright (C) 2004 Sylvain Munaut + * Copyright (C) 2003 Montavista Software, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * +*/ + +static struct mpc52xx_intr __iomem *intr; +static struct mpc52xx_sdma __iomem *sdma; +static struct irq_host *mpc52xx_irqhost = NULL; + +static unsigned char mpc52xx_map_senses[4] = { + IRQ_TYPE_LEVEL_HIGH, + IRQ_TYPE_EDGE_RISING, + IRQ_TYPE_EDGE_FALLING, + IRQ_TYPE_LEVEL_LOW, +}; + +/* + * +*/ + +static inline void io_be_setbit(u32 __iomem * addr, int bitno) +{ + out_be32(addr, in_be32(addr) | (1 << bitno)); +} + +static inline void io_be_clrbit(u32 __iomem * addr, int bitno) +{ + out_be32(addr, in_be32(addr) & ~(1 << bitno)); +} + +/* + * IRQ[0-3] interrupt irq_chip +*/ + +static void mpc52xx_extirq_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->ctrl, 11 - l2irq); +} + +static void mpc52xx_extirq_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->ctrl, 11 - l2irq); +} + +static void mpc52xx_extirq_ack(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->ctrl, 27 - l2irq); +} + +static struct irq_chip mpc52xx_extirq_irqchip = { + .typename = " MPC52xx IRQ[0-3] ", + .mask = mpc52xx_extirq_mask, + .unmask = mpc52xx_extirq_unmask, + .ack = mpc52xx_extirq_ack, +}; + +/* + * Main interrupt irq_chip +*/ + +static void mpc52xx_main_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->main_mask, 15 - l2irq); +} + +static void mpc52xx_main_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->main_mask, 15 - l2irq); +} + +static struct irq_chip mpc52xx_main_irqchip = { + .typename = "MPC52xx Main", + .mask = mpc52xx_main_mask, + .mask_ack = mpc52xx_main_mask, + .unmask = mpc52xx_main_unmask, +}; + +/* + * Peripherals interrupt irq_chip +*/ + +static void mpc52xx_periph_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->per_mask, 31 - l2irq); +} + +static void mpc52xx_periph_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->per_mask, 31 - l2irq); +} + +static struct irq_chip mpc52xx_periph_irqchip = { + .typename = "MPC52xx Peripherals", + .mask = mpc52xx_periph_mask, + .mask_ack = mpc52xx_periph_mask, + .unmask = mpc52xx_periph_unmask, +}; + +/* + * SDMA interrupt irq_chip +*/ + +static void mpc52xx_sdma_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&sdma->IntMask, l2irq); +} + +static void mpc52xx_sdma_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&sdma->IntMask, l2irq); +} + +static void mpc52xx_sdma_ack(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + out_be32(&sdma->IntPend, 1 << l2irq); +} + +static struct irq_chip mpc52xx_sdma_irqchip = { + .typename = "MPC52xx SDMA", + .mask = mpc52xx_sdma_mask, + .unmask = mpc52xx_sdma_unmask, + .ack = mpc52xx_sdma_ack, +}; + +/* + * irq_host +*/ + +static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node) +{ + pr_debug("%s: node=%p\n", __func__, node); + return mpc52xx_irqhost->host_data == node; +} + +static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, + u32 * intspec, unsigned int intsize, + irq_hw_number_t * out_hwirq, + unsigned int *out_flags) +{ + int intrvect_l1; + int intrvect_l2; + int intrvect_type; + int intrvect_linux; + + if (intsize != 3) + return -1; + + intrvect_l1 = (int)intspec[0]; + intrvect_l2 = (int)intspec[1]; + intrvect_type = (int)intspec[2]; + + intrvect_linux = + (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK; + intrvect_linux |= + (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK; + + pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1, + intrvect_l2); + + *out_hwirq = intrvect_linux; + *out_flags = mpc52xx_map_senses[intrvect_type]; + + return 0; +} + +/* + * this function retrieves the correct IRQ type out + * of the MPC regs + * Only externals IRQs needs this +*/ +static int mpc52xx_irqx_gettype(int irq) +{ + int type; + u32 ctrl_reg; + + ctrl_reg = in_be32(&intr->ctrl); + type = (ctrl_reg >> (22 - irq * 2)) & 0x3; + + return mpc52xx_map_senses[type]; +} + +static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t irq) +{ + int l1irq; + int l2irq; + struct irq_chip *good_irqchip; + void *good_handle; + int type; + + l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + /* + * Most of ours IRQs will be level low + * Only external IRQs on some platform may be others + */ + type = IRQ_TYPE_LEVEL_LOW; + + switch (l1irq) { + case MPC52xx_IRQ_L1_CRIT: + pr_debug("%s: Critical. l2=%x\n", __func__, l2irq); + + BUG_ON(l2irq != 0); + + type = mpc52xx_irqx_gettype(l2irq); + good_irqchip = &mpc52xx_extirq_irqchip; + break; + + case MPC52xx_IRQ_L1_MAIN: + pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq); + + if ((l2irq >= 1) && (l2irq <= 3)) { + type = mpc52xx_irqx_gettype(l2irq); + good_irqchip = &mpc52xx_extirq_irqchip; + } else { + good_irqchip = &mpc52xx_main_irqchip; + } + break; + + case MPC52xx_IRQ_L1_PERP: + pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq); + good_irqchip = &mpc52xx_periph_irqchip; + break; + + case MPC52xx_IRQ_L1_SDMA: + pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq); + good_irqchip = &mpc52xx_sdma_irqchip; + break; + + default: + pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq); + printk(KERN_ERR "Unknow IRQ!\n"); + return -EINVAL; + } + + switch (type) { + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_RISING: + good_handle = handle_edge_irq; + break; + default: + good_handle = handle_level_irq; + } + + set_irq_chip_and_handler(virq, good_irqchip, good_handle); + + pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq, + (int)irq, type); + + return 0; +} + +static struct irq_host_ops mpc52xx_irqhost_ops = { + .match = mpc52xx_irqhost_match, + .xlate = mpc52xx_irqhost_xlate, + .map = mpc52xx_irqhost_map, +}; + +/* + * init (public) +*/ + +void __init mpc52xx_init_irq(void) +{ + struct device_node *picnode = NULL; + int picnode_regsize; + u32 picnode_regoffset; + + struct device_node *sdmanode = NULL; + int sdmanode_regsize; + u32 sdmanode_regoffset; + + u64 size64; + int flags; + + u32 intr_ctrl; + + picnode = of_find_compatible_node(NULL, "interrupt-controller", + "mpc5200-pic"); + if (picnode == NULL) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to find the interrupt controller " + "in the OpenFirmware device tree\n"); + goto end; + } + + sdmanode = of_find_compatible_node(NULL, "dma-controller", + "mpc5200-bestcomm"); + if (sdmanode == NULL) { + printk(KERN_ERR "MPC52xx PIC" + "Unable to find the Bestcomm DMA controller device " + "in the OpenFirmware device tree\n"); + goto end; + } + + /* Retrieve PIC ressources */ + picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags); + if (picnode_regoffset == 0) { + printk(KERN_ERR "MPC52xx PIC" + "Unable to get the interrupt controller address\n"); + goto end; + } + + picnode_regoffset = + of_translate_address(picnode, (u32 *) picnode_regoffset); + picnode_regsize = (int)size64; + + /* Retrieve SDMA ressources */ + sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags); + if (sdmanode_regoffset == 0) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to get the Bestcomm DMA controller address\n"); + goto end; + } + + sdmanode_regoffset = + of_translate_address(sdmanode, (u32 *) sdmanode_regoffset); + sdmanode_regsize = (int)size64; + + /* Remap the necessary zones */ + intr = ioremap(picnode_regoffset, picnode_regsize); + if (intr == NULL) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to ioremap interrupt controller registers!\n"); + goto end; + } + + sdma = ioremap(sdmanode_regoffset, sdmanode_regsize); + if (sdma == NULL) { + iounmap(intr); + printk(KERN_ERR "MPC52xx PIC: " + "Unable to ioremap Bestcomm DMA registers!\n"); + goto end; + } + + printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n", + picnode_regoffset); + printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n", + sdmanode_regoffset); + + /* Disable all interrupt sources. */ + out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ + out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ + out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ + out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ + intr_ctrl = in_be32(&intr->ctrl); + intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ + intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ + 0x00001000 | /* MEE master external enable */ + 0x00000000 | /* 0 means disable IRQ 0-3 */ + 0x00000001; /* CEb route critical normally */ + out_be32(&intr->ctrl, intr_ctrl); + + /* Zero a bunch of the priority settings. */ + out_be32(&intr->per_pri1, 0); + out_be32(&intr->per_pri2, 0); + out_be32(&intr->per_pri3, 0); + out_be32(&intr->main_pri1, 0); + out_be32(&intr->main_pri2, 0); + + /* + * As last step, add an irq host to translate the real + * hw irq information provided by the ofw to linux virq + */ + + mpc52xx_irqhost = + irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ, + &mpc52xx_irqhost_ops, -1); + + if (mpc52xx_irqhost) { + mpc52xx_irqhost->host_data = picnode; + printk(KERN_INFO "MPC52xx PIC is up and running!\n"); + } else { + printk(KERN_ERR + "MPC52xx PIC: Unable to allocate the IRQ host\n"); + } + +end: + of_node_put(picnode); + of_node_put(sdmanode); +} + +/* + * get_irq (public) +*/ +unsigned int mpc52xx_get_irq(void) +{ + u32 status; + int irq = NO_IRQ_IGNORE; + + status = in_be32(&intr->enc_status); + if (status & 0x00000400) { /* critical */ + irq = (status >> 8) & 0x3; + if (irq == 2) /* high priority peripheral */ + goto peripheral; + irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else if (status & 0x00200000) { /* main */ + irq = (status >> 16) & 0x1f; + if (irq == 4) /* low priority peripheral */ + goto peripheral; + irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else if (status & 0x20000000) { /* peripheral */ + peripheral: + irq = (status >> 24) & 0x1f; + if (irq == 0) { /* bestcomm */ + status = in_be32(&sdma->IntPend); + irq = ffs(status) - 1; + irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else + irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } + + pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, + irq_linear_revmap(mpc52xx_irqhost, irq)); + + return irq_linear_revmap(mpc52xx_irqhost, irq); +} + diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h new file mode 100644 index 0000000..e9aa622 --- /dev/null +++ b/include/asm-powerpc/mpc52xx.h @@ -0,0 +1,287 @@ +/* + * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips + * May need to be cleaned as the port goes on ... + * + * Copyright (C) 2004-2005 Sylvain Munaut + * Copyright (C) 2003 MontaVista, Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef __ASM_POWERPC_MPC52xx_H__ +#define __ASM_POWERPC_MPC52xx_H__ + +#ifndef __ASSEMBLY__ +#include +#include +#endif /* __ASSEMBLY__ */ + + +/* ======================================================================== */ +/* HW IRQ mapping */ +/* ======================================================================== */ + +#define MPC52xx_IRQ_L1_CRIT (0) +#define MPC52xx_IRQ_L1_MAIN (1) +#define MPC52xx_IRQ_L1_PERP (2) +#define MPC52xx_IRQ_L1_SDMA (3) + +#define MPC52xx_IRQ_L1_OFFSET (6) +#define MPC52xx_IRQ_L1_MASK (0xc0) + +#define MPC52xx_IRQ_L2_OFFSET (0) +#define MPC52xx_IRQ_L2_MASK (0x3f) + +#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0) + + +/* ======================================================================== */ +/* Structures mapping of some unit register set */ +/* ======================================================================== */ + +#ifndef __ASSEMBLY__ + +/* Interrupt controller Register set */ +struct mpc52xx_intr { + u32 per_mask; /* INTR + 0x00 */ + u32 per_pri1; /* INTR + 0x04 */ + u32 per_pri2; /* INTR + 0x08 */ + u32 per_pri3; /* INTR + 0x0c */ + u32 ctrl; /* INTR + 0x10 */ + u32 main_mask; /* INTR + 0x14 */ + u32 main_pri1; /* INTR + 0x18 */ + u32 main_pri2; /* INTR + 0x1c */ + u32 reserved1; /* INTR + 0x20 */ + u32 enc_status; /* INTR + 0x24 */ + u32 crit_status; /* INTR + 0x28 */ + u32 main_status; /* INTR + 0x2c */ + u32 per_status; /* INTR + 0x30 */ + u32 reserved2; /* INTR + 0x34 */ + u32 per_error; /* INTR + 0x38 */ +}; + +/* Memory Mapping Control */ +struct mpc52xx_mmap_ctl { + u32 mbar; /* MMAP_CTRL + 0x00 */ + + u32 cs0_start; /* MMAP_CTRL + 0x04 */ + u32 cs0_stop; /* MMAP_CTRL + 0x08 */ + u32 cs1_start; /* MMAP_CTRL + 0x0c */ + u32 cs1_stop; /* MMAP_CTRL + 0x10 */ + u32 cs2_start; /* MMAP_CTRL + 0x14 */ + u32 cs2_stop; /* MMAP_CTRL + 0x18 */ + u32 cs3_start; /* MMAP_CTRL + 0x1c */ + u32 cs3_stop; /* MMAP_CTRL + 0x20 */ + u32 cs4_start; /* MMAP_CTRL + 0x24 */ + u32 cs4_stop; /* MMAP_CTRL + 0x28 */ + u32 cs5_start; /* MMAP_CTRL + 0x2c */ + u32 cs5_stop; /* MMAP_CTRL + 0x30 */ + + u32 sdram0; /* MMAP_CTRL + 0x34 */ + u32 sdram1; /* MMAP_CTRL + 0X38 */ + + u32 reserved[4]; /* MMAP_CTRL + 0x3c .. 0x48 */ + + u32 boot_start; /* MMAP_CTRL + 0x4c */ + u32 boot_stop; /* MMAP_CTRL + 0x50 */ + + u32 ipbi_ws_ctrl; /* MMAP_CTRL + 0x54 */ + + u32 cs6_start; /* MMAP_CTRL + 0x58 */ + u32 cs6_stop; /* MMAP_CTRL + 0x5c */ + u32 cs7_start; /* MMAP_CTRL + 0x60 */ + u32 cs7_stop; /* MMAP_CTRL + 0x64 */ +}; + +/* SDRAM control */ +struct mpc52xx_sdram { + u32 mode; /* SDRAM + 0x00 */ + u32 ctrl; /* SDRAM + 0x04 */ + u32 config1; /* SDRAM + 0x08 */ + u32 config2; /* SDRAM + 0x0c */ +}; + +/* SDMA */ +struct mpc52xx_sdma { + u32 taskBar; /* SDMA + 0x00 */ + u32 currentPointer; /* SDMA + 0x04 */ + u32 endPointer; /* SDMA + 0x08 */ + u32 variablePointer; /* SDMA + 0x0c */ + + u8 IntVect1; /* SDMA + 0x10 */ + u8 IntVect2; /* SDMA + 0x11 */ + u16 PtdCntrl; /* SDMA + 0x12 */ + + u32 IntPend; /* SDMA + 0x14 */ + u32 IntMask; /* SDMA + 0x18 */ + + u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */ + + u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */ + + u32 cReqSelect; /* SDMA + 0x5c */ + u32 task_size0; /* SDMA + 0x60 */ + u32 task_size1; /* SDMA + 0x64 */ + u32 MDEDebug; /* SDMA + 0x68 */ + u32 ADSDebug; /* SDMA + 0x6c */ + u32 Value1; /* SDMA + 0x70 */ + u32 Value2; /* SDMA + 0x74 */ + u32 Control; /* SDMA + 0x78 */ + u32 Status; /* SDMA + 0x7c */ + u32 PTDDebug; /* SDMA + 0x80 */ +}; + +/* GPT */ +struct mpc52xx_gpt { + u32 mode; /* GPTx + 0x00 */ + u32 count; /* GPTx + 0x04 */ + u32 pwm; /* GPTx + 0x08 */ + u32 status; /* GPTx + 0X0c */ +}; + +/* GPIO */ +struct mpc52xx_gpio { + u32 port_config; /* GPIO + 0x00 */ + u32 simple_gpioe; /* GPIO + 0x04 */ + u32 simple_ode; /* GPIO + 0x08 */ + u32 simple_ddr; /* GPIO + 0x0c */ + u32 simple_dvo; /* GPIO + 0x10 */ + u32 simple_ival; /* GPIO + 0x14 */ + u8 outo_gpioe; /* GPIO + 0x18 */ + u8 reserved1[3]; /* GPIO + 0x19 */ + u8 outo_dvo; /* GPIO + 0x1c */ + u8 reserved2[3]; /* GPIO + 0x1d */ + u8 sint_gpioe; /* GPIO + 0x20 */ + u8 reserved3[3]; /* GPIO + 0x21 */ + u8 sint_ode; /* GPIO + 0x24 */ + u8 reserved4[3]; /* GPIO + 0x25 */ + u8 sint_ddr; /* GPIO + 0x28 */ + u8 reserved5[3]; /* GPIO + 0x29 */ + u8 sint_dvo; /* GPIO + 0x2c */ + u8 reserved6[3]; /* GPIO + 0x2d */ + u8 sint_inten; /* GPIO + 0x30 */ + u8 reserved7[3]; /* GPIO + 0x31 */ + u16 sint_itype; /* GPIO + 0x34 */ + u16 reserved8; /* GPIO + 0x36 */ + u8 gpio_control; /* GPIO + 0x38 */ + u8 reserved9[3]; /* GPIO + 0x39 */ + u8 sint_istat; /* GPIO + 0x3c */ + u8 sint_ival; /* GPIO + 0x3d */ + u8 bus_errs; /* GPIO + 0x3e */ + u8 reserved10; /* GPIO + 0x3f */ +}; + +#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 4 +#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD 5 +#define MPC52xx_GPIO_PCI_DIS (1<<15) + +/* GPIO with WakeUp*/ +struct mpc52xx_gpio_wkup { + u8 wkup_gpioe; /* GPIO_WKUP + 0x00 */ + u8 reserved1[3]; /* GPIO_WKUP + 0x03 */ + u8 wkup_ode; /* GPIO_WKUP + 0x04 */ + u8 reserved2[3]; /* GPIO_WKUP + 0x05 */ + u8 wkup_ddr; /* GPIO_WKUP + 0x08 */ + u8 reserved3[3]; /* GPIO_WKUP + 0x09 */ + u8 wkup_dvo; /* GPIO_WKUP + 0x0C */ + u8 reserved4[3]; /* GPIO_WKUP + 0x0D */ + u8 wkup_inten; /* GPIO_WKUP + 0x10 */ + u8 reserved5[3]; /* GPIO_WKUP + 0x11 */ + u8 wkup_iinten; /* GPIO_WKUP + 0x14 */ + u8 reserved6[3]; /* GPIO_WKUP + 0x15 */ + u16 wkup_itype; /* GPIO_WKUP + 0x18 */ + u8 reserved7[2]; /* GPIO_WKUP + 0x1A */ + u8 wkup_maste; /* GPIO_WKUP + 0x1C */ + u8 reserved8[3]; /* GPIO_WKUP + 0x1D */ + u8 wkup_ival; /* GPIO_WKUP + 0x20 */ + u8 reserved9[3]; /* GPIO_WKUP + 0x21 */ + u8 wkup_istat; /* GPIO_WKUP + 0x24 */ + u8 reserved10[3]; /* GPIO_WKUP + 0x25 */ +}; + +/* XLB Bus control */ +struct mpc52xx_xlb { + u8 reserved[0x40]; + u32 config; /* XLB + 0x40 */ + u32 version; /* XLB + 0x44 */ + u32 status; /* XLB + 0x48 */ + u32 int_enable; /* XLB + 0x4c */ + u32 addr_capture; /* XLB + 0x50 */ + u32 bus_sig_capture; /* XLB + 0x54 */ + u32 addr_timeout; /* XLB + 0x58 */ + u32 data_timeout; /* XLB + 0x5c */ + u32 bus_act_timeout; /* XLB + 0x60 */ + u32 master_pri_enable; /* XLB + 0x64 */ + u32 master_priority; /* XLB + 0x68 */ + u32 base_address; /* XLB + 0x6c */ + u32 snoop_window; /* XLB + 0x70 */ +}; + +#define MPC52xx_XLB_CFG_PLDIS (1 << 31) +#define MPC52xx_XLB_CFG_SNOOP (1 << 15) + +/* Clock Distribution control */ +struct mpc52xx_cdm { + u32 jtag_id; /* CDM + 0x00 reg0 read only */ + u32 rstcfg; /* CDM + 0x04 reg1 read only */ + u32 breadcrumb; /* CDM + 0x08 reg2 */ + + u8 mem_clk_sel; /* CDM + 0x0c reg3 byte0 */ + u8 xlb_clk_sel; /* CDM + 0x0d reg3 byte1 read only */ + u8 ipb_clk_sel; /* CDM + 0x0e reg3 byte2 */ + u8 pci_clk_sel; /* CDM + 0x0f reg3 byte3 */ + + u8 ext_48mhz_en; /* CDM + 0x10 reg4 byte0 */ + u8 fd_enable; /* CDM + 0x11 reg4 byte1 */ + u16 fd_counters; /* CDM + 0x12 reg4 byte2,3 */ + + u32 clk_enables; /* CDM + 0x14 reg5 */ + + u8 osc_disable; /* CDM + 0x18 reg6 byte0 */ + u8 reserved0[3]; /* CDM + 0x19 reg6 byte1,2,3 */ + + u8 ccs_sleep_enable; /* CDM + 0x1c reg7 byte0 */ + u8 osc_sleep_enable; /* CDM + 0x1d reg7 byte1 */ + u8 reserved1; /* CDM + 0x1e reg7 byte2 */ + u8 ccs_qreq_test; /* CDM + 0x1f reg7 byte3 */ + + u8 soft_reset; /* CDM + 0x20 u8 byte0 */ + u8 no_ckstp; /* CDM + 0x21 u8 byte0 */ + u8 reserved2[2]; /* CDM + 0x22 u8 byte1,2,3 */ + + u8 pll_lock; /* CDM + 0x24 reg9 byte0 */ + u8 pll_looselock; /* CDM + 0x25 reg9 byte1 */ + u8 pll_sm_lockwin; /* CDM + 0x26 reg9 byte2 */ + u8 reserved3; /* CDM + 0x27 reg9 byte3 */ + + u16 reserved4; /* CDM + 0x28 reg10 byte0,1 */ + u16 mclken_div_psc1; /* CDM + 0x2a reg10 byte2,3 */ + + u16 reserved5; /* CDM + 0x2c reg11 byte0,1 */ + u16 mclken_div_psc2; /* CDM + 0x2e reg11 byte2,3 */ + + u16 reserved6; /* CDM + 0x30 reg12 byte0,1 */ + u16 mclken_div_psc3; /* CDM + 0x32 reg12 byte2,3 */ + + u16 reserved7; /* CDM + 0x34 reg13 byte0,1 */ + u16 mclken_div_psc6; /* CDM + 0x36 reg13 byte2,3 */ +}; + +#endif /* __ASSEMBLY__ */ + + +/* ========================================================================= */ +/* Prototypes for MPC52xx sysdev */ +/* ========================================================================= */ + +#ifndef __ASSEMBLY__ + +extern void mpc52xx_init_irq(void); +extern unsigned int mpc52xx_get_irq(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_POWERPC_MPC52xx_H__ */ + -- cgit v0.10.2 From c37858d333a50815c74349396e31a535f4128e0b Mon Sep 17 00:00:00 2001 From: Nicolas DET Date: Sun, 5 Nov 2006 12:57:16 +0100 Subject: [PATCH] Add Efika platform support Add Efika (http://www.bplan-gmbh.de/efika_spec_en.html) platform support for arch/powerpc. Signed-off-by: Nicolas DET Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7107d47..a41d191 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -386,6 +386,14 @@ config PPC_CHRP select PPC_UDBG_16550 default y +config PPC_EFIKA + bool "bPlan Efika 5k2. MPC5200B based computer" + depends on PPC_MULTIPLATFORM && PPC32 + select PPC_RTAS + select RTAS_PROC + select PPC_MPC52xx + default y + config PPC_PMAC bool "Apple PowerMac based machines" depends on PPC_MULTIPLATFORM diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index e58fa95..7ad2673 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -5,6 +5,7 @@ ifeq ($(CONFIG_PPC64),y) obj-$(CONFIG_PPC_PMAC) += powermac/ endif endif +obj-$(CONFIG_PPC_EFIKA) += efika/ obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ diff --git a/arch/powerpc/platforms/efika/Makefile b/arch/powerpc/platforms/efika/Makefile new file mode 100644 index 0000000..17b2a78 --- /dev/null +++ b/arch/powerpc/platforms/efika/Makefile @@ -0,0 +1 @@ +obj-y += setup.o mpc52xx.o pci.o diff --git a/arch/powerpc/platforms/efika/efika.h b/arch/powerpc/platforms/efika/efika.h new file mode 100644 index 0000000..2f060fd --- /dev/null +++ b/arch/powerpc/platforms/efika/efika.h @@ -0,0 +1,19 @@ +/* + * Efika 5K2 platform setup - Header file + * + * Copyright (C) 2006 bplan GmbH + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef __ARCH_POWERPC_EFIKA__ +#define __ARCH_POWERPC_EFIKA__ + +#define EFIKA_PLATFORM_NAME "Efika" + +extern void __init efika_pcisetup(void); + +#endif diff --git a/arch/powerpc/platforms/efika/pci.c b/arch/powerpc/platforms/efika/pci.c new file mode 100644 index 0000000..62e05b2 --- /dev/null +++ b/arch/powerpc/platforms/efika/pci.c @@ -0,0 +1,119 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "efika.h" + +#ifdef CONFIG_PCI +/* + * Access functions for PCI config space using RTAS calls. + */ +static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 * val) +{ + struct pci_controller *hose = bus->sysdata; + unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) + | (((bus->number - hose->first_busno) & 0xff) << 16) + | (hose->index << 24); + int ret = -1; + int rval; + + rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len); + *val = ret; + return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) + | (((bus->number - hose->first_busno) & 0xff) << 16) + | (hose->index << 24); + int rval; + + rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, + addr, len, val); + return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops rtas_pci_ops = { + rtas_read_config, + rtas_write_config +}; + +void __init efika_pcisetup(void) +{ + const int *bus_range; + int len; + struct pci_controller *hose; + struct device_node *root; + struct device_node *pcictrl; + + root = of_find_node_by_path("/"); + if (root == NULL) { + printk(KERN_WARNING EFIKA_PLATFORM_NAME + ": Unable to find the root node\n"); + return; + } + + for (pcictrl = NULL;;) { + pcictrl = of_get_next_child(root, pcictrl); + if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0)) + break; + } + + of_node_put(root); + + if (pcictrl == NULL) { + printk(KERN_WARNING EFIKA_PLATFORM_NAME + ": Unable to find the PCI bridge node\n"); + return; + } + + bus_range = get_property(pcictrl, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING EFIKA_PLATFORM_NAME + ": Can't get bus-range for %s\n", pcictrl->full_name); + return; + } + + if (bus_range[1] == bus_range[0]) + printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d", + bus_range[0]); + else + printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d", + bus_range[0], bus_range[1]); + printk(" controlled by %s\n", pcictrl->full_name); + printk("\n"); + + hose = pcibios_alloc_controller(); + if (!hose) { + printk(KERN_WARNING EFIKA_PLATFORM_NAME + ": Can't allocate PCI controller structure for %s\n", + pcictrl->full_name); + return; + } + + hose->arch_data = of_node_get(pcictrl); + hose->first_busno = bus_range[0]; + hose->last_busno = bus_range[1]; + hose->ops = &rtas_pci_ops; + + pci_process_bridge_OF_ranges(hose, pcictrl, 0); +} + +#else +void __init efika_pcisetup(void) +{} +#endif diff --git a/arch/powerpc/platforms/efika/setup.c b/arch/powerpc/platforms/efika/setup.c new file mode 100644 index 0000000..3bc1b5f --- /dev/null +++ b/arch/powerpc/platforms/efika/setup.c @@ -0,0 +1,149 @@ +/* + * + * Efika 5K2 platform setup + * Some code really inspired from the lite5200b platform. + * + * Copyright (C) 2006 bplan GmbH + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "efika.h" + +static void efika_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + const char *revision = NULL; + const char *codegendescription = NULL; + const char *codegenvendor = NULL; + + root = of_find_node_by_path("/"); + if (root) { + revision = get_property(root, "revision", NULL); + codegendescription = + get_property(root, "CODEGEN,description", NULL); + codegenvendor = get_property(root, "CODEGEN,vendor", NULL); + + of_node_put(root); + } + + if (codegendescription) + seq_printf(m, "machine\t\t: %s\n", codegendescription); + else + seq_printf(m, "machine\t\t: Efika\n"); + + if (revision) + seq_printf(m, "revision\t: %s\n", revision); + + if (codegenvendor) + seq_printf(m, "vendor\t\t: %s\n", codegenvendor); + + of_node_put(root); +} + +static void __init efika_setup_arch(void) +{ + rtas_initialize(); + +#ifdef CONFIG_BLK_DEV_INITRD + initrd_below_start_ok = 1; + + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif + ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ + + efika_pcisetup(); + + if (ppc_md.progress) + ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0); +} + +static void __init efika_init(void) +{ + struct device_node *np; + struct device_node *cnp = NULL; + const u32 *base; + + /* Find every child of the SOC node and add it to of_platform */ + np = of_find_node_by_name(NULL, "builtin"); + if (np) { + char name[BUS_ID_SIZE]; + while ((cnp = of_get_next_child(np, cnp))) { + strcpy(name, cnp->name); + + base = get_property(cnp, "reg", NULL); + if (base == NULL) + continue; + + snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base); + of_platform_device_create(cnp, name, NULL); + + printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name); + } + } + + if (ppc_md.progress) + ppc_md.progress(" Have fun with your Efika! ", 0x7777); +} + +static int __init efika_probe(void) +{ + char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), + "model", NULL); + + if (model == NULL) + return 0; + if (strcmp(model, "EFIKA5K2")) + return 0; + + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 0x44; + DMA_MODE_WRITE = 0x48; + + return 1; +} + +define_machine(efika) +{ + .name = EFIKA_PLATFORM_NAME, + .probe = efika_probe, + .setup_arch = efika_setup_arch, + .init = efika_init, + .show_cpuinfo = efika_show_cpuinfo, + .init_IRQ = mpc52xx_init_irq, + .get_irq = mpc52xx_get_irq, + .restart = rtas_restart, + .power_off = rtas_power_off, + .halt = rtas_halt, + .set_rtc_time = rtas_set_rtc_time, + .get_rtc_time = rtas_get_rtc_time, + .progress = rtas_progress, + .get_boot_time = rtas_get_boot_time, + .calibrate_decr = generic_calibrate_decr, + .phys_mem_access_prot = pci_phys_mem_access_prot, +}; -- cgit v0.10.2 From a9b14973a8c42b2aecc968851372203c6567e196 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Thu, 19 Oct 2006 19:52:26 -0500 Subject: [PATCH] Slight refactor of interrupt mapping for FSL parts * Cleaned up interrupt mapping a little by adding a helper function which parses the irq out of the device-tree, and puts it into a resource. * Changed the arch/ppc platform files to specify PHY_POLL, instead of -1 * Changed the fixed phy to use PHY_IGNORE_INTERRUPT * Added ethtool.h and mii.h to phy.h includes Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index dbe92ae..ad31e56 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void) } for (k = 0; k < 32; k++) - mdio_data.irq[k] = -1; + mdio_data.irq[k] = PHY_POLL; while ((child = of_get_next_child(np, child)) != NULL) { int irq = irq_of_parse_and_map(child, 0); @@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx"; static const char *gfar_rx_intr = "rx"; static const char *gfar_err_intr = "error"; + static int __init gfar_of_init(void) { struct device_node *np; @@ -204,8 +206,7 @@ static int __init gfar_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); model = get_property(np, "model", NULL); @@ -214,12 +215,10 @@ static int __init gfar_of_init(void) r[1].name = gfar_tx_intr; r[2].name = gfar_rx_intr; - r[2].start = r[2].end = irq_of_parse_and_map(np, 1); - r[2].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 1, &r[2]); r[3].name = gfar_err_intr; - r[3].start = r[3].end = irq_of_parse_and_map(np, 2); - r[3].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 2, &r[3]); n_res += 2; } @@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); if (IS_ERR(i2c_dev)) { @@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); usb_dev_mph = platform_device_register_simple("fsl-ehci", i, r, 2); @@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void) if (ret) goto unreg_mph; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); usb_dev_dr = platform_device_register_simple("fsl-ehci", i, r, 2); @@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void) r[2].name = fcc_regs_c; fs_enet_data.fcc_regs_c = r[2].start; - r[3].start = r[3].end = irq_of_parse_and_map(np, 0); - r[3].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[3]); fs_enet_dev = platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); @@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void) goto err; r[1].name = scc_pram; - r[2].start = r[2].end = irq_of_parse_and_map(np, 0); - r[2].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[2]); cpm_uart_dev = platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 3397f0d..b84f8df 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -121,8 +121,8 @@ mpc834x_sys_setup_arch(void) mdata->irq[0] = MPC83xx_IRQ_EXT1; mdata->irq[1] = MPC83xx_IRQ_EXT2; - mdata->irq[2] = -1; - mdata->irq[31] = -1; + mdata->irq[2] = PHY_POLL; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 4f839da..00a3ba5 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -92,9 +92,9 @@ mpc8540ads_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 14ecec7..3a06046 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -156,9 +156,9 @@ mpc8560ads_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 5ce0f69..2d59eb7 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -451,9 +451,9 @@ mpc85xx_cds_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; - mdata->irq[3] = -1; - mdata->irq[31] = -1; + mdata->irq[2] = PHY_POLL; + mdata->irq[3] = PHY_POLL; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 764d580..1d10ab9 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -129,7 +129,7 @@ sbc8560_setup_arch(void) mdata->irq[25] = MPC85xx_IRQ_EXT6; mdata->irq[26] = MPC85xx_IRQ_EXT7; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 4bb18ab..b1f5b73 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -123,7 +123,7 @@ gp3_setup_arch(void) mdata->irq[2] = MPC85xx_IRQ_EXT5; mdata->irq[4] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index dd45f2e..4ee2bd1 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -137,9 +137,9 @@ tqm85xx_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT8; mdata->irq[1] = MPC85xx_IRQ_EXT8; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT8; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c index 1f9ea368..0bc0676 100644 --- a/arch/ppc/platforms/mpc8272ads_setup.c +++ b/arch/ppc/platforms/mpc8272ads_setup.c @@ -266,10 +266,10 @@ static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev, int idx) { m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[1] = -1; - m82xx_mii_bb_pdata.irq[2] = -1; + m82xx_mii_bb_pdata.irq[1] = PHY_POLL; + m82xx_mii_bb_pdata.irq[2] = PHY_POLL; m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[31] = -1; + m82xx_mii_bb_pdata.irq[31] = PHY_POLL; m82xx_mii_bb_pdata.mdio_dat.offset = diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c index e95d2c1..8a0c07e 100644 --- a/arch/ppc/platforms/mpc866ads_setup.c +++ b/arch/ppc/platforms/mpc866ads_setup.c @@ -361,7 +361,7 @@ int __init mpc866ads_init(void) fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; + fmpi->irq[0xf] = PHY_POLL; /* Since either of the uarts could be used as console, they need to ready */ #ifdef CONFIG_SERIAL_CPM_SMC1 @@ -380,7 +380,7 @@ int __init mpc866ads_init(void) fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; + fmpi->irq[0xf] = PHY_POLL; return 0; } diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index f14e992..096d4a1 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) goto device_create_fail; } - phydev->irq = -1; + phydev->irq = PHY_IGNORE_INTERRUPT; phydev->dev.bus = &mdio_bus_type; if(number) diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 5246297..39f04ef 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -17,6 +17,7 @@ */ #include #include +#include #include /* Definitions used by the flattened device tree */ @@ -331,6 +332,12 @@ extern int of_irq_map_one(struct device_node *device, int index, struct pci_dev; extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); +static inline void of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +{ + r->start = r->end = irq_of_parse_and_map(dev, index); + r->flags = IORESOURCE_IRQ; +} + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/linux/phy.h b/include/linux/phy.h index 9447a57..892d6ab 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -20,6 +20,9 @@ #include #include +#include +#include +#include #define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ SUPPORTED_10baseT_Full | \ -- cgit v0.10.2 From 66a91e9c0ab62ea938afaba7352741d8c554a589 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Tue, 7 Nov 2006 16:57:22 -0600 Subject: [PATCH] of_irq_to_resource now returns the virq Mostly this is to allow for error checking (check the return for NO_IRQ) Added a check that the resource is non-NULL, too. Signed-off-by: Andrew Fleming Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 39f04ef..1fd7a22 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -332,10 +332,18 @@ extern int of_irq_map_one(struct device_node *device, int index, struct pci_dev; extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); -static inline void of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) { - r->start = r->end = irq_of_parse_and_map(dev, index); - r->flags = IORESOURCE_IRQ; + int irq = irq_of_parse_and_map(dev, index); + + /* Only dereference the resource if both the + * resource and the irq are valid. */ + if (r && irq != NO_IRQ) { + r->start = r->end = irq; + r->flags = IORESOURCE_IRQ; + } + + return irq; } -- cgit v0.10.2 From a416dd8d9cd3a3fa77b9839e0e6fc3c54927d8c3 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 8 Nov 2006 10:22:59 +1100 Subject: [PATCH] Do a single one-line printk in bad_page_fault() bad_page_fault() prints a message telling the user what type of bad fault we took. The first line of this message is currently implemented as two separate printks. This has the unfortunate effect that if several cpus simultaneously take a bad fault, the first and second parts of the printk get jumbled up, which looks dodge and is hard to read. So do a single one-line printk for each fault type. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index e8fa506..03aeb3a 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) /* kernel has accessed a bad area */ - printk(KERN_ALERT "Unable to handle kernel paging request for "); switch (regs->trap) { - case 0x300: - case 0x380: - printk("data at address 0x%08lx\n", regs->dar); - break; - case 0x400: - case 0x480: - printk("instruction fetch\n"); - break; - default: - printk("unknown fault\n"); + case 0x300: + case 0x380: + printk(KERN_ALERT "Unable to handle kernel paging request for " + "data at address 0x%08lx\n", regs->dar); + break; + case 0x400: + case 0x480: + printk(KERN_ALERT "Unable to handle kernel paging request for " + "instruction fetch\n"); + break; + default: + printk(KERN_ALERT "Unable to handle kernel paging request for " + "unknown fault\n"); + break; } printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", regs->nip); -- cgit v0.10.2 From e9c4b4bd56a7dfdc8879a5876e498991c9194321 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 8 Nov 2006 17:50:44 -0700 Subject: [PATCH] Remove dtb file created by wrapper script When the wrapper script is passed a dts file, it runs 'dtc' to create a dtb file. This patch deletes that dtb file once its no longer needed. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index b5fb1fe..024e4d4 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -184,6 +184,9 @@ fi if [ -n "$dtb" ]; then addsec $tmp "$dtb" .kernel:dtb + if [ -n "$dts" ]; then + rm $dtb + fi fi if [ "$platform" != "miboot" ]; then -- cgit v0.10.2 From 25787afa5c16d35cdfb191f63a3a406b3206744e Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 8 Nov 2006 17:52:25 -0700 Subject: [PATCH] Remove arch/powerpc/boot/zImage file. The bootwrapper Makefile does not clean up the 'zImage' file that may be left laying around. This patch removes it when cleaning that directory. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 789def3..042bac3 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -75,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ - empty.c zImage.coff.lds zImage.lds zImage.sandpoint + empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< -- cgit v0.10.2 From 0613ffbf53625ccecb96500b1cc7b0ef70cc8f04 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 9 Nov 2006 18:53:52 +0100 Subject: [PATCH] Fix compile warnings with CONFIG_PM=n Fix compile warnings with CONFIG_PM=n arch/powerpc/platforms/powermac/feature.c:489: warning: 'save_gpio_levels' defined but not used arch/powerpc/platforms/powermac/feature.c:490: warning: 'save_gpio_extint' defined but not used arch/powerpc/platforms/powermac/feature.c:491: warning: 'save_gpio_normal' defined but not used arch/powerpc/platforms/powermac/feature.c:492: warning: 'save_unin_clock_ctl' defined but not used Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index e49621b..c29a6a0 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -486,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param, static u32 save_fcr[6]; static u32 save_mbcr; -static u32 save_gpio_levels[2]; -static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; -static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; -static u32 save_unin_clock_ctl; static struct dbdma_regs save_dbdma[13]; static struct dbdma_regs save_alt_dbdma[13]; @@ -1548,6 +1544,10 @@ void g5_phy_disable_cpu1(void) #ifdef CONFIG_PM +static u32 save_gpio_levels[2]; +static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; +static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; +static u32 save_unin_clock_ctl; static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) { -- cgit v0.10.2 From fc9e8b4e275b6882cb537154c8fc7cde3692eea0 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 9 Nov 2006 15:42:44 -0600 Subject: [PATCH] Optimize qe_brg struct to use an array The qe_brg structure manually defined each of the 16 BRG registers, which made any code that used them cumbersome. This patch replaces the fields with a single 16-element array. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 2bae632..812c87c 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -175,8 +175,7 @@ void qe_setbrg(u32 brg, u32 rate) u32 divisor, tempval; int div16 = 0; - bp = &qe_immr->brg.brgc1; - bp += brg; + bp = &qe_immr->brg.brgc[brg]; divisor = (get_brg_clk() / rate); if (divisor > QE_BRGC_DIVISOR_MAX + 1) { diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h index ce12f85..9fdd049 100644 --- a/include/asm-powerpc/immap_qe.h +++ b/include/asm-powerpc/immap_qe.h @@ -136,22 +136,7 @@ struct qe_timers { /* BRG */ struct qe_brg { - __be32 brgc1; /* BRG1 configuration register */ - __be32 brgc2; /* BRG2 configuration register */ - __be32 brgc3; /* BRG3 configuration register */ - __be32 brgc4; /* BRG4 configuration register */ - __be32 brgc5; /* BRG5 configuration register */ - __be32 brgc6; /* BRG6 configuration register */ - __be32 brgc7; /* BRG7 configuration register */ - __be32 brgc8; /* BRG8 configuration register */ - __be32 brgc9; /* BRG9 configuration register */ - __be32 brgc10; /* BRG10 configuration register */ - __be32 brgc11; /* BRG11 configuration register */ - __be32 brgc12; /* BRG12 configuration register */ - __be32 brgc13; /* BRG13 configuration register */ - __be32 brgc14; /* BRG14 configuration register */ - __be32 brgc15; /* BRG15 configuration register */ - __be32 brgc16; /* BRG16 configuration register */ + __be32 brgc[16]; /* BRG configuration registers */ u8 res0[0x40]; } __attribute__ ((packed)); -- cgit v0.10.2 From 57744ea95edd340d7140852ce86c743df2cd588c Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 10 Nov 2006 12:01:02 -0800 Subject: [PATCH] Check for null init_early routine Add a check for a null ppc_md.init_early to allow platforms that don't require an init_early routine to just set this member to null. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ae6b67c..2fef772 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -380,7 +380,8 @@ void __init setup_system(void) * setting up the hash table pointers. It also sets up some interrupt-mapping * related options that will be used by finish_device_tree() */ - ppc_md.init_early(); + if (ppc_md.init_early) + ppc_md.init_early(); /* * We can discover serial ports now since the above did setup the -- cgit v0.10.2 From b61c5509fe8f6c665c146ab14f960000d4a5d1a9 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Fri, 10 Nov 2006 18:08:30 -0600 Subject: [PATCH] Make git ignore new wrapper generated files The new 'wrapper' code generates files that git should ignore; add them to .gitignore. Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 45c9ad2..590e72f 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -1,20 +1,27 @@ addnote +empty.c +hack-coff infblock.c infblock.h infcodes.c infcodes.h inffast.c inffast.h +inffixed.h inflate.c +inflate.h inftrees.c inftrees.h infutil.c infutil.h kernel-vmlinux.strip.c kernel-vmlinux.strip.gz +mktree uImage zImage zImage.vmode +zImage.coff.lds +zImage.lds zconf.h zlib.h zutil.h -- cgit v0.10.2 From 19a79859e168640f8e16d7b216d211c1c52b687a Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 11 Nov 2006 10:53:19 +0100 Subject: [PATCH] ppc: Fix io.h for config with CONFIG_PCI not set When CONFIG_PCI option is not set, the variables pci_dram_offset, isa_io_base and isa_mem_base are not defined. Currently, the test is handled in each platform header. This patch moves the test in io.h once and for all. Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/mpc85xx.h b/include/asm-powerpc/mpc85xx.h index ccdb8a2..5414299 100644 --- a/include/asm-powerpc/mpc85xx.h +++ b/include/asm-powerpc/mpc85xx.h @@ -31,14 +31,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* Let modules/drivers get at CCSRBAR */ extern phys_addr_t get_ccsrbar(void); diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index a4c411b..b744baf 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -26,17 +26,11 @@ #if defined(CONFIG_4xx) #include -#elif defined(CONFIG_PPC_MPC52xx) -#include #elif defined(CONFIG_8xx) #include #elif defined(CONFIG_8260) #include -#elif defined(CONFIG_83xx) -#include -#elif defined(CONFIG_85xx) -#include -#elif defined(CONFIG_APUS) +#elif defined(CONFIG_APUS) || !defined(CONFIG_PCI) #define _IO_BASE 0 #define _ISA_MEM_BASE 0 #define PCI_DRAM_OFFSET 0 diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h index 64c8874..d9d21aa 100644 --- a/include/asm-ppc/mpc52xx.h +++ b/include/asm-ppc/mpc52xx.h @@ -29,17 +29,6 @@ struct pt_regs; #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_PCI -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define _IO_BASE 0 -#define _ISA_MEM_BASE 0 -#define PCI_DRAM_OFFSET 0 -#endif - - /* ======================================================================== */ /* PPC Sys devices definition */ /* ======================================================================== */ diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index 02ed2c3..c306197 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h @@ -25,14 +25,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* * The "residual" board information structure the boot loader passes * into the kernel. diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index 9b48511..d7e4a79 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h @@ -44,14 +44,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* * The "residual" board information structure the boot loader passes * into the kernel. -- cgit v0.10.2 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 diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index eeab26b..34815b0 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 v0.10.2 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 diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index ee48995..57e1c02 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 v0.10.2 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 diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fbe5b61..bf26755 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 v0.10.2 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 diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c9d8e3b..94324b3 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 ff59911..e8dcb6f 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 v0.10.2 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 diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 94324b3..1a402e4 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 e8dcb6f..7f62403 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 v0.10.2 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 diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 1a402e4..51f0cfd 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 v0.10.2 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 diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index a84903e..21ebe8f 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 e6baaee..6b9ef73 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 v0.10.2 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 diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index 2853ea1..87fb75f 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 v0.10.2 From 2b4ac44e7c7e16cf9411b81693ff3e604f332bf1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 10 Nov 2006 12:27:48 -0800 Subject: [PATCH] vmalloc: optimization, cleanup, bugfixes - reorder 'struct vm_struct' to speedup lookups on CPUS with small cache lines. The fields 'next,addr,size' should be now in the same cache line, to speedup lookups. - One minor cleanup in __get_vm_area_node() - Bugfixes in vmalloc_user() and vmalloc_32_user() NULL returns from __vmalloc() and __find_vm_area() were not tested. [akpm@osdl.org: remove redundant BUG_ONs] Signed-off-by: Eric Dumazet Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index dc9a29d..924e502 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -23,13 +23,14 @@ struct vm_area_struct; #endif struct vm_struct { + /* keep next,addr,size together to speedup lookups */ + struct vm_struct *next; void *addr; unsigned long size; unsigned long flags; struct page **pages; unsigned int nr_pages; unsigned long phys_addr; - struct vm_struct *next; }; /* diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 46606c1..7dc6aa7 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -186,10 +186,8 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl if (unlikely(!area)) return NULL; - if (unlikely(!size)) { - kfree (area); + if (unlikely(!size)) return NULL; - } /* * We always allocate a guard page. @@ -532,11 +530,12 @@ void *vmalloc_user(unsigned long size) void *ret; ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); - write_lock(&vmlist_lock); - area = __find_vm_area(ret); - area->flags |= VM_USERMAP; - write_unlock(&vmlist_lock); - + if (ret) { + write_lock(&vmlist_lock); + area = __find_vm_area(ret); + area->flags |= VM_USERMAP; + write_unlock(&vmlist_lock); + } return ret; } EXPORT_SYMBOL(vmalloc_user); @@ -605,11 +604,12 @@ void *vmalloc_32_user(unsigned long size) void *ret; ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); - write_lock(&vmlist_lock); - area = __find_vm_area(ret); - area->flags |= VM_USERMAP; - write_unlock(&vmlist_lock); - + if (ret) { + write_lock(&vmlist_lock); + area = __find_vm_area(ret); + area->flags |= VM_USERMAP; + write_unlock(&vmlist_lock); + } return ret; } EXPORT_SYMBOL(vmalloc_32_user); -- cgit v0.10.2 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 diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index a1d2e97..f952bfe 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 v0.10.2 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 diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 1468239..683b12c 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 39a9f8c..2af12fc 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 5c0dec3..235e892 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 1d9efe5..e715c79 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 v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0b07ca1..a41b8df 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 v0.10.2 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 diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index 9ed640d..ea42611 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 a18a9ae..61dc46f 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 acdc266..86e65de 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 eb24107..538e947 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 v0.10.2 From d8b295f29091310d746509bb6d5828aaf4907a18 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Nov 2006 12:27:53 -0800 Subject: [PATCH] Fix missing parens in set_personality() If you call set_personality() with an expression such as: set_personality(foo ? PERS_FOO1 : PERS_FOO2); then this evaluates to: ((current->personality == foo ? PERS_FOO1 : PERS_FOO2) ? ... which is obviously not the intended result. Add the missing parents to ensure this gets evaluated as expected: ((current->personality == (foo ? PERS_FOO1 : PERS_FOO2)) ? ... Signed-off-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/personality.h b/include/linux/personality.h index bf4cf20..012cd55 100644 --- a/include/linux/personality.h +++ b/include/linux/personality.h @@ -114,7 +114,7 @@ struct exec_domain { * Change personality of the currently running process. */ #define set_personality(pers) \ - ((current->personality == pers) ? 0 : __set_personality(pers)) + ((current->personality == (pers)) ? 0 : __set_personality(pers)) #endif /* __KERNEL__ */ -- cgit v0.10.2 From 5fd934a9a1b72c718ad5c388fd2e0fd90486cbf3 Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Fri, 10 Nov 2006 12:27:53 -0800 Subject: [PATCH] .gitignore: add miscellaneous files Prevent git from reporting this useless status: On branch refs/heads/master Untracked files: (use "git add" to add to commit) TAGS scripts/kconfig/lkc_defs.h scripts/kconfig/qconf.moc nothing to commit Signed-off-by: Franck Bui-Huu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/.gitignore b/.gitignore index e1d5c17..9eb4b77 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ # Top-level generic files # tags +TAGS vmlinux* System.map Module.symvers diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore index e8ad1f6..b49584c 100644 --- a/scripts/kconfig/.gitignore +++ b/scripts/kconfig/.gitignore @@ -6,6 +6,8 @@ lex.*.c *.tab.c *.tab.h zconf.hash.c +*.moc +lkc_defs.h # # configuration programs -- cgit v0.10.2 From 0130b0b32ee53dc7add773fcea984f6a26ef1da3 Mon Sep 17 00:00:00 2001 From: Sharyathi Nagesh Date: Fri, 10 Nov 2006 12:27:54 -0800 Subject: [PATCH] fix Data Acess error in dup_fd On running the Stress Test on machine for more than 72 hours following error message was observed. 0:mon> e cpu 0x0: Vector: 300 (Data Access) at [c00000007ce2f7f0] pc: c000000000060d90: .dup_fd+0x240/0x39c lr: c000000000060d6c: .dup_fd+0x21c/0x39c sp: c00000007ce2fa70 msr: 800000000000b032 dar: ffffffff00000028 dsisr: 40000000 current = 0xc000000074950980 paca = 0xc000000000454500 pid = 27330, comm = bash 0:mon> t [c00000007ce2fa70] c000000000060d28 .dup_fd+0x1d8/0x39c (unreliable) [c00000007ce2fb30] c000000000060f48 .copy_files+0x5c/0x88 [c00000007ce2fbd0] c000000000061f5c .copy_process+0x574/0x1520 [c00000007ce2fcd0] c000000000062f88 .do_fork+0x80/0x1c4 [c00000007ce2fdc0] c000000000011790 .sys_clone+0x5c/0x74 [c00000007ce2fe30] c000000000008950 .ppc_clone+0x8/0xc The problem is because of race window. When if(expand) block is executed in dup_fd unlocking of oldf->file_lock give a window for fdtable in oldf to be modified. So actual open_files in oldf may not match with open_files variable. Cc: Vadim Lobanov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 3da978e..4b4eab2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -687,6 +687,7 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) * the latest pointer. */ spin_lock(&oldf->file_lock); + open_files = count_open_files(old_fdt); old_fdt = files_fdtable(oldf); } -- cgit v0.10.2 From f72fa707604c015a6625e80f269506032d5430dc Mon Sep 17 00:00:00 2001 From: Pavel Emelianov Date: Fri, 10 Nov 2006 12:27:56 -0800 Subject: [PATCH] Fix misrouted interrupts deadlocks While testing kernel on machine with "irqpoll" option I've caught such a lockup: __do_IRQ() spin_lock(&desc->lock); desc->chip->ack(); /* IRQ is ACKed */ note_interrupt() misrouted_irq() handle_IRQ_event() if (...) local_irq_enable_in_hardirq(); /* interrupts are enabled from now */ ... __do_IRQ() /* same IRQ we've started from */ spin_lock(&desc->lock); /* LOCKUP */ Looking at misrouted_irq() code I've found that a potential deadlock like this can also take place: 1CPU: __do_IRQ() spin_lock(&desc->lock); /* irq = A */ misrouted_irq() for (i = 1; i < NR_IRQS; i++) { spin_lock(&desc->lock); /* irq = B */ if (desc->status & IRQ_INPROGRESS) { 2CPU: __do_IRQ() spin_lock(&desc->lock); /* irq = B */ misrouted_irq() for (i = 1; i < NR_IRQS; i++) { spin_lock(&desc->lock); /* irq = A */ if (desc->status & IRQ_INPROGRESS) { As the second lock on both CPUs is taken before checking that this irq is being handled in another processor this may cause a deadlock. This issue is only theoretical. I propose the attached patch to fix booth problems: when trying to handle misrouted IRQ active desc->lock may be unlocked. Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 543ea2e..9c7e2e4 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -147,7 +147,11 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (unlikely(irqfixup)) { /* Don't punish working computers */ if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) { - int ok = misrouted_irq(irq); + int ok; + + spin_unlock(&desc->lock); + ok = misrouted_irq(irq); + spin_lock(&desc->lock); if (action_ret == IRQ_NONE) desc->irqs_unhandled -= ok; } -- cgit v0.10.2 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 diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index fd9e281..94a2746 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c index 3bac197..214e2fd 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 3fc92b0..fad9136 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig index 922389b..727b10d 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 9e7bd94..27fe242 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 da98d9f..fef9727 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 21d9612..623dc95 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 v0.10.2 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 diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 493f4c6..a72bcea 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 v0.10.2 From 616e8a091a035c0bd9b871695f4af191df123caa Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 13 Nov 2006 18:04:59 +0100 Subject: [PATCH] Fix bad data direction in SG_IO Contrary to what the name misleads you to believe, SG_DXFER_TO_FROM_DEV is really just a normal read seen from the device side. This patch fixes http://lkml.org/lkml/2006/10/13/100 Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 2dc3264..a19338e 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -246,10 +246,10 @@ static int sg_io(struct file *file, request_queue_t *q, switch (hdr->dxfer_direction) { default: return -EINVAL; - case SG_DXFER_TO_FROM_DEV: case SG_DXFER_TO_DEV: writing = 1; break; + case SG_DXFER_TO_FROM_DEV: case SG_DXFER_FROM_DEV: break; } -- cgit v0.10.2 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 diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index bddfebd..8821494 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 v0.10.2 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 diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7f62403..dee8355 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 v0.10.2 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 diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 7350443..fce3fcd 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 v0.10.2 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 diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 690828e..96a0980 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 v0.10.2 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 diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7af2a4b..5c1fc46 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 v0.10.2 From aa8d18731508bb0a16f69b77e5f4541f0d6fb553 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 14 Nov 2006 15:15:40 +0000 Subject: [ARM] Remove OP_MAX_COUNTER OP_MAX_COUNTER never referenced, and is a reminant of an earlier oprofile implementation. Remove it. Signed-off-by: Russell King diff --git a/arch/arm/oprofile/op_counter.h b/arch/arm/oprofile/op_counter.h index 8c5351d..ca942a6 100644 --- a/arch/arm/oprofile/op_counter.h +++ b/arch/arm/oprofile/op_counter.h @@ -10,8 +10,6 @@ #ifndef OP_COUNTER_H #define OP_COUNTER_H -#define OP_MAX_COUNTER 5 - /* Per performance monitor configuration as set via * oprofilefs. */ -- cgit v0.10.2 From 64e72e41acae0dab733fb0d5d789b76d115210c0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:56:33 +0100 Subject: Revert "[PATCH] MMCONFIG and new Intel motherboards" This reverts 4c6e052adfe285ede5884e4e8c4d33af33932c13 commit. Following Linus' i386 change: revert resource reservation for mmcfg config now. Will be revisited in .20 hopefully. diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index e61093b..f8b6b28 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -163,37 +163,6 @@ static __init void unreachable_devices(void) } } -static __init void pci_mmcfg_insert_resources(void) -{ -#define PCI_MMCFG_RESOURCE_NAME_LEN 19 - int i; - struct resource *res; - char *names; - unsigned num_buses; - - res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), - pci_mmcfg_config_num, GFP_KERNEL); - - if (!res) { - printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); - return; - } - - names = (void *)&res[pci_mmcfg_config_num]; - for (i = 0; i < pci_mmcfg_config_num; i++, res++) { - num_buses = pci_mmcfg_config[i].end_bus_number - - pci_mmcfg_config[i].start_bus_number + 1; - res->name = names; - snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", - pci_mmcfg_config[i].pci_segment_group_number); - res->start = pci_mmcfg_config[i].base_address; - res->end = res->start + (num_buses << 20) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - insert_resource(&iomem_resource, res); - names += PCI_MMCFG_RESOURCE_NAME_LEN; - } -} - void __init pci_mmcfg_init(int type) { int i; @@ -237,7 +206,6 @@ void __init pci_mmcfg_init(int type) } unreachable_devices(); - pci_mmcfg_insert_resources(); raw_pci_ops = &pci_mmcfg; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; -- cgit v0.10.2 From 14f448e36192d6d2cd7dfd81cb044977b2f9dd9b Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Tue, 14 Nov 2006 16:57:45 +0100 Subject: [PATCH] x86-64: Fix partial page check to ensure unusable memory is not being marked usable. Fix partial page check in e820_register_active_regions to ensure partial pages are not being marked as active in the memory pool. Signed-off-by: Aaron Durbin Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index a75c829..855b561 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -278,7 +278,7 @@ e820_register_active_regions(int nid, unsigned long start_pfn, >> PAGE_SHIFT; /* Skip map entries smaller than a page */ - if (ei_startpfn > ei_endpfn) + if (ei_startpfn >= ei_endpfn) continue; /* Check if end_pfn_map should be updated */ -- cgit v0.10.2 From 14679eb3c50897889ba62f9a37e3bcd8a205b5e7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: Fix PTRACE_[SG]ET_THREAD_AREA regression with ia32 emulation. ptrace(PTRACE_[SG]ET_THREAD_AREA) calls from ia32 code should be passed onto the x86_64 implementation. The default case in sys32_ptrace used to call to sys_ptrace(), but is now EINVAL. This patch fixes a regression caused by that changed. Signed-off-by: Mike McCormack Signed-off-by: Andi Kleen diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 3a7561d..04566fe 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -244,6 +244,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_DETACH: case PTRACE_SYSCALL: case PTRACE_SETOPTIONS: + case PTRACE_SET_THREAD_AREA: + case PTRACE_GET_THREAD_AREA: return sys_ptrace(request, pid, addr, data); default: -- cgit v0.10.2 From 51d67a488b53a5cc8401460480c124eaec71e2d4 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: shorten the x86_64 boot setup GDT to what the comment says Stephen Tweedie, Herbert Xu, and myself have been struggling with a very nasty bug in Xen. But it also pointed out a small bug in the x86_64 kernel boot setup. The GDT limit being setup by the initial bzImage code when entering into protected mode is way too big. The comment by the code states that the size of the GDT is 2048, but the actual size being set up is much bigger (32768). This happens simply because of one extra '0'. Instead of setting up a 0x800 size, 0x8000 is set up. On bare metal this is fine because the CPU wont load any segments unless they are explicitly used. But unfortunately, this breaks Xen on vmx FV, since it (for now) blindly loads all the segments into the VMCS if they are less than the gdt limit. Since the real mode segments are around 0x3000, we are getting junk into the VMCS and that later causes an exception. Stephen Tweedie has written up a patch to fix the Xen side and will be submitting that to those folks. But that doesn't excuse the GDT limit being a magnitude too big. AK: changed to compute true gdt size in assembler, fixed comment Signed-off-by: Steven Rostedt Signed-off-by: Andi Kleen diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S index c3bfd22..770940c 100644 --- a/arch/x86_64/boot/setup.S +++ b/arch/x86_64/boot/setup.S @@ -836,13 +836,12 @@ gdt: .word 0x9200 # data read/write .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit) +gdt_end: idt_48: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L gdt_48: - .word 0x8000 # gdt limit=2048, - # 256 GDT entries - + .word gdt_end-gdt-1 # gdt limit .word 0, 0 # gdt base (filled in later) # Include video setup & detection code -- cgit v0.10.2 From 5e58a02a8f6a7a1c9ae41f39286bcd3aea0d6f24 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: Handle reserve_bootmem_generic beyond end_pfn This can happen on kexec kernels with some configurations, in particularly on Unisys ES7000 systems. Analysis by Amul Shah Cc: Amul Shah Signed-off-by: Andi Kleen diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 971dc11..f1f977a 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -655,9 +655,22 @@ void free_initrd_mem(unsigned long start, unsigned long end) void __init reserve_bootmem_generic(unsigned long phys, unsigned len) { - /* Should check here against the e820 map to avoid double free */ #ifdef CONFIG_NUMA int nid = phys_to_nid(phys); +#endif + unsigned long pfn = phys >> PAGE_SHIFT; + if (pfn >= end_pfn) { + /* This can happen with kdump kernels when accessing firmware + tables. */ + if (pfn < end_pfn_map) + return; + printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n", + phys, len); + return; + } + + /* Should check here against the e820 map to avoid double free */ +#ifdef CONFIG_NUMA reserve_bootmem_node(NODE_DATA(nid), phys, len); #else reserve_bootmem(phys, len); -- cgit v0.10.2 From 15803a43288da434d34d41c4ed650c3c1728d42c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: setup saved_max_pfn correctly (kdump) x86_64: setup saved_max_pfn correctly 2.6.19-rc4 has broken CONFIG_CRASH_DUMP support on x86_64. It is impossible to read out the kernel contents from /proc/vmcore because saved_max_pfn is set to zero instead of the max_pfn value before the user map is setup. This happens because saved_max_pfn is initialized at parse_early_param() time, and at this time no active regions have been registered. save_max_pfn is setup from e820_end_of_ram(), more exact find_max_pfn_with_active_regions() which returns 0 because no regions exist. This patch fixes this by registering before and removing after the call to e820_end_of_ram(). Signed-off-by: Magnus Damm Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 855b561..6fe191c 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -594,7 +594,9 @@ static int __init parse_memmap_opt(char *p) * size before original memory map is * reset. */ + e820_register_active_regions(0, 0, -1UL); saved_max_pfn = e820_end_of_ram(); + remove_all_active_ranges(); #endif end_pfn_map = 0; e820.nr_map = 0; -- cgit v0.10.2 From fa18f477d0987c011cce047a7c3cd1284f547a14 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86: Add acpi_user_timer_override option for Asus boards Timer overrides are normally disabled on Nvidia board because they are commonly wrong, except on new ones with HPET support. Unfortunately there are quite some Asus boards around that don't have HPET, but need a timer override. We don't know yet how to handle this transparently, but at least add a command line option to force the timer override and let them boot. Cc: len.brown@intel.com Signed-off-by: Andi Kleen diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index dd00fd5..6747384 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -164,6 +164,10 @@ and is between 256 and 4096 characters. It is defined in the file acpi_skip_timer_override [HW,ACPI] Recognize and ignore IRQ0/pin2 Interrupt Override. For broken nForce2 BIOS resulting in XT-PIC timer. + acpi_use_timer_override [HW,ACPI} + Use timer override. For some broken Nvidia NF5 boards + that require a timer override, but don't have + HPET acpi_dbg_layer= [HW,ACPI] Format: diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 22e4c466..d12fb97 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -82,6 +82,7 @@ EXPORT_SYMBOL(acpi_strict); acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; +int acpi_use_timer_override __initdata; #ifdef CONFIG_X86_LOCAL_APIC static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; @@ -1300,6 +1301,13 @@ static int __init parse_acpi_skip_timer_override(char *arg) return 0; } early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override); + +static int __init parse_acpi_use_timer_override(char *arg) +{ + acpi_use_timer_override = 1; + return 0; +} +early_param("acpi_use_timer_override", parse_acpi_use_timer_override); #endif /* CONFIG_X86_IO_APIC */ static int __init setup_acpi_sci(char *s) diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index fe799b1..c984169 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c @@ -27,11 +27,17 @@ static int __init check_bridge(int vendor, int device) #ifdef CONFIG_ACPI /* According to Nvidia all timer overrides are bogus unless HPET is enabled. */ - if (vendor == PCI_VENDOR_ID_NVIDIA) { + if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { nvidia_hpet_detected = 0; acpi_table_parse(ACPI_HPET, nvidia_hpet_check); if (nvidia_hpet_detected == 0) { acpi_skip_timer_override = 1; + printk(KERN_INFO "Nvidia board " + "detected. Ignoring ACPI " + "timer override.\n"); + printk(KERN_INFO "If you got timer trouble " + "try acpi_use_timer_override\n"); + } } #endif diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c index 2b1245d..68273bf 100644 --- a/arch/x86_64/kernel/early-quirks.c +++ b/arch/x86_64/kernel/early-quirks.c @@ -45,7 +45,13 @@ static void nvidia_bugs(void) /* * All timer overrides on Nvidia are * wrong unless HPET is enabled. + * Unfortunately that's not true on many Asus boards. + * We don't know yet how to detect this automatically, but + * at least allow a command line override. */ + if (acpi_use_timer_override) + return; + nvidia_hpet_detected = 0; acpi_table_parse(ACPI_HPET, nvidia_hpet_check); if (nvidia_hpet_detected == 0) { @@ -53,6 +59,8 @@ static void nvidia_bugs(void) printk(KERN_INFO "Nvidia board " "detected. Ignoring ACPI " "timer override.\n"); + printk(KERN_INFO "If you got timer trouble " + "try acpi_use_timer_override\n"); } #endif /* RED-PEN skip them on mptables too? */ diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h index 6016632..c80b3a9 100644 --- a/include/asm-i386/acpi.h +++ b/include/asm-i386/acpi.h @@ -132,6 +132,7 @@ extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); #ifdef CONFIG_X86_IO_APIC extern int acpi_skip_timer_override; +extern int acpi_use_timer_override; #endif static inline void acpi_noirq_set(void) { acpi_noirq = 1; } diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h index ed59aa4..9d1916e 100644 --- a/include/asm-x86_64/acpi.h +++ b/include/asm-x86_64/acpi.h @@ -163,6 +163,7 @@ extern u8 x86_acpiid_to_apicid[]; #define ARCH_HAS_POWER_INIT 1 extern int acpi_skip_timer_override; +extern int acpi_use_timer_override; #endif /*__KERNEL__*/ -- cgit v0.10.2 From 8c131af1db510793f87dc43edbc8950a35370df3 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: Fix vgetcpu when CONFIG_HOTPLUG_CPU is disabled The vgetcpu per CPU initialization previously relied on CPU hotplug events for all CPUs to initialize the per CPU state. That only worked only on kernels with CONFIG_HOTPLUG_CPU enabled. On the others some CPUs didn't get their state initialized properly and vgetcpu wouldn't work. Change the initialization sequence to instead run in a normal initcall (which runs after the normal CPU bootup) and initialize all running CPUs there. Later hotplug CPUs are still handled with an hotplug notifier. This actually simplifies the code somewhat. Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 4f67697..9f74c88 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -376,9 +376,8 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, /* prevent preemption and reschedule on another processor */ int me = get_cpu(); if (cpu == me) { - WARN_ON(1); put_cpu(); - return -EBUSY; + return 0; } spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 88722f1..e3ef544 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -876,15 +876,6 @@ static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; -static int __cpuinit -time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu) -{ - unsigned cpu = (unsigned long) hcpu; - if (action == CPU_ONLINE) - vsyscall_set_cpu(cpu); - return NOTIFY_DONE; -} - void __init time_init(void) { if (nohpet) @@ -925,8 +916,6 @@ void __init time_init(void) vxtime.last_tsc = get_cycles_sync(); set_cyc2ns_scale(cpu_khz); setup_irq(0, &irq0); - hotcpu_notifier(time_cpu_notifier, 0); - time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id()); #ifndef CONFIG_SMP time_init_gtod(); diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index a98b460..a730bac 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include @@ -243,32 +246,17 @@ static ctl_table kernel_root_table2[] = { #endif -static void __cpuinit write_rdtscp_cb(void *info) -{ - write_rdtscp_aux((unsigned long)info); -} - -void __cpuinit vsyscall_set_cpu(int cpu) +/* Assume __initcall executes before all user space. Hopefully kmod + doesn't violate that. We'll find out if it does. */ +static void __cpuinit vsyscall_set_cpu(int cpu) { unsigned long *d; unsigned long node = 0; #ifdef CONFIG_NUMA node = cpu_to_node[cpu]; #endif - if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) { - void *info = (void *)((node << 12) | cpu); - /* Can happen on preemptive kernel */ - if (get_cpu() == cpu) - write_rdtscp_cb(info); -#ifdef CONFIG_SMP - else { - /* the notifier is unfortunately not executed on the - target CPU */ - smp_call_function_single(cpu,write_rdtscp_cb,info,0,1); - } -#endif - put_cpu(); - } + if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) + write_rdtscp_aux((node << 12) | cpu); /* Store cpu number in limit so that it can be loaded quickly in user space in vgetcpu. @@ -280,6 +268,21 @@ void __cpuinit vsyscall_set_cpu(int cpu) *d |= (node >> 4) << 48; } +static void __cpuinit cpu_vsyscall_init(void *arg) +{ + /* preemption should be already off */ + vsyscall_set_cpu(raw_smp_processor_id()); +} + +static int __cpuinit +cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) +{ + long cpu = (long)arg; + if (action == CPU_ONLINE) + smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); + return NOTIFY_DONE; +} + static void __init map_vsyscall(void) { extern char __vsyscall_0; @@ -299,6 +302,8 @@ static int __init vsyscall_init(void) #ifdef CONFIG_SYSCTL register_sysctl_table(kernel_root_table2, 0); #endif + on_each_cpu(cpu_vsyscall_init, NULL, 0, 1); + hotcpu_notifier(cpu_vsyscall_notifier, 0); return 0; } diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h index fd452fc..01d1c17 100644 --- a/include/asm-x86_64/vsyscall.h +++ b/include/asm-x86_64/vsyscall.h @@ -59,8 +59,6 @@ extern seqlock_t xtime_lock; extern int sysctl_vsyscall; -extern void vsyscall_set_cpu(int cpu); - #define ARCH_HAVE_XTIME_LOCK 1 #endif /* __KERNEL__ */ -- cgit v0.10.2 From 9446868b5383eb87f76b2d4389dea4bb968a6657 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 14 Nov 2006 16:57:46 +0100 Subject: [PATCH] x86-64: Fix race in exit_idle When another interrupt happens in exit_idle the exit idle notifier could be called an incorrect number of times. Add a test_and_clear_bit_pda and use it handle the bit atomically against interrupts to avoid this. Pointed out by Stephane Eranian Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 49f7fac..f622605 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -88,9 +88,8 @@ void enter_idle(void) static void __exit_idle(void) { - if (read_pda(isidle) == 0) + if (test_and_clear_bit_pda(0, isidle) == 0) return; - write_pda(isidle, 0); atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); } diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h index 14996d9..5642634 100644 --- a/include/asm-x86_64/pda.h +++ b/include/asm-x86_64/pda.h @@ -109,6 +109,15 @@ extern struct x8664_pda _proxy_pda; #define sub_pda(field,val) pda_to_op("sub",field,val) #define or_pda(field,val) pda_to_op("or",field,val) +/* This is not atomic against other CPUs -- CPU preemption needs to be off */ +#define test_and_clear_bit_pda(bit,field) ({ \ + int old__; \ + asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0" \ + : "=r" (old__), "+m" (_proxy_pda.field) \ + : "dIr" (bit), "i" (pda_offset(field)) : "memory"); \ + old__; \ +}) + #endif #define PDA_STACKOFFSET (5*8) -- cgit v0.10.2 From 8b126b77536186eef69d408eb7959ce7f558f251 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 14 Nov 2006 02:03:23 -0800 Subject: [PATCH] setup_irq(): better mismatch debugging When we get a mismatch between handlers on the same IRQ, all we get is "IRQ handler type mismatch for IRQ n". Let's print the name of the presently-registered handler with which we got the mismatch. Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 6879202..b385878 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -216,6 +216,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) { struct irq_desc *desc = irq_desc + irq; struct irqaction *old, **p; + const char *old_name = NULL; unsigned long flags; int shared = 0; @@ -255,8 +256,10 @@ int setup_irq(unsigned int irq, struct irqaction *new) * set the trigger type must match. */ if (!((old->flags & new->flags) & IRQF_SHARED) || - ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) + ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) { + old_name = old->name; goto mismatch; + } #if defined(CONFIG_IRQ_PER_CPU) /* All handlers must agree on per-cpuness */ @@ -322,11 +325,13 @@ int setup_irq(unsigned int irq, struct irqaction *new) return 0; mismatch: - spin_unlock_irqrestore(&desc->lock, flags); if (!(new->flags & IRQF_PROBE_SHARED)) { printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); + if (old_name) + printk(KERN_ERR "current handler: %s\n", old_name); dump_stack(); } + spin_unlock_irqrestore(&desc->lock, flags); return -EBUSY; } -- cgit v0.10.2 From f3ac84324fd949f671e6cf5620add5de02498386 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Tue, 14 Nov 2006 02:03:25 -0800 Subject: [PATCH] fix via586 irq routing for pirq 5 Fix interrupt routing for via 586 bridges. pirq can be 5 which needs to be mapped to INTD. But currently the access functions can handle only pirq 1-4. this is similar to the other via chipsets where pirq 4 and 5 are both mapped to INTD. Fixes bugzilla #7490 Cc: Daniel Paschka Cc: Adrian Bunk Signed-off-by: Daniel Ritz Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index dbc4aae..6916399 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -255,13 +255,13 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i */ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 }; return read_config_nybble(router, 0x55, pirqmap[pirq-1]); } static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 }; write_config_nybble(router, 0x55, pirqmap[pirq-1], irq); return 1; } -- cgit v0.10.2 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 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 204b1c8..5b44838 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 v0.10.2 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 diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index b1d5291..45ed035 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 v0.10.2 From ba8df43c0ee93ec05fc526278a80aaf4cb5ab1fa Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 14 Nov 2006 02:03:29 -0800 Subject: [PATCH] autofs4: panic after mount fail Resolve the panic on failed mount of an autofs filesystem originally reported by Mao Bibo. It addresses two issues that happen after the mount fail. The first a NULL pointer reference to a field (pipe) in the autofs superblock info structure and second the lack of super block cleanup by the autofs and autofs4 modules. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 54c518c..38ede5c 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -25,6 +25,14 @@ void autofs_kill_sb(struct super_block *sb) struct autofs_sb_info *sbi = autofs_sbi(sb); unsigned int n; + /* + * In the event of a failure in get_sb_nodev the superblock + * info is not present so nothing else has been setup, so + * just exit when we are called from deactivate_super. + */ + if (!sbi) + return; + if ( !sbi->catatonic ) autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ @@ -136,7 +144,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; - sbi->catatonic = 0; + sbi->pipe = NULL; + sbi->catatonic = 1; sbi->exp_timeout = 0; sbi->oz_pgrp = process_group(current); autofs_initialize_hash(&sbi->dirhash); @@ -180,6 +189,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) if ( !pipe->f_op || !pipe->f_op->write ) goto fail_fput; sbi->pipe = pipe; + sbi->catatonic = 0; /* * Success! Install the root dentry now to indicate completion. @@ -198,6 +208,8 @@ fail_iput: iput(root_inode); fail_free: kfree(sbi); + s->s_fs_info = NULL; + kill_anon_super(s); fail_unlock: return -EINVAL; } diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 633f628..19a9caf 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -41,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) wq = nwq; } fput(sbi->pipe); /* Close the pipe */ + sbi->pipe = NULL; autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ } diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 51fd859..ce7c0f1 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -99,6 +99,9 @@ static void autofs4_force_release(struct autofs_sb_info *sbi) struct dentry *this_parent = sbi->sb->s_root; struct list_head *next; + if (!sbi->sb->s_root) + return; + spin_lock(&dcache_lock); repeat: next = this_parent->d_subdirs.next; @@ -146,6 +149,14 @@ void autofs4_kill_sb(struct super_block *sb) { struct autofs_sb_info *sbi = autofs4_sbi(sb); + /* + * In the event of a failure in get_sb_nodev the superblock + * info is not present so nothing else has been setup, so + * just exit when we are called from deactivate_super. + */ + if (!sbi) + return; + sb->s_fs_info = NULL; if ( !sbi->catatonic ) @@ -310,7 +321,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; sbi->pipefd = -1; - sbi->catatonic = 0; + sbi->pipe = NULL; + sbi->catatonic = 1; sbi->exp_timeout = 0; sbi->oz_pgrp = process_group(current); sbi->sb = s; @@ -388,6 +400,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) goto fail_fput; sbi->pipe = pipe; sbi->pipefd = pipefd; + sbi->catatonic = 0; /* * Success! Install the root dentry now to indicate completion. @@ -412,6 +425,8 @@ fail_ino: kfree(ino); fail_free: kfree(sbi); + s->s_fs_info = NULL; + kill_anon_super(s); fail_unlock: return -EINVAL; } diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index c0a6c8d..1e4a539 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -41,10 +41,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) wake_up_interruptible(&wq->queue); wq = nwq; } - if (sbi->pipe) { - fput(sbi->pipe); /* Close the pipe */ - sbi->pipe = NULL; - } + fput(sbi->pipe); /* Close the pipe */ + sbi->pipe = NULL; } static int autofs4_write(struct file *file, const void *addr, int bytes) -- cgit v0.10.2 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 diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 61dc46f..eab3e28 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 v0.10.2 From 69ae9e3ee4ce99140a7db424bebf55d8d180da2f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 14 Nov 2006 02:03:31 -0800 Subject: [PATCH] usb: MAINTAINERS updates Looks like I still take care of the USB gadget/peripheral framework. Signed-off-by: David Brownell Acked-by: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 8732dae..a5508f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3072,6 +3072,13 @@ L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained +USB GADGET/PERIPHERAL SUBSYSTEM +P: David Brownell +M: dbrownell@users.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +W: http://www.linux-usb.org/gadget +S: Maintained + USB HID/HIDBP DRIVERS P: Vojtech Pavlik M: vojtech@suse.cz @@ -3255,10 +3262,11 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained -USB "USBNET" DRIVER +USB "USBNET" DRIVER FRAMEWORK P: David Brownell M: dbrownell@users.sourceforge.net L: linux-usb-devel@lists.sourceforge.net +W: http://www.linux-usb.org/usbnet S: Maintained USB W996[87]CF DRIVER -- cgit v0.10.2 From 68589bc353037f233fe510ad9ff432338c95db66 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 14 Nov 2006 02:03:32 -0800 Subject: [PATCH] hugetlb: prepare_hugepage_range check offset too (David:) If hugetlbfs_file_mmap() returns a failure to do_mmap_pgoff() - for example, because the given file offset is not hugepage aligned - then do_mmap_pgoff will go to the unmap_and_free_vma backout path. But at this stage the vma hasn't been marked as hugepage, and the backout path will call unmap_region() on it. That will eventually call down to the non-hugepage version of unmap_page_range(). On ppc64, at least, that will cause serious problems if there are any existing hugepage pagetable entries in the vicinity - for example if there are any other hugepage mappings under the same PUD. unmap_page_range() will trigger a bad_pud() on the hugepage pud entries. I suspect this will also cause bad problems on ia64, though I don't have a machine to test it on. (Hugh:) prepare_hugepage_range() should check file offset alignment when it checks virtual address and length, to stop MAP_FIXED with a bad huge offset from unmapping before it fails further down. PowerPC should apply the same prepare_hugepage_range alignment checks as ia64 and all the others do. Then none of the alignment checks in hugetlbfs_file_mmap are required (nor is the check for too small a mapping); but even so, move up setting of VM_HUGETLB and add a comment to warn of what David Gibson discovered - if hugetlbfs_file_mmap fails before setting it, do_mmap_pgoff's unmap_region when unwinding from error will go the non-huge way, which may cause bad behaviour on architectures (powerpc and ia64) which segregate their huge mappings into a separate region of the address space. Signed-off-by: Hugh Dickins Cc: "Luck, Tony" Cc: "David S. Miller" Acked-by: Adam Litke Acked-by: David Gibson Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index eee5c1cf..f3a9585 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -70,8 +70,10 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr) * Don't actually need to do any preparation, but need to make sure * the address is in the right region. */ -int prepare_hugepage_range(unsigned long addr, unsigned long len) +int prepare_hugepage_range(unsigned long addr, unsigned long len, pgoff_t pgoff) { + if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT)) + return -EINVAL; if (len & ~HPAGE_MASK) return -EINVAL; if (addr & ~HPAGE_MASK) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index fd68b74..506d897 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -491,11 +491,15 @@ static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas) return 0; } -int prepare_hugepage_range(unsigned long addr, unsigned long len) +int prepare_hugepage_range(unsigned long addr, unsigned long len, pgoff_t pgoff) { int err = 0; - if ( (addr+len) < addr ) + if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT)) + return -EINVAL; + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) return -EINVAL; if (addr < 0x100000000UL) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 0bea6a6..7f47569 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -62,24 +62,19 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) loff_t len, vma_len; int ret; - if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1)) - return -EINVAL; - - if (vma->vm_start & ~HPAGE_MASK) - return -EINVAL; - - if (vma->vm_end & ~HPAGE_MASK) - return -EINVAL; - - if (vma->vm_end - vma->vm_start < HPAGE_SIZE) - return -EINVAL; + /* + * vma alignment has already been checked by prepare_hugepage_range. + * If you add any error returns here, do so after setting VM_HUGETLB, + * so is_vm_hugetlb_page tests below unmap_region go the right way + * when do_mmap_pgoff unwinds (may be important on powerpc and ia64). + */ + vma->vm_flags |= VM_HUGETLB | VM_RESERVED; + vma->vm_ops = &hugetlb_vm_ops; vma_len = (loff_t)(vma->vm_end - vma->vm_start); mutex_lock(&inode->i_mutex); file_accessed(file); - vma->vm_flags |= VM_HUGETLB | VM_RESERVED; - vma->vm_ops = &hugetlb_vm_ops; ret = -ENOMEM; len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 5081d27..ace64e5 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -60,8 +60,11 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr, * If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ -static inline int prepare_hugepage_range(unsigned long addr, unsigned long len) +static inline int prepare_hugepage_range(unsigned long addr, unsigned long len, + pgoff_t pgoff) { + if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT)) + return -EINVAL; if (len & ~HPAGE_MASK) return -EINVAL; if (addr & ~HPAGE_MASK) @@ -69,7 +72,8 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len) return 0; } #else -int prepare_hugepage_range(unsigned long addr, unsigned long len); +int prepare_hugepage_range(unsigned long addr, unsigned long len, + pgoff_t pgoff); #endif #ifndef ARCH_HAS_SETCLEAR_HUGE_PTE @@ -107,7 +111,7 @@ static inline unsigned long hugetlb_total_pages(void) #define hugetlb_report_meminfo(buf) 0 #define hugetlb_report_node_meminfo(n, buf) 0 #define follow_huge_pmd(mm, addr, pmd, write) NULL -#define prepare_hugepage_range(addr, len) (-EINVAL) +#define prepare_hugepage_range(addr,len,pgoff) (-EINVAL) #define pmd_huge(x) 0 #define is_hugepage_only_range(mm, addr, len) 0 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) diff --git a/mm/mmap.c b/mm/mmap.c index 497e502..bdace87 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1379,7 +1379,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, * Check if the given range is hugepage aligned, and * can be made suitable for hugepages. */ - ret = prepare_hugepage_range(addr, len); + ret = prepare_hugepage_range(addr, len, pgoff); } else { /* * Ensure that a normal request is not falling in a -- cgit v0.10.2 From cb07c9a1864a8eac9f3123e428100d5b2a16e65a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 14 Nov 2006 02:03:38 -0800 Subject: [PATCH] hugetlb: check for brk() entering a hugepage region Unlike mmap(), the codepath for brk() creates a vma without first checking that it doesn't touch a region exclusively reserved for hugepages. On powerpc, this can allow it to create a normal page vma in a hugepage region, causing oopses and other badness. Add a test to prevent this. With this patch, brk() will simply fail if it attempts to move the break into a hugepage reserved region. Signed-off-by: David Gibson Cc: Adam Litke Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/mmap.c b/mm/mmap.c index bdace87..2526463 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1880,6 +1880,10 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL; + error = is_hugepage_only_range(current->mm, addr, len); + if (error) + return error; + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; error = arch_mmap_check(addr, len, flags); -- cgit v0.10.2 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 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a8fd0c3..915a55a 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 v0.10.2 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 diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 6ffe2b2..4105c3b 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 v0.10.2 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 diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 570d2f0..d5f519e 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 v0.10.2 From cd2579d7aa7bfc966cc271a88e77f8cfc3b0b7ba Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 14 Nov 2006 13:43:38 +0000 Subject: [PATCH] hugetlb: fix error return for brk() entering a hugepage region Commit cb07c9a1864a8eac9f3123e428100d5b2a16e65a causes the wrong return value. is_hugepage_only_range() is a boolean, so we should return -EINVAL rather than 1. Also - we can use "mm" instead of looking up "current->mm" again. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds diff --git a/mm/mmap.c b/mm/mmap.c index 2526463..7b40abd 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1880,9 +1880,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL; - error = is_hugepage_only_range(current->mm, addr, len); - if (error) - return error; + if (is_hugepage_only_range(mm, addr, len)) + return -EINVAL; flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; -- cgit v0.10.2 From 9a3a04ac386f44175b6a4142eaeab3d4170a57f3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 14 Nov 2006 15:20:51 -0800 Subject: Revert "[PATCH] fix Data Acess error in dup_fd" This reverts commit 0130b0b32ee53dc7add773fcea984f6a26ef1da3. Sergey Vlasov points out (and Vadim Lobanov concurs) that the bug it was supposed to fix must be some unrelated memory corruption, and the "fix" actually causes more problems: "However, the new code does not look safe in all cases. If some other task has opened more files while dup_fd() released oldf->file_lock, the new code will update open_files to the new larger value. But newf was allocated with the old smaller value of open_files, therefore subsequent accesses to newf may try to write into unallocated memory." so revert it. Cc: Sharyathi Nagesh Cc: Sergey Vlasov Cc: Vadim Lobanov Cc: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 4b4eab2..3da978e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -687,7 +687,6 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) * the latest pointer. */ spin_lock(&oldf->file_lock); - open_files = count_open_files(old_fdt); old_fdt = files_fdtable(oldf); } -- cgit v0.10.2 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 diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index e9e9bf3..58c955e 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 v0.10.2 From 134a11f0c37c043d3ea557ea15b95b084e3cc2c8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Nov 2006 12:08:37 +0100 Subject: [PATCH] ALSA: hda-intel - Disable MSI support by default Disable MSI support on HD-audio driver as default since there are too many broken devices. The module option is changed from disable_msi to enable_msi, too. For turning MSI support on, pass enable_msi=1, instead. Signed-off-by: Takashi Iwai Signed-off-by: Linus Torvalds diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 138673a..3472d9c 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -753,7 +753,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) single_cmd - Use single immediate commands to communicate with codecs (for debugging only) - disable_msi - Disable Message Signaled Interrupt (MSI) + enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) This module supports one card and autoprobe. diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0e292dc..e35cfd3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -55,7 +55,7 @@ static char *model; static int position_fix; static int probe_mask = -1; static int single_cmd; -static int disable_msi; +static int enable_msi; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -69,8 +69,8 @@ module_param(probe_mask, int, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); -module_param(disable_msi, int, 0); -MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); +module_param(enable_msi, int, 0); +MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); /* just for backward compatibility */ @@ -1531,7 +1531,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; chip->driver_type = driver_type; - chip->msi = !disable_msi; + chip->msi = enable_msi; chip->position_fix = position_fix; chip->single_cmd = single_cmd; -- cgit v0.10.2 From efa53ebe0d2f50bf342eb1976824f59bba9941eb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 13 Nov 2006 11:32:50 +0800 Subject: [PATCH] ieee80211: Fix kernel panic when QoS is enabled The 802.11 header length is affected by the wireless mode (WDS or not) and type (QoS or not). We should use the variable hdr_len instead of the hard coded IEEE80211_3ADDR_LEN, otherwise we may touch invalid memory. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index ae25449..854fc13 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -390,7 +390,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account * for it when determining the amount of payload space. */ - bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; + bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; @@ -412,7 +412,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } else { nr_frags = 1; bytes_per_frag = bytes_last_frag = bytes; - frag_size = bytes + IEEE80211_3ADDR_LEN; + frag_size = bytes + hdr_len; } rts_required = (frag_size > ieee->rts -- cgit v0.10.2 From 45c99533252ef2297f37c5fdd672a3e0eb566870 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 14 Nov 2006 10:52:12 -0700 Subject: [PATCH] Use delayed disable mode of ioapic edge triggered interrupts Komuro reports that ISA interrupts do not work after a disable_irq(), causing some PCMCIA drivers to not work, with messages like eth0: Asix AX88190: io 0x300, irq 3, hw_addr xx:xx:xx:xx:xx:xx eth0: found link beat eth0: autonegotiation complete: 100baseT-FD selected eth0: interrupt(s) dropped! eth0: interrupt(s) dropped! eth0: interrupt(s) dropped! ... Linus Torvalds said: "Now, edge-triggered interrupts are a _lot_ harder to mask, because the Intel APIC is an unbelievable piece of sh*t, and has the edge-detect logic _before_ the mask logic, so if a edge happens _while_ the device is masked, you'll never ever see the edge ever again (unmasking will not cause a new edge, so you simply lost the interrupt). So when you "mask" an edge-triggered IRQ, you can't really mask it at all, because if you did that, you'd lose it forever if the IRQ comes in while you masked it. Instead, we're supposed to leave it active, and set a flag, and IF the IRQ comes in, we just remember it, and mask it at that point instead, and then on unmasking, we have to replay it by sending a self-IPI." This trivial patch solves the problem. Signed-off-by: Eric W. Biederman Cc: Ingo Molnar Acked-by: Komuro Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index ad84bc2..3b7a63e 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1287,9 +1287,11 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger) trigger == IOAPIC_LEVEL) set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_fasteoi_irq, "fasteoi"); - else + else { + irq_desc[irq].status |= IRQ_DELAYED_DISABLE; set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge"); + } set_intr_gate(vector, interrupt[irq]); } diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 41bfc49..14654e6 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -790,9 +790,11 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger) trigger == IOAPIC_LEVEL) set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_fasteoi_irq, "fasteoi"); - else + else { + irq_desc[irq].status |= IRQ_DELAYED_DISABLE; set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge"); + } } static void __init setup_IO_APIC_irqs(void) -- cgit v0.10.2 From b4d38e38e66f8e1b32a1b1c00e533175314c8d56 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 11 Oct 2006 16:48:28 -0400 Subject: [SCSI] Reduce polling in sd.c If a drive reports that no media is present, there's no point in continuing to ask it about media status. This patch (as696) cuts the TUR polling short as soon as the drive reports no media instead of going a full 3 iterations. Signed-off-by: Alan Stern Signed-off-by: James Bottomley diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 84ff203..152f4ff 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1051,6 +1051,14 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); + /* + * If the drive has indicated to us that it + * doesn't have any media in it, don't bother + * with any more polling. + */ + if (media_not_present(sdkp, &sshdr)) + return; + if (the_result) sense_valid = scsi_sense_valid(&sshdr); retries++; @@ -1059,14 +1067,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) ((driver_byte(the_result) & DRIVER_SENSE) && sense_valid && sshdr.sense_key == UNIT_ATTENTION))); - /* - * If the drive has indicated to us that it doesn't have - * any media in it, don't bother with any of the rest of - * this crap. - */ - if (media_not_present(sdkp, &sshdr)) - return; - if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { /* no sense, TUR either succeeded or failed * with a status error */ -- cgit v0.10.2 From cbf093e8c7447a202e376199cc017161262bd7cd Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 14 Nov 2006 20:50:59 -0600 Subject: [IA64] bte_unaligned_copy() transfers one extra cache line. When called to do a transfer that has a start offset within the cache line which is uneven between source and destination and a length which terminates the source of the copy exactly on a cache line, one extra line gets copied into a temporary buffer. This is normally not an issue since the buffer is a kernel buffer and only the requested information gets copied into the user buffer. The problem arises when the source ends at the very last physical page of memory. That last cache line does not exist and results in the SHUB chip raising an MCA. Signed-off-by: Robin Holt Signed-off-by: Dean Nelson Signed-off-by: Tony Luck diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index 7f73ad4..ff1c556 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -381,14 +381,13 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) * bcopy to the destination. */ - /* Add the leader from source */ - headBteLen = len + (src & L1_CACHE_MASK); - /* Add the trailing bytes from footer. */ - headBteLen += L1_CACHE_BYTES - (headBteLen & L1_CACHE_MASK); - headBteSource = src & ~L1_CACHE_MASK; headBcopySrcOffset = src & L1_CACHE_MASK; headBcopyDest = dest; headBcopyLen = len; + + headBteSource = src - headBcopySrcOffset; + /* Add the leading and trailing bytes from source */ + headBteLen = L1_CACHE_ALIGN(len + headBcopySrcOffset); } if (headBcopyLen > 0) { -- cgit v0.10.2 From f456393e195e0aa16029985f63cd93b601a0d315 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 30 Oct 2006 15:18:39 -0800 Subject: [SCSI] libsas: modify error handler to use scsi_eh_* functions This patch adds an EH done queue to sas_ha, converts the error handling strategy function and the sas_scsi_task_done functions in libsas to use the scsi_eh_* commands for error'd commands, and adds checks for the INITIATOR_ABORTED flag so that we do the right thing if a sas_task has been aborted by the initiator. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index c836a23..a2b479a 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -112,6 +112,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) } } + INIT_LIST_HEAD(&sas_ha->eh_done_q); + return 0; Undo_ports: diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index e46e793..6a97b07 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include "../scsi_sas_internal.h" @@ -46,6 +47,7 @@ static void sas_scsi_task_done(struct sas_task *task) { struct task_status_struct *ts = &task->task_status; struct scsi_cmnd *sc = task->uldd_task; + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host); unsigned ts_flags = task->task_state_flags; int hs = 0, stat = 0; @@ -116,7 +118,7 @@ static void sas_scsi_task_done(struct sas_task *task) sas_free_task(task); /* This is very ugly but this is how SCSI Core works. */ if (ts_flags & SAS_TASK_STATE_ABORTED) - scsi_finish_command(sc); + scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q); else sc->scsi_done(sc); } @@ -307,6 +309,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) spin_unlock_irqrestore(&core->task_queue_lock, flags); } + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("%s: task 0x%p already aborted\n", + __FUNCTION__, task); + return TASK_IS_ABORTED; + } + spin_unlock_irqrestore(&task->task_state_lock, flags); + for (i = 0; i < 5; i++) { SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_abort_task(task); @@ -409,13 +420,16 @@ Again: SAS_DPRINTK("going over list...\n"); list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); + list_del_init(&cmd->eh_entry); + if (!task) { + SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); + continue; + } SAS_DPRINTK("trying to find task 0x%p\n", task); - list_del_init(&cmd->eh_entry); res = sas_scsi_find_task(task); cmd->eh_eflags = 0; - shost->host_failed--; switch (res) { case TASK_IS_DONE: @@ -491,6 +505,7 @@ Again: } } out: + scsi_eh_flush_done_q(&ha->eh_done_q); SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); return; clear_q: @@ -508,12 +523,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) unsigned long flags; if (!task) { - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", + SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", cmd, task); return EH_HANDLED; } spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " + "EH_NOT_HANDLED\n", cmd, task); + return EH_NOT_HANDLED; + } if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9582e84..7bf2e8b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -338,6 +338,8 @@ struct sas_ha_struct { void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); void *lldd_ha; /* not touched by sas class code */ + + struct list_head eh_done_q; }; #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) @@ -530,9 +532,10 @@ struct sas_task { -#define SAS_TASK_STATE_PENDING 1 -#define SAS_TASK_STATE_DONE 2 -#define SAS_TASK_STATE_ABORTED 4 +#define SAS_TASK_STATE_PENDING 1 +#define SAS_TASK_STATE_DONE 2 +#define SAS_TASK_STATE_ABORTED 4 +#define SAS_TASK_INITIATOR_ABORTED 8 static inline struct sas_task *sas_alloc_task(gfp_t flags) { -- cgit v0.10.2 From 79a5eb609b74e7b3638861c41b98eafa74920a1f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 30 Oct 2006 15:18:50 -0800 Subject: [SCSI] libsas: add sas_abort_task This patch adds an external function, sas_abort_task, to enable LLDDs to abort sas_tasks. It also adds a work_struct so that the actual work of aborting a task can be shifted from tasklet context (in the LLDD) onto the scsi_host's workqueue. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 6a97b07..c5fd375 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -33,6 +33,7 @@ #include #include #include "../scsi_sas_internal.h" +#include "../scsi_transport_api.h" #include #include @@ -798,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) spin_unlock_irqrestore(&core->task_queue_lock, flags); } +static int do_sas_task_abort(struct sas_task *task) +{ + struct scsi_cmnd *sc = task->uldd_task; + struct sas_internal *si = + to_sas_internal(task->dev->port->ha->core.shost->transportt); + unsigned long flags; + int res; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, + task); + return 0; + } + + task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + if (!si->dft->lldd_abort_task) + return -ENODEV; + + res = si->dft->lldd_abort_task(task); + if ((task->task_state_flags & SAS_TASK_STATE_DONE) || + (res == TMF_RESP_FUNC_COMPLETE)) + { + /* SMP commands don't have scsi_cmds(?) */ + if (!sc) { + task->task_done(task); + return 0; + } + scsi_req_abort_cmd(sc); + scsi_schedule_eh(sc->device->host); + return 0; + } + + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + return -EAGAIN; +} + +void sas_task_abort(struct sas_task *task) +{ + int i; + + for (i = 0; i < 5; i++) + if (!do_sas_task_abort(task)) + return; + + SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); +} + EXPORT_SYMBOL_GPL(sas_queuecommand); EXPORT_SYMBOL_GPL(sas_target_alloc); EXPORT_SYMBOL_GPL(sas_slave_configure); @@ -805,3 +864,4 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); EXPORT_SYMBOL_GPL(sas_change_queue_depth); EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); +EXPORT_SYMBOL_GPL(sas_task_abort); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 7bf2e8b..a1fc20a 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -528,6 +528,8 @@ struct sas_task { void *lldd_task; /* for use by LLDDs */ void *uldd_task; + + struct work_struct abort_work; }; @@ -627,4 +629,6 @@ void sas_unregister_dev(struct domain_device *); void sas_init_dev(struct domain_device *); +void sas_task_abort(struct sas_task *task); + #endif /* _SASLIB_H_ */ -- cgit v0.10.2 From fe4a36cf652031d2744a536ba5121032840380cb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 30 Oct 2006 15:18:56 -0800 Subject: [SCSI] aic94xx: handle REQ_TASK_ABORT This patch straightens out the code that distinguishes the various escb opcodes in escb_tasklet_complete so that they can be handled correctly. It also provides all the necessary code to create a workqueue item that tells libsas to abort a sas_task. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 7ee49b5..1911c5d 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -25,6 +25,7 @@ */ #include +#include #include "aic94xx.h" #include "aic94xx_reg.h" @@ -342,6 +343,18 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } } +/* start up the ABORT TASK tmf... */ +static void task_kill_later(struct asd_ascb *ascb) +{ + struct asd_ha_struct *asd_ha = ascb->ha; + struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; + struct Scsi_Host *shost = sas_ha->core.shost; + struct sas_task *task = ascb->uldd_task; + + INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task); + queue_work(shost->work_q, &task->abort_work); +} + static void escb_tasklet_complete(struct asd_ascb *ascb, struct done_list_struct *dl) { @@ -368,6 +381,58 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, ascb->scb->header.opcode); } + /* Catch these before we mask off the sb_opcode bits */ + switch (sb_opcode) { + case REQ_TASK_ABORT: { + struct asd_ascb *a, *b; + u16 tc_abort; + + tc_abort = *((u16*)(&dl->status_block[1])); + tc_abort = le16_to_cpu(tc_abort); + + ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", + __FUNCTION__, dl->status_block[3]); + + /* Find the pending task and abort it. */ + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) + if (a->tc_index == tc_abort) { + task_kill_later(a); + break; + } + goto out; + } + case REQ_DEVICE_RESET: { + struct asd_ascb *a, *b; + u16 conn_handle; + + conn_handle = *((u16*)(&dl->status_block[1])); + conn_handle = le16_to_cpu(conn_handle); + + ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__, + dl->status_block[3]); + + /* Kill all pending tasks and reset the device */ + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { + struct sas_task *task = a->uldd_task; + struct domain_device *dev = task->dev; + u16 x; + + x = *((u16*)(&dev->lldd_dev)); + if (x == conn_handle) + task_kill_later(a); + } + + /* FIXME: Reset device port (huh?) */ + goto out; + } + case SIGNAL_NCQ_ERROR: + ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__); + goto out; + case CLEAR_NCQ_ERROR: + ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__); + goto out; + } + sb_opcode &= ~DL_PHY_MASK; switch (sb_opcode) { @@ -397,22 +462,6 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, sas_phy_disconnected(sas_phy); sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); break; - case REQ_TASK_ABORT: - ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__, - phy_id); - break; - case REQ_DEVICE_RESET: - ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__, - phy_id); - break; - case SIGNAL_NCQ_ERROR: - ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__, - phy_id); - break; - case CLEAR_NCQ_ERROR: - ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__, - phy_id); - break; default: ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__, phy_id, sb_opcode); @@ -432,7 +481,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, break; } - +out: asd_invalidate_edb(ascb, edb); } -- cgit v0.10.2 From 2dc611de5a3fd955cd0298c50691d4c05046db97 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 4 Nov 2006 20:04:21 +0100 Subject: [SCSI] use one-element sg list in scsi_send_eh_cmnd scsi_send_eh_cmnd is the last user of non-sg commands currently. This patch switches it to a one-element SG list. Also updates the kerneldoc comment for scsi_send_eh_cmnd to reflect reality while we're at it. Test on my mptsas card, but this should get testing with as many drivers as possible. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index aff1b0c..2ecb6ff 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -453,9 +453,18 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) } /** - * scsi_send_eh_cmnd - send a cmd to a device as part of error recovery. - * @scmd: SCSI Cmd to send. - * @timeout: Timeout for cmd. + * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * @scmd: SCSI command structure to hijack + * @cmnd: CDB to send + * @cmnd_size: size in bytes of @cmnd + * @timeout: timeout for this request + * @copy_sense: request sense data if set to 1 + * + * This function is used to send a scsi command down to a target device + * as part of the error recovery process. If @copy_sense is 0 the command + * sent must be one that does not transfer any data. If @copy_sense is 1 + * the command must be REQUEST_SENSE and this functions copies out the + * sense buffer it got into @scmd->sense_buffer. * * Return value: * SUCCESS or FAILED or NEEDS_RETRY @@ -469,6 +478,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, DECLARE_COMPLETION_ONSTACK(done); unsigned long timeleft; unsigned long flags; + struct scatterlist sgl; unsigned char old_cmnd[MAX_COMMAND_SIZE]; enum dma_data_direction old_data_direction; unsigned short old_use_sg; @@ -500,19 +510,24 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, if (shost->hostt->unchecked_isa_dma) gfp_mask |= __GFP_DMA; - scmd->sc_data_direction = DMA_FROM_DEVICE; - scmd->request_bufflen = 252; - scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask); - if (!scmd->request_buffer) + sgl.page = alloc_page(gfp_mask); + if (!sgl.page) return FAILED; + sgl.offset = 0; + sgl.length = 252; + + scmd->sc_data_direction = DMA_FROM_DEVICE; + scmd->request_bufflen = sgl.length; + scmd->request_buffer = &sgl; + scmd->use_sg = 1; } else { scmd->request_buffer = NULL; scmd->request_bufflen = 0; scmd->sc_data_direction = DMA_NONE; + scmd->use_sg = 0; } scmd->underflow = 0; - scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); if (sdev->scsi_level <= SCSI_2) @@ -583,7 +598,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, memcpy(scmd->sense_buffer, scmd->request_buffer, sizeof(scmd->sense_buffer)); } - kfree(scmd->request_buffer); + __free_page(sgl.page); } -- cgit v0.10.2 From 3b00315799d78f76531b71435fbc2643cd71ae4c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 4 Nov 2006 20:10:55 +0100 Subject: [SCSI] untangle scsi_prep_fn I wanted to add some BUG checks to scsi_prep_fn to make sure no one sends us a non-sg command, but this function is a horrible mess. So I decided to detangle the function and document what the valid cases are. While doing that I found that REQ_TYPE_SPECIAL commands aren't used by the SCSI layer anymore and we can get rid of the code handling them. The new structure of scsi_prep_fn is: (1) check if we're allowed to send this command (2) big switch on cmd_type. For the two valid types call into a function to set the command up, else error (3) code to handle error cases Because FS and BLOCK_PC commands are handled entirely separate after the patch this introduces a tiny amount of code duplication. This improves readabiulity though and will help to avoid the bidi command overhead for FS commands so it's a good thing. I've tested this on both sata and mptsas. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 743f67e..ee35a62 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -995,25 +995,14 @@ static int scsi_init_io(struct scsi_cmnd *cmd) int count; /* - * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer - */ - if (blk_pc_request(req) && !req->bio) { - cmd->request_bufflen = req->data_len; - cmd->request_buffer = req->data; - req->buffer = req->data; - cmd->use_sg = 0; - return 0; - } - - /* - * we used to not use scatter-gather for single segment request, + * We used to not use scatter-gather for single segment request, * but now we do (it makes highmem I/O easier to support without * kmapping pages) */ cmd->use_sg = req->nr_phys_segments; /* - * if sg table allocation fails, requeue request later. + * If sg table allocation fails, requeue request later. */ sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); if (unlikely(!sgpnt)) { @@ -1021,24 +1010,21 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_DEFER; } + req->buffer = NULL; cmd->request_buffer = (char *) sgpnt; - cmd->request_bufflen = req->nr_sectors << 9; if (blk_pc_request(req)) cmd->request_bufflen = req->data_len; - req->buffer = NULL; + else + cmd->request_bufflen = req->nr_sectors << 9; /* * Next, walk the list, and fill in the addresses and sizes of * each segment. */ count = blk_rq_map_sg(req->q, req, cmd->request_buffer); - - /* - * mapped well, send it off - */ if (likely(count <= cmd->use_sg)) { cmd->use_sg = count; - return 0; + return BLKPREP_OK; } printk(KERN_ERR "Incorrect number of segments after building list\n"); @@ -1068,6 +1054,27 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, return -EOPNOTSUPP; } +static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, + struct request *req) +{ + struct scsi_cmnd *cmd; + + if (!req->special) { + cmd = scsi_get_command(sdev, GFP_ATOMIC); + if (unlikely(!cmd)) + return NULL; + req->special = cmd; + } else { + cmd = req->special; + } + + /* pull a tag out of the request if we have one */ + cmd->tag = req->tag; + cmd->request = req; + + return cmd; +} + static void scsi_blk_pc_done(struct scsi_cmnd *cmd) { BUG_ON(!blk_pc_request(cmd->request)); @@ -1080,9 +1087,37 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd) scsi_io_completion(cmd, cmd->request_bufflen); } -static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) +static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { - struct request *req = cmd->request; + struct scsi_cmnd *cmd; + + cmd = scsi_get_cmd_from_req(sdev, req); + if (unlikely(!cmd)) + return BLKPREP_DEFER; + + /* + * BLOCK_PC requests may transfer data, in which case they must + * a bio attached to them. Or they might contain a SCSI command + * that does not transfer data, in which case they may optionally + * submit a request without an attached bio. + */ + if (req->bio) { + int ret; + + BUG_ON(!req->nr_phys_segments); + + ret = scsi_init_io(cmd); + if (unlikely(ret)) + return ret; + } else { + BUG_ON(req->data_len); + BUG_ON(req->data); + + cmd->request_bufflen = 0; + cmd->request_buffer = NULL; + cmd->use_sg = 0; + req->buffer = NULL; + } BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); @@ -1098,154 +1133,138 @@ static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; cmd->done = scsi_blk_pc_done; + return BLKPREP_OK; } -static int scsi_prep_fn(struct request_queue *q, struct request *req) +/* + * Setup a REQ_TYPE_FS command. These are simple read/write request + * from filesystems that still need to be translated to SCSI CDBs from + * the ULD. + */ +static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { - struct scsi_device *sdev = q->queuedata; struct scsi_cmnd *cmd; - int specials_only = 0; + struct scsi_driver *drv; + int ret; /* - * Just check to see if the device is online. If it isn't, we - * refuse to process any commands. The device must be brought - * online before trying any recovery commands + * Filesystem requests must transfer data. */ - if (unlikely(!scsi_device_online(sdev))) { - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to offline device\n"); - goto kill; - } - if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { - /* OK, we're not in a running state don't prep - * user commands */ - if (sdev->sdev_state == SDEV_DEL) { - /* Device is fully deleted, no commands - * at all allowed down */ - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to dead device\n"); - goto kill; - } - /* OK, we only allow special commands (i.e. not - * user initiated ones */ - specials_only = sdev->sdev_state; + BUG_ON(!req->nr_phys_segments); + + cmd = scsi_get_cmd_from_req(sdev, req); + if (unlikely(!cmd)) + return BLKPREP_DEFER; + + ret = scsi_init_io(cmd); + if (unlikely(ret)) + return ret; + + /* + * Initialize the actual SCSI command for this request. + */ + drv = *(struct scsi_driver **)req->rq_disk->private_data; + if (unlikely(!drv->init_command(cmd))) { + scsi_release_buffers(cmd); + scsi_put_command(cmd); + return BLKPREP_KILL; } + return BLKPREP_OK; +} + +static int scsi_prep_fn(struct request_queue *q, struct request *req) +{ + struct scsi_device *sdev = q->queuedata; + int ret = BLKPREP_OK; + /* - * Find the actual device driver associated with this command. - * The SPECIAL requests are things like character device or - * ioctls, which did not originate from ll_rw_blk. Note that - * the special field is also used to indicate the cmd for - * the remainder of a partially fulfilled request that can - * come up when there is a medium error. We have to treat - * these two cases differently. We differentiate by looking - * at request->cmd, as this tells us the real story. + * If the device is not in running state we will reject some + * or all commands. */ - if (blk_special_request(req) && req->special) - cmd = req->special; - else if (blk_pc_request(req) || blk_fs_request(req)) { - if (unlikely(specials_only) && !(req->cmd_flags & REQ_PREEMPT)){ - if (specials_only == SDEV_QUIESCE || - specials_only == SDEV_BLOCK) - goto defer; - + if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { + switch (sdev->sdev_state) { + case SDEV_OFFLINE: + /* + * If the device is offline we refuse to process any + * commands. The device must be brought online + * before trying any recovery commands. + */ sdev_printk(KERN_ERR, sdev, - "rejecting I/O to device being removed\n"); - goto kill; + "rejecting I/O to offline device\n"); + ret = BLKPREP_KILL; + break; + case SDEV_DEL: + /* + * If the device is fully deleted, we refuse to + * process any commands as well. + */ + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to dead device\n"); + ret = BLKPREP_KILL; + break; + case SDEV_QUIESCE: + case SDEV_BLOCK: + /* + * If the devices is blocked we defer normal commands. + */ + if (!(req->cmd_flags & REQ_PREEMPT)) + ret = BLKPREP_DEFER; + break; + default: + /* + * For any other not fully online state we only allow + * special commands. In particular any user initiated + * command is not allowed. + */ + if (!(req->cmd_flags & REQ_PREEMPT)) + ret = BLKPREP_KILL; + break; } - - /* - * Now try and find a command block that we can use. - */ - if (!req->special) { - cmd = scsi_get_command(sdev, GFP_ATOMIC); - if (unlikely(!cmd)) - goto defer; - } else - cmd = req->special; - - /* pull a tag out of the request if we have one */ - cmd->tag = req->tag; - } else { - blk_dump_rq_flags(req, "SCSI bad req"); - goto kill; + + if (ret != BLKPREP_OK) + goto out; } - - /* note the overloading of req->special. When the tag - * is active it always means cmd. If the tag goes - * back for re-queueing, it may be reset */ - req->special = cmd; - cmd->request = req; - - /* - * FIXME: drop the lock here because the functions below - * expect to be called without the queue lock held. Also, - * previously, we dequeued the request before dropping the - * lock. We hope REQ_STARTED prevents anything untoward from - * happening now. - */ - if (blk_fs_request(req) || blk_pc_request(req)) { - int ret; + switch (req->cmd_type) { + case REQ_TYPE_BLOCK_PC: + ret = scsi_setup_blk_pc_cmnd(sdev, req); + break; + case REQ_TYPE_FS: + ret = scsi_setup_fs_cmnd(sdev, req); + break; + default: /* - * This will do a couple of things: - * 1) Fill in the actual SCSI command. - * 2) Fill in any other upper-level specific fields - * (timeout). + * All other command types are not supported. * - * If this returns 0, it means that the request failed - * (reading past end of disk, reading offline device, - * etc). This won't actually talk to the device, but - * some kinds of consistency checking may cause the - * request to be rejected immediately. + * Note that these days the SCSI subsystem does not use + * REQ_TYPE_SPECIAL requests anymore. These are only used + * (directly or via blk_insert_request) by non-SCSI drivers. */ + blk_dump_rq_flags(req, "SCSI bad req"); + ret = BLKPREP_KILL; + break; + } - /* - * This sets up the scatter-gather table (allocating if - * required). - */ - ret = scsi_init_io(cmd); - switch(ret) { - /* For BLKPREP_KILL/DEFER the cmd was released */ - case BLKPREP_KILL: - goto kill; - case BLKPREP_DEFER: - goto defer; - } - + out: + switch (ret) { + case BLKPREP_KILL: + req->errors = DID_NO_CONNECT << 16; + break; + case BLKPREP_DEFER: /* - * Initialize the actual SCSI command for this request. + * If we defer, the elv_next_request() returns NULL, but the + * queue must be restarted, so we plug here if no returning + * command will automatically do that. */ - if (blk_pc_request(req)) { - scsi_setup_blk_pc_cmnd(cmd); - } else if (req->rq_disk) { - struct scsi_driver *drv; - - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - goto kill; - } - } + if (sdev->device_busy == 0) + blk_plug_device(q); + break; + default: + req->cmd_flags |= REQ_DONTPREP; } - /* - * The request is now prepped, no need to come back here - */ - req->cmd_flags |= REQ_DONTPREP; - return BLKPREP_OK; - - defer: - /* If we defer, the elv_next_request() returns NULL, but the - * queue must be restarted, so we plug here if no returning - * command will automatically do that. */ - if (sdev->device_busy == 0) - blk_plug_device(q); - return BLKPREP_DEFER; - kill: - req->errors = DID_NO_CONNECT << 16; - return BLKPREP_KILL; + return ret; } /* -- cgit v0.10.2 From 4f777ed26086452737ea52597cf8de26137090d5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 4 Nov 2006 20:11:36 +0100 Subject: [SCSI] kill scsi_assign_lock scsi_assign_lock has been unused for a long time and is a bad idea in general, so kill it. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 75a535a..6f70f2b 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -375,7 +375,6 @@ Summary: scsi_add_device - creates new scsi device (lu) instance scsi_add_host - perform sysfs registration and set up transport class scsi_adjust_queue_depth - change the queue depth on a SCSI device - scsi_assign_lock - replace default host_lock with given lock scsi_bios_ptable - return copy of block device's partition table scsi_block_requests - prevent further commands being queued to given host scsi_deactivate_tcq - turn off tag command queueing @@ -489,20 +488,6 @@ void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, /** - * scsi_assign_lock - replace default host_lock with given lock - * @shost: a pointer to a scsi host instance - * @lock: pointer to lock to replace host_lock for this host - * - * Returns nothing - * - * Might block: no - * - * Defined in: include/scsi/scsi_host.h . - **/ -void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) - - -/** * scsi_bios_ptable - return copy of block device's partition table * @dev: pointer to block device * @@ -1366,17 +1351,11 @@ Locks Each struct Scsi_Host instance has a spin_lock called struct Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer -is initialized to point at default_lock with the scsi_assign_lock() function. -Thereafter lock and unlock operations performed by the mid level use the -struct Scsi_Host::host_lock pointer. - -LLDs can override the use of struct Scsi_Host::default_lock by -using scsi_assign_lock(). The earliest opportunity to do this would -be in the detect() function after it has invoked scsi_register(). It -could be replaced by a coarser grain lock (e.g. per driver) or a -lock of equal granularity (i.e. per host). Using finer grain locks -(e.g. per SCSI device) may be possible by juggling locks in -queuecommand(). +is initialized to point at default_lock. Thereafter lock and unlock +operations performed by the mid level use the struct Scsi_Host::host_lock +pointer. Previously drivers could override the host_lock pointer but +this is not allowed anymore. + Autosense ========= diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 68ef163..2ffdc9e 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -301,8 +301,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) if (!shost) return NULL; - spin_lock_init(&shost->default_lock); - scsi_assign_lock(shost, &shost->default_lock); + shost->host_lock = &shost->default_lock; + spin_lock_init(shost->host_lock); shost->shost_state = SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); INIT_LIST_HEAD(&shost->__targets); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index ba5b3eb..e618e711 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -651,11 +651,6 @@ extern const char *scsi_host_state_name(enum scsi_host_state); extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); -static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) -{ - shost->host_lock = lock; -} - static inline struct device *scsi_get_device(struct Scsi_Host *shost) { return shost->shost_gendev.parent; -- cgit v0.10.2 From fd44bab5c709bbcd30fbebe9ad45a76c58cd32a7 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Wed, 15 Nov 2006 12:47:08 -0800 Subject: [SCSI] sd: clearer output of disk cache state Signed-off-by: Luben Tuikov Signed-off-by: James Bottomley diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 152f4ff..f6a4528 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1467,7 +1467,6 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); if (scsi_status_is_good(res)) { - int ct = 0; int offset = data.header_length + data.block_descriptor_length; if (offset >= SD_BUF_SIZE - 2) { @@ -1496,11 +1495,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, sdkp->DPOFUA = 0; } - ct = sdkp->RCD + 2*sdkp->WCE; - - printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", - diskname, sd_cache_types[ct], - sdkp->DPOFUA ? " w/ FUA" : ""); + printk(KERN_NOTICE "SCSI device %s: " + "write cache: %s, read cache: %s, %s\n", + diskname, + sdkp->WCE ? "enabled" : "disabled", + sdkp->RCD ? "disabled" : "enabled", + sdkp->DPOFUA ? "supports DPO and FUA" + : "doesn't support DPO or FUA"); return; } -- cgit v0.10.2 From 42252854011b31fe63ffeca44ac941e6fe8277ae Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Tue, 7 Nov 2006 21:56:38 +0200 Subject: [SCSI] st: log message changes Printk -> sdev_printk change originally from Luben Tuikov . Loglevel changes prompted by Matthew Wilcox . Signed-off-by: Kai Makisara Signed-off-by: James Bottomley diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3babdc7..febfac9 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2005 Kai Makisara + Copyright 1992 - 2006 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20050830"; +static const char *verstr = "20061107"; #include @@ -999,7 +999,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_WARNING + printk(KERN_INFO "%s: Block limits %d - %d bytes.\n", name, STp->min_block, STp->max_block); } else { @@ -1221,7 +1221,7 @@ static int st_flush(struct file *filp, fl_owner_t id) } DEBC( if (STp->nbr_requests) - printk(KERN_WARNING "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", + printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { @@ -4053,11 +4053,11 @@ static int st_probe(struct device *dev) goto out_free_tape; } - sdev_printk(KERN_WARNING, SDp, + sdev_printk(KERN_NOTICE, SDp, "Attached scsi tape %s\n", tape_name(tpnt)); - printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", - tape_name(tpnt), tpnt->try_dio ? "yes" : "no", - queue_dma_alignment(SDp->request_queue) + 1); + sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n", + tape_name(tpnt), tpnt->try_dio ? "yes" : "no", + queue_dma_alignment(SDp->request_queue) + 1); return 0; -- cgit v0.10.2 From 08157cd0787004e2ebf9ee8cc92257244da53848 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 8 Nov 2006 19:56:19 -0800 Subject: [SCSI] SCSI/aha1740: handle SCSI API errors Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index c3c38a7..d7af9c6 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -586,7 +586,7 @@ static struct scsi_host_template aha1740_template = { static int aha1740_probe (struct device *dev) { - int slotbase; + int slotbase, rc; unsigned int irq_level, irq_type, translation; struct Scsi_Host *shpnt; struct aha1740_hostdata *host; @@ -641,10 +641,16 @@ static int aha1740_probe (struct device *dev) } eisa_set_drvdata (edev, shpnt); - scsi_add_host (shpnt, dev); /* XXX handle failure */ + + rc = scsi_add_host (shpnt, dev); + if (rc) + goto err_irq; + scsi_scan_host (shpnt); return 0; + err_irq: + free_irq(irq_level, shpnt); err_unmap: dma_unmap_single (&edev->dev, host->ecb_dma_addr, sizeof (host->ecb), DMA_BIDIRECTIONAL); -- cgit v0.10.2 From bf4713418b9d8543e7b64bf6c742f1959828033e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 8 Nov 2006 19:56:24 -0800 Subject: [SCSI] revert "[SCSI] ips soft lockup during reset/initialization" Revert 15084a4a63bc300c18b28a8a9afac870c552abce - it caused a scheduling-inside-spinlock bug. Cc: Nishanth Aravamudan Cc: Nick Piggin Cc: Jack Hammer Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index f06a06a..8b704f7 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -5001,7 +5001,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) @@ -5027,7 +5027,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 240) @@ -5045,7 +5045,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) @@ -5095,7 +5095,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) @@ -5121,7 +5121,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 240) @@ -5139,7 +5139,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) @@ -5191,7 +5191,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 45) { @@ -5217,7 +5217,7 @@ ips_init_morpheus(ips_ha_t * ha) if (Post != 0x4F00) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 120) { @@ -5247,7 +5247,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) { @@ -5307,12 +5307,12 @@ ips_reset_copperhead(ips_ha_t * ha) outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); outb(0, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5352,12 +5352,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha) writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); writeb(0, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5398,7 +5398,7 @@ ips_reset_morpheus(ips_ha_t * ha) writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR); /* Delay for 5 Seconds */ - msleep(5 * IPS_ONE_SEC); + MDELAY(5 * IPS_ONE_SEC); /* Do a PCI config read to wait for adapter */ pci_read_config_byte(ha->pcidev, 4, &junk); -- cgit v0.10.2 From db3a8815fb03f9985713b4ab29e208b7074f939c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 8 Nov 2006 19:56:20 -0800 Subject: [SCSI] minor bug fixes and cleanups BusLogic: use kzalloc(), remove cast to/from void* aic7xxx_old: fix typo in cast NCR53c406a: ifdef out static built code fd_mcs: ifdef out static built code ncr53c8xx: ifdef out static built code Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 7c59bba..689dc4c 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2186,21 +2186,21 @@ static int __init BusLogic_init(void) if (BusLogic_ProbeOptions.NoProbe) return -ENODEV; - BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *) - kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC); + BusLogic_ProbeInfoList = + kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL); if (BusLogic_ProbeInfoList == NULL) { BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); return -ENOMEM; } - memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo)); - PrototypeHostAdapter = (struct BusLogic_HostAdapter *) - kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC); + + PrototypeHostAdapter = + kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL); if (PrototypeHostAdapter == NULL) { kfree(BusLogic_ProbeInfoList); BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL); return -ENOMEM; } - memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); + #ifdef MODULE if (BusLogic != NULL) BusLogic_Setup(BusLogic); diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index d461381..8578555 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -220,9 +220,11 @@ static void *addresses[] = { static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; #define PORT_COUNT ARRAY_SIZE(ports) +#ifndef MODULE /* possible interrupt channels */ static unsigned short intrs[] = { 10, 11, 12, 15 }; #define INTR_COUNT ARRAY_SIZE(intrs) +#endif /* !MODULE */ /* signatures for NCR 53c406a based controllers */ #if USE_BIOS @@ -605,6 +607,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost) return 0; } +#ifndef MODULE /* called from init/main.c */ static int __init NCR53c406a_setup(char *str) { @@ -661,6 +664,8 @@ static int __init NCR53c406a_setup(char *str) __setup("ncr53c406a=", NCR53c406a_setup); +#endif /* !MODULE */ + static const char *NCR53c406a_info(struct Scsi_Host *SChost) { DEB(printk("NCR53c406a_info called\n")); diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index ef8285c..668569e 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -294,6 +294,7 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; static int user_fifo_count = 0; static int user_fifo_size = 0; +#ifndef MODULE static int __init fd_mcs_setup(char *str) { static int done_setup = 0; @@ -311,6 +312,7 @@ static int __init fd_mcs_setup(char *str) } __setup("fd_mcs=", fd_mcs_setup); +#endif /* !MODULE */ static void print_banner(struct Scsi_Host *shpnt) { diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 6cc2bc2..5a88fa0 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -589,10 +589,12 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) static struct ncr_driver_setup driver_setup = SCSI_NCR_DRIVER_SETUP; +#ifndef MODULE #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT static struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; #endif +#endif /* !MODULE */ #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) @@ -641,6 +643,13 @@ static struct ncr_driver_setup #define OPT_IARB 26 #endif +#ifdef MODULE +#define ARG_SEP ' ' +#else +#define ARG_SEP ',' +#endif + +#ifndef MODULE static char setup_token[] __initdata = "tags:" "mpar:" "spar:" "disc:" @@ -660,12 +669,6 @@ static char setup_token[] __initdata = #endif ; /* DONNOT REMOVE THIS ';' */ -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - static int __init get_setup_token(char *p) { char *cur = setup_token; @@ -682,7 +685,6 @@ static int __init get_setup_token(char *p) return 0; } - static int __init sym53c8xx__setup(char *str) { #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT @@ -804,6 +806,7 @@ static int __init sym53c8xx__setup(char *str) #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ return 1; } +#endif /* !MODULE */ /*=================================================================== ** @@ -8321,12 +8324,12 @@ char *ncr53c8xx; /* command line passed by insmod */ module_param(ncr53c8xx, charp, 0); #endif +#ifndef MODULE static int __init ncr53c8xx_setup(char *str) { return sym53c8xx__setup(str); } -#ifndef MODULE __setup("ncr53c8xx=", ncr53c8xx_setup); #endif -- cgit v0.10.2 From e5f82ab8342b527231cfcccde1fe265666e86b7b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Nov 2006 19:55:50 -0800 Subject: [SCSI] qla2xxx: make some functions static This patch makes some needlessly global functions static. Signed-off-by: Adrian Bunk Acked-by: Andrew Vasquez Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3f20d76..5e70c49 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -274,7 +274,7 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str) return str; } -char * +static char * qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) { char un_str[10]; @@ -312,7 +312,7 @@ qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) return (str); } -char * +static char * qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) { sprintf(str, "%d.%02d.%02d ", ha->fw_major_version, @@ -621,7 +621,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) * Note: * Only return FAILED if command not returned by firmware. **************************************************************************/ -int +static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -758,7 +758,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -889,7 +889,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -950,7 +950,7 @@ eh_bus_reset_done: * * Note: **************************************************************************/ -int +static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index c71dbd5..15390ad 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -449,7 +449,7 @@ nvram_data_to_access_addr(uint32_t naddr) return FARX_ACCESS_NVRAM_DATA | naddr; } -uint32_t +static uint32_t qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) { int rval; @@ -490,7 +490,7 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, return dwptr; } -int +static int qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) { int rval; @@ -512,7 +512,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) return rval; } -void +static void qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, uint8_t *flash_id) { @@ -537,7 +537,7 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, } } -int +static int qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { -- cgit v0.10.2 From 297295ae6653af1356dd35a8edc411e2715aec57 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 8 Nov 2006 19:56:26 -0800 Subject: [SCSI] ips: fix soft lockup during reset initialization Resetting the adapter causes the ServeRAID driver to exceed the max time allowed by the softlock watchdog. Resetting the hardware can easily require 30 or more seconds. To avoid the "BUG: soft lockup detected on CPU#0!" result, this patch adds a touch_nmi_watchdog() to the driver's MDELAY macro. Cc: Nishanth Aravamudan Cc: Nick Piggin Acked-by: Jack Hammer Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 34680f3..b726dcc 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -51,6 +51,7 @@ #define _IPS_H_ #include +#include #include #include @@ -116,9 +117,11 @@ dev_printk(level , &((pcidev)->dev) , format , ## arg) #endif - #ifndef MDELAY - #define MDELAY mdelay - #endif + #define MDELAY(n) \ + do { \ + mdelay(n); \ + touch_nmi_watchdog(); \ + } while (0) #ifndef min #define min(x,y) ((x) < (y) ? x : y) -- cgit v0.10.2 From 667c667f86c87cd4f72296d650e5e65f2d89cb31 Mon Sep 17 00:00:00 2001 From: Henne Date: Wed, 8 Nov 2006 19:56:28 -0800 Subject: [SCSI] scsi: t128 scsi_cmnd convertion Changes the obsolete Scsi_Cmnd to struct scsi_cmnd and remove the trailing whitespaces. Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 646e840..76a069b 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -8,20 +8,20 @@ * drew@colorado.edu * +1 (303) 440-4894 * - * DISTRIBUTION RELEASE 3. + * DISTRIBUTION RELEASE 3. * - * For more information, please consult + * For more information, please consult * * Trantor Systems, Ltd. * T128/T128F/T228 SCSI Host Adapter * Hardware Specifications - * - * Trantor Systems, Ltd. + * + * Trantor Systems, Ltd. * 5415 Randall Place * Fremont, CA 94538 * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - * - * and + * + * and * * NCR 5380 Family * SCSI Protocol Controller @@ -48,15 +48,15 @@ #define TDEBUG_TRANSFER 0x2 /* - * The trantor boards are memory mapped. They use an NCR5380 or + * The trantor boards are memory mapped. They use an NCR5380 or * equivalent (my sample board had part second sourced from ZILOG). - * NCR's recommended "Pseudo-DMA" architecture is used, where + * NCR's recommended "Pseudo-DMA" architecture is used, where * a PAL drives the DMA signals on the 5380 allowing fast, blind - * transfers with proper handshaking. + * transfers with proper handshaking. */ /* - * Note : a boot switch is provided for the purpose of informing the + * Note : a boot switch is provided for the purpose of informing the * firmware to boot or not boot from attached SCSI devices. So, I imagine * there are fewer people who've yanked the ROM like they do on the Seagate * to make bootup faster, and I'll probably use this for autodetection. @@ -92,19 +92,20 @@ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ #ifndef ASM -static int t128_abort(Scsi_Cmnd *); +static int t128_abort(struct scsi_cmnd *); static int t128_biosparam(struct scsi_device *, struct block_device *, sector_t, int*); static int t128_detect(struct scsi_host_template *); -static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int t128_bus_reset(Scsi_Cmnd *); +static int t128_queue_command(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); +static int t128_bus_reset(struct scsi_cmnd *); #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif #ifndef CAN_QUEUE -#define CAN_QUEUE 32 +#define CAN_QUEUE 32 #endif #ifndef HOSTS_C @@ -120,7 +121,7 @@ static int t128_bus_reset(Scsi_Cmnd *); #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) -#if !(TDEBUG & TDEBUG_TRANSFER) +#if !(TDEBUG & TDEBUG_TRANSFER) #define NCR5380_read(reg) readb(T128_address(reg)) #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #else @@ -129,7 +130,7 @@ static int t128_bus_reset(Scsi_Cmnd *); , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) #define NCR5380_write(reg, value) { \ - printk("scsi%d : write %02x to register %d at address %08x\n", \ + printk("scsi%d : write %02x to register %d at address %08x\n", \ instance->hostno, (value), (reg), T128_address(reg)); \ writeb((value), (T128_address(reg))); \ } @@ -142,10 +143,10 @@ static int t128_bus_reset(Scsi_Cmnd *); #define NCR5380_bus_reset t128_bus_reset #define NCR5380_proc_info t128_proc_info -/* 15 14 12 10 7 5 3 +/* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ - -#define T128_IRQS 0xc4a8 + +#define T128_IRQS 0xc4a8 #endif /* else def HOSTS_C */ #endif /* ndef ASM */ -- cgit v0.10.2 From 056f4faa572f64fa926491a7d42c627c9dc507a7 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 13 Nov 2006 14:51:46 +1100 Subject: [POWERPC] Add the thread_siblings files to sysfs This adds the /sys/devices/system/cpu/*/topology/thread_siblings files on powerpc. These files are already available on other architectures. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 8f7ee16..9fe7894 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -96,7 +96,13 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev, #ifdef CONFIG_SMP #include -#define smt_capable() (cpu_has_feature(CPU_FTR_SMT)) +#define smt_capable() (cpu_has_feature(CPU_FTR_SMT)) + +#ifdef CONFIG_PPC64 +#include + +#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) +#endif #endif #endif /* __KERNEL__ */ -- cgit v0.10.2 From 9716a340310a383751a06589d0775fad04bd3f54 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 13 Nov 2006 14:52:42 +1100 Subject: [POWERPC] Wire up sys_move_pages All the infrastructure is already in place for this, so we only need to allocate a syscall number and hook it up. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h index c6a0318..97b4354 100644 --- a/include/asm-powerpc/systbl.h +++ b/include/asm-powerpc/systbl.h @@ -304,3 +304,4 @@ SYSCALL_SPU(fchmodat) SYSCALL_SPU(faccessat) COMPAT_SYS_SPU(get_robust_list) COMPAT_SYS_SPU(set_robust_list) +COMPAT_SYS(move_pages) diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index b5fe932..0e4ea37 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -323,10 +323,11 @@ #define __NR_faccessat 298 #define __NR_get_robust_list 299 #define __NR_set_robust_list 300 +#define __NR_move_pages 301 #ifdef __KERNEL__ -#define __NR_syscalls 301 +#define __NR_syscalls 302 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls -- cgit v0.10.2 From 85e04e371b5a321b5df2bc3f8e0099a64fb087d7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 9 Nov 2006 11:55:41 +0100 Subject: [SCSI] block: convert jiffies to msecs in scsi_ioctl() Use the proper conversion function for convert jiffies to msecs in sg_io(). Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 2dc3264..ac63964 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -304,7 +304,7 @@ static int sg_io(struct file *file, request_queue_t *q, if (rq->bio) blk_queue_bounce(q, &rq->bio); - rq->timeout = (hdr->timeout * HZ) / 1000; + rq->timeout = jiffies_to_msecs(hdr->timeout); if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) -- cgit v0.10.2 From 504fb37a0801d843bc1907c1a1f9c719c3509863 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 9 Nov 2006 10:09:35 +0100 Subject: [SCSI] fix module unload induced compile warning Signed-off-by: Ingo Molnar Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c59f315..780d6dc 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -871,9 +871,9 @@ EXPORT_SYMBOL(scsi_device_get); */ void scsi_device_put(struct scsi_device *sdev) { +#ifdef CONFIG_MODULE_UNLOAD struct module *module = sdev->host->hostt->module; -#ifdef CONFIG_MODULE_UNLOAD /* The module refcount will be zero if scsi_device_get() * was called from a module removal routine */ if (module && module_refcount(module) != 0) -- cgit v0.10.2 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 diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c index fa4b13f..b3fbb45 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 2a94485..f24fa73 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 9961a67..26eee69 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 v0.10.2 From 44597f65f6af3c692560a639f61d25398d13d1b6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 15 Nov 2006 20:03:40 -0800 Subject: Linux 2.6.19-rc6 Getting there. Hopefully the MSI and other interrupt problems are all solved now. Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 8484be1..958fad6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc5 +EXTRAVERSION =-rc6 NAME=Avast! A bilge rat! # *DOCUMENTATION* -- cgit v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 06e4f77..6e86866 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 v0.10.2 From 7fdeaf68a16f8102659cf1b30f57247d8ccbeef0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 14 Nov 2006 19:47:09 -0800 Subject: [NETFILTER]: nfnetlink_log: fix byteorder of NFULA_SEQ_GLOBAL NFULA_SEQ_GLOBAL should be in network byteorder. Spotted by Al Viro. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b2bf8f2..1e5207b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -544,7 +544,7 @@ __build_packet_message(struct nfulnl_instance *inst, } /* global sequence number */ if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) { - tmp_uint = atomic_inc_return(&global_seq); + tmp_uint = htonl(atomic_inc_return(&global_seq)); NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint); } -- cgit v0.10.2 From d8a585d78efdf191a64ca655136ac1e49fd27cf4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 14 Nov 2006 19:48:09 -0800 Subject: [NETFILTER]: Use pskb_trim in {ip,ip6,nfnetlink}_queue Based on patch by James D. Nurmi: I've got some code very dependant on nfnetlink_queue, and turned up a large number of warns coming from skb_trim. While it's quite possibly my code, having not seen it on older kernels made me a bit suspect. Anyhow, based on some googling I turned up this thread: http://lkml.org/lkml/2006/8/13/56 And believe the issue to be related, so attached is a small patch to the kernel -- not sure if this is completely correct, but for anyone else hitting the WARN_ON(1) in skbuff.h, it might be helpful.. Signed-off-by: James D. Nurmi Ported to ip6_queue and nfnetlink_queue and added return value checks. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 7edad79..97556cc 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -351,9 +351,10 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) if (v->data_len < sizeof(*user_iph)) return 0; diff = v->data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, v->data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, v->data_len)) + return -ENOMEM; + } else if (diff > 0) { if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9510c24..9fec832 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -349,9 +349,10 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) if (v->data_len < sizeof(*user_iph)) return 0; diff = v->data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, v->data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, v->data_len)) + return -ENOMEM; + } else if (diff > 0) { if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 6e4ada3..e815a9a 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -622,9 +622,10 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) int diff; diff = data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, data_len)) + return -ENOMEM; + } else if (diff > 0) { if (data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { -- cgit v0.10.2 From b96e7ecbd052a0916b6078e7600604d7e276a336 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Tue, 14 Nov 2006 19:48:48 -0800 Subject: [NETFILTER]: ip6_tables: fixed conflicted optname for getsockopt 66 and 67 for getsockopt on IPv6 socket is doubly used for IPv6 Advanced API and ip6tables. This moves numbers for ip6tables to 68 and 69. This also kills XT_SO_* because {ip,ip6,arp}_tables doesn't have so much common numbers now. The old userland tools keep to behave as ever, because old kernel always calls functions of IPv6 Advanced API for their numbers. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/include/linux/in6.h b/include/linux/in6.h index 9be6a47..f28621f 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -225,7 +225,7 @@ struct in6_flowlabel_req #endif /* - * Netfilter + * Netfilter (1) * * Following socket options are used in ip6_tables; * see include/linux/netfilter_ipv6/ip6_tables.h. @@ -240,4 +240,14 @@ struct in6_flowlabel_req #define IPV6_RECVTCLASS 66 #define IPV6_TCLASS 67 +/* + * Netfilter (2) + * + * Following socket options are used in ip6_tables; + * see include/linux/netfilter_ipv6/ip6_tables.h. + * + * IP6T_SO_GET_REVISION_MATCH 68 + * IP6T_SO_GET_REVISION_TARGET 69 + */ + #endif diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 04319a7..022edfa 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -96,22 +96,6 @@ struct _xt_align /* Error verdict. */ #define XT_ERROR_TARGET "ERROR" -/* - * New IP firewall options for [gs]etsockopt at the RAW IP level. - * Unlike BSD Linux inherits IP options so you don't have to use a raw - * socket for this. Instead we check rights in the calls. */ -#define XT_BASE_CTL 64 /* base for firewall socket options */ - -#define XT_SO_SET_REPLACE (XT_BASE_CTL) -#define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1) -#define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS - -#define XT_SO_GET_INFO (XT_BASE_CTL) -#define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1) -#define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2) -#define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3) -#define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET - #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 44e39b6..0be2354 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -112,19 +112,20 @@ struct arpt_entry * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use a raw * socket for this. Instead we check rights in the calls. + * + * ATTENTION: check linux/in.h before adding new number here. */ -#define ARPT_CTL_OFFSET 32 -#define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET) - -#define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET) -#define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET) -#define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET) - -#define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET) -#define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET) -/* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */ -#define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) -#define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) +#define ARPT_BASE_CTL 96 + +#define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) +#define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1) +#define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS + +#define ARPT_SO_GET_INFO (ARPT_BASE_CTL) +#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) +/* #define ARPT_SO_GET_REVISION_MATCH (APRT_BASE_CTL + 2) */ +#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3) +#define ARPT_SO_GET_MAX (ARPT_SO_GET_REVISION_TARGET) /* CONTINUE verdict for targets */ #define ARPT_CONTINUE XT_CONTINUE diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index a536bbd..4f06dad 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -101,18 +101,21 @@ struct ipt_entry /* * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use a raw - * socket for this. Instead we check rights in the calls. */ -#define IPT_BASE_CTL XT_BASE_CTL - -#define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE -#define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS -#define IPT_SO_SET_MAX XT_SO_SET_MAX - -#define IPT_SO_GET_INFO XT_SO_GET_INFO -#define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES -#define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH -#define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET -#define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET + * socket for this. Instead we check rights in the calls. + * + * ATTENTION: check linux/in.h before adding new number here. + */ +#define IPT_BASE_CTL 64 + +#define IPT_SO_SET_REPLACE (IPT_BASE_CTL) +#define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) +#define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS + +#define IPT_SO_GET_INFO (IPT_BASE_CTL) +#define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) +#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) +#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) +#define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET #define IPT_CONTINUE XT_CONTINUE #define IPT_RETURN XT_RETURN diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index d7a8e9c0..4aed340 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -107,18 +107,21 @@ struct ip6t_entry /* * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use - * a raw socket for this. Instead we check rights in the calls. */ -#define IP6T_BASE_CTL XT_BASE_CTL - -#define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE -#define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS -#define IP6T_SO_SET_MAX XT_SO_SET_MAX - -#define IP6T_SO_GET_INFO XT_SO_GET_INFO -#define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES -#define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH -#define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET -#define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET + * a raw socket for this. Instead we check rights in the calls. + * + * ATTENTION: check linux/in6.h before adding new number here. + */ +#define IP6T_BASE_CTL 64 + +#define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) +#define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) +#define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS + +#define IP6T_SO_GET_INFO (IP6T_BASE_CTL) +#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) +#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 4) +#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 5) +#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET /* CONTINUE verdict for targets */ #define IP6T_CONTINUE XT_CONTINUE -- cgit v0.10.2 From 337dde798dd1f3e4d4df4e684a0b4355dd65103d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 14 Nov 2006 19:49:13 -0800 Subject: [NETFILTER]: ip6_tables: use correct nexthdr value in ipv6_find_hdr() nexthdr is NEXTHDR_FRAGMENT, the nexthdr value from the fragment header is hp->nexthdr. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 167c2ea..204e021 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1494,7 +1494,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if (_frag_off) { if (target < 0 && ((!ipv6_ext_hdr(hp->nexthdr)) || - nexthdr == NEXTHDR_NONE)) { + hp->nexthdr == NEXTHDR_NONE)) { if (fragoff) *fragoff = _frag_off; return hp->nexthdr; -- cgit v0.10.2 From 52bf376c63eebe72e862a1a6e713976b038c3f50 Mon Sep 17 00:00:00 2001 From: John Heffner Date: Tue, 14 Nov 2006 20:25:17 -0800 Subject: [TCP]: Fix up sysctl_tcp_mem initialization. Fix up tcp_mem initial settings to take into account the size of the hash entries (different on SMP and non-SMP systems). Signed-off-by: John Heffner Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4322318..c05e8ed 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2316,9 +2316,10 @@ void __init tcp_init(void) sysctl_max_syn_backlog = 128; } - sysctl_tcp_mem[0] = 768 << order; - sysctl_tcp_mem[1] = 1024 << order; - sysctl_tcp_mem[2] = 1536 << order; + /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */ + sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order; + sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3; + sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7); max_share = min(4UL*1024*1024, limit); -- cgit v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6e86866..1dbdd6b 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 c312a12..c321316 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 v0.10.2 From 351a58390aad350bd5e22c7cc468f44a9330685c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 16 Nov 2006 00:42:58 -0800 Subject: [IA64] irqs: use `name' not `typename' `typename' is going away and is usually uninitialised anwyay. Signed-off-by: Andrew Morton Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 9bf15fe..c195faf 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -664,7 +664,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", __FUNCTION__, vector, - idesc->chip->typename, irq_type->typename); + idesc->chip->name, irq_type->name); idesc->chip = irq_type; } return 0; diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index f07c086..6fe404d 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -76,7 +76,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); } #endif - seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) -- cgit v0.10.2 From 06344db3162323247e9ac8d76d5acdb79d05f3c0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 16 Nov 2006 00:43:02 -0800 Subject: [IA64] typename -> name conversion convert irq chip typename -> name. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Tony Luck diff --git a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c index 8145547..c2f58ff 100644 --- a/arch/ia64/hp/sim/hpsim_irq.c +++ b/arch/ia64/hp/sim/hpsim_irq.c @@ -27,7 +27,7 @@ hpsim_set_affinity_noop (unsigned int a, cpumask_t b) } static struct hw_interrupt_type irq_type_hp_sim = { - .typename = "hpsim", + .name = "hpsim", .startup = hpsim_irq_startup, .shutdown = hpsim_irq_noop, .enable = hpsim_irq_noop, diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index c195faf..60d6495 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -426,7 +426,7 @@ iosapic_end_level_irq (unsigned int irq) #define iosapic_ack_level_irq nop struct hw_interrupt_type irq_type_iosapic_level = { - .typename = "IO-SAPIC-level", + .name = "IO-SAPIC-level", .startup = iosapic_startup_level_irq, .shutdown = iosapic_shutdown_level_irq, .enable = iosapic_enable_level_irq, @@ -473,7 +473,7 @@ iosapic_ack_edge_irq (unsigned int irq) #define iosapic_end_edge_irq nop struct hw_interrupt_type irq_type_iosapic_edge = { - .typename = "IO-SAPIC-edge", + .name = "IO-SAPIC-edge", .startup = iosapic_startup_edge_irq, .shutdown = iosapic_disable_edge_irq, .enable = iosapic_enable_edge_irq, diff --git a/arch/ia64/kernel/irq_lsapic.c b/arch/ia64/kernel/irq_lsapic.c index 1ab58b0..c2f07be 100644 --- a/arch/ia64/kernel/irq_lsapic.c +++ b/arch/ia64/kernel/irq_lsapic.c @@ -34,7 +34,7 @@ static int lsapic_retrigger(unsigned int irq) } struct hw_interrupt_type irq_type_ia64_lsapic = { - .typename = "LSAPIC", + .name = "LSAPIC", .startup = lsapic_noop_startup, .shutdown = lsapic_noop, .enable = lsapic_noop, diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 7bb6ad1..0b49459 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -201,7 +201,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) } struct hw_interrupt_type irq_type_sn = { - .typename = "SN hub", + .name = "SN hub", .startup = sn_startup_irq, .shutdown = sn_shutdown_irq, .enable = sn_enable_irq, -- cgit v0.10.2 From 5fbb004aba15bbca64c3fb611113295bda7ee9ea Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 16 Nov 2006 00:43:07 -0800 Subject: [IA64] use generic_handle_irq() Use generic_handle_irq() to handle mixed-type irq handling. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 6fe404d..54d55e4 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -197,7 +197,7 @@ void fixup_irqs(void) struct pt_regs *old_regs = set_irq_regs(NULL); vectors_in_migration[irq]=0; - __do_IRQ(irq); + generic_handle_irq(irq); set_irq_regs(old_regs); } } diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 9c6dafa..ba3ba8b 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -186,7 +186,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); - __do_IRQ(local_vector_to_irq(vector)); + generic_handle_irq(local_vector_to_irq(vector)); /* * Disable interrupts and send EOI: @@ -242,7 +242,7 @@ void ia64_process_pending_intr(void) * Probably could shared code. */ vectors_in_migration[local_vector_to_irq(vector)]=0; - __do_IRQ(local_vector_to_irq(vector)); + generic_handle_irq(local_vector_to_irq(vector)); set_irq_regs(old_regs); /* -- cgit v0.10.2 From cea196bb2eb918c30f97a2b752bcec929d761f64 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Thu, 16 Nov 2006 00:43:12 -0800 Subject: [IA64] a fix towards allmodconfig build The HP_SIMSCSI driver can't be built as a module (unhealthy dependencies on things that shouldn't really be exported). Signed-off-by: Andrew Morton Signed-off-by: Tony Luck diff --git a/arch/ia64/hp/sim/Kconfig b/arch/ia64/hp/sim/Kconfig index 18ccb12..f92306b 100644 --- a/arch/ia64/hp/sim/Kconfig +++ b/arch/ia64/hp/sim/Kconfig @@ -13,8 +13,8 @@ config HP_SIMSERIAL_CONSOLE depends on HP_SIMSERIAL config HP_SIMSCSI - tristate "Simulated SCSI disk" - depends on SCSI + bool "Simulated SCSI disk" + depends on SCSI=y endmenu -- cgit v0.10.2 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 diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a41b8df..c47add8 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 abc5149..bb1fac1 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 v0.10.2 From b86432b42eba5671969a9e6483ee219674b7ee25 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 16 Nov 2006 01:19:10 -0800 Subject: [PATCH] some irq_chip variables point to NULL I got an oops when booting 2.6.19-rc5-mm1 on my ia64 machine. Below is the log. Oops 11012296146944 [1] Modules linked in: binfmt_misc dm_mirror dm_multipath dm_mod thermal processor f an container button sg eepro100 e100 mii Pid: 0, CPU 0, comm: swapper psr : 0000121008022038 ifs : 800000000000040b ip : [] Not tainted ip is at __do_IRQ+0x371/0x3e0 unat: 0000000000000000 pfs : 000000000000040b rsc : 0000000000000003 rnat: 656960155aa56aa5 bsps: a00000010058b890 pr : 656960155aa55a65 ldrs: 0000000000000000 ccv : 0000000000000000 fpsr: 0009804c0270033f csd : 0000000000000000 ssd : 0000000000000000 b0 : a0000001000e1390 b6 : a0000001005beac0 b7 : e00000007f01aa00 f6 : 000000000000000000000 f7 : 0ffe69090000000000000 f8 : 1000a9090000000000000 f9 : 0ffff8000000000000000 f10 : 1000a908ffffff6f70000 f11 : 1003e0000000000000909 r1 : a000000100fbbff0 r2 : 0000000000010002 r3 : 0000000000010001 r8 : fffffffffffbffff r9 : a000000100bd8060 r10 : a000000100dd83b8 r11 : fffffffffffeffff r12 : a000000100bcbbb0 r13 : a000000100bc4000 r14 : 0000000000010000 r15 : 0000000000010000 r16 : a000000100c01aa8 r17 : a000000100d2c350 r18 : 0000000000000000 r19 : a000000100d2c300 r20 : a000000100c01a88 r21 : 0000000080010100 r22 : a000000100c01ac0 r23 : a0000001000108e0 r24 : e000000477980004 r25 : 0000000000000000 r26 : 0000000000000000 r27 : e00000000913400c r28 : e0000004799ee51c r29 : e0000004778b87f0 r30 : a000000100d2c300 r31 : a00000010005c7e0 Call Trace: [] show_stack+0x40/0xa0 sp=a000000100bcb760 bsp=a000000100bc4f40 [] show_regs+0x840/0x880 sp=a000000100bcb930 bsp=a000000100bc4ee8 [] die+0x250/0x320 sp=a000000100bcb930 bsp=a000000100bc4ea0 [] ia64_do_page_fault+0x8d0/0xa20 sp=a000000100bcb950 bsp=a000000100bc4e50 [] ia64_leave_kernel+0x0/0x290 sp=a000000100bcb9e0 bsp=a000000100bc4e50 [] __do_IRQ+0x370/0x3e0 sp=a000000100bcbbb0 bsp=a000000100bc4df0 [] ia64_handle_irq+0x170/0x220 sp=a000000100bcbbb0 bsp=a000000100bc4dc0 [] ia64_leave_kernel+0x0/0x290 sp=a000000100bcbbb0 bsp=a000000100bc4dc0 [] ia64_pal_call_static+0x90/0xc0 sp=a000000100bcbd80 bsp=a000000100bc4d78 [] default_idle+0x90/0x160 sp=a000000100bcbd80 bsp=a000000100bc4d58 [] cpu_idle+0x1f0/0x440 sp=a000000100bcbe20 bsp=a000000100bc4d18 [] rest_init+0xc0/0xe0 sp=a000000100bcbe20 bsp=a000000100bc4d00 [] start_kernel+0x6a0/0x6c0 sp=a000000100bcbe20 bsp=a000000100bc4ca0 [] __end_ivt_text+0x6d0/0x6f0 sp=a000000100bcbe30 bsp=a000000100bc4c00 <0>Kernel panic - not syncing: Aiee, killing interrupt handler! The root cause is that some irq_chip variables, especially ia64_msi_chip, initiate their memeber end to point to NULL. __do_IRQ doesn't check if irq_chip->end is null and just calls it after processing the interrupt. As irq_chip->end is called at many places, so I fix it by reinitiating irq_chip->end to dummy_irq_chip.end, e.g., a noop function. Signed-off-by: Zhang Yanmin Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 2d0dc3e..ebfd24a 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -233,6 +233,8 @@ void irq_chip_set_defaults(struct irq_chip *chip) chip->shutdown = chip->disable; if (!chip->name) chip->name = chip->typename; + if (!chip->end) + chip->end = dummy_irq_chip.end; } static inline void mask_ack_irq(struct irq_desc *desc, int irq) -- cgit v0.10.2 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 diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index 7d9453c..bf36b68 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 51f0ecc..d23bf0d 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 v0.10.2 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 diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index bf36b68..f29e66e 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 v0.10.2 From a9083081b56800691e79d541638fd2fc6366db0f Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Thu, 16 Nov 2006 01:19:16 -0800 Subject: [PATCH] eCryptfs: dput() lower d_parent on rename On rename, for both the old and new lower dentry objects, eCryptfs is missing a dput on the lower parent directory dentry. This patch will prevent the BUG() at fs/dcache.c:613 from being hit after renaming a file inside eCryptfs and then doing a umount on the lower filesystem. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ff4865d..ebec8cf 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -630,6 +630,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); out_lock: unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); + dput(lower_new_dentry->d_parent); + dput(lower_old_dentry->d_parent); dput(lower_new_dentry); dput(lower_old_dentry); return rc; -- cgit v0.10.2 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 diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index b77b309..e815b35 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig index 574a678..5ca471a 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 5e29cb0..7dc1055 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 09a13c1..1aeddb4 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 v0.10.2 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 diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c index e3e1927..ec44efd 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 v0.10.2 From d6ddf55440833fd9404138026af246c51ebeef22 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 16 Nov 2006 01:19:22 -0800 Subject: [PATCH] hfs_fill_super returns success even if no root inode http://kernelfun.blogspot.com/2006/11/mokb-14-11-2006-linux-26x-selinux.html mount that image... fs: filesystem was not cleanly unmounted, running fsck.hfs is recommended. mounting read-only. hfs: get root inode failed. BUG: unable to handle kernel NULL pointer dereference at virtual address 00000018 printing eip ... EIP is at superblock_doinit+0x21/0x767 ... [] selinux_sb_kern_mount+0xc/0x4b [] vfs_kern_mount+0x99/0xf6 [] do_kern_mount+0x2d/0x3e [] do_mount+0x5fa/0x66d [] sys_mount+0x77/0xae [] syscall_call+0x7/0xb DWARF2 unwinder stuck at syscall_call+0x7/0xb hfs_fill_super() returns success even if root_inode = hfs_iget(sb, &fd.search_key->cat, &rec); or sb->s_root = d_alloc_root(root_inode); fails. This superblock finds its way to superblock_doinit() which does: struct dentry *root = sb->s_root; struct inode *inode = root->d_inode; and boom. Need to make sure the error cases return an error, I think. [akpm@osdl.org: return -ENOMEM on oom] Signed-off-by: Eric Sandeen Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfs/super.c b/fs/hfs/super.c index d43b4fc..85b17b3 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -390,11 +390,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) hfs_find_exit(&fd); goto bail_no_root; } + res = -EINVAL; root_inode = hfs_iget(sb, &fd.search_key->cat, &rec); hfs_find_exit(&fd); if (!root_inode) goto bail_no_root; + res = -ENOMEM; sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) goto bail_iput; -- cgit v0.10.2 From 55aa601e14cbec987fa577a895e9297df1d0a71d Mon Sep 17 00:00:00 2001 From: Phillip Susi Date: Thu, 16 Nov 2006 01:19:23 -0800 Subject: [PATCH] Update udf documentation to reflect current state of read/write support Change Documentation/filesystems/udf.txt from saying that read/write mounts on cd media are not supported to instead state the current level of support. Specifically that it works fine on dvd+rw media and can be made to work on cd-rw media via the pktcdvd device. Cc: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/udf.txt b/Documentation/filesystems/udf.txt index 511b423..fde829a 100644 --- a/Documentation/filesystems/udf.txt +++ b/Documentation/filesystems/udf.txt @@ -7,8 +7,17 @@ If you encounter problems with reading UDF discs using this driver, please report them to linux_udf@hpesjro.fc.hp.com, which is the developer's list. -Write support requires a block driver which supports writing. The current -scsi and ide cdrom drivers do not support writing. +Write support requires a block driver which supports writing. Currently +dvd+rw drives and media support true random sector writes, and so a udf +filesystem on such devices can be directly mounted read/write. CD-RW +media however, does not support this. Instead the media can be formatted +for packet mode using the utility cdrwtool, then the pktcdvd driver can +be bound to the underlying cd device to provide the required buffering +and read-modify-write cycles to allow the filesystem random sector writes +while providing the hardware with only full packet writes. While not +required for dvd+rw media, use of the pktcdvd driver often enhances +performance due to very poor read-modify-write support supplied internally +by drive firmware. ------------------------------------------------------------------------------- The following mount options are supported: -- cgit v0.10.2 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 diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 08b1617..fc702e4 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 v0.10.2 From 64aaa4f8b7e676ccd3f6448df6867097b873b0a6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 16 Nov 2006 01:19:27 -0800 Subject: [PATCH] AFS: Amend the AFS configuration options Amend the text of AFS configuration options. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/Kconfig b/fs/Kconfig index 133dcc8..7b1511d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -2060,8 +2060,7 @@ config CODA_FS_OLD_API For most cases you probably want to say N. config AFS_FS -# for fs/nls/Config.in - tristate "Andrew File System support (AFS) (Experimental)" + tristate "Andrew File System support (AFS) (EXPERIMENTAL)" depends on INET && EXPERIMENTAL select RXRPC help -- cgit v0.10.2 From 565762f3fae23ec4db26607cf4726de7b5075b3b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 16 Nov 2006 01:19:28 -0800 Subject: [PATCH] Don't give bad kprobes example aka ") < 0))" typo Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index ba26201..d71faff 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -442,9 +442,10 @@ static int __init kprobe_init(void) kp.fault_handler = handler_fault; kp.symbol_name = "do_fork"; - if ((ret = register_kprobe(&kp) < 0)) { + ret = register_kprobe(&kp); + if (ret < 0) { printk("register_kprobe failed, returned %d\n", ret); - return -1; + return ret; } printk("kprobe registered\n"); return 0; -- cgit v0.10.2 From da63fc7ce63b43426dc3c69c05e28de2872c159a Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 16 Nov 2006 01:19:28 -0800 Subject: [PATCH] fat: add fat_getattr() This adds fat_getattr() for setting stat->blksize. (FAT uses the size of cluster for proper I/O) Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/file.c b/fs/fat/file.c index 8337451..0aa813d 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -303,7 +303,17 @@ void fat_truncate(struct inode *inode) fat_flush_inodes(inode->i_sb, inode, NULL); } +int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + generic_fillattr(inode, stat); + stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; + return 0; +} +EXPORT_SYMBOL_GPL(fat_getattr); + struct inode_operations fat_file_inode_operations = { .truncate = fat_truncate, .setattr = fat_notify_change, + .getattr = fat_getattr, }; diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index b0f01b3..4524619 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -654,6 +654,7 @@ static struct inode_operations msdos_dir_inode_operations = { .rmdir = msdos_rmdir, .rename = msdos_rename, .setattr = fat_notify_change, + .getattr = fat_getattr, }; static int msdos_fill_super(struct super_block *sb, void *data, int silent) diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index edb711f..0afd745 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -1004,6 +1004,7 @@ static struct inode_operations vfat_dir_inode_operations = { .rmdir = vfat_rmdir, .rename = vfat_rename, .setattr = fat_notify_change, + .getattr = fat_getattr, }; static int vfat_fill_super(struct super_block *sb, void *data, int silent) diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index ce6c858..24a9ef1 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -402,6 +402,8 @@ extern const struct file_operations fat_file_operations; extern struct inode_operations fat_file_inode_operations; extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); extern void fat_truncate(struct inode *inode); +extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat); /* fat/inode.c */ extern void fat_attach(struct inode *inode, loff_t i_pos); -- cgit v0.10.2 From 31be8309532a6743f301cb2e83bd12ca07988b09 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 16 Nov 2006 01:19:29 -0800 Subject: [PATCH] Fix strange size check in __get_vm_area_node() Recently, __get_vm_area_node() was changed like following if (unlikely(!area)) return NULL; - if (unlikely(!size)) { - kfree (area); + if (unlikely(!size)) return NULL; - } It is leaking `area', also original code seems strange already. Probably, we wanted to do this patch. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 7dc6aa7..86897ee 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -181,14 +181,13 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl } addr = ALIGN(start, align); size = PAGE_ALIGN(size); + if (unlikely(!size)) + return NULL; area = kmalloc_node(sizeof(*area), gfp_mask & GFP_LEVEL_MASK, node); if (unlikely(!area)) return NULL; - if (unlikely(!size)) - return NULL; - /* * We always allocate a guard page. */ -- cgit v0.10.2 From ae56fb16337c882c52806508f93ead4034004c7a Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Thu, 16 Nov 2006 01:19:30 -0800 Subject: [PATCH] eCryptfs: CIFS nlink fixes When CIFS is the lower filesystem, the old lower dentry needs to be explicitly dropped from inside eCryptfs to force a revalidate. In addition, when CIFS is the lower filesystem, the inode attributes need to be copied back up from the lower inode to the eCryptfs inode on an eCryptfs revalidate. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 0b9992a..52d1e36 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -57,6 +57,12 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); nd->dentry = dentry_save; nd->mnt = vfsmount_save; + if (dentry->d_inode) { + struct inode *lower_inode = + ecryptfs_inode_to_lower(dentry->d_inode); + + ecryptfs_copy_attr_all(dentry->d_inode, lower_inode); + } out: return rc; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ebec8cf..dfcc684 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -470,6 +470,7 @@ out_lock: unlock_dir(lower_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); + d_drop(lower_old_dentry); d_drop(new_dentry); d_drop(old_dentry); return rc; @@ -484,7 +485,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) lock_parent(lower_dentry); rc = vfs_unlink(lower_dir_inode, lower_dentry); if (rc) { - ecryptfs_printk(KERN_ERR, "Error in vfs_unlink\n"); + printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); goto out_unlock; } ecryptfs_copy_attr_times(dir, lower_dir_inode); -- cgit v0.10.2 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 diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a19338e..e55a756 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 d2c02df..3ac4890 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 v0.10.2 From 31ec35d6c81175016a6372571eab23b6bd40b406 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 16 Nov 2006 20:54:20 +0000 Subject: [CIFS] Incorrect hardlink count when original file is cached (oplocked) Fixes Samba bug 2823 In this case hardlink count is stale for one of the two inodes (ie the original file) until it is closed - since revalidate does not go to server while file is cached locally. Signed-off-by: Steve French diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 0bee8b7..8e25996 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -69,17 +69,30 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, rc = -EOPNOTSUPP; } -/* if (!rc) */ - { - /* renew_parental_timestamps(old_file); - inode->i_nlink++; - mark_inode_dirty(inode); - d_instantiate(direntry, inode); */ - /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */ + d_drop(direntry); /* force new lookup from server of target */ + + /* if source file is cached (oplocked) revalidate will not go to server + until the file is closed or oplock broken so update nlinks locally */ + if(old_file->d_inode) { + cifsInode = CIFS_I(old_file->d_inode); + if(rc == 0) { + old_file->d_inode->i_nlink++; + old_file->d_inode->i_ctime = CURRENT_TIME; + /* parent dir timestamps will update from srv + within a second, would it really be worth it + to set the parent dir cifs inode time to zero + to force revalidate (faster) for it too? */ + } + /* if not oplocked will force revalidate to get info + on source file from srv */ + cifsInode->time = 0; + + /* Will update parent dir timestamps from srv within a second. + Would it really be worth it to set the parent dir (cifs + inode) time field to zero to force revalidate on parent + directory faster ie + CIFS_I(inode)->time = 0; */ } - d_drop(direntry); /* force new lookup from server */ - cifsInode = CIFS_I(old_file->d_inode); - cifsInode->time = 0; /* will force revalidate to go get info when needed */ cifs_hl_exit: kfree(fromName); -- cgit v0.10.2 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 diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1eaf00e..85522da 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 v0.10.2 From 6b3d1a95ba714bfb1cc81362f7f3e01b7654b4f3 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 16 Nov 2006 10:22:03 +0100 Subject: [PATCH] x86-64: Fix vsyscall.c compilation on UP Broken by earlier patch by me. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index a730bac..92546c1 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -274,6 +274,7 @@ static void __cpuinit cpu_vsyscall_init(void *arg) vsyscall_set_cpu(raw_smp_processor_id()); } +#ifdef CONFIG_HOTPLUG_CPU static int __cpuinit cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { @@ -282,6 +283,7 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); return NOTIFY_DONE; } +#endif static void __init map_vsyscall(void) { -- cgit v0.10.2 From ccf9ff524ccb195d648ecb0b168340560b42532c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 16 Nov 2006 11:49:16 +0100 Subject: [PATCH] x86_64: fix CONFIG_CC_STACKPROTECTOR build bug on x86_64, the CONFIG_CC_STACKPROTECTOR build fails if used in a distcc setup that has "CC" defined to "distcc gcc": gcc: gcc: linker input file unused because linking not done gcc: gcc: linker input file unused because linking not done gcc: gcc: linker input file unused because linking not done this is because the gcc-x86_64-has-stack-protector.sh script has a 2-parameters assumption. Fix this by passing $(CC) as a single parameter. Signed-off-by: Ingo Molnar Please-Use-Me-More: make randconfig Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 1397214..6e38d4d 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -66,8 +66,8 @@ AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,) -cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector ) -cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector-all ) +cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector ) +cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector-all ) CFLAGS += $(cflags-y) CFLAGS_KERNEL += $(cflags-kernel-y) -- cgit v0.10.2 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 diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 6f11359..da09e79 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 v0.10.2 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 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bd76b4c..c971d78 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 f0edb87..30921f5 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -175,9 +175,15 @@ #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 v0.10.2 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 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c971d78..c186b4e 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 30921f5..bae117d 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bc1ac07..e87fb538 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 v0.10.2 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 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9be6b30..ea4714e 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 da09e79..6995ea3 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6daf85c..8fde85c 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 9a808a3..68e7ebb 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 9b50eff..0e76e6d 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e87fb538..cc701e8 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 8fde85c..6d08a3b 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index cc701e8..efb047f 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 v0.10.2 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 diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fccd195..7729c07 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 v0.10.2 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 diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 6238aff..d72cf8b 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 v0.10.2 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 diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 0be9d62..e4971d6 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 v0.10.2 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 diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 2788b8c..6f9d880 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 v0.10.2 From 7bb0386f102ece8819182ccf7fffe8bbebc32b19 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 19 Oct 2006 12:24:42 +0900 Subject: debugfs: check return value correctly The return value is stored in "*dentry", not in "dentry". Signed-off-by: Akinobu Mita Signed-off-by: Greg Kroah-Hartman diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e77676d..a736d44 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -147,13 +147,13 @@ static int debugfs_create_by_name(const char *name, mode_t mode, *dentry = NULL; mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(dentry)) { + if (!IS_ERR(*dentry)) { if ((mode & S_IFMT) == S_IFDIR) error = debugfs_mkdir(parent->d_inode, *dentry, mode); else error = debugfs_create(parent->d_inode, *dentry, mode); } else - error = PTR_ERR(dentry); + error = PTR_ERR(*dentry); mutex_unlock(&parent->d_inode->i_mutex); return error; -- cgit v0.10.2 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 diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index d433f27..aa25f8b 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 v0.10.2 From 8d6286fdfd290589f8446ec1503702227263dcfd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 16 Nov 2006 22:48:25 +0000 Subject: [CIFS] Fix timezone handling on stat to os/2 We were adjusting for timezone on readdir but not on stat Signed-off-by: Steve French diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1ad8c9f..c4fa91b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -318,6 +318,7 @@ int cifs_get_inode_info(struct inode **pinode, struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *tmp_path; char *buf = NULL; + int adjustTZ = FALSE; pTcon = cifs_sb->tcon; cFYI(1,("Getting info on %s", search_path)); @@ -348,6 +349,7 @@ int cifs_get_inode_info(struct inode **pinode, pfindData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + adjustTZ = TRUE; } } @@ -444,6 +446,10 @@ int cifs_get_inode_info(struct inode **pinode, inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); cFYI(0, ("Attributes came in as 0x%x", attr)); + if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { + inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; + inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; + } /* set default mode. will override for dirs below */ if (atomic_read(&cifsInfo->inUse) == 0) -- cgit v0.10.2 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 diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 6767545..869725a 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 v0.10.2 From 00081d3729a450c37afb01c01528f4f305806d86 Mon Sep 17 00:00:00 2001 From: Jason Parekh Date: Fri, 17 Nov 2006 01:05:58 -0500 Subject: Input: appletouch - verious updates for MacBooks Change a bit the finger detection method used by the appletouch driver to reduce touchpad "jumpiness": - Adjust the method for detecting multiple fingers. Previously, it recognized a new finger when a low sensor reading is followed by a high sensor reading. The new method checks for 'humps' in the sensor readings, so there doesn't necessarily have to be a low sensor between two high sensors for two fingers to be triggered. This allows detecting presence of two fingers on the touchpad even when they touch each other. - Change absolute coordinate calculation to us to get rid of "jumps". Instead of using full value from a sensor once it passes the threshold subtract theshold value from the reading. - Allow adjusting threshold value via module parameter. The patch doesn't seem to affect the Powerbooks but does greatly improve the touchpad behaviour on the MacBooks. Signed-off-by: Jason Parekh Signed-off-by: Stelian Pop Signed-off-by: Dmitry Torokhov diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 4c21351..4825db4 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -154,6 +154,13 @@ MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); MODULE_LICENSE("GPL"); +/* + * Make the threshold a module parameter + */ +static int threshold = ATP_THRESHOLD; +module_param(threshold, int, 0644); +MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value"); + static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); @@ -183,16 +190,48 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int i; /* values to calculate mean */ int pcum = 0, psum = 0; + int is_increasing = 0; *fingers = 0; for (i = 0; i < nb_sensors; i++) { - if (xy_sensors[i] < ATP_THRESHOLD) + if (xy_sensors[i] < threshold) { + if (is_increasing) + is_increasing = 0; + continue; - if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD)) + } + + /* + * Makes the finger detection more versatile. For example, + * two fingers with no gap will be detected. Also, my + * tests show it less likely to have intermittent loss + * of multiple finger readings while moving around (scrolling). + * + * Changes the multiple finger detection to counting humps on + * sensors (transitions from nonincreasing to increasing) + * instead of counting transitions from low sensors (no + * finger reading) to high sensors (finger above + * sensor) + * + * - Jason Parekh + */ + if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { (*fingers)++; - pcum += xy_sensors[i] * i; - psum += xy_sensors[i]; + is_increasing = 1; + } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { + is_increasing = 0; + } + + /* + * Subtracts threshold so a high sensor that just passes the threshold + * won't skew the calculated absolute coordinate. Fixes an issue + * where slowly moving the mouse would occassionaly jump a number of + * pixels (let me restate--slowly moving the mouse makes this issue + * most apparent). + */ + pcum += (xy_sensors[i] - threshold) * i; + psum += (xy_sensors[i] - threshold); } if (psum > 0) { -- cgit v0.10.2 From 009ad0e7b43d6cabd74e47db6180f14315b71417 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Fri, 17 Nov 2006 01:06:13 -0500 Subject: Input: appletouch - add Geyser IV support The new Core2 Duo MacBook Pro has a new keyboard+trackpad named "Geyser IV". According to the Info.plist in the OS X kext, it looks like the Geyser IV trackpad is identical to the Geyser III trackpad: same IOClass (AppleUSBGrIIITrackpad), same acceleration tables. Signed-off-by: Julien BLACHE Signed-off-by: Dmitry Torokhov diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 4825db4..69c4456 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -47,6 +47,14 @@ #define GEYSER3_ISO_PRODUCT_ID 0x0218 #define GEYSER3_JIS_PRODUCT_ID 0x0219 +/* + * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext + * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables + */ +#define GEYSER4_ANSI_PRODUCT_ID 0x021A +#define GEYSER4_ISO_PRODUCT_ID 0x021B +#define GEYSER4_JIS_PRODUCT_ID 0x021C + #define ATP_DEVICE(prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ @@ -68,10 +76,16 @@ static struct usb_device_id atp_table [] = { { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + /* Core Duo MacBook & MacBook Pro */ { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, + /* Core2 Duo MacBook & MacBook Pro */ + { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) }, + /* Terminating entry */ { } }; @@ -108,7 +122,7 @@ MODULE_DEVICE_TABLE (usb, atp_table); */ #define ATP_THRESHOLD 5 -/* MacBook Pro (Geyser 3) initialization constants */ +/* MacBook Pro (Geyser 3 & 4) initialization constants */ #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 @@ -181,7 +195,10 @@ static inline int atp_is_geyser_3(struct atp *dev) return (productId == GEYSER3_ANSI_PRODUCT_ID) || (productId == GEYSER3_ISO_PRODUCT_ID) || - (productId == GEYSER3_JIS_PRODUCT_ID); + (productId == GEYSER3_JIS_PRODUCT_ID) || + (productId == GEYSER4_ANSI_PRODUCT_ID) || + (productId == GEYSER4_ISO_PRODUCT_ID) || + (productId == GEYSER4_JIS_PRODUCT_ID); } static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, -- cgit v0.10.2 From e5d9832c207f952e15ccddda5f2d52c94036acd7 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Fri, 17 Nov 2006 01:06:25 -0500 Subject: Input: appletouch - use canonical names in USB IDs Small readability improvement for appletouch: use canonical names instead of raw USB IDs for some of the devices. Signed-off-by: Julien BLACHE Signed-off-by: Dmitry Torokhov diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 69c4456..c77291d 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -38,14 +38,21 @@ #define APPLE_VENDOR_ID 0x05AC /* These names come from Info.plist in AppleUSBTrackpad.kext */ -#define GEYSER_ANSI_PRODUCT_ID 0x0214 -#define GEYSER_ISO_PRODUCT_ID 0x0215 -#define GEYSER_JIS_PRODUCT_ID 0x0216 +#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E +#define FOUNTAIN_ISO_PRODUCT_ID 0x020F + +#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A + +#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B + +#define GEYSER_ANSI_PRODUCT_ID 0x0214 +#define GEYSER_ISO_PRODUCT_ID 0x0215 +#define GEYSER_JIS_PRODUCT_ID 0x0216 /* MacBook devices */ -#define GEYSER3_ANSI_PRODUCT_ID 0x0217 -#define GEYSER3_ISO_PRODUCT_ID 0x0218 -#define GEYSER3_JIS_PRODUCT_ID 0x0219 +#define GEYSER3_ANSI_PRODUCT_ID 0x0217 +#define GEYSER3_ISO_PRODUCT_ID 0x0218 +#define GEYSER3_JIS_PRODUCT_ID 0x0219 /* * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext @@ -66,10 +73,10 @@ /* table of devices that work with this driver */ static struct usb_device_id atp_table [] = { - { ATP_DEVICE(0x020E) }, - { ATP_DEVICE(0x020F) }, - { ATP_DEVICE(0x030A) }, - { ATP_DEVICE(0x030B) }, + { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) }, + { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) }, /* PowerBooks Oct 2005 */ { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, -- cgit v0.10.2 From 5b44f1aaee7e3b24f6e21662d7fef1534111a2df Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Fri, 17 Nov 2006 01:06:36 -0500 Subject: Input: MAC mouse button emulation - relax dependencies Mouse button emulation for the one-button mouse Apple machines isn't restricted to older ADB based machines. There are PPC Powerbooks where the keyboard and the mouse are no longer on the ADB bus but regular USB, and users still like (and need) to be able to emulate the middle mouse button with F11 and the right mouse button with F12. Signed-off-by: Dmitry Torokhov diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 7f8477d..31015d5 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -162,7 +162,6 @@ config INPUT_ADBHID config MAC_EMUMOUSEBTN bool "Support for mouse button 2+3 emulation" - depends on INPUT_ADBHID help This provides generic support for emulating the 2nd and 3rd mouse button with keypresses. If you say Y here, the emulation is still -- cgit v0.10.2 From 6c595fb12fa6c1fe382cc086fdade4acd93c643f Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Fri, 17 Nov 2006 01:06:54 -0500 Subject: Input: mousedev - remap BTN_FORWARD from BTN_LEFT to BTN_MIDDLE In mousedev the BTN_LEFT and BTN_FORWARD were mapped to mouse button 0, causing that the user space program cannot distinguish between them through /dev/input/mice. All mice have BTN_LEFT, but not all have BTN_MIDDLE (e.g. Clevo D410J laptop). Mapping BTN_FORWARD to mouse button 2 makes the BTN_FORWARD button useful on this laptop. Signed-off-by: Marton Nemeth Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a22a74a..664bcc8 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -196,12 +196,12 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int switch (code) { case BTN_TOUCH: case BTN_0: - case BTN_FORWARD: case BTN_LEFT: index = 0; break; case BTN_STYLUS: case BTN_1: case BTN_RIGHT: index = 1; break; case BTN_2: + case BTN_FORWARD: case BTN_STYLUS2: case BTN_MIDDLE: index = 2; break; case BTN_3: -- cgit v0.10.2 From a216a4b6e6f1fdfd3d1f20f03d9d45f05a63d643 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 17 Nov 2006 01:07:06 -0500 Subject: Input: i8042 - fix shutdown issue on some boxes with active MUXes MUX error handling has a workaround for KBCs that get confused which port data came from and signal MUXERR while data is actually good. Unfortunately this workaround hurts with KBCs that signal timeouts as 0xfc (spec says that only 0xfd, 0xfe and 0xff are alowed with MUXERR) since it causes endless attempts to rescan i8042 serio ports. The solution is to treat 0xfc as timeout (0xfe). Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index d365f22..debe944 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -322,23 +322,27 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) dfl = 0; if (str & I8042_STR_MUXERR) { dbg("MUX error, status is %02x, data is %02x", str, data); - switch (data) { - default: /* * When MUXERR condition is signalled the data register can only contain * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately - * it is not always the case. Some KBC just get confused which port the - * data came from and signal error leaving the data intact. They _do not_ - * revert to legacy mode (actually I've never seen KBC reverting to legacy - * mode yet, when we see one we'll add proper handling). - * Anyway, we will assume that the data came from the same serio last byte + * it is not always the case. Some KBCs also report 0xfc when there is + * nothing connected to the port while others sometimes get confused which + * port the data came from and signal error leaving the data intact. They + * _do not_ revert to legacy mode (actually I've never seen KBC reverting + * to legacy mode yet, when we see one we'll add proper handling). + * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the + * rest assume that the data came from the same serio last byte * was transmitted (if transmission happened not too long ago). */ + + switch (data) { + default: if (time_before(jiffies, last_transmit + HZ/10)) { str = last_str; break; } /* fall through - report timeout */ + case 0xfc: case 0xfd: case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; -- cgit v0.10.2 From f40219bf936bb677566f42758d505e27fad0908e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 17 Nov 2006 01:07:26 -0500 Subject: Input: add Philips UCB1400 touchscreen driver Signed-off-by: Nicolas Pitre Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 9418bbe..29ca0ab 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -144,4 +144,19 @@ config TOUCHSCREEN_TOUCHWIN To compile this driver as a module, choose M here: the module will be called touchwin. +config TOUCHSCREEN_UCB1400 + tristate "Philips UCB1400 touchscreen" + select SND_AC97_BUS + help + This enables support for the Philips UCB1400 touchscreen interface. + The UCB1400 is an AC97 audio codec. The touchscreen interface + will be initialized only after the ALSA subsystem has been + brought up and the UCB1400 detected. You therefore have to + configure ALSA support as well (either built-in or modular, + independently of whether this driver is itself built-in or + modular) for this driver to work. + + To compile this driver as a module, choose M here: the + module will be called ucb1400_ts. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 1abb8f1..30e6e22 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o +obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c new file mode 100644 index 0000000..6ef0836 --- /dev/null +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -0,0 +1,579 @@ +/* + * Philips UCB1400 touchscreen driver + * + * Author: Nicolas Pitre + * Created: September 25, 2006 + * Copyright: MontaVista Software, Inc. + * + * 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. + * + * This code is heavily based on ucb1x00-*.c copyrighted by Russell King + * covering the UCB1100, UCB1200 and UCB1300.. Support for the UCB1400 has + * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * Interesting UCB1400 AC-link registers + */ + +#define UCB_IE_RIS 0x5e +#define UCB_IE_FAL 0x60 +#define UCB_IE_STATUS 0x62 +#define UCB_IE_CLEAR 0x62 +#define UCB_IE_ADC (1 << 11) +#define UCB_IE_TSPX (1 << 12) + +#define UCB_TS_CR 0x64 +#define UCB_TS_CR_TSMX_POW (1 << 0) +#define UCB_TS_CR_TSPX_POW (1 << 1) +#define UCB_TS_CR_TSMY_POW (1 << 2) +#define UCB_TS_CR_TSPY_POW (1 << 3) +#define UCB_TS_CR_TSMX_GND (1 << 4) +#define UCB_TS_CR_TSPX_GND (1 << 5) +#define UCB_TS_CR_TSMY_GND (1 << 6) +#define UCB_TS_CR_TSPY_GND (1 << 7) +#define UCB_TS_CR_MODE_INT (0 << 8) +#define UCB_TS_CR_MODE_PRES (1 << 8) +#define UCB_TS_CR_MODE_POS (2 << 8) +#define UCB_TS_CR_BIAS_ENA (1 << 11) +#define UCB_TS_CR_TSPX_LOW (1 << 12) +#define UCB_TS_CR_TSMX_LOW (1 << 13) + +#define UCB_ADC_CR 0x66 +#define UCB_ADC_SYNC_ENA (1 << 0) +#define UCB_ADC_VREFBYP_CON (1 << 1) +#define UCB_ADC_INP_TSPX (0 << 2) +#define UCB_ADC_INP_TSMX (1 << 2) +#define UCB_ADC_INP_TSPY (2 << 2) +#define UCB_ADC_INP_TSMY (3 << 2) +#define UCB_ADC_INP_AD0 (4 << 2) +#define UCB_ADC_INP_AD1 (5 << 2) +#define UCB_ADC_INP_AD2 (6 << 2) +#define UCB_ADC_INP_AD3 (7 << 2) +#define UCB_ADC_EXT_REF (1 << 5) +#define UCB_ADC_START (1 << 7) +#define UCB_ADC_ENA (1 << 15) + +#define UCB_ADC_DATA 0x68 +#define UCB_ADC_DAT_VALID (1 << 15) +#define UCB_ADC_DAT_VALUE(x) ((x) & 0x3ff) + +#define UCB_ID 0x7e +#define UCB_ID_1400 0x4304 + + +struct ucb1400 { + ac97_t *ac97; + struct input_dev *ts_idev; + + int irq; + + wait_queue_head_t ts_wait; + struct task_struct *ts_task; + + unsigned int irq_pending; /* not bit field shared */ + unsigned int ts_restart:1; + unsigned int adcsync:1; +}; + +static int adcsync; + +static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg) +{ + return ucb->ac97->bus->ops->read(ucb->ac97, reg); +} + +static inline void ucb1400_reg_write(struct ucb1400 *ucb, u16 reg, u16 val) +{ + ucb->ac97->bus->ops->write(ucb->ac97, reg, val); +} + +static inline void ucb1400_adc_enable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); +} + +static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel) +{ + unsigned int val; + + if (ucb->adcsync) + adc_channel |= UCB_ADC_SYNC_ENA; + + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel); + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel | UCB_ADC_START); + + for (;;) { + val = ucb1400_reg_read(ucb, UCB_ADC_DATA); + if (val & UCB_ADC_DAT_VALID) + break; + /* yield to other processes */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + return UCB_ADC_DAT_VALUE(val); +} + +static inline void ucb1400_adc_disable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_ADC_CR, 0); +} + +/* Switch to interrupt mode. */ +static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_INT); +} + +/* + * Switch to pressure mode, and read pressure. We don't need to wait + * here, since both plates are being driven. + */ +static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); +} + +/* + * Switch to X position mode and measure Y plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); +} + +/* + * Switch to Y position mode and measure X plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX); +} + +/* + * Switch to X plate resistance mode. Set MX to ground, PX to + * supply. Measure current. + */ +static inline unsigned int ucb1400_ts_read_xres(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, 0); +} + +/* + * Switch to Y plate resistance mode. Set MY to ground, PY to + * supply. Measure current. + */ +static inline unsigned int ucb1400_ts_read_yres(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, 0); +} + +static inline int ucb1400_ts_pen_down(struct ucb1400 *ucb) +{ + unsigned short val = ucb1400_reg_read(ucb, UCB_TS_CR); + return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)); +} + +static inline void ucb1400_ts_irq_enable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_IE_CLEAR, UCB_IE_TSPX); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_TSPX); +} + +static inline void ucb1400_ts_irq_disable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_IE_FAL, 0); +} + +static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y) +{ + input_report_abs(idev, ABS_X, x); + input_report_abs(idev, ABS_Y, y); + input_report_abs(idev, ABS_PRESSURE, pressure); + input_sync(idev); +} + +static void ucb1400_ts_event_release(struct input_dev *idev) +{ + input_report_abs(idev, ABS_PRESSURE, 0); + input_sync(idev); +} + +static void ucb1400_handle_pending_irq(struct ucb1400 *ucb) +{ + unsigned int isr; + + isr = ucb1400_reg_read(ucb, UCB_IE_STATUS); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, isr); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + if (isr & UCB_IE_TSPX) + ucb1400_ts_irq_disable(ucb); + else + printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr); + + enable_irq(ucb->irq); +} + +static int ucb1400_ts_thread(void *_ucb) +{ + struct ucb1400 *ucb = _ucb; + struct task_struct *tsk = current; + int valid = 0; + + tsk->policy = SCHED_FIFO; + tsk->rt_priority = 1; + + while (!kthread_should_stop()) { + unsigned int x, y, p; + long timeout; + + ucb->ts_restart = 0; + + if (ucb->irq_pending) { + ucb->irq_pending = 0; + ucb1400_handle_pending_irq(ucb); + } + + ucb1400_adc_enable(ucb); + x = ucb1400_ts_read_xpos(ucb); + y = ucb1400_ts_read_ypos(ucb); + p = ucb1400_ts_read_pressure(ucb); + ucb1400_adc_disable(ucb); + + /* Switch back to interrupt mode. */ + ucb1400_ts_mode_int(ucb); + + msleep(10); + + if (ucb1400_ts_pen_down(ucb)) { + ucb1400_ts_irq_enable(ucb); + + /* + * If we spat out a valid sample set last time, + * spit out a "pen off" sample here. + */ + if (valid) { + ucb1400_ts_event_release(ucb->ts_idev); + valid = 0; + } + + timeout = MAX_SCHEDULE_TIMEOUT; + } else { + valid = 1; + ucb1400_ts_evt_add(ucb->ts_idev, p, x, y); + timeout = msecs_to_jiffies(10); + } + + wait_event_interruptible_timeout(ucb->ts_wait, + ucb->irq_pending || ucb->ts_restart || kthread_should_stop(), + timeout); + try_to_freeze(); + } + + /* Send the "pen off" if we are stopping with the pen still active */ + if (valid) + ucb1400_ts_event_release(ucb->ts_idev); + + ucb->ts_task = NULL; + return 0; +} + +/* + * A restriction with interrupts exists when using the ucb1400, as + * the codec read/write routines may sleep while waiting for codec + * access completion and uses semaphores for access control to the + * AC97 bus. A complete codec read cycle could take anywhere from + * 60 to 100uSec so we *definitely* don't want to spin inside the + * interrupt handler waiting for codec access. So, we handle the + * interrupt by scheduling a RT kernel thread to run in process + * context instead of interrupt context. + */ +static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) +{ + struct ucb1400 *ucb = devid; + + if (irqnr == ucb->irq) { + disable_irq(ucb->irq); + ucb->irq_pending = 1; + wake_up(&ucb->ts_wait); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static int ucb1400_ts_open(struct input_dev *idev) +{ + struct ucb1400 *ucb = idev->private; + int ret = 0; + + BUG_ON(ucb->ts_task); + + ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts"); + if (IS_ERR(ucb->ts_task)) { + ret = PTR_ERR(ucb->ts_task); + ucb->ts_task = NULL; + } + + return ret; +} + +static void ucb1400_ts_close(struct input_dev *idev) +{ + struct ucb1400 *ucb = idev->private; + + if (ucb->ts_task) + kthread_stop(ucb->ts_task); + + ucb1400_ts_irq_disable(ucb); + ucb1400_reg_write(ucb, UCB_TS_CR, 0); +} + +#ifdef CONFIG_PM +static int ucb1400_ts_resume(struct device *dev) +{ + struct ucb1400 *ucb = dev_get_drvdata(dev); + + if (ucb->ts_task) { + /* + * Restart the TS thread to ensure the + * TS interrupt mode is set up again + * after sleep. + */ + ucb->ts_restart = 1; + wake_up(&ucb->ts_wait); + } + return 0; +} +#else +#define ucb1400_ts_resume NULL +#endif + +#ifndef NO_IRQ +#define NO_IRQ 0 +#endif + +/* + * Try to probe our interrupt, rather than relying on lots of + * hard-coded machine dependencies. + */ +static int ucb1400_detect_irq(struct ucb1400 *ucb) +{ + unsigned long mask, timeout; + + mask = probe_irq_on(); + if (!mask) { + probe_irq_off(mask); + return -EBUSY; + } + + /* Enable the ADC interrupt. */ + ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); + ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* Cause an ADC interrupt. */ + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); + + /* Wait for the conversion to complete. */ + timeout = jiffies + HZ/2; + while (!(ucb1400_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VALID)) { + cpu_relax(); + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "ucb1400: timed out in IRQ probe\n"); + probe_irq_off(mask); + return -ENODEV; + } + } + ucb1400_reg_write(ucb, UCB_ADC_CR, 0); + + /* Disable and clear interrupt. */ + ucb1400_reg_write(ucb, UCB_IE_RIS, 0); + ucb1400_reg_write(ucb, UCB_IE_FAL, 0); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* Read triggered interrupt. */ + ucb->irq = probe_irq_off(mask); + if (ucb->irq < 0 || ucb->irq == NO_IRQ) + return -ENODEV; + + return 0; +} + +static int ucb1400_ts_probe(struct device *dev) +{ + struct ucb1400 *ucb; + struct input_dev *idev; + int error, id, x_res, y_res; + + ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL); + idev = input_allocate_device(); + if (!ucb || !idev) { + error = -ENOMEM; + goto err_free_devs; + } + + ucb->ts_idev = idev; + ucb->adcsync = adcsync; + ucb->ac97 = to_ac97_t(dev); + init_waitqueue_head(&ucb->ts_wait); + + id = ucb1400_reg_read(ucb, UCB_ID); + if (id != UCB_ID_1400) { + error = -ENODEV; + goto err_free_devs; + } + + error = ucb1400_detect_irq(ucb); + if (error) { + printk(KERN_ERR "UCB1400: IRQ probe failed\n"); + goto err_free_devs; + } + + error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING, + "UCB1400", ucb); + if (error) { + printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n", + ucb->irq, error); + goto err_free_devs; + } + printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); + + idev->private = ucb; + idev->cdev.dev = dev; + idev->name = "UCB1400 touchscreen interface"; + idev->id.vendor = ucb1400_reg_read(ucb, AC97_VENDOR_ID1); + idev->id.product = id; + idev->open = ucb1400_ts_open; + idev->close = ucb1400_ts_close; + idev->evbit[0] = BIT(EV_ABS); + + ucb1400_adc_enable(ucb); + x_res = ucb1400_ts_read_xres(ucb); + y_res = ucb1400_ts_read_yres(ucb); + ucb1400_adc_disable(ucb); + printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res); + + input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0); + input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0); + input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0); + + error = input_register_device(idev); + if (error) + goto err_free_irq; + + dev_set_drvdata(dev, ucb); + return 0; + + err_free_irq: + free_irq(ucb->irq, ucb); + err_free_devs: + input_free_device(idev); + kfree(ucb); + return error; +} + +static int ucb1400_ts_remove(struct device *dev) +{ + struct ucb1400 *ucb = dev_get_drvdata(dev); + + free_irq(ucb->irq, ucb); + input_unregister_device(ucb->ts_idev); + dev_set_drvdata(dev, NULL); + kfree(ucb); + return 0; +} + +static struct device_driver ucb1400_ts_driver = { + .owner = THIS_MODULE, + .bus = &ac97_bus_type, + .probe = ucb1400_ts_probe, + .remove = ucb1400_ts_remove, + .resume = ucb1400_ts_resume, +}; + +static int __init ucb1400_ts_init(void) +{ + return driver_register(&ucb1400_ts_driver); +} + +static void __exit ucb1400_ts_exit(void) +{ + driver_unregister(&ucb1400_ts_driver); +} + +module_param(adcsync, int, 0444); + +module_init(ucb1400_ts_init); +module_exit(ucb1400_ts_exit); + +MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9d92fe17b652f5496c97bc83fdfe925f3182f602 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 17 Nov 2006 01:07:39 -0500 Subject: Input: serio - remove serio_unregister_port_delayed() Now that i8042 reserves IRQs early there are no more users of this function and it should be removed. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 3cb99d4..cd55ddb 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -44,7 +44,6 @@ EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_child_port); -EXPORT_SYMBOL(__serio_unregister_port_delayed); EXPORT_SYMBOL(__serio_register_driver); EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_open); @@ -64,7 +63,6 @@ static struct bus_type serio_bus; static void serio_add_driver(struct serio_driver *drv); static void serio_add_port(struct serio *serio); -static void serio_destroy_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio); @@ -173,7 +171,6 @@ enum serio_event_type { SERIO_RESCAN, SERIO_RECONNECT, SERIO_REGISTER_PORT, - SERIO_UNREGISTER_PORT, SERIO_REGISTER_DRIVER, }; @@ -307,11 +304,6 @@ static void serio_handle_event(void) serio_add_port(event->object); break; - case SERIO_UNREGISTER_PORT: - serio_disconnect_port(event->object); - serio_destroy_port(event->object); - break; - case SERIO_RECONNECT: serio_reconnect_port(event->object); break; @@ -716,16 +708,6 @@ void serio_unregister_child_port(struct serio *serio) mutex_unlock(&serio_mutex); } -/* - * Submits register request to kseriod for subsequent execution. - * Can be used when it is not obvious whether the serio_mutex is - * taken or not and when delayed execution is feasible. - */ -void __serio_unregister_port_delayed(struct serio *serio, struct module *owner) -{ - serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT); -} - /* * Serio driver operations diff --git a/include/linux/serio.h b/include/linux/serio.h index b99c5ca..8f52228 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -85,11 +85,6 @@ static inline void serio_register_port(struct serio *serio) void serio_unregister_port(struct serio *serio); void serio_unregister_child_port(struct serio *serio); -void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); -static inline void serio_unregister_port_delayed(struct serio *serio) -{ - __serio_unregister_port_delayed(serio, THIS_MODULE); -} void __serio_register_driver(struct serio_driver *drv, struct module *owner); static inline void serio_register_driver(struct serio_driver *drv) -- cgit v0.10.2 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 diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index 3aa6ebf..f836137 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 v0.10.2 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 diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 708d5a1..979b93e 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 v0.10.2 From 0796bdb7e9e4a48b401f4fba1ee5dc79a45528ef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 17 Nov 2006 05:57:49 +0100 Subject: [PATCH] x86_64: stack unwinder crash fix the new dwarf2 unwinder crashes while trying to dump the stack: Leftover inexact backtrace: Unable to handle kernel paging request at ffffffff82800000 RIP: [] dump_trace+0x35b/0x3d2 PGD 203027 PUD 205027 PMD 0 Oops: 0000 [2] PREEMPT SMP CPU 0 Modules linked in: Pid: 30, comm: khelper Not tainted 2.6.19-rc6-rt1 #11 RIP: 0010:[] [] dump_trace+0x35b/0x3d2 RSP: 0000:ffff81003fb9d848 EFLAGS: 00010006 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff805b3520 RDI: 0000000000000000 RBP: ffffffff827ffff9 R08: ffffffff80aad000 R09: 0000000000000005 R10: ffffffff80aae000 R11: ffffffff8037961b R12: ffff81003fb9d858 R13: 0000000000000000 R14: ffffffff80598460 R15: ffffffff80ab1fc0 FS: 0000000000000000(0000) GS:ffffffff806c4200(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: ffffffff82800000 CR3: 0000000000201000 CR4: 00000000000006e0 this crash happened because it did not sanitize the dwarf2 data it got, and got an unaligned stack pointer - which happily walked past the process stack (and eventually reached the end of kernel memory and pagefaulted there) due to this naive iteration condition: HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0); note that i386 is alot more conservative when it comes to trusting stack pointers: static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) { return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3; } but the x86_64 code did not take this bit of i386 code. The fix is to align the stack pointer. Signed-off-by: Ingo Molnar Cc: Andi Kleen Cc: Jan Beulich Cc: Thomas Gleixner Cc: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 7819022a..a153d0a 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -290,6 +290,12 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s if (tsk && tsk != current) stack = (unsigned long *)tsk->thread.rsp; } + /* + * Align the stack pointer on word boundary, later loops + * rely on that (and corruption / debug info bugs can cause + * unaligned values here): + */ + stack = (unsigned long *)((unsigned long)stack & ~(sizeof(long)-1)); /* * Print function call entries within a stack. 'cond' is the -- cgit v0.10.2 From dc1829a4c378d793fb3b95d56135d89a0d7ff72a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 17 Nov 2006 14:26:18 +0100 Subject: [PATCH] i386/x86_64: ACPI cpu_idle_wait() fix The scheduler on Andreas Friedrich's hyperthreading system stopped working properly: the scheduler would never move tasks to another CPU! The lask known working kernel was 2.6.8. After a couple of attempts to corner the bug, the following smoking gun was found: BIOS reported wrong ACPI idfor the processor CPU#1: set_cpus_allowed(), swapper:1, 3 -> 2 [] show_trace_log_lvl+0x34/0x4a [] show_trace+0x2c/0x2e [] dump_stack+0x2b/0x2d [] set_cpus_allowed+0x52/0xec [] cpu_idle_wait+0x2e/0x100 [] acpi_processor_power_exit+0x45/0x58 [] acpi_processor_remove+0x46/0xea [] acpi_start_single_object+0x47/0x54 [] acpi_bus_register_driver+0xa4/0xd3 [] acpi_processor_init+0x57/0x77 [] init+0x146/0x2fd [] kernel_thread_helper+0x7/0x10 a quick look at cpu_idle_wait() shows how broken that code is on i386: it changes the init task's affinity map but never restores it ... and because all userspace tasks get forked by init, they all inherited that single-CPU affinity mask. x86_64 cloned this bug too. Signed-off-by: Ingo Molnar Cc: Andreas Friedrich Cc: Wolfgang Erig Cc: Andrew Morton Cc: Adrian Bunk Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 1e1fa3e..dd53c58 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -205,7 +205,7 @@ void cpu_idle(void) void cpu_idle_wait(void) { unsigned int cpu, this_cpu = get_cpu(); - cpumask_t map; + cpumask_t map, tmp = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); put_cpu(); @@ -227,6 +227,8 @@ void cpu_idle_wait(void) } cpus_and(map, map, cpu_online_map); } while (!cpus_empty(map)); + + set_cpus_allowed(current, tmp); } EXPORT_SYMBOL_GPL(cpu_idle_wait); diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index f622605..7451a4c 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -144,7 +144,7 @@ static void poll_idle (void) void cpu_idle_wait(void) { unsigned int cpu, this_cpu = get_cpu(); - cpumask_t map; + cpumask_t map, tmp = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); put_cpu(); @@ -167,6 +167,8 @@ void cpu_idle_wait(void) } cpus_and(map, map, cpu_online_map); } while (!cpus_empty(map)); + + set_cpus_allowed(current, tmp); } EXPORT_SYMBOL_GPL(cpu_idle_wait); -- cgit v0.10.2 From 1ff5683043196b9ad628a5de6bf8eeca52ee8bfd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 17 Nov 2006 19:57:22 +0100 Subject: [PATCH] lockdep: fix static keys in module-allocated percpu areas lockdep got confused by certain locks in modules: INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. Call Trace: [] dump_trace+0xaa/0x3f2 [] show_trace+0x3a/0x60 [] dump_stack+0x15/0x17 [] __lock_acquire+0x724/0x9bb [] lock_acquire+0x4d/0x67 [] rt_spin_lock+0x3d/0x41 [] :ip_conntrack:__ip_ct_refresh_acct+0x131/0x174 [] :ip_conntrack:udp_packet+0xbf/0xcf [] :ip_conntrack:ip_conntrack_in+0x394/0x4a7 [] nf_iterate+0x41/0x7f [] nf_hook_slow+0x64/0xd5 [] ip_rcv+0x24e/0x506 [...] Steven Rostedt found the bug: static_obj() check did not take PERCPU_ENOUGH_ROOM into account, so in-module DEFINE_PER_CPU-area locks were triggering this message. Signed-off-by: Ingo Molnar Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds diff --git a/kernel/lockdep.c b/kernel/lockdep.c index b739be2..c9fefdb 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -1081,7 +1081,8 @@ static int static_obj(void *obj) */ for_each_possible_cpu(i) { start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); - end = (unsigned long) &__per_cpu_end + per_cpu_offset(i); + end = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM + + per_cpu_offset(i); if ((addr >= start) && (addr < end)) return 1; -- cgit v0.10.2 From 808dbbb6bb61173bf52946a28f99089d2efa4c55 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 17 Nov 2006 11:14:56 -0800 Subject: x86: be more careful when walking back the frame pointer chain When showing the stack backtrace, make sure that we never accept not only an unchanging frame pointer, but also a frame pointer that moves back down the stack frame. It must always grow up (toward older stack frames). I doubt this has triggered, but a subtly corrupt stack with extremely unlucky contents could cause us to loop forever on a bogus endless frame pointer chain. This review was triggered by much worse problems happening in some of the other stack unwinding code. Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 00489b7..fe9c5e8 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -129,15 +129,19 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { + unsigned long new_ebp; addr = *(unsigned long *)(ebp + 4); ops->address(data, addr); /* * break out of recursive entries (such as - * end_of_stack_stop_unwind_function): + * end_of_stack_stop_unwind_function). Also, + * we can never allow a frame pointer to + * move downwards! */ - if (ebp == *(unsigned long *)ebp) + new_ebp = *(unsigned long *)ebp; + if (new_ebp <= ebp) break; - ebp = *(unsigned long *)ebp; + ebp = new_ebp; } #else while (valid_stack_ptr(tinfo, stack)) { -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index a52ecad..ea09d0c 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 81abdfa..2cd8ff8 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 0000000..8cd12ab --- /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 v0.10.2 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 diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 8cd12ab..da3fc63 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 v0.10.2 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 diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index da3fc63..1aad913 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 v0.10.2 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 diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 1aad913..22aab87 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 v0.10.2 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 diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 22aab87..ec39093 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 v0.10.2 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 diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c84286c..068fe4f 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 v0.10.2 From ba9b1cd713b33720ca0f035dab2fdbc10bf7328d Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Sat, 18 Nov 2006 03:58:58 +0100 Subject: [PATCH] Update my CREDITS entry I moved from Sweden to Finland 2.5 years ago, thought it might be time to update my CREDITS entry (simply removing the address completely seemed the sanest option). Signed-off-by: David Weinehall Signed-off-by: Linus Torvalds diff --git a/CREDITS b/CREDITS index 606d407..ccd4f9f 100644 --- a/CREDITS +++ b/CREDITS @@ -3511,14 +3511,12 @@ D: The Linux Support Team Erlangen N: David Weinehall E: tao@acc.umu.se +P: 1024D/DC47CA16 7ACE 0FB0 7A74 F994 9B36 E1D1 D14E 8526 DC47 CA16 W: http://www.acc.umu.se/~tao/ -W: http://www.acc.umu.se/~mcalinux/ +D: v2.0 kernel maintainer D: Fixes for the NE/2-driver D: Miscellaneous MCA-support D: Cleanup of the Config-files -S: Axtorpsvagen 40:20 -S: S-903 37 UMEA -S: Sweden N: Matt Welsh E: mdw@metalab.unc.edu -- cgit v0.10.2 From 610a5b742e9df4e59047f22d13d8bd83cafce388 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 17 Nov 2006 11:51:41 +1100 Subject: [CRYPTO] api: Remove one too many semicolon This patch has removed one too many semicolon in crypto.h. Signed-off-by: Yoichi Yuasa Signed-off-by: Herbert Xu diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 8f2ffa4..6485e97 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -245,7 +245,7 @@ int crypto_alg_available(const char *name, u32 flags) __deprecated_for_modules; int crypto_has_alg(const char *name, u32 type, u32 mask); #else -static int crypto_alg_available(const char *name, u32 flags); +static int crypto_alg_available(const char *name, u32 flags) __deprecated_for_modules; static inline int crypto_alg_available(const char *name, u32 flags) { -- cgit v0.10.2 From eb370f0bd409f8bcdc88583ae04f94453e19d882 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Fri, 17 Nov 2006 00:14:35 +0100 Subject: [ARM] 3933/1: Source drivers/ata/Kconfig ARM doesn't source drivers/Kconfig like most architectures do, so the newly added drivers/ata is currently not made available on ARM. SATA is used on some ARM machines, like the Thecus N2100, so we need to source drivers/ata/Kconfig. Signed-off-by: Martin Michlmayr Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index adb05de..ce00c57 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -879,6 +879,8 @@ endif source "drivers/scsi/Kconfig" +source "drivers/ata/Kconfig" + source "drivers/md/Kconfig" source "drivers/message/fusion/Kconfig" -- cgit v0.10.2 From 8de35efb6afa75f25415d54e21221eea759db261 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Nov 2006 15:59:10 +0000 Subject: [ARM] ebsa110: fix warnings generated by asm/arch/io.h Remove two warnings: drivers/serial/8250_early.c:136: warning: unused variable 'mapsize' include/linux/io.h:47: warning: passing argument 1 of '__readb' discards qualifiers from pointer target type Signed-off-by: Russell King diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c index c648bfb..db38afb 100644 --- a/arch/arm/mach-ebsa110/io.c +++ b/arch/arm/mach-ebsa110/io.c @@ -28,7 +28,7 @@ #include #include -static void __iomem *__isamem_convert_addr(void __iomem *addr) +static void __iomem *__isamem_convert_addr(const volatile void __iomem *addr) { u32 ret, a = (u32 __force) addr; @@ -63,7 +63,7 @@ static void __iomem *__isamem_convert_addr(void __iomem *addr) /* * read[bwl] and write[bwl] */ -u8 __readb(void __iomem *addr) +u8 __readb(const volatile void __iomem *addr) { void __iomem *a = __isamem_convert_addr(addr); u32 ret; @@ -75,7 +75,7 @@ u8 __readb(void __iomem *addr) return ret; } -u16 __readw(void __iomem *addr) +u16 __readw(const volatile void __iomem *addr) { void __iomem *a = __isamem_convert_addr(addr); @@ -85,7 +85,7 @@ u16 __readw(void __iomem *addr) return __raw_readw(a); } -u32 __readl(void __iomem *addr) +u32 __readl(const volatile void __iomem *addr) { void __iomem *a = __isamem_convert_addr(addr); u32 ret; diff --git a/include/asm-arm/arch-ebsa110/io.h b/include/asm-arm/arch-ebsa110/io.h index ae04844..722c5e0 100644 --- a/include/asm-arm/arch-ebsa110/io.h +++ b/include/asm-arm/arch-ebsa110/io.h @@ -27,9 +27,9 @@ void __outw(u16 val, unsigned int port); u32 __inl(unsigned int port); void __outl(u32 val, unsigned int port); -u8 __readb(void __iomem *addr); -u16 __readw(void __iomem *addr); -u32 __readl(void __iomem *addr); +u8 __readb(const volatile void __iomem *addr); +u16 __readw(const volatile void __iomem *addr); +u32 __readl(const volatile void __iomem *addr); void __writeb(u8 val, void __iomem *addr); void __writew(u16 val, void __iomem *addr); @@ -64,8 +64,14 @@ void __writel(u32 val, void __iomem *addr); #define writew(v,b) __writew(v,b) #define writel(v,b) __writel(v,b) -#define __arch_ioremap(cookie,sz,c) ((void __iomem *)(cookie)) -#define __arch_iounmap(cookie) do { } while (0) +static inline void __iomem *__arch_ioremap(unsigned long cookie, size_t size, + unsigned int flags) +{ + return (void __iomem *)cookie; +} + +#define __arch_ioremap __arch_ioremap +#define __arch_iounmap(cookie) do { } while (0) extern void insb(unsigned int port, void *buf, int sz); extern void insw(unsigned int port, void *buf, int sz); -- cgit v0.10.2 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 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0f70192..a20d84d 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 v0.10.2 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 diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index 1ce01fb..05fffb9 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 v0.10.2 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 diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 32aab0d..714bae7 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 v0.10.2 From 8243229f0940ab4e9f501879d3ffb7476b02ee6a Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Sat, 18 Nov 2006 22:19:40 -0800 Subject: [PATCH] x86_64: fix memory hotplug build with NUMA=n This is to fix compile error of x86-64 memory hotplug without any NUMA option. CC arch/x86_64/mm/init.o arch/x86_64/mm/init.c:501: error: redefinition of 'memory_add_physaddr_to_nid' include/linux/memory_hotplug.h:71: error: previous definition of 'memory_add_phys addr_to_nid' was here arch/x86_64/mm/init.c:509: error: redefinition of 'memory_add_physaddr_to_nid' arch/x86_64/mm/init.c:501: error: previous definition of 'memory_add_physaddr_to_ nid' was here I confirmed compile completion with !NUMA, (NUMA & !ACPI_NUMA), or (NUMA & ACPI_NUMA). Signed-off-by: Yasunori Goto Acked-by: Andi Kleen Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index f1f977a..4c0c00e 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -496,7 +496,7 @@ int remove_memory(u64 start, u64 size) } EXPORT_SYMBOL_GPL(remove_memory); -#ifndef CONFIG_ACPI_NUMA +#if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA) int memory_add_physaddr_to_nid(u64 start) { return 0; @@ -504,13 +504,6 @@ int memory_add_physaddr_to_nid(u64 start) EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); #endif -#ifndef CONFIG_ACPI_NUMA -int memory_add_physaddr_to_nid(u64 start) -{ - return 0; -} -#endif - #endif /* CONFIG_MEMORY_HOTPLUG */ #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE -- cgit v0.10.2 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 diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c index da06f13..7ebce2e 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 v0.10.2 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 diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index eb57a98..cfd2718 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 v0.10.2 From ace5f1d425beaa272b6e91cecc87b2c075d7feb2 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 20 Nov 2006 15:46:22 +1000 Subject: [PATCH] m68knommu: fix up for the irq_handler_t changes Switch to using irq_handler_t for interrupt function handler pointers. Change name of m68knommu's irq_hanlder_t data structure so it doesn't clash with the common type (include/linux/interrupt.h). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index bde9811..7b21959 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -62,7 +62,7 @@ int (*mach_kbdrate) (struct kbd_repeat *); void (*mach_kbd_leds) (unsigned int); /* machine dependent irq functions */ void (*mach_init_IRQ) (void); -irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); +irq_handler_t mach_default_handler; int (*mach_get_irq_list) (struct seq_file *, void *); void (*mach_process_int) (int irq, struct pt_regs *fp); void (*mach_trap_init) (void); diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c index c5667bd..9226264 100644 --- a/arch/m68knommu/kernel/time.c +++ b/arch/m68knommu/kernel/time.c @@ -54,7 +54,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) update_process_times(user_mode(regs)); #endif if (current->pid) - profile_tick(CPU_PROFILING, regs); + profile_tick(CPU_PROFILING); /* * If we have an externally synchronized Linux clock, then update diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c index b4b5509..a57239e 100644 --- a/arch/m68knommu/platform/5307/ints.c +++ b/arch/m68knommu/platform/5307/ints.c @@ -33,7 +33,7 @@ /* * This table stores the address info for each vector handler. */ -irq_handler_t irq_list[SYS_IRQS]; +struct irq_entry irq_list[SYS_IRQS]; #define NUM_IRQ_NODES 16 static irq_node_t nodes[NUM_IRQ_NODES]; @@ -44,7 +44,7 @@ volatile unsigned int num_spurious; unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; -static irqreturn_t default_irq_handler(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t default_irq_handler(int irq, void *ptr) { #if 1 printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n", @@ -70,7 +70,7 @@ void __init init_IRQ(void) for (i = 0; i < SYS_IRQS; i++) { if (mach_default_handler) - irq_list[i].handler = (*mach_default_handler)[i]; + irq_list[i].handler = mach_default_handler; else irq_list[i].handler = default_irq_handler; irq_list[i].flags = IRQ_FLG_STD; @@ -100,7 +100,7 @@ irq_node_t *new_irq_node(void) int request_irq( unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), + irq_handler_t handler, unsigned long flags, const char *devname, void *dev_id) @@ -157,7 +157,7 @@ void free_irq(unsigned int irq, void *dev_id) } if (mach_default_handler) - irq_list[irq].handler = (*mach_default_handler)[irq]; + irq_list[irq].handler = mach_default_handler; else irq_list[irq].handler = default_irq_handler; irq_list[irq].flags = IRQ_FLG_STD; @@ -168,8 +168,7 @@ void free_irq(unsigned int irq, void *dev_id) EXPORT_SYMBOL(free_irq); -int sys_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), +int sys_request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *devname, void *dev_id) { if (irq > IRQ7) { @@ -211,7 +210,7 @@ void sys_free_irq(unsigned int irq, void *dev_id) printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", __FUNCTION__, irq, irq_list[irq].devname); - irq_list[irq].handler = (*mach_default_handler)[irq]; + irq_list[irq].handler = mach_default_handler; irq_list[irq].flags = 0; irq_list[irq].dev_id = NULL; irq_list[irq].devname = NULL; @@ -241,7 +240,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) if (vec >= VEC_INT1 && vec <= VEC_INT7) { vec -= VEC_SPUR; kstat_cpu(0).irqs[vec]++; - irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); + irq_list[vec].handler(vec, irq_list[vec].dev_id); } else { if (mach_process_int) mach_process_int(vec, fp); diff --git a/include/asm-m68knommu/irq_regs.h b/include/asm-m68knommu/irq_regs.h new file mode 100644 index 0000000..3dd9c0b --- /dev/null +++ b/include/asm-m68knommu/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-m68knommu/irqnode.h b/include/asm-m68knommu/irqnode.h index a2503df..6132a98 100644 --- a/include/asm-m68knommu/irqnode.h +++ b/include/asm-m68knommu/irqnode.h @@ -8,7 +8,7 @@ * interrupt source (if it supports chaining). */ typedef struct irq_node { - irqreturn_t (*handler)(int, void *, struct pt_regs *); + irq_handler_t handler; unsigned long flags; void *dev_id; const char *devname; @@ -18,12 +18,12 @@ typedef struct irq_node { /* * This structure has only 4 elements for speed reasons */ -typedef struct irq_handler { - irqreturn_t (*handler)(int, void *, struct pt_regs *); +struct irq_entry { + irq_handler_t handler; unsigned long flags; void *dev_id; const char *devname; -} irq_handler_t; +}; /* count of spurious interrupts */ extern volatile unsigned int num_spurious; diff --git a/include/asm-m68knommu/machdep.h b/include/asm-m68knommu/machdep.h index 27c90af..6ce28f8 100644 --- a/include/asm-m68knommu/machdep.h +++ b/include/asm-m68knommu/machdep.h @@ -18,7 +18,7 @@ extern int (*mach_kbdrate) (struct kbd_repeat *); extern void (*mach_kbd_leds) (unsigned int); /* machine dependent irq functions */ extern void (*mach_init_IRQ) (void); -extern irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); +extern irq_handler_t mach_default_handler; extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void (*mach_free_irq) (unsigned int irq, void *dev_id); -- cgit v0.10.2 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 diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 86e69b7..dd0c262 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 9d87316..e60d6f2 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 ff40ea1..5eb5d24 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig index 5ca471a..90c1454 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 v0.10.2 From d2133717d5f994cca970b5aeb9d4664feeb92ff4 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Tue, 21 Nov 2006 18:55:16 +1100 Subject: [XFS] Fix uninitialized br_state and br_startoff in xfs_bmap_add_extent_delay_real() SGI-PV: 957008 SGI-Modid: xfs-linux-melb:xfs-kern:27457a Signed-off-by: Lachlan McIlroy Signed-off-by: Shailendra Tripathi Signed-off-by: Tim Shimmin diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 5b050c0..498ad50d 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -1171,6 +1171,8 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_blockcount(ep, temp); r[0] = *new; + r[1].br_state = PREV.br_state; + r[1].br_startblock = 0; r[1].br_startoff = new_endoff; temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; r[1].br_blockcount = temp2; -- cgit v0.10.2 From e5ffd2bb62c3f2c0d9f34e0d16fab6e2c8b056fb Mon Sep 17 00:00:00 2001 From: David Chinner Date: Tue, 21 Nov 2006 18:55:33 +1100 Subject: [XFS] Stale the correct inode when freeing clusters. SGI-PV: 958376 SGI-Modid: xfs-linux-melb:xfs-kern:27503a Signed-off-by: David Chinner Signed-off-by: Tim Shimmin diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index d72c80d..44dfac5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2258,7 +2258,7 @@ xfs_ifree_cluster( AIL_LOCK(mp,s); iip->ili_flush_lsn = iip->ili_item.li_lsn; AIL_UNLOCK(mp, s); - xfs_iflags_set(ip, XFS_ISTALE); + xfs_iflags_set(iip->ili_inode, XFS_ISTALE); pre_flushed++; } lip = lip->li_bio_list; -- cgit v0.10.2 From 9a14f2964b459c18198ee59ff7212321def82df7 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 20 Nov 2006 11:29:09 -0500 Subject: [PATCH] x86_64: Align data segment to PAGE_SIZE boundary o Explicitly align data segment to PAGE_SIZE boundary otherwise depending on config options and tool chain it might be placed on a non PAGE_SIZE aligned boundary and vmlinux loaders like kexec fail when they encounter a PT_LOAD type segment which is not aligned to PAGE_SIZE boundary. Signed-off-by: Vivek Goyal Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index edb24aa..d9534e7 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -60,6 +60,7 @@ SECTIONS } #endif + . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { *(.data) -- cgit v0.10.2 From 3af9815328bba76e8d11d71d6dbbd6f38beafe58 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 20 Nov 2006 11:29:09 -0500 Subject: [PATCH] x86_64: Align data segment to PAGE_SIZE boundary o Explicitly align data segment to PAGE_SIZE boundary otherwise depending on config options and tool chain it might be placed on a non PAGE_SIZE aligned boundary and vmlinux loaders like kexec fail when they encounter a PT_LOAD type segment which is not aligned to PAGE_SIZE boundary. Signed-off-by: Vivek Goyal Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index edb24aa..d9534e7 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -60,6 +60,7 @@ SECTIONS } #endif + . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { *(.data) -- cgit v0.10.2 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 diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 2cc71b6..491779a 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 v0.10.2 From ea73ee23c43d6eb75f88c4fc9e1230b44673c0d2 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 6 Nov 2006 09:45:44 -0800 Subject: [IPV6] ROUTE: Try to use router which is not known unreachable. Only routers in "FAILED" state should be considered unreachable. Otherwise, we do not try to use speicific routes unless all least specific routers are considered unreachable. Signed-off-by: YOSHIFUJI Hideaki diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c953466..5132821 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -330,6 +330,8 @@ static int inline rt6_check_neigh(struct rt6_info *rt) read_lock_bh(&neigh->lock); if (neigh->nud_state & NUD_VALID) m = 2; + else if (!(neigh->nud_state & NUD_FAILED)) + m = 1; read_unlock_bh(&neigh->lock); } return m; -- cgit v0.10.2 From 557e92efd44878beccd08d5dd54ed343be0e5819 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 6 Nov 2006 09:45:45 -0800 Subject: [IPV6] ROUTE: Prefer reachable nexthop only if the caller requests. Signed-off-by: YOSHIFUJI Hideaki diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5132821..a972a66 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -349,9 +349,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; #endif n = rt6_check_neigh(rt); - if (n > 1) - m |= 16; - else if (!n && strict & RT6_LOOKUP_F_REACHABLE) + if (!n && (strict & RT6_LOOKUP_F_REACHABLE)) return -1; return m; } -- cgit v0.10.2 From ea659e0775281e1c02556e939bf749bb4f55e50c Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 6 Nov 2006 09:45:45 -0800 Subject: [IPV6] ROUTE: Do not enable router reachability probing in router mode. RFC4191 explicitly states that the procedures are applicable to hosts only. We should not have changed behavior of routers. Signed-off-by: YOSHIFUJI Hideaki diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a972a66..b39ae99 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -380,10 +380,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, continue; if (m > mpri) { - rt6_probe(match); + if (strict & RT6_LOOKUP_F_REACHABLE) + rt6_probe(match); match = rt; mpri = m; - } else { + } else if (strict & RT6_LOOKUP_F_REACHABLE) { rt6_probe(rt); } } @@ -636,7 +637,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, int strict = 0; int attempts = 3; int err; - int reachable = RT6_LOOKUP_F_REACHABLE; + int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; strict |= flags & RT6_LOOKUP_F_IFACE; @@ -733,7 +734,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, int strict = 0; int attempts = 3; int err; - int reachable = RT6_LOOKUP_F_REACHABLE; + int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; strict |= flags & RT6_LOOKUP_F_IFACE; -- cgit v0.10.2 From b3fdd9f115c776d381b30b296849f8e4046bcdaa Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 6 Nov 2006 10:06:22 -0800 Subject: [IPV6] IP6TUNNEL: Delete all tunnel device when unloading module. Signed-off-by: Yasuyuki Kozakai Signed-off-by: YOSHIFUJI Hideaki diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 84d7ebd..c8d4160 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1149,6 +1149,20 @@ fail: return err; } +static void __exit ip6ip6_destroy_tunnels(void) +{ + int h; + struct ip6_tnl *t; + + for (h = 0; h < HASH_SIZE; h++) { + while ((t = tnls_r_l[h]) != NULL) + unregister_netdevice(t->dev); + } + + t = tnls_wc[0]; + unregister_netdevice(t->dev); +} + /** * ip6_tunnel_cleanup - free resources and unregister protocol **/ @@ -1158,7 +1172,9 @@ static void __exit ip6_tunnel_cleanup(void) if (xfrm6_tunnel_deregister(&ip6ip6_handler)) printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); - unregister_netdev(ip6ip6_fb_tnl_dev); + rtnl_lock(); + ip6ip6_destroy_tunnels(); + rtnl_unlock(); } module_init(ip6_tunnel_init); -- cgit v0.10.2 From 53ab61c6d8f391bda04dbc1e95bac348fe81103b Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 6 Nov 2006 10:06:23 -0800 Subject: [IPV6] IP6TUNNEL: Add missing nf_reset() on input path. Signed-off-by: Yasuyuki Kozakai Signed-off-by: YOSHIFUJI Hideaki diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index c8d4160..b9f4029 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -542,6 +542,7 @@ ip6ip6_rcv(struct sk_buff *skb) skb->dev = t->dev; dst_release(skb->dst); skb->dst = NULL; + nf_reset(skb); if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); ip6ip6_ecn_decapsulate(ipv6h, skb); -- cgit v0.10.2 From e52726dece1d2e3976c0caf2f4e9e1c452d31282 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 18 Nov 2006 22:14:05 +0100 Subject: [Bluetooth] Attach low-level connections to the Bluetooth bus To receive uvents for the low-level ACL and SCO links, they must be assigned to a subsystem. It is enough to attach them to the already established Bluetooth bus. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 954eb74..3eeeb7a 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -259,7 +259,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn) BT_DBG("conn %p", conn); - conn->dev.parent = &hdev->dev; + conn->dev.bus = &bt_bus; + conn->dev.parent = &hdev->dev; + conn->dev.release = bt_release; snprintf(conn->dev.bus_id, BUS_ID_SIZE, -- cgit v0.10.2 From 6bd57416127e92d35e6798925502c84e14a3a966 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 18 Nov 2006 22:14:22 +0100 Subject: [Bluetooth] Handling pending connect attempts after inquiry After an inquiry completed or got canceled the Bluetooth core should check for any pending connect attempts. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 65f0948..bb94e6d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -57,6 +57,7 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) { __u8 status; + struct hci_conn *pend; BT_DBG("%s ocf 0x%x", hdev->name, ocf); @@ -71,6 +72,15 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb clear_bit(HCI_INQUIRY, &hdev->flags); hci_req_complete(hdev, status); } + + hci_dev_lock(hdev); + + pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); + if (pend) + hci_acl_connect(pend); + + hci_dev_unlock(hdev); + break; default: @@ -565,11 +575,20 @@ static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status) static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); + struct hci_conn *pend; BT_DBG("%s status %d", hdev->name, status); clear_bit(HCI_INQUIRY, &hdev->flags); hci_req_complete(hdev, status); + + hci_dev_lock(hdev); + + pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); + if (pend) + hci_acl_connect(pend); + + hci_dev_unlock(hdev); } /* Inquiry Result */ -- cgit v0.10.2 From ff2d367ac33b9278c9516ac1888207dac11d10b0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 18 Nov 2006 22:14:42 +0100 Subject: [Bluetooth] Check if RFCOMM session is still attached to the TTY If the RFCOMM session is no longer attached to the TTY device, then it makes no sense to go through with changing the termios settings. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index b8e3a5f..1fb5d42 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -765,7 +765,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) BT_DBG("tty %p termios %p", tty, old); - if (!dev) + if (!dev || !dev->dlc || !dev->dlc->session) return; /* Handle turning off CRTSCTS */ -- cgit v0.10.2 From 820ae1b865caa05e0614004d0183ca70de2b8665 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 18 Nov 2006 22:15:00 +0100 Subject: [Bluetooth] Always include MTU in L2CAP config responses When sending a positive config response it shall include the actual MTU to be used on this channel. This differs from the Bluetooth 1.1 specification where it was enough to acknowledge the config request. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2b3dcb8..c09d4a2 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1353,12 +1353,12 @@ static inline int l2cap_conf_output(struct sock *sk, void **ptr) /* Configure output options and let the other side know * which ones we don't like. */ - if (pi->conf_mtu < pi->omtu) { - l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu); + if (pi->conf_mtu < pi->omtu) result = L2CAP_CONF_UNACCEPT; - } else { + else pi->omtu = pi->conf_mtu; - } + + l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu); BT_DBG("sk %p result %d", sk, result); return result; -- cgit v0.10.2 From 354f60a9952d0af59e684b91cc6e06b95fbbf5ef Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 18 Nov 2006 22:15:20 +0100 Subject: [Bluetooth] Ignore L2CAP config requests on disconnect Any L2CAP connection in disconnecting state shall not response to any further config requests from the remote side. So in case such a request is received, ignore it. Signed-off-by: Ville Tervo Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c09d4a2..bbf78e6 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1533,6 +1533,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) return -ENOENT; + if (sk->sk_state == BT_DISCONN) + goto unlock; + l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req)); if (flags & 0x0001) { -- cgit v0.10.2 From fb47ddb2db9c18664bd7b06c201a2398885b64fc Mon Sep 17 00:00:00 2001 From: David L Stevens Date: Sun, 19 Nov 2006 10:38:39 -0800 Subject: [IGMP]: Fix IGMPV3_EXP() normalization bit shift value. The IGMPV3_EXP() macro doesn't correctly shift the normalization bit, so time-out values are longer than they should be. Thanks to Dirk Ooms for finding the problem in IGMPv3 - MLDv2 had a similar problem that was already fixed a year ago. :-( Signed-off-by: David L Stevens Signed-off-by: David S. Miller diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 03f43e2..21dd569 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -191,7 +191,7 @@ struct ip_mc_list #define IGMPV3_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) #define IGMPV3_EXP(thresh, nbmant, nbexp, value) \ ((value) < (thresh) ? (value) : \ - ((IGMPV3_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \ + ((IGMPV3_MASK(value, nbmant) | (1<<(nbmant))) << \ (IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp)))) #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value) -- cgit v0.10.2 From 334f3d45d3e0c925eb15003560cdd6f5383c88d0 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 19 Nov 2006 14:53:07 -0800 Subject: [XFRM]: Sub-policies broke policy events XFRM policy events are broken when sub-policy feature is turned on. A simple test to verify this: run ip xfrm mon on one window and add then delete a policy on another window .. Signed-off-by: Jamal Hadi Salim Acked-by: Masahide NAKAMURA Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b43e764..2dae1c1 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2060,6 +2060,9 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * len += RTA_SPACE(headlen); headlen = sizeof(*id); } +#ifdef CONFIG_XFRM_SUB_POLICY + len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); +#endif len += NLMSG_SPACE(headlen); skb = alloc_skb(len, GFP_ATOMIC); -- cgit v0.10.2 From 785fd8b8a597519127c6d9e16e81f48af2ad391e Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 19 Nov 2006 14:55:30 -0800 Subject: [XFRM]: nlmsg length not computed correctly in the presence of subpolicies I actually dont have a test case for these; i just found them by inspection. Refer to patch "[XFRM]: Sub-policies broke policy events" for more info Signed-off-by: Jamal Hadi Salim Acked-by: Masahide NAKAMURA Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2dae1c1..c4cde57 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1927,6 +1927,9 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); +#ifdef CONFIG_XFRM_SUB_POLICY + len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); +#endif skb = alloc_skb(len, GFP_ATOMIC); if (skb == NULL) return -ENOMEM; @@ -2034,6 +2037,9 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); +#ifdef CONFIG_XFRM_SUB_POLICY + len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); +#endif skb = alloc_skb(len, GFP_ATOMIC); if (skb == NULL) return -ENOMEM; @@ -2109,10 +2115,12 @@ static int xfrm_notify_policy_flush(struct km_event *c) struct nlmsghdr *nlh; struct sk_buff *skb; unsigned char *b; + int len = 0; #ifdef CONFIG_XFRM_SUB_POLICY struct xfrm_userpolicy_type upt; + len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); #endif - int len = NLMSG_LENGTH(0); + len += NLMSG_LENGTH(0); skb = alloc_skb(len, GFP_ATOMIC); if (skb == NULL) -- cgit v0.10.2 From 4498c80d9c1ebdf42837be6a52ead35a2aa2b819 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 21 Nov 2006 16:17:41 -0800 Subject: [BLUETOOTH]: Fix unaligned access in hci_send_to_sock. The "u16 *" derefs of skb->data need to be wrapped inside of a get_unaligned(). Thanks to Gustavo Zacarias for the bug report. Signed-off-by: David S. Miller diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f26a9eb..711a085 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -120,10 +120,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) if (!hci_test_bit(evt, &flt->event_mask)) continue; - if (flt->opcode && ((evt == HCI_EV_CMD_COMPLETE && - flt->opcode != *(__u16 *)(skb->data + 3)) || - (evt == HCI_EV_CMD_STATUS && - flt->opcode != *(__u16 *)(skb->data + 4)))) + if (flt->opcode && + ((evt == HCI_EV_CMD_COMPLETE && + flt->opcode != + get_unaligned((__u16 *)(skb->data + 3))) || + (evt == HCI_EV_CMD_STATUS && + flt->opcode != + get_unaligned((__u16 *)(skb->data + 4))))) continue; } -- cgit v0.10.2 From 6c12c18dfb0ccae21816de3e0c323b5250450d82 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 21 Nov 2006 10:31:08 -0600 Subject: [POWERPC] Revert "[POWERPC] Enable generic rtc hook for the MPC8349 mITX" This reverts commit a8ed4f7ec3aa472134d7de6176f823b2667e450b. As advised by David Brownell: http://marc.theaimsgroup.com/?l=linux-kernel&m=116387226902131&w=2 Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 5446bab..e2bcaaf 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -108,10 +108,6 @@ static int __init mpc834x_itx_probe(void) return 1; } -#ifdef CONFIG_RTC_CLASS -late_initcall(rtc_class_hookup); -#endif - define_machine(mpc834x_itx) { .name = "MPC834x ITX", .probe = mpc834x_itx_probe, -- cgit v0.10.2 From df9c23095fc8652798c41dd860676d3dafb2f1dc Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 21 Nov 2006 10:31:14 -0600 Subject: [POWERPC] Revert "[POWERPC] Add powerpc get/set_rtc_time interface to new generic rtc class" This reverts commit 7a69af63e788a324d162201a0b23df41bcf158dd. As advised by David Brownell: http://marc.theaimsgroup.com/?l=linux-kernel&m=116387226902131&w=2 Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a1b5e4b..46a24de 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -1014,48 +1014,6 @@ void __init time_init(void) set_dec(tb_ticks_per_jiffy); } -#ifdef CONFIG_RTC_CLASS -static int set_rtc_class_time(struct rtc_time *tm) -{ - int err; - struct class_device *class_dev = - rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); - - if (class_dev == NULL) - return -ENODEV; - - err = rtc_set_time(class_dev, tm); - - rtc_class_close(class_dev); - - return 0; -} - -static void get_rtc_class_time(struct rtc_time *tm) -{ - int err; - struct class_device *class_dev = - rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); - - if (class_dev == NULL) - return; - - err = rtc_read_time(class_dev, tm); - - rtc_class_close(class_dev); - - return; -} - -int __init rtc_class_hookup(void) -{ - ppc_md.get_rtc_time = get_rtc_class_time; - ppc_md.set_rtc_time = set_rtc_class_time; - - return 0; -} -#endif /* CONFIG_RTC_CLASS */ - #define FEBRUARY 2 #define STARTOFTIME 1970 diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index a782850..4cff977 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -39,10 +39,6 @@ extern void generic_calibrate_decr(void); extern void wakeup_decrementer(void); extern void snapshot_timebase(void); -#ifdef CONFIG_RTC_CLASS -extern int __init rtc_class_hookup(void); -#endif - /* Some sane defaults: 125 MHz timebase, 1GHz processor */ extern unsigned long ppc_proc_freq; #define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8) -- cgit v0.10.2 From 700f9672c9a61c12334651a94d17ec04620e1976 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 21 Nov 2006 17:33:01 -0800 Subject: [IRDA]: Lockdep fix. On Sat, 2006-11-18 at 16:12 +0300, Andrey Borzenkov wrote: > ============================================= > [ INFO: possible recursive locking detected ] > 2.6.19-rc5-2avb #2 > - --------------------------------------------- > pppd/26425 is trying to acquire lock: > (&hashbin->hb_spinlock){....}, at: [] irlmp_slsap_inuse+0x5a/0x170 > [irda] > > but task is already holding lock: > (&hashbin->hb_spinlock){....}, at: [] irlmp_slsap_inuse+0x37/0x170 > [irda] > > other info that might help us debug this: > 1 lock held by pppd/26425: > #0: (&hashbin->hb_spinlock){....}, at: [] > irlmp_slsap_inuse+0x37/0x170 [irda] > > stack backtrace: > [] dump_trace+0x1cc/0x200 > [] show_trace_log_lvl+0x1a/0x30 > [] show_trace+0x12/0x20 > [] dump_stack+0x19/0x20 > [] __lock_acquire+0x8fa/0xc20 > [] lock_acquire+0x5d/0x80 > [] _spin_lock+0x2c/0x40 > [] irlmp_slsap_inuse+0x5a/0x170 [irda] > [] irlmp_open_lsap+0x62/0x180 [irda] > [] irttp_open_tsap+0x181/0x230 [irda] > [] ircomm_open_tsap+0x5d/0xa0 [ircomm] > [] ircomm_open+0xb8/0xd0 [ircomm] > [] ircomm_tty_open+0x4f7/0x570 [ircomm_tty] > [] tty_open+0x174/0x340 > [] chrdev_open+0x89/0x170 > [] __dentry_open+0xa6/0x1d0 > [] nameidata_to_filp+0x35/0x40 > [] do_filp_open+0x49/0x50 > [] do_sys_open+0x47/0xd0 > [] sys_open+0x1c/0x20 > [] sysenter_past_esp+0x56/0x8d > [] 0xb7f86410 > ======================= The comment at the nesting lock says: /* Careful for priority inversions here ! * irlmp->links is never taken while another IrDA * spinlock is held, so we are safe. Jean II */ So, under the assumption the author was right, it just needs a lockdep annotation. Signed-off-by: Peter Zijlstra Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 5073261..fede837 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -1678,7 +1678,8 @@ static int irlmp_slsap_inuse(__u8 slsap_sel) * every IrLAP connection and check every LSAP associated with each * the connection. */ - spin_lock_irqsave(&irlmp->links->hb_spinlock, flags); + spin_lock_irqsave_nested(&irlmp->links->hb_spinlock, flags, + SINGLE_DEPTH_NESTING); lap = (struct lap_cb *) hashbin_get_first(irlmp->links); while (lap != NULL) { IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;); -- cgit v0.10.2 From f2776ff047229c3e7cee2454e2704dd6f98fa32f Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 21 Nov 2006 17:41:56 -0800 Subject: [IPV6]: Fix address/interface handling in UDP and DCCP, according to the scoping architecture. TCP and RAW do not have this issue. Closes Bug #7432. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index eb0ff7a..fc4242c 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -277,7 +277,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, __u64 seq; sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport, - &hdr->saddr, dh->dccph_sport, skb->dev->ifindex); + &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); if (sk == NULL) { ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e0c3934..c83f23e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -242,14 +242,13 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, { struct ipv6_pinfo *np; struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; - struct net_device *dev = skb->dev; struct in6_addr *saddr = &hdr->saddr; struct in6_addr *daddr = &hdr->daddr; struct udphdr *uh = (struct udphdr*)(skb->data+offset); struct sock *sk; int err; - sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex); + sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb)); if (sk == NULL) return; @@ -348,7 +347,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh, read_lock(&udp_hash_lock); sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); - dif = skb->dev->ifindex; + dif = inet6_iif(skb); sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); if (!sk) { kfree_skb(skb); @@ -429,7 +428,7 @@ static int udpv6_rcv(struct sk_buff **pskb) * check socket cache ... must talk to Alan about his plans * for sock caches... i'll skip this for now. */ - sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, dev->ifindex); + sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb)); if (sk == NULL) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) -- cgit v0.10.2 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 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1dbdd6b..c20bb99 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 v0.10.2 From 8746ed3dae14e87e9f7ad8e44649b72e22b33274 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 21 Nov 2006 18:19:42 -0600 Subject: [POWERPC] Fix ucc_geth of_device discovery on mpc832x mpc832x, as in mpc8360, needs to explicitly find and create the platform device for ucc_geth in 2.6.19. This code will likely be readapted to Benh's new of_ methods for 2.6.20. Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 54dea9d4..a43ac71 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -136,6 +137,24 @@ static void __init mpc832x_sys_setup_arch(void) #endif } +static int __init mpc832x_declare_of_platform_devices(void) +{ + struct device_node *np; + + for (np = NULL; (np = of_find_compatible_node(np, "network", + "ucc_geth")) != NULL;) { + int ucc_num; + char bus_id[BUS_ID_SIZE]; + + ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1; + snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num); + of_platform_device_create(np, bus_id, NULL); + } + + return 0; +} +device_initcall(mpc832x_declare_of_platform_devices); + void __init mpc832x_sys_init_IRQ(void) { -- cgit v0.10.2 From 52bad64d95bd89e08c49ec5a071fa6dcbe5a1a9c Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 Nov 2006 14:54:01 +0000 Subject: WorkStruct: Separate delayable and non-delayable events. Separate delayable work items from non-delayable work items be splitting them into a separate structure (delayed_work), which incorporates a work_struct and the timer_list removed from work_struct. The work_struct struct is huge, and this limits it's usefulness. On a 64-bit architecture it's nearly 100 bytes in size. This reduces that by half for the non-delayable type of event. Signed-Off-By: David Howells diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index bbea888..5306f26 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -307,7 +307,7 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status) static int check_interval = 5 * 60; /* 5 minutes */ static void mcheck_timer(void *data); -static DECLARE_WORK(mcheck_work, mcheck_timer, NULL); +static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer, NULL); static void mcheck_check_cpu(void *info) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 915a55a..0bb4b4d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -937,12 +937,9 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK) return; - PREPARE_WORK(&ap->port_task, fn, data); + PREPARE_DELAYED_WORK(&ap->port_task, fn, data); - if (!delay) - rc = queue_work(ata_wq, &ap->port_task); - else - rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); /* rc == 0 means that another user is using port task */ WARN_ON(rc == 0); @@ -5320,8 +5317,8 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host, ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif - INIT_WORK(&ap->port_task, NULL, NULL); - INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); + INIT_DELAYED_WORK(&ap->port_task, NULL, NULL); + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 02b2b27..9f6b7cc 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -332,7 +332,7 @@ void ata_scsi_error(struct Scsi_Host *host) if (ap->pflags & ATA_PFLAG_LOADING) ap->pflags &= ~ATA_PFLAG_LOADING; else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) - queue_work(ata_aux_wq, &ap->hotplug_task); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0); if (ap->pflags & ATA_PFLAG_RECOVERED) ata_port_printk(ap, KERN_INFO, "EH complete\n"); diff --git a/drivers/char/random.c b/drivers/char/random.c index eb6b13f..f2ab61f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1424,7 +1424,7 @@ static unsigned int ip_cnt; static void rekey_seq_generator(void *private_); -static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); +static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator, NULL); /* * Lock avoidance: diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e90ea39..7297acf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -3580,7 +3580,7 @@ static void initialize_tty_struct(struct tty_struct *tty) tty->overrun_time = jiffies; tty->buf.head = tty->buf.tail = NULL; tty_buffer_init(tty); - INIT_WORK(&tty->buf.work, flush_to_ldisc, tty); + INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc, tty); init_MUTEX(&tty->buf.pty_sem); mutex_init(&tty->termios_mutex); init_waitqueue_head(&tty->write_wait); diff --git a/fs/aio.c b/fs/aio.c index 9476659..11a1a71 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -227,7 +227,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) INIT_LIST_HEAD(&ctx->active_reqs); INIT_LIST_HEAD(&ctx->run_list); - INIT_WORK(&ctx->wq, aio_kick_handler, ctx); + INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler, ctx); if (aio_setup_ring(ctx) < 0) goto out_freectx; @@ -876,7 +876,7 @@ static void aio_kick_handler(void *data) * we're in a worker thread already, don't use queue_delayed_work, */ if (requeue) - queue_work(aio_wq, &ctx->wq); + queue_delayed_work(aio_wq, &ctx->wq, 0); } diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 5fea638..6f0487d 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -143,7 +143,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, INIT_LIST_HEAD(&clp->cl_state_owners); INIT_LIST_HEAD(&clp->cl_unused); spin_lock_init(&clp->cl_lock); - INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); + INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state, clp); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); clp->cl_boot_time = CURRENT_TIME; clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index ec1114b..5ed798bc 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -21,7 +21,8 @@ static void nfs_expire_automounts(void *list); LIST_HEAD(nfs_automount_list); -static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list); +static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts, + &nfs_automount_list); int nfs_mountpoint_expiry_timeout = 500 * HZ; static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, diff --git a/include/linux/aio.h b/include/linux/aio.h index 0d71c00..9e350fd 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -194,7 +194,7 @@ struct kioctx { struct aio_ring_info ring_info; - struct work_struct wq; + struct delayed_work wq; }; /* prototypes */ diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index efe0ee4..06c58c4 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -158,7 +158,7 @@ static inline void con_schedule_flip(struct tty_struct *t) if (t->buf.tail != NULL) t->buf.tail->commit = t->buf.tail->used; spin_unlock_irqrestore(&t->buf.lock, flags); - schedule_work(&t->buf.work); + schedule_delayed_work(&t->buf.work, 0); } #endif diff --git a/include/linux/libata.h b/include/linux/libata.h index abd2deb..5f04006 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -568,8 +568,8 @@ struct ata_port { struct ata_host *host; struct device *dev; - struct work_struct port_task; - struct work_struct hotplug_task; + struct delayed_work port_task; + struct delayed_work hotplug_task; struct work_struct scsi_rescan_task; unsigned int hsm_task_state; diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 7ccfc7e..95796e6 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -51,7 +51,7 @@ struct nfs_client { unsigned long cl_lease_time; unsigned long cl_last_renewal; - struct work_struct cl_renewd; + struct delayed_work cl_renewd; struct rpc_wait_queue cl_rpcwaitq; diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index a2eb9b4..4a68125 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h @@ -30,7 +30,7 @@ struct rpc_inode { #define RPC_PIPE_WAIT_FOR_OPEN 1 int flags; struct rpc_pipe_ops *ops; - struct work_struct queue_timeout; + struct delayed_work queue_timeout; }; static inline struct rpc_inode * diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 60394fb..3e04c15 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -177,7 +177,7 @@ struct rpc_xprt { unsigned long connect_timeout, bind_timeout, reestablish_timeout; - struct work_struct connect_worker; + struct delayed_work connect_worker; unsigned short port; /* diff --git a/include/linux/tty.h b/include/linux/tty.h index 44091c0..c1f7164 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -53,7 +53,7 @@ struct tty_buffer { }; struct tty_bufhead { - struct work_struct work; + struct delayed_work work; struct semaphore pty_sem; spinlock_t lock; struct tty_buffer *head; /* Queue head */ diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 9bca353..9faacca 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -17,6 +17,10 @@ struct work_struct { void (*func)(void *); void *data; void *wq_data; +}; + +struct delayed_work { + struct work_struct work; struct timer_list timer; }; @@ -28,32 +32,48 @@ struct execute_work { .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ .data = (d), \ + } + +#define __DELAYED_WORK_INITIALIZER(n, f, d) { \ + .work = __WORK_INITIALIZER((n).work, (f), (d)), \ .timer = TIMER_INITIALIZER(NULL, 0, 0), \ } #define DECLARE_WORK(n, f, d) \ struct work_struct n = __WORK_INITIALIZER(n, f, d) +#define DECLARE_DELAYED_WORK(n, f, d) \ + struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, d) + /* - * initialize a work-struct's func and data pointers: + * initialize a work item's function and data pointers */ #define PREPARE_WORK(_work, _func, _data) \ do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ + (_work)->func = (_func); \ + (_work)->data = (_data); \ } while (0) +#define PREPARE_DELAYED_WORK(_work, _func, _data) \ + PREPARE_WORK(&(_work)->work, (_func), (_data)) + /* - * initialize all of a work-struct: + * initialize all of a work item in one go */ #define INIT_WORK(_work, _func, _data) \ do { \ INIT_LIST_HEAD(&(_work)->entry); \ (_work)->pending = 0; \ PREPARE_WORK((_work), (_func), (_data)); \ + } while (0) + +#define INIT_DELAYED_WORK(_work, _func, _data) \ + do { \ + INIT_WORK(&(_work)->work, (_func), (_data)); \ init_timer(&(_work)->timer); \ } while (0) + extern struct workqueue_struct *__create_workqueue(const char *name, int singlethread); #define create_workqueue(name) __create_workqueue((name), 0) @@ -62,24 +82,24 @@ extern struct workqueue_struct *__create_workqueue(const char *name, extern void destroy_workqueue(struct workqueue_struct *wq); extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work)); -extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay)); +extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay)); extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay); + struct delayed_work *work, unsigned long delay); extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq)); extern int FASTCALL(schedule_work(struct work_struct *work)); -extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay)); +extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay)); -extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay); +extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay); extern int schedule_on_each_cpu(void (*func)(void *info), void *info); extern void flush_scheduled_work(void); extern int current_is_keventd(void); extern int keventd_up(void); extern void init_workqueues(void); -void cancel_rearming_delayed_work(struct work_struct *work); +void cancel_rearming_delayed_work(struct delayed_work *work); void cancel_rearming_delayed_workqueue(struct workqueue_struct *, - struct work_struct *); + struct delayed_work *); int execute_in_process_context(void (*fn)(void *), void *, struct execute_work *); @@ -88,13 +108,13 @@ int execute_in_process_context(void (*fn)(void *), void *, * function may still be running on return from cancel_delayed_work(). Run * flush_scheduled_work() to wait on it. */ -static inline int cancel_delayed_work(struct work_struct *work) +static inline int cancel_delayed_work(struct delayed_work *work) { int ret; ret = del_timer_sync(&work->timer); if (ret) - clear_bit(0, &work->pending); + clear_bit(0, &work->work.pending); return ret; } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 17c2f03..44fc54b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -122,29 +122,33 @@ EXPORT_SYMBOL_GPL(queue_work); static void delayed_work_timer_fn(unsigned long __data) { - struct work_struct *work = (struct work_struct *)__data; - struct workqueue_struct *wq = work->wq_data; + struct delayed_work *dwork = (struct delayed_work *)__data; + struct workqueue_struct *wq = dwork->work.wq_data; int cpu = smp_processor_id(); if (unlikely(is_single_threaded(wq))) cpu = singlethread_cpu; - __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); + __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), &dwork->work); } /** * queue_delayed_work - queue work on a workqueue after delay * @wq: workqueue to use - * @work: work to queue + * @work: delayable work to queue * @delay: number of jiffies to wait before queueing * * Returns 0 if @work was already on a queue, non-zero otherwise. */ int fastcall queue_delayed_work(struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { int ret = 0; - struct timer_list *timer = &work->timer; + struct timer_list *timer = &dwork->timer; + struct work_struct *work = &dwork->work; + + if (delay == 0) + return queue_work(wq, work); if (!test_and_set_bit(0, &work->pending)) { BUG_ON(timer_pending(timer)); @@ -153,7 +157,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, /* This stores wq for the moment, for the timer_fn */ work->wq_data = wq; timer->expires = jiffies + delay; - timer->data = (unsigned long)work; + timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; add_timer(timer); ret = 1; @@ -172,10 +176,11 @@ EXPORT_SYMBOL_GPL(queue_delayed_work); * Returns 0 if @work was already on a queue, non-zero otherwise. */ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { int ret = 0; - struct timer_list *timer = &work->timer; + struct timer_list *timer = &dwork->timer; + struct work_struct *work = &dwork->work; if (!test_and_set_bit(0, &work->pending)) { BUG_ON(timer_pending(timer)); @@ -184,7 +189,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, /* This stores wq for the moment, for the timer_fn */ work->wq_data = wq; timer->expires = jiffies + delay; - timer->data = (unsigned long)work; + timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; add_timer_on(timer, cpu); ret = 1; @@ -468,31 +473,31 @@ EXPORT_SYMBOL(schedule_work); /** * schedule_delayed_work - put work task in global workqueue after delay - * @work: job to be done - * @delay: number of jiffies to wait + * @dwork: job to be done + * @delay: number of jiffies to wait or 0 for immediate execution * * After waiting for a given time this puts a job in the kernel-global * workqueue. */ -int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) +int fastcall schedule_delayed_work(struct delayed_work *dwork, unsigned long delay) { - return queue_delayed_work(keventd_wq, work, delay); + return queue_delayed_work(keventd_wq, dwork, delay); } EXPORT_SYMBOL(schedule_delayed_work); /** * schedule_delayed_work_on - queue work in global workqueue on CPU after delay * @cpu: cpu to use - * @work: job to be done + * @dwork: job to be done * @delay: number of jiffies to wait * * After waiting for a given time this puts a job in the kernel-global * workqueue on the specified CPU. */ int schedule_delayed_work_on(int cpu, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { - return queue_delayed_work_on(cpu, keventd_wq, work, delay); + return queue_delayed_work_on(cpu, keventd_wq, dwork, delay); } EXPORT_SYMBOL(schedule_delayed_work_on); @@ -539,12 +544,12 @@ EXPORT_SYMBOL(flush_scheduled_work); * cancel_rearming_delayed_workqueue - reliably kill off a delayed * work whose handler rearms the delayed work. * @wq: the controlling workqueue structure - * @work: the delayed work struct + * @dwork: the delayed work struct */ void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq, - struct work_struct *work) + struct delayed_work *dwork) { - while (!cancel_delayed_work(work)) + while (!cancel_delayed_work(dwork)) flush_workqueue(wq); } EXPORT_SYMBOL(cancel_rearming_delayed_workqueue); @@ -552,11 +557,11 @@ EXPORT_SYMBOL(cancel_rearming_delayed_workqueue); /** * cancel_rearming_delayed_work - reliably kill off a delayed keventd * work whose handler rearms the delayed work. - * @work: the delayed work struct + * @dwork: the delayed work struct */ -void cancel_rearming_delayed_work(struct work_struct *work) +void cancel_rearming_delayed_work(struct delayed_work *dwork) { - cancel_rearming_delayed_workqueue(keventd_wq, work); + cancel_rearming_delayed_workqueue(keventd_wq, dwork); } EXPORT_SYMBOL(cancel_rearming_delayed_work); diff --git a/mm/slab.c b/mm/slab.c index 3c4a7e3..a65bc5e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -753,7 +753,7 @@ int slab_is_available(void) return g_cpucache_up == FULL; } -static DEFINE_PER_CPU(struct work_struct, reap_work); +static DEFINE_PER_CPU(struct delayed_work, reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) { @@ -916,16 +916,16 @@ static void next_reap_node(void) */ static void __devinit start_cpu_timer(int cpu) { - struct work_struct *reap_work = &per_cpu(reap_work, cpu); + struct delayed_work *reap_work = &per_cpu(reap_work, cpu); /* * When this gets called from do_initcalls via cpucache_init(), * init_workqueues() has already run, so keventd will be setup * at that time. */ - if (keventd_up() && reap_work->func == NULL) { + if (keventd_up() && reap_work->work.func == NULL) { init_reap_node(cpu); - INIT_WORK(reap_work, cache_reap, NULL); + INIT_DELAYED_WORK(reap_work, cache_reap, NULL); schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu); } } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 4b36114..f2ed09e 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -35,7 +35,7 @@ static unsigned long linkwatch_flags; static unsigned long linkwatch_nextevent; static void linkwatch_event(void *dummy); -static DECLARE_WORK(linkwatch_work, linkwatch_event, NULL); +static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event, NULL); static LIST_HEAD(lweventlist); static DEFINE_SPINLOCK(lweventlist_lock); @@ -171,10 +171,9 @@ void linkwatch_fire_event(struct net_device *dev) unsigned long delay = linkwatch_nextevent - jiffies; /* If we wrap around we'll delay it by at most HZ. */ - if (!delay || delay > HZ) - schedule_work(&linkwatch_work); - else - schedule_delayed_work(&linkwatch_work, delay); + if (delay > HZ) + delay = 0; + schedule_delayed_work(&linkwatch_work, delay); } } } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 00cb388..d5725cb 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -285,7 +285,7 @@ static struct file_operations content_file_operations; static struct file_operations cache_flush_operations; static void do_cache_clean(void *data); -static DECLARE_WORK(cache_cleaner, do_cache_clean, NULL); +static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean, NULL); void cache_register(struct cache_detail *cd) { @@ -337,7 +337,7 @@ void cache_register(struct cache_detail *cd) spin_unlock(&cache_list_lock); /* start the cleaning process */ - schedule_work(&cache_cleaner); + schedule_delayed_work(&cache_cleaner, 0); } int cache_unregister(struct cache_detail *cd) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9a0b41a..97be3f7 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -837,7 +837,8 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) INIT_LIST_HEAD(&rpci->pipe); rpci->pipelen = 0; init_waitqueue_head(&rpci->waitq); - INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci); + INIT_DELAYED_WORK(&rpci->queue_timeout, + rpc_timeout_upcall_queue, rpci); rpci->ops = NULL; } } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 757fc91..3c7532c 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1262,7 +1262,7 @@ static void xs_connect(struct rpc_task *task) xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; } else { dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); - schedule_work(&xprt->connect_worker); + schedule_delayed_work(&xprt->connect_worker, 0); /* flush_scheduled_work can sleep... */ if (!RPC_IS_ASYNC(task)) @@ -1375,7 +1375,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) /* XXX: header size can vary due to auth type, IPv6, etc. */ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); - INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt); + INIT_DELAYED_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_UDP_CONN_TO; xprt->reestablish_timeout = XS_UDP_REEST_TO; @@ -1420,7 +1420,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; - INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); + INIT_DELAYED_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_TCP_CONN_TO; xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; -- cgit v0.10.2 From 6bb49e5965c1fc399b4d3cd2b5cf2da535b330c0 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 Nov 2006 14:54:45 +0000 Subject: WorkStruct: Typedef the work function prototype Define a type for the work function prototype. It's not only kept in the work_struct struct, it's also passed as an argument to several functions. This makes it easier to change it. Signed-Off-By: David Howells diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9e6d3a8..5a14fac 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -996,7 +996,7 @@ static DECLARE_WORK(floppy_work, NULL, NULL); static void schedule_bh(void (*handler) (void)) { - PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)handler, NULL); schedule_work(&floppy_work); } @@ -1008,7 +1008,7 @@ static void cancel_activity(void) spin_lock_irqsave(&floppy_lock, flags); do_floppy = NULL; - PREPARE_WORK(&floppy_work, (void *)empty, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)empty, NULL); del_timer(&fd_timer); spin_unlock_irqrestore(&floppy_lock, flags); } diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 9faacca..cef40b2 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -11,10 +11,12 @@ struct workqueue_struct; +typedef void (*work_func_t)(void *data); + struct work_struct { unsigned long pending; struct list_head entry; - void (*func)(void *); + work_func_t func; void *data; void *wq_data; }; @@ -91,7 +93,7 @@ extern int FASTCALL(schedule_work(struct work_struct *work)); extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay)); extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay); -extern int schedule_on_each_cpu(void (*func)(void *info), void *info); +extern int schedule_on_each_cpu(work_func_t func, void *info); extern void flush_scheduled_work(void); extern int current_is_keventd(void); extern int keventd_up(void); @@ -100,8 +102,7 @@ extern void init_workqueues(void); void cancel_rearming_delayed_work(struct delayed_work *work); void cancel_rearming_delayed_workqueue(struct workqueue_struct *, struct delayed_work *); -int execute_in_process_context(void (*fn)(void *), void *, - struct execute_work *); +int execute_in_process_context(work_func_t fn, void *, struct execute_work *); /* * Kill off a pending schedule_delayed_work(). Note that the work callback diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 44fc54b..1e9d61e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -217,7 +217,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) while (!list_empty(&cwq->worklist)) { struct work_struct *work = list_entry(cwq->worklist.next, struct work_struct, entry); - void (*f) (void *) = work->func; + work_func_t f = work->func; void *data = work->data; list_del_init(cwq->worklist.next); @@ -513,7 +513,7 @@ EXPORT_SYMBOL(schedule_delayed_work_on); * * schedule_on_each_cpu() is very slow. */ -int schedule_on_each_cpu(void (*func)(void *info), void *info) +int schedule_on_each_cpu(work_func_t func, void *info) { int cpu; struct work_struct *works; @@ -578,7 +578,7 @@ EXPORT_SYMBOL(cancel_rearming_delayed_work); * Returns: 0 - function was executed * 1 - function was scheduled for execution */ -int execute_in_process_context(void (*fn)(void *data), void *data, +int execute_in_process_context(work_func_t fn, void *data, struct execute_work *ew) { if (!in_interrupt()) { -- cgit v0.10.2 From 365970a1ea76d81cb1ad2f652acb605f06dae256 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 Nov 2006 14:54:49 +0000 Subject: WorkStruct: Merge the pending bit into the wq_data pointer Reclaim a word from the size of the work_struct by folding the pending bit and the wq_data pointer together. This shouldn't cause misalignment problems as all pointers should be at least 4-byte aligned. Signed-Off-By: David Howells diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5a14fac..aa1eb44 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1868,7 +1868,7 @@ static void show_floppy(void) printk("fdc_busy=%lu\n", fdc_busy); if (do_floppy) printk("do_floppy=%p\n", do_floppy); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("floppy_work.func=%p\n", floppy_work.func); if (timer_pending(&fd_timer)) printk("fd_timer.function=%p\n", fd_timer.function); @@ -4498,7 +4498,7 @@ static void floppy_release_irq_and_dma(void) printk("floppy timer still active:%s\n", timeout_message); if (timer_pending(&fd_timer)) printk("auxiliary floppy timer still active\n"); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("work still pending\n"); #endif old_fdc = fdc; diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index cef40b2..ecc017d 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -14,11 +14,15 @@ struct workqueue_struct; typedef void (*work_func_t)(void *data); struct work_struct { - unsigned long pending; + /* the first word is the work queue pointer and the pending flag + * rolled into one */ + unsigned long management; +#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ +#define WORK_STRUCT_FLAG_MASK (3UL) +#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) struct list_head entry; work_func_t func; void *data; - void *wq_data; }; struct delayed_work { @@ -65,7 +69,7 @@ struct execute_work { #define INIT_WORK(_work, _func, _data) \ do { \ INIT_LIST_HEAD(&(_work)->entry); \ - (_work)->pending = 0; \ + (_work)->management = 0; \ PREPARE_WORK((_work), (_func), (_data)); \ } while (0) @@ -75,6 +79,21 @@ struct execute_work { init_timer(&(_work)->timer); \ } while (0) +/** + * work_pending - Find out whether a work item is currently pending + * @work: The work item in question + */ +#define work_pending(work) \ + test_bit(WORK_STRUCT_PENDING, &(work)->management) + +/** + * delayed_work_pending - Find out whether a delayable work item is currently + * pending + * @work: The work item in question + */ +#define delayed_work_pending(work) \ + test_bit(WORK_STRUCT_PENDING, &(work)->work.management) + extern struct workqueue_struct *__create_workqueue(const char *name, int singlethread); @@ -115,7 +134,7 @@ static inline int cancel_delayed_work(struct delayed_work *work) ret = del_timer_sync(&work->timer); if (ret) - clear_bit(0, &work->work.pending); + clear_bit(WORK_STRUCT_PENDING, &work->work.management); return ret; } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 1e9d61e..9674797 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -80,6 +80,29 @@ static inline int is_single_threaded(struct workqueue_struct *wq) return list_empty(&wq->list); } +static inline void set_wq_data(struct work_struct *work, void *wq) +{ + unsigned long new, old, res; + + /* assume the pending flag is already set and that the task has already + * been queued on this workqueue */ + new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING); + res = work->management; + if (res != new) { + do { + old = res; + new = (unsigned long) wq; + new |= (old & WORK_STRUCT_FLAG_MASK); + res = cmpxchg(&work->management, old, new); + } while (res != old); + } +} + +static inline void *get_wq_data(struct work_struct *work) +{ + return (void *) (work->management & WORK_STRUCT_WQ_DATA_MASK); +} + /* Preempt must be disabled. */ static void __queue_work(struct cpu_workqueue_struct *cwq, struct work_struct *work) @@ -87,7 +110,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, unsigned long flags; spin_lock_irqsave(&cwq->lock, flags); - work->wq_data = cwq; + set_wq_data(work, cwq); list_add_tail(&work->entry, &cwq->worklist); cwq->insert_sequence++; wake_up(&cwq->more_work); @@ -108,7 +131,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) { int ret = 0, cpu = get_cpu(); - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { if (unlikely(is_single_threaded(wq))) cpu = singlethread_cpu; BUG_ON(!list_empty(&work->entry)); @@ -123,7 +146,7 @@ EXPORT_SYMBOL_GPL(queue_work); static void delayed_work_timer_fn(unsigned long __data) { struct delayed_work *dwork = (struct delayed_work *)__data; - struct workqueue_struct *wq = dwork->work.wq_data; + struct workqueue_struct *wq = get_wq_data(&dwork->work); int cpu = smp_processor_id(); if (unlikely(is_single_threaded(wq))) @@ -150,12 +173,12 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, if (delay == 0) return queue_work(wq, work); - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); /* This stores wq for the moment, for the timer_fn */ - work->wq_data = wq; + set_wq_data(work, wq); timer->expires = jiffies + delay; timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; @@ -182,12 +205,12 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, struct timer_list *timer = &dwork->timer; struct work_struct *work = &dwork->work; - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); /* This stores wq for the moment, for the timer_fn */ - work->wq_data = wq; + set_wq_data(work, wq); timer->expires = jiffies + delay; timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; @@ -223,8 +246,8 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) list_del_init(cwq->worklist.next); spin_unlock_irqrestore(&cwq->lock, flags); - BUG_ON(work->wq_data != cwq); - clear_bit(0, &work->pending); + BUG_ON(get_wq_data(work) != cwq); + clear_bit(WORK_STRUCT_PENDING, &work->management); f(data); spin_lock_irqsave(&cwq->lock, flags); -- cgit v0.10.2 From 65f27f38446e1976cc98fd3004b110fedcddd189 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 Nov 2006 14:55:48 +0000 Subject: WorkStruct: Pass the work_struct pointer instead of context data Pass the work_struct pointer to the work function rather than context data. The work function can use container_of() to work out the data. For the cases where the container of the work_struct may go away the moment the pending bit is cleared, it is made possible to defer the release of the structure by deferring the clearing of the pending bit. To make this work, an extra flag is introduced into the management side of the work_struct. This governs auto-release of the structure upon execution. Ordinarily, the work queue executor would release the work_struct for further scheduling or deallocation by clearing the pending bit prior to jumping to the work function. This means that, unless the driver makes some guarantee itself that the work_struct won't go away, the work function may not access anything else in the work_struct or its container lest they be deallocated.. This is a problem if the auxiliary data is taken away (as done by the last patch). However, if the pending bit is *not* cleared before jumping to the work function, then the work function *may* access the work_struct and its container with no problems. But then the work function must itself release the work_struct by calling work_release(). In most cases, automatic release is fine, so this is the default. Special initiators exist for the non-auto-release case (ending in _NAR). Signed-Off-By: David Howells diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 5306f26..c7587fc 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -306,8 +306,8 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status) */ static int check_interval = 5 * 60; /* 5 minutes */ -static void mcheck_timer(void *data); -static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer, NULL); +static void mcheck_timer(struct work_struct *work); +static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer); static void mcheck_check_cpu(void *info) { @@ -315,7 +315,7 @@ static void mcheck_check_cpu(void *info) do_machine_check(NULL, 0); } -static void mcheck_timer(void *data) +static void mcheck_timer(struct work_struct *work) { on_each_cpu(mcheck_check_cpu, NULL, 1, 1); schedule_delayed_work(&mcheck_work, check_interval * HZ); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 62c2e74..9800147 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -753,14 +753,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta } struct create_idle { + struct work_struct work; struct task_struct *idle; struct completion done; int cpu; }; -void do_fork_idle(void *_c_idle) +void do_fork_idle(struct work_struct *work) { - struct create_idle *c_idle = _c_idle; + struct create_idle *c_idle = + container_of(work, struct create_idle, work); c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); @@ -775,10 +777,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) int timeout; unsigned long start_rip; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; - DECLARE_WORK(work, do_fork_idle, &c_idle); /* allocate memory for gdts of secondary cpus. Hotplug is considered */ if (!cpu_gdt_descr[cpu].address && @@ -825,9 +827,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) * thread. */ if (!keventd_up() || current_is_keventd()) - work.func(work.data); + c_idle.work.func(&c_idle.work); else { - schedule_work(&work); + schedule_work(&c_idle.work); wait_for_completion(&c_idle.done); } diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index e3ef544..9f05bc9 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -563,7 +563,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *v) { unsigned int cpu; for_each_online_cpu(cpu) { @@ -639,7 +639,7 @@ static struct notifier_block time_cpufreq_notifier_block = { static int __init cpufreq_tsc(void) { - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER)) cpufreq_init = 1; diff --git a/block/as-iosched.c b/block/as-iosched.c index 50b95e4..f371c93 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1274,9 +1274,10 @@ static void as_merged_requests(request_queue_t *q, struct request *req, * * FIXME! dispatch queue is not a queue at all! */ -static void as_work_handler(void *data) +static void as_work_handler(struct work_struct *work) { - struct request_queue *q = data; + struct as_data *ad = container_of(work, struct as_data, antic_work); + struct request_queue *q = ad->q; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1332,7 +1333,7 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e) ad->antic_timer.function = as_antic_timeout; ad->antic_timer.data = (unsigned long)q; init_timer(&ad->antic_timer); - INIT_WORK(&ad->antic_work, as_work_handler, q); + INIT_WORK(&ad->antic_work, as_work_handler); INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1d9c3c7..6cec3a1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1841,9 +1841,11 @@ queue_fail: return 1; } -static void cfq_kick_queue(void *data) +static void cfq_kick_queue(struct work_struct *work) { - request_queue_t *q = data; + struct cfq_data *cfqd = + container_of(work, struct cfq_data, unplug_work); + request_queue_t *q = cfqd->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1987,7 +1989,7 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) cfqd->idle_class_timer.function = cfq_idle_class_timer; cfqd->idle_class_timer.data = (unsigned long) cfqd; - INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); + INIT_WORK(&cfqd->unplug_work, cfq_kick_queue); cfqd->cfq_quantum = cfq_quantum; cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 9eaee66..eb4cf6d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -34,7 +34,7 @@ */ #include -static void blk_unplug_work(void *data); +static void blk_unplug_work(struct work_struct *work); static void blk_unplug_timeout(unsigned long data); static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); @@ -227,7 +227,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) if (q->unplug_delay == 0) q->unplug_delay = 1; - INIT_WORK(&q->unplug_work, blk_unplug_work, q); + INIT_WORK(&q->unplug_work, blk_unplug_work); q->unplug_timer.function = blk_unplug_timeout; q->unplug_timer.data = (unsigned long)q; @@ -1631,9 +1631,9 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, } } -static void blk_unplug_work(void *data) +static void blk_unplug_work(struct work_struct *work) { - request_queue_t *q = data; + request_queue_t *q = container_of(work, request_queue_t, unplug_work); blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, q->rq.count[READ] + q->rq.count[WRITE]); diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c index 9b5b156..2ebffb8 100644 --- a/crypto/cryptomgr.c +++ b/crypto/cryptomgr.c @@ -40,9 +40,10 @@ struct cryptomgr_param { char template[CRYPTO_MAX_ALG_NAME]; }; -static void cryptomgr_probe(void *data) +static void cryptomgr_probe(struct work_struct *work) { - struct cryptomgr_param *param = data; + struct cryptomgr_param *param = + container_of(work, struct cryptomgr_param, work); struct crypto_template *tmpl; struct crypto_instance *inst; int err; @@ -112,7 +113,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) param->larval.type = larval->alg.cra_flags; param->larval.mask = larval->mask; - INIT_WORK(¶m->work, cryptomgr_probe, param); + INIT_WORK(¶m->work, cryptomgr_probe); schedule_work(¶m->work); return NOTIFY_STOP; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 068fe4f..02b30ae 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -50,6 +50,7 @@ ACPI_MODULE_NAME("osl") struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; + struct work_struct work; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -564,12 +565,9 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); } -static void acpi_os_execute_deferred(void *context) +static void acpi_os_execute_deferred(struct work_struct *work) { - struct acpi_os_dpc *dpc = NULL; - - - dpc = (struct acpi_os_dpc *)context; + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); if (!dpc) { printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); return; @@ -602,7 +600,6 @@ acpi_status acpi_os_execute(acpi_execute_type type, { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - struct work_struct *task; ACPI_FUNCTION_TRACE("os_queue_for_execution"); @@ -615,28 +612,22 @@ acpi_status acpi_os_execute(acpi_execute_type type, /* * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. The kernel handles the tq_struct list in a + * freed by the callee. The kernel handles the work_struct list in a * way that allows us to also free its memory inside the callee. * Because we may want to schedule several tasks with different * parameters we can't use the approach some kernel code uses of - * having a static tq_struct. - * We can save time and code by allocating the DPC and tq_structs - * from the same memory. + * having a static work_struct. */ - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); if (!dpc) 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(kacpid_wq, task)) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); kfree(dpc); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0bb4b4d..b5f2da6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -914,7 +914,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * ata_port_queue_task - Queue port_task * @ap: The ata_port to queue port_task for * @fn: workqueue function to be scheduled - * @data: data value to pass to workqueue function + * @data: data for @fn to use * @delay: delay time for workqueue function * * Schedule @fn(@data) for execution after @delay jiffies using @@ -929,7 +929,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * LOCKING: * Inherited from caller. */ -void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, +void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay) { int rc; @@ -937,7 +937,8 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK) return; - PREPARE_DELAYED_WORK(&ap->port_task, fn, data); + PREPARE_DELAYED_WORK(&ap->port_task, fn); + ap->port_task_data = data; rc = queue_delayed_work(ata_wq, &ap->port_task, delay); @@ -4292,10 +4293,11 @@ fsm_start: return poll_next; } -static void ata_pio_task(void *_data) +static void ata_pio_task(struct work_struct *work) { - struct ata_queued_cmd *qc = _data; - struct ata_port *ap = qc->ap; + struct ata_port *ap = + container_of(work, struct ata_port, port_task.work); + struct ata_queued_cmd *qc = ap->port_task_data; u8 status; int poll_next; @@ -5317,9 +5319,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host, ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif - INIT_DELAYED_WORK(&ap->port_task, NULL, NULL); - INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); - INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); + INIT_DELAYED_WORK(&ap->port_task, NULL); + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5c1fc46..c872b32 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3079,7 +3079,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev) /** * ata_scsi_hotplug - SCSI part of hotplug - * @data: Pointer to ATA port to perform SCSI hotplug on + * @work: Pointer to ATA port to perform SCSI hotplug on * * Perform SCSI part of hotplug. It's executed from a separate * workqueue after EH completes. This is necessary because SCSI @@ -3089,9 +3089,10 @@ static void ata_scsi_remove_dev(struct ata_device *dev) * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_hotplug(void *data) +void ata_scsi_hotplug(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, hotplug_task.work); int i; if (ap->pflags & ATA_PFLAG_UNLOADING) { @@ -3190,7 +3191,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, /** * ata_scsi_dev_rescan - initiate scsi_rescan_device() - * @data: Pointer to ATA port to perform scsi_rescan_device() + * @work: Pointer to ATA port to perform scsi_rescan_device() * * After ATA pass thru (SAT) commands are executed successfully, * libata need to propagate the changes to SCSI layer. This @@ -3200,9 +3201,10 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_dev_rescan(void *data) +void ata_scsi_dev_rescan(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, scsi_rescan_task); struct ata_device *dev; unsigned int i; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0ed263b..7e0f3af 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -81,7 +81,7 @@ extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); extern int ata_scsi_offline_dev(struct ata_device *dev); -extern void ata_scsi_hotplug(void *data); +extern void ata_scsi_hotplug(struct work_struct *work); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -111,7 +111,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); -extern void ata_scsi_dev_rescan(void *data); +extern void ata_scsi_dev_rescan(struct work_struct *work); extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index aa1eb44..3f1b382 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -992,11 +992,11 @@ static void empty(void) { } -static DECLARE_WORK(floppy_work, NULL, NULL); +static DECLARE_WORK(floppy_work, NULL); static void schedule_bh(void (*handler) (void)) { - PREPARE_WORK(&floppy_work, (work_func_t)handler, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)handler); schedule_work(&floppy_work); } @@ -1008,7 +1008,7 @@ static void cancel_activity(void) spin_lock_irqsave(&floppy_lock, flags); do_floppy = NULL; - PREPARE_WORK(&floppy_work, (work_func_t)empty, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)empty); del_timer(&fd_timer); spin_unlock_irqrestore(&floppy_lock, flags); } diff --git a/drivers/char/random.c b/drivers/char/random.c index f2ab61f..fa76468 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1422,9 +1422,9 @@ static struct keydata { static unsigned int ip_cnt; -static void rekey_seq_generator(void *private_); +static void rekey_seq_generator(struct work_struct *work); -static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator, NULL); +static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); /* * Lock avoidance: @@ -1438,7 +1438,7 @@ static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator, NULL); * happen, and even if that happens only a not perfectly compliant * ISN is generated, nothing fatal. */ -static void rekey_seq_generator(void *private_) +static void rekey_seq_generator(struct work_struct *work) { struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 5f49280..c64f5bc 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -219,13 +219,13 @@ static struct sysrq_key_op sysrq_term_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -static void moom_callback(void *ignored) +static void moom_callback(struct work_struct *ignored) { out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); } -static DECLARE_WORK(moom_work, moom_callback, NULL); +static DECLARE_WORK(moom_work, moom_callback); static void sysrq_handle_moom(int key, struct tty_struct *tty) { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 7297acf..83e9e7d 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1254,7 +1254,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** * do_tty_hangup - actual handler for hangup events - * @data: tty device + * @work: tty device * * This can be called by the "eventd" kernel thread. That is process * synchronous but doesn't hold any locks, so we need to make sure we @@ -1274,9 +1274,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * tasklist_lock to walk task list for hangup event * */ -static void do_tty_hangup(void *data) +static void do_tty_hangup(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) data; + struct tty_struct *tty = + container_of(work, struct tty_struct, hangup_work); struct file * cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; @@ -1433,7 +1434,7 @@ void tty_vhangup(struct tty_struct * tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - do_tty_hangup((void *) tty); + do_tty_hangup(&tty->hangup_work); } EXPORT_SYMBOL(tty_vhangup); @@ -3304,12 +3305,13 @@ int tty_ioctl(struct inode * inode, struct file * file, * Nasty bug: do_SAK is being called in interrupt context. This can * deadlock. We punt it up to process context. AKPM - 16Mar2001 */ -static void __do_SAK(void *arg) +static void __do_SAK(struct work_struct *work) { + struct tty_struct *tty = + container_of(work, struct tty_struct, SAK_work); #ifdef TTY_SOFT_SAK tty_hangup(tty); #else - struct tty_struct *tty = arg; struct task_struct *g, *p; int session; int i; @@ -3388,7 +3390,7 @@ void do_SAK(struct tty_struct *tty) { if (!tty) return; - PREPARE_WORK(&tty->SAK_work, __do_SAK, tty); + PREPARE_WORK(&tty->SAK_work, __do_SAK); schedule_work(&tty->SAK_work); } @@ -3396,7 +3398,7 @@ EXPORT_SYMBOL(do_SAK); /** * flush_to_ldisc - * @private_: tty structure passed from work queue. + * @work: tty structure passed from work queue. * * This routine is called out of the software interrupt to flush data * from the buffer chain to the line discipline. @@ -3406,9 +3408,10 @@ EXPORT_SYMBOL(do_SAK); * receive_buf method is single threaded for each tty instance. */ -static void flush_to_ldisc(void *private_) +static void flush_to_ldisc(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) private_; + struct tty_struct *tty = + container_of(work, struct tty_struct, buf.work.work); unsigned long flags; struct tty_ldisc *disc; struct tty_buffer *tbuf, *head; @@ -3553,7 +3556,7 @@ void tty_flip_buffer_push(struct tty_struct *tty) spin_unlock_irqrestore(&tty->buf.lock, flags); if (tty->low_latency) - flush_to_ldisc((void *) tty); + flush_to_ldisc(&tty->buf.work.work); else schedule_delayed_work(&tty->buf.work, 1); } @@ -3580,17 +3583,17 @@ static void initialize_tty_struct(struct tty_struct *tty) tty->overrun_time = jiffies; tty->buf.head = tty->buf.tail = NULL; tty_buffer_init(tty); - INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc, tty); + INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); init_MUTEX(&tty->buf.pty_sem); mutex_init(&tty->termios_mutex); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); - INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); + INIT_WORK(&tty->hangup_work, do_tty_hangup); mutex_init(&tty->atomic_read_lock); mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); - INIT_WORK(&tty->SAK_work, NULL, NULL); + INIT_WORK(&tty->SAK_work, NULL); } /* diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 8e4413f..8ee04ad 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -155,7 +155,7 @@ static void con_flush_chars(struct tty_struct *tty); static void set_vesa_blanking(char __user *p); static void set_cursor(struct vc_data *vc); static void hide_cursor(struct vc_data *vc); -static void console_callback(void *ignored); +static void console_callback(struct work_struct *ignored); static void blank_screen_t(unsigned long dummy); static void set_palette(struct vc_data *vc); @@ -174,7 +174,7 @@ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ static int blankinterval = 10*60*HZ; static int vesa_off_interval; -static DECLARE_WORK(console_work, console_callback, NULL); +static DECLARE_WORK(console_work, console_callback); /* * fg_console is the current virtual console, @@ -2154,7 +2154,7 @@ out: * with other console code and prevention of re-entrancy is * ensured with console_sem. */ -static void console_callback(void *ignored) +static void console_callback(struct work_struct *ignored) { acquire_console_sem(); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index dd0c262..7a7c6e6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); -static void handle_update(void *data); +static void handle_update(struct work_struct *work); /** * Two notifier lists: the "policy" list is involved in the @@ -665,7 +665,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) mutex_init(&policy->lock); mutex_lock(&policy->lock); init_completion(&policy->kobj_unregister); - INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); + INIT_WORK(&policy->update, handle_update); /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU @@ -895,9 +895,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) } -static void handle_update(void *data) +static void handle_update(struct work_struct *work) { - unsigned int cpu = (unsigned int)(long)data; + struct cpufreq_policy *policy = + container_of(work, struct cpufreq_policy, update); + unsigned int cpu = policy->cpu; dprintk("handle_update for cpu %u called\n", cpu); cpufreq_update_policy(cpu); } diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index cbb9366..8451b29 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -567,9 +567,9 @@ static int atkbd_set_leds(struct atkbd *atkbd) * interrupt context. */ -static void atkbd_event_work(void *data) +static void atkbd_event_work(struct work_struct *work) { - struct atkbd *atkbd = data; + struct atkbd *atkbd = container_of(work, struct atkbd, event_work); mutex_lock(&atkbd->event_mutex); @@ -943,7 +943,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); - INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); + INIT_WORK(&atkbd->event_work, atkbd_event_work); mutex_init(&atkbd->event_mutex); switch (serio->id.type) { diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index e5b1b60..b3e84d3 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -251,9 +251,9 @@ EXPORT_SYMBOL(ps2_command); * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.) */ -static void ps2_execute_scheduled_command(void *data) +static void ps2_execute_scheduled_command(struct work_struct *work) { - struct ps2work *ps2work = data; + struct ps2work *ps2work = container_of(work, struct ps2work, work); ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command); kfree(ps2work); @@ -278,7 +278,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman ps2work->ps2dev = ps2dev; ps2work->command = command; memcpy(ps2work->param, param, send); - INIT_WORK(&ps2work->work, ps2_execute_scheduled_command, ps2work); + INIT_WORK(&ps2work->work, ps2_execute_scheduled_command); if (!schedule_work(&ps2work->work)) { kfree(ps2work); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 726ec5e..0329440 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -183,7 +183,7 @@ void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); -static void e1000_reset_task(struct net_device *dev); +static void e1000_reset_task(struct work_struct *work); static void e1000_smartspeed(struct e1000_adapter *adapter); static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb); @@ -908,8 +908,7 @@ e1000_probe(struct pci_dev *pdev, adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; - INIT_WORK(&adapter->reset_task, - (void (*)(void *))e1000_reset_task, netdev); + INIT_WORK(&adapter->reset_task, e1000_reset_task); e1000_check_options(adapter); @@ -3154,9 +3153,10 @@ e1000_tx_timeout(struct net_device *netdev) } static void -e1000_reset_task(struct net_device *netdev) +e1000_reset_task(struct work_struct *work) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, reset_task); e1000_reinit_locked(adapter); } diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 04c43ef..55866b6 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -160,7 +160,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev) rpc->e_lock = SPIN_LOCK_UNLOCKED; rpc->rpd = dev; - INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev); + INIT_WORK(&rpc->dpc_handler, aer_isr); rpc->prod_idx = rpc->cons_idx = 0; mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index daf0cad..3c0a58f 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -118,7 +118,7 @@ extern struct bus_type pcie_port_bus_type; extern void aer_enable_rootport(struct aer_rpc *rpc); extern void aer_delete_rootport(struct aer_rpc *rpc); extern int aer_init(struct pcie_device *dev); -extern void aer_isr(void *context); +extern void aer_isr(struct work_struct *work); extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); extern int aer_osc_setup(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 1c7e660..08e1303 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -690,14 +690,14 @@ static void aer_isr_one_error(struct pcie_device *p_device, /** * aer_isr - consume errors detected by root port - * @context: pointer to a private data of pcie device + * @work: definition of this work item * * Invoked, as DPC, when root port records new detected error **/ -void aer_isr(void *context) +void aer_isr(struct work_struct *work) { - struct pcie_device *p_device = (struct pcie_device *) context; - struct aer_rpc *rpc = get_service_data(p_device); + struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); + struct pcie_device *p_device = rpc->rpd; struct aer_err_source *e_src; mutex_lock(&rpc->rpc_mutex); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 94a2746..d3c5e96 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -362,9 +362,10 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, goto retry; } -static void scsi_target_reap_usercontext(void *data) +static void scsi_target_reap_usercontext(struct work_struct *work) { - struct scsi_target *starget = data; + struct scsi_target *starget = + container_of(work, struct scsi_target, ew.work); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; @@ -400,7 +401,7 @@ void scsi_target_reap(struct scsi_target *starget) starget->state = STARGET_DEL; spin_unlock_irqrestore(shost->host_lock, flags); execute_in_process_context(scsi_target_reap_usercontext, - starget, &starget->ew); + &starget->ew); return; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e1a9166..259c90c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -218,16 +218,16 @@ static void scsi_device_cls_release(struct class_device *class_dev) put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release_usercontext(void *data) +static void scsi_device_dev_release_usercontext(struct work_struct *work) { - struct device *dev = data; struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; unsigned long flags; - parent = dev->parent; - sdev = to_scsi_device(dev); + sdev = container_of(work, struct scsi_device, ew.work); + + parent = sdev->sdev_gendev.parent; starget = to_scsi_target(parent); spin_lock_irqsave(sdev->host->host_lock, flags); @@ -258,7 +258,7 @@ static void scsi_device_dev_release_usercontext(void *data) static void scsi_device_dev_release(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - execute_in_process_context(scsi_device_dev_release_usercontext, dev, + execute_in_process_context(scsi_device_dev_release_usercontext, &sdp->ew); } diff --git a/fs/aio.c b/fs/aio.c index 11a1a71..ca1c518 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -53,13 +53,13 @@ static kmem_cache_t *kioctx_cachep; static struct workqueue_struct *aio_wq; /* Used for rare fput completion. */ -static void aio_fput_routine(void *); -static DECLARE_WORK(fput_work, aio_fput_routine, NULL); +static void aio_fput_routine(struct work_struct *); +static DECLARE_WORK(fput_work, aio_fput_routine); static DEFINE_SPINLOCK(fput_lock); static LIST_HEAD(fput_head); -static void aio_kick_handler(void *); +static void aio_kick_handler(struct work_struct *); static void aio_queue_work(struct kioctx *); /* aio_setup @@ -227,7 +227,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) INIT_LIST_HEAD(&ctx->active_reqs); INIT_LIST_HEAD(&ctx->run_list); - INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler, ctx); + INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler); if (aio_setup_ring(ctx) < 0) goto out_freectx; @@ -470,7 +470,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) wake_up(&ctx->wait); } -static void aio_fput_routine(void *data) +static void aio_fput_routine(struct work_struct *data) { spin_lock_irq(&fput_lock); while (likely(!list_empty(&fput_head))) { @@ -859,9 +859,9 @@ static inline void aio_run_all_iocbs(struct kioctx *ctx) * space. * Run on aiod's context. */ -static void aio_kick_handler(void *data) +static void aio_kick_handler(struct work_struct *work) { - struct kioctx *ctx = data; + struct kioctx *ctx = container_of(work, struct kioctx, wq.work); mm_segment_t oldfs = get_fs(); int requeue; diff --git a/fs/bio.c b/fs/bio.c index f95c874..c6c07ca 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -955,16 +955,16 @@ static void bio_release_pages(struct bio *bio) * run one bio_put() against the BIO. */ -static void bio_dirty_fn(void *data); +static void bio_dirty_fn(struct work_struct *work); -static DECLARE_WORK(bio_dirty_work, bio_dirty_fn, NULL); +static DECLARE_WORK(bio_dirty_work, bio_dirty_fn); static DEFINE_SPINLOCK(bio_dirty_lock); static struct bio *bio_dirty_list; /* * This runs in process context */ -static void bio_dirty_fn(void *data) +static void bio_dirty_fn(struct work_struct *work) { unsigned long flags; struct bio *bio; diff --git a/fs/file.c b/fs/file.c index 8e81775..3787e82 100644 --- a/fs/file.c +++ b/fs/file.c @@ -91,8 +91,10 @@ out: spin_unlock(&fddef->lock); } -static void free_fdtable_work(struct fdtable_defer *f) +static void free_fdtable_work(struct work_struct *work) { + struct fdtable_defer *f = + container_of(work, struct fdtable_defer, wq); struct fdtable *fdt; spin_lock_bh(&f->lock); @@ -351,7 +353,7 @@ static void __devinit fdtable_defer_list_init(int cpu) { struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu); spin_lock_init(&fddef->lock); - INIT_WORK(&fddef->wq, (void (*)(void *))free_fdtable_work, fddef); + INIT_WORK(&fddef->wq, free_fdtable_work); init_timer(&fddef->timer); fddef->timer.data = (unsigned long)fddef; fddef->timer.function = fdtable_timer; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 6f0487d..23ab145 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -143,7 +143,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, INIT_LIST_HEAD(&clp->cl_state_owners); INIT_LIST_HEAD(&clp->cl_unused); spin_lock_init(&clp->cl_lock); - INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state, clp); + INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); clp->cl_boot_time = CURRENT_TIME; clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 5ed798bc..371b804 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -18,11 +18,10 @@ #define NFSDBG_FACILITY NFSDBG_VFS -static void nfs_expire_automounts(void *list); +static void nfs_expire_automounts(struct work_struct *work); LIST_HEAD(nfs_automount_list); -static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts, - &nfs_automount_list); +static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts); int nfs_mountpoint_expiry_timeout = 500 * HZ; static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, @@ -165,9 +164,9 @@ struct inode_operations nfs_referral_inode_operations = { .follow_link = nfs_follow_mountpoint, }; -static void nfs_expire_automounts(void *data) +static void nfs_expire_automounts(struct work_struct *work) { - struct list_head *list = (struct list_head *)data; + struct list_head *list = &nfs_automount_list; mark_mounts_for_expiry(list); if (!list_empty(list)) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 6f34667..c26cd97 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -185,7 +185,7 @@ extern const u32 nfs4_fs_locations_bitmap[2]; extern void nfs4_schedule_state_renewal(struct nfs_client *); extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); extern void nfs4_kill_renewd(struct nfs_client *); -extern void nfs4_renew_state(void *); +extern void nfs4_renew_state(struct work_struct *); /* nfs4state.c */ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp); diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index 7b6df18..8232985 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c @@ -59,9 +59,10 @@ #define NFSDBG_FACILITY NFSDBG_PROC void -nfs4_renew_state(void *data) +nfs4_renew_state(struct work_struct *work) { - struct nfs_client *clp = (struct nfs_client *)data; + struct nfs_client *clp = + container_of(work, struct nfs_client, cl_renewd.work); struct rpc_cred *cred; long lease, timeout; unsigned long last, now; diff --git a/include/linux/libata.h b/include/linux/libata.h index 5f04006..b3f32ea 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -568,6 +568,7 @@ struct ata_port { struct ata_host *host; struct device *dev; + void *port_task_data; struct delayed_work port_task; struct delayed_work hotplug_task; struct work_struct scsi_rescan_task; @@ -747,7 +748,7 @@ extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); -extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), +extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay); extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, unsigned long interval_msec, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index ecc017d..4a3ea83 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -11,18 +11,19 @@ struct workqueue_struct; -typedef void (*work_func_t)(void *data); +struct work_struct; +typedef void (*work_func_t)(struct work_struct *work); struct work_struct { - /* the first word is the work queue pointer and the pending flag - * rolled into one */ + /* the first word is the work queue pointer and the flags rolled into + * one */ unsigned long management; #define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ +#define WORK_STRUCT_NOAUTOREL 1 /* F if work item automatically released on exec */ #define WORK_STRUCT_FLAG_MASK (3UL) #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) struct list_head entry; work_func_t func; - void *data; }; struct delayed_work { @@ -34,48 +35,77 @@ struct execute_work { struct work_struct work; }; -#define __WORK_INITIALIZER(n, f, d) { \ +#define __WORK_INITIALIZER(n, f) { \ + .management = 0, \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ - .data = (d), \ } -#define __DELAYED_WORK_INITIALIZER(n, f, d) { \ - .work = __WORK_INITIALIZER((n).work, (f), (d)), \ +#define __WORK_INITIALIZER_NAR(n, f) { \ + .management = (1 << WORK_STRUCT_NOAUTOREL), \ + .entry = { &(n).entry, &(n).entry }, \ + .func = (f), \ + } + +#define __DELAYED_WORK_INITIALIZER(n, f) { \ + .work = __WORK_INITIALIZER((n).work, (f)), \ + .timer = TIMER_INITIALIZER(NULL, 0, 0), \ + } + +#define __DELAYED_WORK_INITIALIZER_NAR(n, f) { \ + .work = __WORK_INITIALIZER_NAR((n).work, (f)), \ .timer = TIMER_INITIALIZER(NULL, 0, 0), \ } -#define DECLARE_WORK(n, f, d) \ - struct work_struct n = __WORK_INITIALIZER(n, f, d) +#define DECLARE_WORK(n, f) \ + struct work_struct n = __WORK_INITIALIZER(n, f) + +#define DECLARE_WORK_NAR(n, f) \ + struct work_struct n = __WORK_INITIALIZER_NAR(n, f) -#define DECLARE_DELAYED_WORK(n, f, d) \ - struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, d) +#define DECLARE_DELAYED_WORK(n, f) \ + struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f) + +#define DECLARE_DELAYED_WORK_NAR(n, f) \ + struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f) /* - * initialize a work item's function and data pointers + * initialize a work item's function pointer */ -#define PREPARE_WORK(_work, _func, _data) \ +#define PREPARE_WORK(_work, _func) \ do { \ (_work)->func = (_func); \ - (_work)->data = (_data); \ } while (0) -#define PREPARE_DELAYED_WORK(_work, _func, _data) \ - PREPARE_WORK(&(_work)->work, (_func), (_data)) +#define PREPARE_DELAYED_WORK(_work, _func) \ + PREPARE_WORK(&(_work)->work, (_func)) /* * initialize all of a work item in one go */ -#define INIT_WORK(_work, _func, _data) \ +#define INIT_WORK(_work, _func) \ do { \ - INIT_LIST_HEAD(&(_work)->entry); \ (_work)->management = 0; \ - PREPARE_WORK((_work), (_func), (_data)); \ + INIT_LIST_HEAD(&(_work)->entry); \ + PREPARE_WORK((_work), (_func)); \ + } while (0) + +#define INIT_WORK_NAR(_work, _func) \ + do { \ + (_work)->management = (1 << WORK_STRUCT_NOAUTOREL); \ + INIT_LIST_HEAD(&(_work)->entry); \ + PREPARE_WORK((_work), (_func)); \ + } while (0) + +#define INIT_DELAYED_WORK(_work, _func) \ + do { \ + INIT_WORK(&(_work)->work, (_func)); \ + init_timer(&(_work)->timer); \ } while (0) -#define INIT_DELAYED_WORK(_work, _func, _data) \ +#define INIT_DELAYED_WORK_NAR(_work, _func) \ do { \ - INIT_WORK(&(_work)->work, (_func), (_data)); \ + INIT_WORK_NAR(&(_work)->work, (_func)); \ init_timer(&(_work)->timer); \ } while (0) @@ -94,6 +124,27 @@ struct execute_work { #define delayed_work_pending(work) \ test_bit(WORK_STRUCT_PENDING, &(work)->work.management) +/** + * work_release - Release a work item under execution + * @work: The work item to release + * + * This is used to release a work item that has been initialised with automatic + * release mode disabled (WORK_STRUCT_NOAUTOREL is set). This gives the work + * function the opportunity to grab auxiliary data from the container of the + * work_struct before clearing the pending bit as the work_struct may be + * subject to deallocation the moment the pending bit is cleared. + * + * In such a case, this should be called in the work function after it has + * fetched any data it may require from the containter of the work_struct. + * After this function has been called, the work_struct may be scheduled for + * further execution or it may be deallocated unless other precautions are + * taken. + * + * This should also be used to release a delayed work item. + */ +#define work_release(work) \ + clear_bit(WORK_STRUCT_PENDING, &(work)->management) + extern struct workqueue_struct *__create_workqueue(const char *name, int singlethread); @@ -112,7 +163,7 @@ extern int FASTCALL(schedule_work(struct work_struct *work)); extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay)); extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay); -extern int schedule_on_each_cpu(work_func_t func, void *info); +extern int schedule_on_each_cpu(work_func_t func); extern void flush_scheduled_work(void); extern int current_is_keventd(void); extern int keventd_up(void); @@ -121,7 +172,7 @@ extern void init_workqueues(void); void cancel_rearming_delayed_work(struct delayed_work *work); void cancel_rearming_delayed_workqueue(struct workqueue_struct *, struct delayed_work *); -int execute_in_process_context(work_func_t fn, void *, struct execute_work *); +int execute_in_process_context(work_func_t fn, struct execute_work *); /* * Kill off a pending schedule_delayed_work(). Note that the work callback diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 5f48748..f7be1ac 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -84,7 +84,7 @@ struct inet_timewait_death_row { }; extern void inet_twdr_hangman(unsigned long data); -extern void inet_twdr_twkill_work(void *data); +extern void inet_twdr_twkill_work(struct work_struct *work); extern void inet_twdr_twcal_tick(unsigned long data); #if (BITS_PER_LONG == 64) diff --git a/ipc/util.c b/ipc/util.c index cd8bb14..a9b7a22 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -514,6 +514,11 @@ void ipc_rcu_getref(void *ptr) container_of(ptr, struct ipc_rcu_hdr, data)->refcount++; } +static void ipc_do_vfree(struct work_struct *work) +{ + vfree(container_of(work, struct ipc_rcu_sched, work)); +} + /** * ipc_schedule_free - free ipc + rcu space * @head: RCU callback structure for queued work @@ -528,7 +533,7 @@ static void ipc_schedule_free(struct rcu_head *head) struct ipc_rcu_sched *sched = container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); - INIT_WORK(&sched->work, vfree, sched); + INIT_WORK(&sched->work, ipc_do_vfree); schedule_work(&sched->work); } diff --git a/kernel/kmod.c b/kernel/kmod.c index bb4e29d..7dc7a9da 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -114,6 +114,7 @@ EXPORT_SYMBOL(request_module); #endif /* CONFIG_KMOD */ struct subprocess_info { + struct work_struct work; struct completion *complete; char *path; char **argv; @@ -221,9 +222,10 @@ static int wait_for_helper(void *data) } /* This is run by khelper thread */ -static void __call_usermodehelper(void *data) +static void __call_usermodehelper(struct work_struct *work) { - struct subprocess_info *sub_info = data; + struct subprocess_info *sub_info = + container_of(work, struct subprocess_info, work); pid_t pid; int wait = sub_info->wait; @@ -264,6 +266,8 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, { DECLARE_COMPLETION_ONSTACK(done); struct subprocess_info sub_info = { + .work = __WORK_INITIALIZER(sub_info.work, + __call_usermodehelper), .complete = &done, .path = path, .argv = argv, @@ -272,7 +276,6 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, .wait = wait, .retval = 0, }; - DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; @@ -280,7 +283,7 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, if (path[0] == '\0') return 0; - queue_work(khelper_wq, &work); + queue_work(khelper_wq, &sub_info.work); wait_for_completion(&done); return sub_info.retval; } @@ -291,6 +294,8 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { + .work = __WORK_INITIALIZER(sub_info.work, + __call_usermodehelper), .complete = &done, .path = path, .argv = argv, @@ -298,7 +303,6 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, .retval = 0, }; struct file *f; - DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; @@ -318,7 +322,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, } sub_info.stdin = f; - queue_work(khelper_wq, &work); + queue_work(khelper_wq, &sub_info.work); wait_for_completion(&done); return sub_info.retval; } diff --git a/kernel/kthread.c b/kernel/kthread.c index 4f9c60e..1db8c72 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -31,6 +31,8 @@ struct kthread_create_info /* Result passed back to kthread_create() from keventd. */ struct task_struct *result; struct completion done; + + struct work_struct work; }; struct kthread_stop_info @@ -111,9 +113,10 @@ static int kthread(void *_create) } /* We are keventd: create a thread. */ -static void keventd_create_kthread(void *_create) +static void keventd_create_kthread(struct work_struct *work) { - struct kthread_create_info *create = _create; + struct kthread_create_info *create = + container_of(work, struct kthread_create_info, work); int pid; /* We want our own signal handler (we take no signals by default). */ @@ -154,20 +157,20 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), ...) { struct kthread_create_info create; - DECLARE_WORK(work, keventd_create_kthread, &create); create.threadfn = threadfn; create.data = data; init_completion(&create.started); init_completion(&create.done); + INIT_WORK(&create.work, keventd_create_kthread); /* * The workqueue needs to start up first: */ if (!helper_wq) - work.func(work.data); + create.work.func(&create.work); else { - queue_work(helper_wq, &work); + queue_work(helper_wq, &create.work); wait_for_completion(&create.done); } if (!IS_ERR(create.result)) { diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c index f1f900a..678ec73 100644 --- a/kernel/power/poweroff.c +++ b/kernel/power/poweroff.c @@ -16,12 +16,12 @@ * callback we use. */ -static void do_poweroff(void *dummy) +static void do_poweroff(struct work_struct *dummy) { kernel_power_off(); } -static DECLARE_WORK(poweroff_work, do_poweroff, NULL); +static DECLARE_WORK(poweroff_work, do_poweroff); static void handle_poweroff(int key, struct tty_struct *tty) { diff --git a/kernel/sys.c b/kernel/sys.c index 98489d8..c87b461 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -880,7 +880,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user return 0; } -static void deferred_cad(void *dummy) +static void deferred_cad(struct work_struct *dummy) { kernel_restart(NULL); } @@ -892,7 +892,7 @@ static void deferred_cad(void *dummy) */ void ctrl_alt_del(void) { - static DECLARE_WORK(cad_work, deferred_cad, NULL); + static DECLARE_WORK(cad_work, deferred_cad); if (C_A_D) schedule_work(&cad_work); diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 9674797..8d1e7cb 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -241,14 +241,14 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) struct work_struct *work = list_entry(cwq->worklist.next, struct work_struct, entry); work_func_t f = work->func; - void *data = work->data; list_del_init(cwq->worklist.next); spin_unlock_irqrestore(&cwq->lock, flags); BUG_ON(get_wq_data(work) != cwq); - clear_bit(WORK_STRUCT_PENDING, &work->management); - f(data); + if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management)) + work_release(work); + f(work); spin_lock_irqsave(&cwq->lock, flags); cwq->remove_sequence++; @@ -527,7 +527,6 @@ EXPORT_SYMBOL(schedule_delayed_work_on); /** * schedule_on_each_cpu - call a function on each online CPU from keventd * @func: the function to call - * @info: a pointer to pass to func() * * Returns zero on success. * Returns -ve errno on failure. @@ -536,7 +535,7 @@ EXPORT_SYMBOL(schedule_delayed_work_on); * * schedule_on_each_cpu() is very slow. */ -int schedule_on_each_cpu(work_func_t func, void *info) +int schedule_on_each_cpu(work_func_t func) { int cpu; struct work_struct *works; @@ -547,7 +546,7 @@ int schedule_on_each_cpu(work_func_t func, void *info) mutex_lock(&workqueue_mutex); for_each_online_cpu(cpu) { - INIT_WORK(per_cpu_ptr(works, cpu), func, info); + INIT_WORK(per_cpu_ptr(works, cpu), func); __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), per_cpu_ptr(works, cpu)); } @@ -591,7 +590,6 @@ EXPORT_SYMBOL(cancel_rearming_delayed_work); /** * execute_in_process_context - reliably execute the routine with user context * @fn: the function to execute - * @data: data to pass to the function * @ew: guaranteed storage for the execute work structure (must * be available when the work executes) * @@ -601,15 +599,14 @@ EXPORT_SYMBOL(cancel_rearming_delayed_work); * Returns: 0 - function was executed * 1 - function was scheduled for execution */ -int execute_in_process_context(work_func_t fn, void *data, - struct execute_work *ew) +int execute_in_process_context(work_func_t fn, struct execute_work *ew) { if (!in_interrupt()) { - fn(data); + fn(&ew->work); return 0; } - INIT_WORK(&ew->work, fn, data); + INIT_WORK(&ew->work, fn); schedule_work(&ew->work); return 1; diff --git a/mm/slab.c b/mm/slab.c index a65bc5e..5de8147 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -313,7 +313,7 @@ static int drain_freelist(struct kmem_cache *cache, static void free_block(struct kmem_cache *cachep, void **objpp, int len, int node); static int enable_cpucache(struct kmem_cache *cachep); -static void cache_reap(void *unused); +static void cache_reap(struct work_struct *unused); /* * This function must be completely optimized away if a constant is passed to @@ -925,7 +925,7 @@ static void __devinit start_cpu_timer(int cpu) */ if (keventd_up() && reap_work->work.func == NULL) { init_reap_node(cpu); - INIT_DELAYED_WORK(reap_work, cache_reap, NULL); + INIT_DELAYED_WORK(reap_work, cache_reap); schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu); } } @@ -3815,7 +3815,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3, * If we cannot acquire the cache chain mutex then just give up - we'll try * again on the next iteration. */ -static void cache_reap(void *unused) +static void cache_reap(struct work_struct *unused) { struct kmem_cache *searchp; struct kmem_list3 *l3; diff --git a/net/core/link_watch.c b/net/core/link_watch.c index f2ed09e..549a2ce 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -34,8 +34,8 @@ enum lw_bits { static unsigned long linkwatch_flags; static unsigned long linkwatch_nextevent; -static void linkwatch_event(void *dummy); -static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event, NULL); +static void linkwatch_event(struct work_struct *dummy); +static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); static LIST_HEAD(lweventlist); static DEFINE_SPINLOCK(lweventlist_lock); @@ -127,7 +127,7 @@ void linkwatch_run_queue(void) } -static void linkwatch_event(void *dummy) +static void linkwatch_event(struct work_struct *dummy) { /* Limit the number of linkwatch events to one * per second so that a runaway driver does not diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index cdd8053..8c74f91 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -197,9 +197,10 @@ EXPORT_SYMBOL_GPL(inet_twdr_hangman); extern void twkill_slots_invalid(void); -void inet_twdr_twkill_work(void *data) +void inet_twdr_twkill_work(struct work_struct *work) { - struct inet_timewait_death_row *twdr = data; + struct inet_timewait_death_row *twdr = + container_of(work, struct inet_timewait_death_row, twkill_work); int i; if ((INET_TWDR_TWKILL_SLOTS - 1) > (sizeof(twdr->thread_slots) * 8)) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0163d98..af7b2c9 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -45,8 +45,7 @@ struct inet_timewait_death_row tcp_death_row = { .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0, (unsigned long)&tcp_death_row), .twkill_work = __WORK_INITIALIZER(tcp_death_row.twkill_work, - inet_twdr_twkill_work, - &tcp_death_row), + inet_twdr_twkill_work), /* Short-time timewait calendar */ .twcal_hand = -1, diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index d5725cb..d96fd46 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -284,8 +284,8 @@ static struct file_operations cache_file_operations; static struct file_operations content_file_operations; static struct file_operations cache_flush_operations; -static void do_cache_clean(void *data); -static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean, NULL); +static void do_cache_clean(struct work_struct *work); +static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); void cache_register(struct cache_detail *cd) { @@ -461,7 +461,7 @@ static int cache_clean(void) /* * We want to regularly clean the cache, so we need to schedule some work ... */ -static void do_cache_clean(void *data) +static void do_cache_clean(struct work_struct *work) { int delay = 5; if (cache_clean() == -1) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 97be3f7..49dba5f 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -54,10 +54,11 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, } static void -rpc_timeout_upcall_queue(void *data) +rpc_timeout_upcall_queue(struct work_struct *work) { LIST_HEAD(free_list); - struct rpc_inode *rpci = (struct rpc_inode *)data; + struct rpc_inode *rpci = + container_of(work, struct rpc_inode, queue_timeout.work); struct inode *inode = &rpci->vfs_inode; void (*destroy_msg)(struct rpc_pipe_msg *); @@ -838,7 +839,7 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) rpci->pipelen = 0; init_waitqueue_head(&rpci->waitq); INIT_DELAYED_WORK(&rpci->queue_timeout, - rpc_timeout_upcall_queue, rpci); + rpc_timeout_upcall_queue); rpci->ops = NULL; } } diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index a1ab4ee..eff44bc 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -41,7 +41,7 @@ static mempool_t *rpc_buffer_mempool __read_mostly; static void __rpc_default_timer(struct rpc_task *task); static void rpciod_killall(void); -static void rpc_async_schedule(void *); +static void rpc_async_schedule(struct work_struct *); /* * RPC tasks sit here while waiting for conditions to improve. @@ -305,7 +305,7 @@ static void rpc_make_runnable(struct rpc_task *task) if (RPC_IS_ASYNC(task)) { int status; - INIT_WORK(&task->u.tk_work, rpc_async_schedule, (void *)task); + INIT_WORK(&task->u.tk_work, rpc_async_schedule); status = queue_work(task->tk_workqueue, &task->u.tk_work); if (status < 0) { printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); @@ -695,9 +695,9 @@ rpc_execute(struct rpc_task *task) return __rpc_execute(task); } -static void rpc_async_schedule(void *arg) +static void rpc_async_schedule(struct work_struct *work) { - __rpc_execute((struct rpc_task *)arg); + __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); } /** diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 8085747..4f9a5d9 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -479,9 +479,10 @@ int xprt_adjust_timeout(struct rpc_rqst *req) return status; } -static void xprt_autoclose(void *args) +static void xprt_autoclose(struct work_struct *work) { - struct rpc_xprt *xprt = (struct rpc_xprt *)args; + struct rpc_xprt *xprt = + container_of(work, struct rpc_xprt, task_cleanup); xprt_disconnect(xprt); xprt->ops->close(xprt); @@ -932,7 +933,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si INIT_LIST_HEAD(&xprt->free); INIT_LIST_HEAD(&xprt->recv); - INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt); + INIT_WORK(&xprt->task_cleanup, xprt_autoclose); init_timer(&xprt->timer); xprt->timer.function = xprt_init_autodisconnect; xprt->timer.data = (unsigned long) xprt; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 3c7532c..cfe3c15 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1060,13 +1060,14 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) /** * xs_udp_connect_worker - set up a UDP socket - * @args: RPC transport to connect + * @work: RPC transport to connect * * Invoked by a work queue tasklet. */ -static void xs_udp_connect_worker(void *args) +static void xs_udp_connect_worker(struct work_struct *work) { - struct rpc_xprt *xprt = (struct rpc_xprt *) args; + struct rpc_xprt *xprt = + container_of(work, struct rpc_xprt, connect_worker.work); struct socket *sock = xprt->sock; int err, status = -EIO; @@ -1144,13 +1145,14 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) /** * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint - * @args: RPC transport to connect + * @work: RPC transport to connect * * Invoked by a work queue tasklet. */ -static void xs_tcp_connect_worker(void *args) +static void xs_tcp_connect_worker(struct work_struct *work) { - struct rpc_xprt *xprt = (struct rpc_xprt *)args; + struct rpc_xprt *xprt = + container_of(work, struct rpc_xprt, connect_worker.work); struct socket *sock = xprt->sock; int err, status = -EIO; @@ -1375,7 +1377,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) /* XXX: header size can vary due to auth type, IPv6, etc. */ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); - INIT_DELAYED_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt); + INIT_DELAYED_WORK(&xprt->connect_worker, xs_udp_connect_worker); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_UDP_CONN_TO; xprt->reestablish_timeout = XS_UDP_REEST_TO; @@ -1420,7 +1422,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; - INIT_DELAYED_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); + INIT_DELAYED_WORK(&xprt->connect_worker, xs_tcp_connect_worker); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_TCP_CONN_TO; xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; diff --git a/security/keys/key.c b/security/keys/key.c index 80de8c3..70eacbe 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -30,8 +30,8 @@ DEFINE_SPINLOCK(key_user_lock); static LIST_HEAD(key_types_list); static DECLARE_RWSEM(key_types_sem); -static void key_cleanup(void *data); -static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL); +static void key_cleanup(struct work_struct *work); +static DECLARE_WORK(key_cleanup_task, key_cleanup); /* we serialise key instantiation and link */ DECLARE_RWSEM(key_construction_sem); @@ -552,7 +552,7 @@ EXPORT_SYMBOL(key_negate_and_link); * do cleaning up in process context so that we don't have to disable * interrupts all over the place */ -static void key_cleanup(void *data) +static void key_cleanup(struct work_struct *work) { struct rb_node *_n; struct key *key; -- cgit v0.10.2 From c4028958b6ecad064b1a6303a6a5906d4fe48d73 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 22 Nov 2006 14:57:56 +0000 Subject: WorkStruct: make allyesconfig Fix up for make allyesconfig. Signed-Off-By: David Howells diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c index 1f9153a..6b5d351 100644 --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -51,10 +51,10 @@ static void mce_checkregs (void *info) } } -static void mce_work_fn(void *data); -static DECLARE_WORK(mce_work, mce_work_fn, NULL); +static void mce_work_fn(struct work_struct *work); +static DECLARE_DELAYED_WORK(mce_work, mce_work_fn); -static void mce_work_fn(void *data) +static void mce_work_fn(struct work_struct *work) { on_each_cpu(mce_checkregs, NULL, 1, 1); schedule_delayed_work(&mce_work, MCE_RATE); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 4bb8b77..02a9b66 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1049,13 +1049,15 @@ void cpu_exit_clear(void) struct warm_boot_cpu_info { struct completion *complete; + struct work_struct task; int apicid; int cpu; }; -static void __cpuinit do_warm_boot_cpu(void *p) +static void __cpuinit do_warm_boot_cpu(struct work_struct *work) { - struct warm_boot_cpu_info *info = p; + struct warm_boot_cpu_info *info = + container_of(work, struct warm_boot_cpu_info, task); do_boot_cpu(info->apicid, info->cpu); complete(info->complete); } @@ -1064,7 +1066,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu) { DECLARE_COMPLETION_ONSTACK(done); struct warm_boot_cpu_info info; - struct work_struct task; int apicid, ret; struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); @@ -1089,7 +1090,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) info.complete = &done; info.apicid = apicid; info.cpu = cpu; - INIT_WORK(&task, do_warm_boot_cpu, &info); + INIT_WORK(&info.task, do_warm_boot_cpu); tsc_sync_disabled = 1; @@ -1097,7 +1098,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, KERNEL_PGD_PTRS); flush_tlb_all(); - schedule_work(&task); + schedule_work(&info.task); wait_for_completion(&done); tsc_sync_disabled = 0; diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index fbc9582..9810c8c 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c @@ -217,7 +217,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *work) { unsigned int cpu; @@ -306,7 +306,7 @@ static int __init cpufreq_tsc(void) { int ret; - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); if (!ret) diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 1370774..49037ed 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -37,8 +37,8 @@ /* EEH event workqueue setup. */ static DEFINE_SPINLOCK(eeh_eventlist_lock); LIST_HEAD(eeh_eventlist); -static void eeh_thread_launcher(void *); -DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); +static void eeh_thread_launcher(struct work_struct *); +DECLARE_WORK(eeh_event_wq, eeh_thread_launcher); /* Serialize reset sequences for a given pci device */ DEFINE_MUTEX(eeh_event_mutex); @@ -103,7 +103,7 @@ static int eeh_event_handler(void * dummy) * eeh_thread_launcher * @dummy - unused */ -static void eeh_thread_launcher(void *dummy) +static void eeh_thread_launcher(struct work_struct *dummy) { if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0) printk(KERN_ERR "Failed to start EEH daemon\n"); diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 87b17c3..f407861 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -135,7 +135,7 @@ static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags); static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page); -static void idt77252_softint(void *dev_id); +static void idt77252_softint(struct work_struct *work); static struct atmdev_ops idt77252_ops = @@ -2866,9 +2866,10 @@ out: } static void -idt77252_softint(void *dev_id) +idt77252_softint(struct work_struct *work) { - struct idt77252_dev *card = dev_id; + struct idt77252_dev *card = + container_of(work, struct idt77252_dev, tqueue); u32 stat; int done; @@ -3697,7 +3698,7 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) card->pcidev = pcidev; sprintf(card->name, "idt77252-%d", card->index); - INIT_WORK(&card->tqueue, idt77252_softint, (void *)card); + INIT_WORK(&card->tqueue, idt77252_softint); membase = pci_resource_start(pcidev, 1); srambase = pci_resource_start(pcidev, 2); diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6d11122..2308e83 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -159,7 +159,7 @@ void aoecmd_work(struct aoedev *d); 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); +void aoecmd_sleepwork(struct work_struct *); struct sk_buff *new_skb(ulong); int aoedev_init(void); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 8a13b1a..97f7f53 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -408,9 +408,9 @@ rexmit_timer(ulong vp) /* this function performs work that has been deferred until sleeping is OK */ void -aoecmd_sleepwork(void *vp) +aoecmd_sleepwork(struct work_struct *work) { - struct aoedev *d = (struct aoedev *) vp; + struct aoedev *d = container_of(work, struct aoedev, work); if (d->flags & DEVFL_GDALLOC) aoeblk_gdalloc(d); diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 6125921..05a9719 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -88,7 +88,7 @@ aoedev_newdev(ulong nframes) kfree(d); return NULL; } - INIT_WORK(&d->work, aoecmd_sleepwork, d); + INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); init_timer(&d->timer); d->timer.data = (ulong) d; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 40a11e5..9d9bff2 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -352,19 +352,19 @@ static enum action (*phase)(void); static void run_fsm(void); -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); -static DECLARE_WORK(fsm_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int); static void schedule_fsm(void) { if (!nice) - schedule_work(&fsm_tq); + schedule_delayed_work(&fsm_tq, 0); else schedule_delayed_work(&fsm_tq, nice-1); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { run_fsm(); } diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h index 932342d..bc37032 100644 --- a/drivers/block/paride/pseudo.h +++ b/drivers/block/paride/pseudo.h @@ -35,7 +35,7 @@ #include #include -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); static void (* ps_continuation)(void); static int (* ps_ready)(void); @@ -45,7 +45,7 @@ static int ps_nice = 0; static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused))); -static DECLARE_WORK(ps_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int); static void ps_set_intr(void (*continuation)(void), int (*ready)(void), @@ -63,14 +63,14 @@ static void ps_set_intr(void (*continuation)(void), if (!ps_tq_active) { ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); } spin_unlock_irqrestore(&ps_spinlock,flags); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { void (*con)(void); unsigned long flags; @@ -92,7 +92,7 @@ static void ps_tq_int(void *data) } ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); spin_unlock_irqrestore(&ps_spinlock,flags); diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 47d6975..54509eb 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -1244,9 +1244,10 @@ out: return IRQ_RETVAL(handled); } -static void carm_fsm_task (void *_data) +static void carm_fsm_task (struct work_struct *work) { - struct carm_host *host = _data; + struct carm_host *host = + container_of(work, struct carm_host, fsm_task); unsigned long flags; unsigned int state; int rc, i, next_dev; @@ -1619,7 +1620,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) host->pdev = pdev; host->flags = pci_dac ? FL_DAC : 0; spin_lock_init(&host->lock); - INIT_WORK(&host->fsm_task, carm_fsm_task, host); + INIT_WORK(&host->fsm_task, carm_fsm_task); init_completion(&host->probe_comp); for (i = 0; i < ARRAY_SIZE(host->req); i++) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 0d5c73f..2098eff 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -376,7 +376,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe); static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); static void ub_reset_enter(struct ub_dev *sc, int try); -static void ub_reset_task(void *arg); +static void ub_reset_task(struct work_struct *work); static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret); @@ -1558,9 +1558,9 @@ static void ub_reset_enter(struct ub_dev *sc, int try) schedule_work(&sc->reset_work); } -static void ub_reset_task(void *arg) +static void ub_reset_task(struct work_struct *work) { - struct ub_dev *sc = arg; + struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); unsigned long flags; struct list_head *p; struct ub_lun *lun; @@ -2179,7 +2179,7 @@ static int ub_probe(struct usb_interface *intf, usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); - INIT_WORK(&sc->reset_work, ub_reset_task, sc); + INIT_WORK(&sc->reset_work, ub_reset_task); init_waitqueue_head(&sc->reset_wait); init_timer(&sc->work_timer); diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 5167517..9256985 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -157,9 +157,10 @@ static void bcm203x_complete(struct urb *urb) } } -static void bcm203x_work(void *user_data) +static void bcm203x_work(struct work_struct *work) { - struct bcm203x_data *data = user_data; + struct bcm203x_data *data = + container_of(work, struct bcm203x_data, work); if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); @@ -246,7 +247,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); - INIT_WORK(&data->work, bcm203x_work, (void *) data); + INIT_WORK(&data->work, bcm203x_work); usb_set_intfdata(intf, data); diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e608dad..acb2de5 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -926,9 +926,10 @@ cy_sched_event(struct cyclades_port *info, int event) * had to poll every port to see if that port needed servicing. */ static void -do_softint(void *private_) +do_softint(struct work_struct *work) { - struct cyclades_port *info = (struct cyclades_port *) private_; + struct cyclades_port *info = + container_of(work, struct cyclades_port, tqueue); struct tty_struct *tty; tty = info->tty; @@ -5328,7 +5329,7 @@ cy_init(void) info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->shutdown_wait); @@ -5403,7 +5404,7 @@ cy_init(void) info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->shutdown_wait); diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 60c1695..806f9ce 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -500,9 +500,9 @@ via_dmablit_timer(unsigned long data) static void -via_dmablit_workqueue(void *data) +via_dmablit_workqueue(struct work_struct *work) { - drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; + drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); drm_device_t *dev = blitq->dev; unsigned long irqsave; drm_via_sg_info_t *cur_sg; @@ -571,7 +571,7 @@ via_init_dmablit(drm_device_t *dev) DRM_INIT_WAITQUEUE(blitq->blit_queue + j); } DRM_INIT_WAITQUEUE(&blitq->busy_queue); - INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq); + INIT_WORK(&blitq->wq, via_dmablit_workqueue); init_timer(&blitq->poll_timer); blitq->poll_timer.function = &via_dmablit_timer; blitq->poll_timer.data = (unsigned long) blitq; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 706733c..7c71eb7 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -200,7 +200,7 @@ static int pc_ioctl(struct tty_struct *, struct file *, static int info_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void pc_set_termios(struct tty_struct *, struct termios *); -static void do_softint(void *); +static void do_softint(struct work_struct *work); static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); static void pc_throttle(struct tty_struct * tty); @@ -1505,7 +1505,7 @@ static void post_fep_init(unsigned int crd) ch->brdchan = bc; ch->mailbox = gd; - INIT_WORK(&ch->tqueue, do_softint, ch); + INIT_WORK(&ch->tqueue, do_softint); ch->board = &boards[crd]; spin_lock_irqsave(&epca_lock, flags); @@ -2566,9 +2566,9 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) /* --------------------- Begin do_softint ----------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { /* Begin do_softint */ - struct channel *ch = (struct channel *) private_; + struct channel *ch = container_of(work, struct channel, tqueue); /* Called in response to a modem change event */ if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */ struct tty_struct *tty = ch->tty; diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 15a4ea8..93b5519 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -723,9 +723,10 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * ------------------------------------------------------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue); struct tty_struct *tty; tty = info->tty; @@ -746,9 +747,10 @@ static void do_softint(void *private_) * do_serial_hangup() -> tty->hangup() -> esp_hangup() * */ -static void do_serial_hangup(void *private_) +static void do_serial_hangup(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue_hangup); struct tty_struct *tty; tty = info->tty; @@ -2501,8 +2503,8 @@ static int __init espserial_init(void) info->magic = ESP_MAGIC; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; - INIT_WORK(&info->tqueue, do_softint, info); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + INIT_WORK(&info->tqueue, do_softint); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup); info->config.rx_timeout = rx_timeout; info->config.flow_on = flow_on; info->config.flow_off = flow_off; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 817dc40..23b25ad 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -102,7 +102,7 @@ static void gen_rtc_interrupt(unsigned long arg); * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void genrtc_troutine(void *data) +static void genrtc_troutine(struct work_struct *work) { unsigned int tmp = get_rtc_ss(); @@ -255,7 +255,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit) irq_active = 1; stop_rtc_timers = 0; lostint = 0; - INIT_WORK(&genrtc_task, genrtc_troutine, NULL); + INIT_WORK(&genrtc_task, genrtc_troutine); oldsecs = get_rtc_ss(); init_timer(&timer_task); diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 2cf63e7..82a41d5 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -69,7 +69,7 @@ #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) struct hvsi_struct { - struct work_struct writer; + struct delayed_work writer; struct work_struct handshaker; wait_queue_head_t emptyq; /* woken when outbuf is emptied */ wait_queue_head_t stateq; /* woken when HVSI state changes */ @@ -744,9 +744,10 @@ static int hvsi_handshake(struct hvsi_struct *hp) return 0; } -static void hvsi_handshaker(void *arg) +static void hvsi_handshaker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, handshaker); if (hvsi_handshake(hp) >= 0) return; @@ -951,9 +952,10 @@ static void hvsi_push(struct hvsi_struct *hp) } /* hvsi_write_worker will keep rescheduling itself until outbuf is empty */ -static void hvsi_write_worker(void *arg) +static void hvsi_write_worker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, writer.work); unsigned long flags; #ifdef DEBUG static long start_j = 0; @@ -1287,8 +1289,8 @@ static int __init hvsi_console_init(void) } hp = &hvsi_ports[hvsi_count]; - INIT_WORK(&hp->writer, hvsi_write_worker, hp); - INIT_WORK(&hp->handshaker, hvsi_handshaker, hp); + INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker); + INIT_WORK(&hp->handshaker, hvsi_handshaker); init_waitqueue_head(&hp->emptyq); init_waitqueue_head(&hp->stateq); spin_lock_init(&hp->lock); diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 54d93f0..c213fdb 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c @@ -84,8 +84,8 @@ static void iiSendPendingMail(i2eBordStrPtr); static void serviceOutgoingFifo(i2eBordStrPtr); // Functions defined in ip2.c as part of interrupt handling -static void do_input(void *); -static void do_status(void *); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); //*************** //* Debug Data * @@ -331,8 +331,8 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) pCh->ClosingWaitTime = 30*HZ; // Initialize task queue objects - INIT_WORK(&pCh->tqueue_input, do_input, pCh); - INIT_WORK(&pCh->tqueue_status, do_status, pCh); + INIT_WORK(&pCh->tqueue_input, do_input); + INIT_WORK(&pCh->tqueue_status, do_status); #ifdef IP2DEBUG_TRACE pCh->trace = ip2trace; @@ -1573,7 +1573,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_input); #else - do_input(pCh); + do_input(&pCh->tqueue_input); #endif // Note we do not need to maintain any flow-control credits at this @@ -1810,7 +1810,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_status); #else - do_status(pCh); + do_status(&pCh->tqueue_status); #endif } } diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index a3f32d4..cda2459 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -189,12 +189,12 @@ static int ip2_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void set_irq(int, int); -static void ip2_interrupt_bh(i2eBordStrPtr pB); +static void ip2_interrupt_bh(struct work_struct *work); static irqreturn_t ip2_interrupt(int irq, void *dev_id); static void ip2_poll(unsigned long arg); static inline void service_all_boards(void); -static void do_input(void *p); -static void do_status(void *p); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); static void ip2_wait_until_sent(PTTY,int); @@ -918,7 +918,7 @@ ip2_init_board( int boardnum ) pCh++; } ex_exit: - INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB); + INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); return; err_release_region: @@ -1125,8 +1125,8 @@ service_all_boards(void) /******************************************************************************/ -/* Function: ip2_interrupt_bh(pB) */ -/* Parameters: pB - pointer to the board structure */ +/* Function: ip2_interrupt_bh(work) */ +/* Parameters: work - pointer to the board structure */ /* Returns: Nothing */ /* */ /* Description: */ @@ -1135,8 +1135,9 @@ service_all_boards(void) /* */ /******************************************************************************/ static void -ip2_interrupt_bh(i2eBordStrPtr pB) +ip2_interrupt_bh(struct work_struct *work) { + i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); // pB better well be set or we have a problem! We can only get // here from the IMMEDIATE queue. Here, we process the boards. // Checking pB doesn't cost much and it saves us from the sanity checkers. @@ -1245,9 +1246,9 @@ ip2_poll(unsigned long arg) ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); } -static void do_input(void *p) +static void do_input(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); unsigned long flags; ip2trace(CHANN, ITRC_INPUT, 21, 0 ); @@ -1279,9 +1280,9 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) } } -static void do_status(void *p) +static void do_status(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); int status; status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 58c955e..1637c1d 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -530,9 +530,9 @@ sched_again: /* Interrupt handlers */ -static void isicom_bottomhalf(void *data) +static void isicom_bottomhalf(struct work_struct *work) { - struct isi_port *port = (struct isi_port *) data; + struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); struct tty_struct *tty = port->tty; if (!tty) @@ -1474,9 +1474,9 @@ static void isicom_start(struct tty_struct *tty) } /* hangup et all */ -static void do_isicom_hangup(void *data) +static void do_isicom_hangup(struct work_struct *work) { - struct isi_port *port = data; + struct isi_port *port = container_of(work, struct isi_port, hangup_tq); struct tty_struct *tty; tty = port->tty; @@ -1966,8 +1966,8 @@ static int __devinit isicom_setup(void) port->channel = channel; port->close_delay = 50 * HZ/100; port->closing_wait = 3000 * HZ/100; - INIT_WORK(&port->hangup_tq, do_isicom_hangup, port); - INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port); + INIT_WORK(&port->hangup_tq, do_isicom_hangup); + INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); port->status = 0; init_waitqueue_head(&port->open_wait); init_waitqueue_head(&port->close_wait); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 96cb1f0..2d025a9 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -222,7 +222,7 @@ static struct semaphore moxaBuffSem; /* * static functions: */ -static void do_moxa_softint(void *); +static void do_moxa_softint(struct work_struct *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); static int moxa_write(struct tty_struct *, const unsigned char *, int); @@ -363,7 +363,7 @@ static int __init moxa_init(void) for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; - INIT_WORK(&ch->tqueue, do_moxa_softint, ch); + INIT_WORK(&ch->tqueue, do_moxa_softint); ch->tty = NULL; ch->close_delay = 5 * HZ / 10; ch->closing_wait = 30 * HZ; @@ -509,9 +509,9 @@ static void __exit moxa_exit(void) module_init(moxa_init); module_exit(moxa_exit); -static void do_moxa_softint(void *private_) +static void do_moxa_softint(struct work_struct *work) { - struct moxa_str *ch = (struct moxa_str *) private_; + struct moxa_str *ch = container_of(work, struct moxa_str, tqueue); struct tty_struct *tty; if (ch && (tty = ch->tty)) { diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 048d911..5ed2486 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -389,7 +389,7 @@ static int mxser_init(void); /* static void mxser_poll(unsigned long); */ static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *); -static void mxser_do_softint(void *); +static void mxser_do_softint(struct work_struct *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); static int mxser_write(struct tty_struct *, const unsigned char *, int); @@ -590,7 +590,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) info->custom_divisor = hwconf->baud_base[i] * 16; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; - INIT_WORK(&info->tqueue, mxser_do_softint, info); + INIT_WORK(&info->tqueue, mxser_do_softint); info->normal_termios = mxvar_sdriver->init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); @@ -917,9 +917,10 @@ static int mxser_init(void) return 0; } -static void mxser_do_softint(void *private_) +static void mxser_do_softint(struct work_struct *work) { - struct mxser_struct *info = private_; + struct mxser_struct *info = + container_of(work, struct mxser_struct, tqueue); struct tty_struct *tty; tty = info->tty; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 1a0bc30..e4d9500 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -421,7 +421,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id); /* * Bottom half interrupt handlers */ -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_transmit(MGSLPC_INFO *info); static void bh_status(MGSLPC_INFO *info); @@ -547,7 +547,7 @@ static int mgslpc_probe(struct pcmcia_device *link) memset(info, 0, sizeof(MGSLPC_INFO)); info->magic = MGSLPC_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -842,9 +842,9 @@ static int bh_action(MGSLPC_INFO *info) return rc; } -static void bh_handler(void* Context) +static void bh_handler(struct work_struct *work) { - MGSLPC_INFO *info = (MGSLPC_INFO*)Context; + MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); int action; if (!info) diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index c084149..fc87070 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -765,7 +765,7 @@ static void sonypi_setbluetoothpower(u8 state) sonypi_device.bluetooth_power = state; } -static void input_keyrelease(void *data) +static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; @@ -1412,7 +1412,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) goto err_inpdev_unregister; } - INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); + INIT_WORK(&sonypi_device.input_work, input_keyrelease); } sonypi_enable(0); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 7e1bd95..99137ab 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -2261,9 +2261,10 @@ static void sx_start(struct tty_struct * tty) * do_sx_hangup() -> tty->hangup() -> sx_hangup() * */ -static void do_sx_hangup(void *private_) +static void do_sx_hangup(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue_hangup); struct tty_struct *tty; func_enter(); @@ -2336,9 +2337,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios } -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue); struct tty_struct *tty; func_enter(); @@ -2411,8 +2413,8 @@ static int sx_init_drivers(void) memset(sx_port, 0, sizeof(sx_port)); for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { sx_port[i].magic = SPECIALIX_MAGIC; - INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]); - INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]); + INIT_WORK(&sx_port[i].tqueue, do_softint); + INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup); sx_port[i].close_delay = 50 * HZ/100; sx_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&sx_port[i].open_wait); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 06784ad..147c30d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -802,7 +802,7 @@ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, u /* * Bottom half interrupt handlers */ -static void mgsl_bh_handler(void* Context); +static void mgsl_bh_handler(struct work_struct *work); static void mgsl_bh_receive(struct mgsl_struct *info); static void mgsl_bh_transmit(struct mgsl_struct *info); static void mgsl_bh_status(struct mgsl_struct *info); @@ -1071,9 +1071,10 @@ static int mgsl_bh_action(struct mgsl_struct *info) /* * Perform bottom half processing of work items queued by ISR. */ -static void mgsl_bh_handler(void* Context) +static void mgsl_bh_handler(struct work_struct *work) { - struct mgsl_struct *info = (struct mgsl_struct*)Context; + struct mgsl_struct *info = + container_of(work, struct mgsl_struct, task); int action; if (!info) @@ -4337,7 +4338,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) } else { memset(info, 0, sizeof(struct mgsl_struct)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, mgsl_bh_handler, info); + INIT_WORK(&info->task, mgsl_bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index d4334c7..07f34d4 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -485,7 +485,7 @@ static void enable_loopback(struct slgt_info *info); static void set_rate(struct slgt_info *info, u32 data_rate); static int bh_action(struct slgt_info *info); -static void bh_handler(void* context); +static void bh_handler(struct work_struct *work); static void bh_transmit(struct slgt_info *info); static void isr_serial(struct slgt_info *info); static void isr_rdma(struct slgt_info *info); @@ -1878,9 +1878,9 @@ static int bh_action(struct slgt_info *info) /* * perform bottom half processing */ -static void bh_handler(void* context) +static void bh_handler(struct work_struct *work) { - struct slgt_info *info = context; + struct slgt_info *info = container_of(work, struct slgt_info, task); int action; if (!info) @@ -3326,7 +3326,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev } else { memset(info, 0, sizeof(struct slgt_info)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->raw_rx_size = DMABUFSIZE; info->close_delay = 5*HZ/10; @@ -4799,6 +4799,6 @@ static void rx_timeout(unsigned long context) spin_lock_irqsave(&info->lock, flags); info->pending_bh |= BH_RECEIVE; spin_unlock_irqrestore(&info->lock, flags); - bh_handler(info); + bh_handler(&info->task); } diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 3e932b6..13a5724 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -602,7 +602,7 @@ static void enable_loopback(SLMP_INFO *info, int enable); static void set_rate(SLMP_INFO *info, u32 data_rate); static int bh_action(SLMP_INFO *info); -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_receive(SLMP_INFO *info); static void bh_transmit(SLMP_INFO *info); static void bh_status(SLMP_INFO *info); @@ -2063,9 +2063,9 @@ int bh_action(SLMP_INFO *info) /* Perform bottom half processing of work items queued by ISR. */ -void bh_handler(void* Context) +void bh_handler(struct work_struct *work) { - SLMP_INFO *info = (SLMP_INFO*)Context; + SLMP_INFO *info = container_of(work, SLMP_INFO, task); int action; if (!info) @@ -3805,7 +3805,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) } else { memset(info, 0, sizeof(SLMP_INFO)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 6ad2d3b..36f91a6 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -325,9 +325,9 @@ static void user_reader_timeout(unsigned long ptr) schedule_work(&chip->work); } -static void timeout_work(void *ptr) +static void timeout_work(struct work_struct *work) { - struct tpm_chip *chip = ptr; + struct tpm_chip *chip = container_of(work, struct tpm_chip, work); down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); @@ -1105,7 +1105,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend init_MUTEX(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); - INIT_WORK(&chip->work, timeout_work, chip); + INIT_WORK(&chip->work, timeout_work); init_timer(&chip->user_read_timer); chip->user_read_timer.function = user_reader_timeout; diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 05f8ce2..b418b16 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -31,9 +31,11 @@ #include #include -void cn_queue_wrapper(void *data) +void cn_queue_wrapper(struct work_struct *work) { - struct cn_callback_data *d = data; + struct cn_callback_entry *cbq = + container_of(work, struct cn_callback_entry, work.work); + struct cn_callback_data *d = &cbq->data; d->callback(d->callback_priv); @@ -57,7 +59,7 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc memcpy(&cbq->id.id, id, sizeof(struct cb_id)); cbq->data.callback = callback; - INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data); + INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper); return cbq; } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index b49bacf..5e7cd45 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -135,40 +135,39 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) { - if (likely(!test_bit(0, &__cbq->work.pending) && + if (likely(!test_bit(WORK_STRUCT_PENDING, + &__cbq->work.work.management) && __cbq->data.ddata == NULL)) { __cbq->data.callback_priv = msg; __cbq->data.ddata = data; __cbq->data.destruct_data = destruct_data; - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; } else { - struct work_struct *w; struct cn_callback_data *d; - w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC); - if (w) { - d = (struct cn_callback_data *)(w+1); - + __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); + if (__cbq) { + d = &__cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = w; + d->free = __cbq; - INIT_LIST_HEAD(&w->entry); - w->pending = 0; - w->func = &cn_queue_wrapper; - w->data = d; - init_timer(&w->timer); + INIT_DELAYED_WORK(&__cbq->work, + &cn_queue_wrapper); - if (queue_work(dev->cbdev->cn_queue, w)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; else { - kfree(w); + kfree(__cbq); err = -EINVAL; } } else diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c4c578d..5ef5ede 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -59,7 +59,7 @@ static unsigned int def_sampling_rate; #define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { struct cpufreq_policy *cur_policy; @@ -82,7 +82,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * is recursive for the same process. -Venki */ static DEFINE_MUTEX (dbs_mutex); -static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); +static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { unsigned int sampling_rate; @@ -420,7 +420,7 @@ static void dbs_check_cpu(int cpu) } } -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { int i; lock_cpu_hotplug(); @@ -435,7 +435,6 @@ static void do_dbs_timer(void *data) static inline void dbs_timer_init(void) { - INIT_WORK(&dbs_work, do_dbs_timer, NULL); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); return; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bf8aa45..e1cc511 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -47,13 +47,17 @@ static unsigned int def_sampling_rate; #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); + +/* Sampling types */ +enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; cputime64_t prev_cpu_wall; struct cpufreq_policy *cur_policy; - struct work_struct work; + struct delayed_work work; + enum dbs_sample sample_type; unsigned int enable; struct cpufreq_frequency_table *freq_table; unsigned int freq_lo; @@ -407,30 +411,31 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) } } -/* Sampling types */ -enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; - -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { unsigned int cpu = smp_processor_id(); struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); + enum dbs_sample sample_type = dbs_info->sample_type; /* We want all CPUs to do sampling nearly on same jiffy */ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + /* Permit rescheduling of this work item */ + work_release(work); + delay -= jiffies % delay; if (!dbs_info->enable) return; /* Common NORMAL_SAMPLE setup */ - INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; if (!dbs_tuners_ins.powersave_bias || - (unsigned long) data == DBS_NORMAL_SAMPLE) { + sample_type == DBS_NORMAL_SAMPLE) { lock_cpu_hotplug(); dbs_check_cpu(dbs_info); unlock_cpu_hotplug(); if (dbs_info->freq_lo) { /* Setup timer for SUB_SAMPLE */ - INIT_WORK(&dbs_info->work, do_dbs_timer, - (void *)DBS_SUB_SAMPLE); + dbs_info->sample_type = DBS_SUB_SAMPLE; delay = dbs_info->freq_hi_jiffies; } } else { @@ -449,7 +454,8 @@ static inline void dbs_timer_init(unsigned int cpu) delay -= jiffies % delay; ondemand_powersave_bias_init(); - INIT_WORK(&dbs_info->work, do_dbs_timer, NULL); + INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); } diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index 4630f19..15edf40 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c @@ -140,12 +140,14 @@ ulong ds1374_get_rtc_time(void) return t1; } -static void ds1374_set_work(void *arg) +static ulong new_time; + +static void ds1374_set_work(struct work_struct *work) { ulong t1, t2; int limit = 10; /* arbitrary retry limit */ - t1 = *(ulong *) arg; + t1 = new_time; mutex_lock(&ds1374_mutex); @@ -167,11 +169,9 @@ static void ds1374_set_work(void *arg) "can't confirm time set from rtc chip\n"); } -static ulong new_time; - static struct workqueue_struct *ds1374_workqueue; -static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time); +static DECLARE_WORK(ds1374_work, ds1374_set_work); int ds1374_set_rtc_time(ulong nowtime) { @@ -180,7 +180,7 @@ int ds1374_set_rtc_time(ulong nowtime) if (in_interrupt()) queue_work(ds1374_workqueue, &ds1374_work); else - ds1374_set_work(&new_time); + ds1374_set_work(NULL); return 0; } diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index d90a3a1..8f4378a 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -31,9 +31,10 @@ #include "config_roms.h" -static void delayed_reset_bus(void * __reset_info) +static void delayed_reset_bus(struct work_struct *work) { - struct hpsb_host *host = (struct hpsb_host*)__reset_info; + struct hpsb_host *host = + container_of(work, struct hpsb_host, delayed_reset.work); int generation = host->csr.generation + 1; /* The generation field rolls over to 2 rather than 0 per IEEE @@ -145,7 +146,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, atomic_set(&h->generation, 0); - INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); + INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus); init_timer(&h->timeout); h->timeout.data = (unsigned long) h; @@ -234,7 +235,7 @@ int hpsb_update_config_rom_image(struct hpsb_host *host) * Config ROM in the near future. */ reset_delay = HZ; - PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host); + PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus); schedule_delayed_work(&host->delayed_reset, reset_delay); return 0; diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index bc6dbfa..d553e38 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -62,7 +62,7 @@ struct hpsb_host { struct class_device class_dev; int update_config_rom; - struct work_struct delayed_reset; + struct delayed_work delayed_reset; unsigned int config_roms; struct list_head addr_space; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 6986ac1..cd156d4 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -493,20 +493,25 @@ static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, scsi_unblock_requests(scsi_id->scsi_host); } -static void sbp2util_write_orb_pointer(void *p) +static void sbp2util_write_orb_pointer(struct work_struct *work) { + struct scsi_id_instance_data *scsi_id = + container_of(work, struct scsi_id_instance_data, + protocol_work.work); quadlet_t data[2]; - data[0] = ORB_SET_NODE_ID( - ((struct scsi_id_instance_data *)p)->hi->host->node_id); - data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma; + data[0] = ORB_SET_NODE_ID(scsi_id->hi->host->node_id); + data[1] = scsi_id->last_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8); + sbp2util_notify_fetch_agent(scsi_id, SBP2_ORB_POINTER_OFFSET, data, 8); } -static void sbp2util_write_doorbell(void *p) +static void sbp2util_write_doorbell(struct work_struct *work) { - sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4); + struct scsi_id_instance_data *scsi_id = + container_of(work, struct scsi_id_instance_data, + protocol_work.work); + sbp2util_notify_fetch_agent(scsi_id, SBP2_DOORBELL_OFFSET, NULL, 4); } /* @@ -843,7 +848,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); - INIT_WORK(&scsi_id->protocol_work, NULL, NULL); + INIT_DELAYED_WORK(&scsi_id->protocol_work, NULL); ud->device.driver_data = scsi_id; @@ -2047,11 +2052,10 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, * We do not accept new commands until the job is over. */ scsi_block_requests(scsi_id->scsi_host); - PREPARE_WORK(&scsi_id->protocol_work, + PREPARE_DELAYED_WORK(&scsi_id->protocol_work, last_orb ? sbp2util_write_doorbell: - sbp2util_write_orb_pointer, - scsi_id); - schedule_work(&scsi_id->protocol_work); + sbp2util_write_orb_pointer); + schedule_delayed_work(&scsi_id->protocol_work, 0); } } diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index abbe48e..1b16d6b 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -348,7 +348,7 @@ struct scsi_id_instance_data { unsigned workarounds; atomic_t state; - struct work_struct protocol_work; + struct delayed_work protocol_work; }; /* For use in scsi_id_instance_data.state */ diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index e11187e..84b2f5c 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -55,11 +55,11 @@ struct addr_req { int status; }; -static void process_req(void *data); +static void process_req(struct work_struct *work); static DEFINE_MUTEX(lock); static LIST_HEAD(req_list); -static DECLARE_WORK(work, process_req, NULL); +static DECLARE_DELAYED_WORK(work, process_req); static struct workqueue_struct *addr_wq; void rdma_addr_register_client(struct rdma_addr_client *client) @@ -215,7 +215,7 @@ out: return ret; } -static void process_req(void *data) +static void process_req(struct work_struct *work) { struct addr_req *req, *temp_req; struct sockaddr_in *src_in, *dst_in; diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 20e9f64..98272fb 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -285,9 +285,10 @@ err: kfree(tprops); } -static void ib_cache_task(void *work_ptr) +static void ib_cache_task(struct work_struct *_work) { - struct ib_update_work *work = work_ptr; + struct ib_update_work *work = + container_of(_work, struct ib_update_work, work); ib_cache_update(work->device, work->port_num); kfree(work); @@ -306,7 +307,7 @@ static void ib_cache_event(struct ib_event_handler *handler, event->event == IB_EVENT_CLIENT_REREGISTER) { work = kmalloc(sizeof *work, GFP_ATOMIC); if (work) { - INIT_WORK(&work->work, ib_cache_task, work); + INIT_WORK(&work->work, ib_cache_task); work->device = event->device; work->port_num = event->element.port_num; schedule_work(&work->work); diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 25b1018..e1990f5 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -101,7 +101,7 @@ struct cm_av { }; struct cm_work { - struct work_struct work; + struct delayed_work work; struct list_head list; struct cm_port *port; struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */ @@ -161,7 +161,7 @@ struct cm_id_private { atomic_t work_count; }; -static void cm_work_handler(void *data); +static void cm_work_handler(struct work_struct *work); static inline void cm_deref_id(struct cm_id_private *cm_id_priv) { @@ -669,8 +669,7 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id) return ERR_PTR(-ENOMEM); timewait_info->work.local_id = local_id; - INIT_WORK(&timewait_info->work.work, cm_work_handler, - &timewait_info->work); + INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler); timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT; return timewait_info; } @@ -2987,9 +2986,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent, } } -static void cm_work_handler(void *data) +static void cm_work_handler(struct work_struct *_work) { - struct cm_work *work = data; + struct cm_work *work = container_of(_work, struct cm_work, work.work); int ret; switch (work->cm_event.event) { @@ -3079,12 +3078,12 @@ int ib_cm_establish(struct ib_cm_id *cm_id) * we need to find the cm_id once we're in the context of the * worker thread, rather than holding a reference on it. */ - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->local_id = cm_id->local_id; work->remote_id = cm_id->remote_id; work->mad_recv_wc = NULL; work->cm_event.event = IB_CM_USER_ESTABLISHED; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); out: return ret; } @@ -3146,11 +3145,11 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, return; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->cm_event.event = event; work->mad_recv_wc = mad_recv_wc; work->port = (struct cm_port *)mad_agent->context; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); } static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 845090b..189f73f 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1341,9 +1341,9 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, return (id_priv->query_id < 0) ? id_priv->query_id : 0; } -static void cma_work_handler(void *data) +static void cma_work_handler(struct work_struct *_work) { - struct cma_work *work = data; + struct cma_work *work = container_of(_work, struct cma_work, work); struct rdma_id_private *id_priv = work->id; int destroy = 0; @@ -1374,7 +1374,7 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1431,7 +1431,7 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1585,7 +1585,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) } work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ADDR_QUERY; work->new_state = CMA_ADDR_RESOLVED; work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index c3fb304..9bfa785 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -828,9 +828,10 @@ static int process_event(struct iwcm_id_private *cm_id_priv, * thread asleep on the destroy_comp list vs. an object destroyed * here synchronously when the last reference is removed. */ -static void cm_work_handler(void *arg) +static void cm_work_handler(struct work_struct *_work) { - struct iwcm_work *work = arg, lwork; + struct iwcm_work lwork, *work = + container_of(_work, struct iwcm_work, work); struct iwcm_id_private *cm_id_priv = work->cm_id; unsigned long flags; int empty; @@ -899,7 +900,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id, goto out; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_WORK(&work->work, cm_work_handler); work->cm_id = cm_id_priv; work->event = *iw_event; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a72bcea..5a54ac3 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -65,8 +65,8 @@ static struct ib_mad_agent_private *find_mad_agent( static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, struct ib_mad_private *mad); static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv); -static void timeout_sends(void *data); -static void local_completions(void *data); +static void timeout_sends(struct work_struct *work); +static void local_completions(struct work_struct *work); static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req, struct ib_mad_agent_private *agent_priv, u8 mgmt_class); @@ -356,10 +356,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, INIT_LIST_HEAD(&mad_agent_priv->wait_list); INIT_LIST_HEAD(&mad_agent_priv->done_list); INIT_LIST_HEAD(&mad_agent_priv->rmpp_list); - INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv); + INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); INIT_LIST_HEAD(&mad_agent_priv->local_list); - INIT_WORK(&mad_agent_priv->local_work, local_completions, - mad_agent_priv); + INIT_WORK(&mad_agent_priv->local_work, local_completions); atomic_set(&mad_agent_priv->refcount, 1); init_completion(&mad_agent_priv->comp); @@ -2198,12 +2197,12 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv, /* * IB MAD completion callback */ -static void ib_mad_completion_handler(void *data) +static void ib_mad_completion_handler(struct work_struct *work) { struct ib_mad_port_private *port_priv; struct ib_wc wc; - port_priv = (struct ib_mad_port_private *)data; + port_priv = container_of(work, struct ib_mad_port_private, work); ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP); while (ib_poll_cq(port_priv->cq, 1, &wc) == 1) { @@ -2324,7 +2323,7 @@ void ib_cancel_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_cancel_mad); -static void local_completions(void *data) +static void local_completions(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_local_private *local; @@ -2334,7 +2333,8 @@ static void local_completions(void *data) struct ib_wc wc; struct ib_mad_send_wc mad_send_wc; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = + container_of(work, struct ib_mad_agent_private, local_work); spin_lock_irqsave(&mad_agent_priv->lock, flags); while (!list_empty(&mad_agent_priv->local_list)) { @@ -2434,14 +2434,15 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) return ret; } -static void timeout_sends(void *data) +static void timeout_sends(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags, delay; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = container_of(work, struct ib_mad_agent_private, + timed_work.work); mad_send_wc.vendor_err = 0; spin_lock_irqsave(&mad_agent_priv->lock, flags); @@ -2799,7 +2800,7 @@ static int ib_mad_port_open(struct ib_device *device, ret = -ENOMEM; goto error8; } - INIT_WORK(&port_priv->work, ib_mad_completion_handler, port_priv); + INIT_WORK(&port_priv->work, ib_mad_completion_handler); spin_lock_irqsave(&ib_mad_port_list_lock, flags); list_add_tail(&port_priv->port_list, &ib_mad_port_list); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index d06b590..d5548e7 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -102,7 +102,7 @@ struct ib_mad_agent_private { struct list_head send_list; struct list_head wait_list; struct list_head done_list; - struct work_struct timed_work; + struct delayed_work timed_work; unsigned long timeout; struct list_head local_list; struct work_struct local_work; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 1ef79d0..3663fd7 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -45,8 +45,8 @@ enum rmpp_state { struct mad_rmpp_recv { struct ib_mad_agent_private *agent; struct list_head list; - struct work_struct timeout_work; - struct work_struct cleanup_work; + struct delayed_work timeout_work; + struct delayed_work cleanup_work; struct completion comp; enum rmpp_state state; spinlock_t lock; @@ -233,9 +233,10 @@ static void nack_recv(struct ib_mad_agent_private *agent, } } -static void recv_timeout_handler(void *data) +static void recv_timeout_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, timeout_work.work); struct ib_mad_recv_wc *rmpp_wc; unsigned long flags; @@ -254,9 +255,10 @@ static void recv_timeout_handler(void *data) ib_free_recv_mad(rmpp_wc); } -static void recv_cleanup_handler(void *data) +static void recv_cleanup_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, cleanup_work.work); unsigned long flags; spin_lock_irqsave(&rmpp_recv->agent->lock, flags); @@ -285,8 +287,8 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, rmpp_recv->agent = agent; init_completion(&rmpp_recv->comp); - INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv); - INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv); + INIT_DELAYED_WORK(&rmpp_recv->timeout_work, recv_timeout_handler); + INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler); spin_lock_init(&rmpp_recv->lock); rmpp_recv->state = RMPP_STATE_ACTIVE; atomic_set(&rmpp_recv->refcount, 1); diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 1706d3c..e45afba 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -360,9 +360,10 @@ static void free_sm_ah(struct kref *kref) kfree(sm_ah); } -static void update_sm_ah(void *port_ptr) +static void update_sm_ah(struct work_struct *work) { - struct ib_sa_port *port = port_ptr; + struct ib_sa_port *port = + container_of(work, struct ib_sa_port, update_task); struct ib_sa_sm_ah *new_ah, *old_ah; struct ib_port_attr port_attr; struct ib_ah_attr ah_attr; @@ -992,8 +993,7 @@ static void ib_sa_add_one(struct ib_device *device) if (IS_ERR(sa_dev->port[i].agent)) goto err; - INIT_WORK(&sa_dev->port[i].update_task, - update_sm_ah, &sa_dev->port[i]); + INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); } ib_set_client_data(device, &sa_client, sa_dev); @@ -1010,7 +1010,7 @@ static void ib_sa_add_one(struct ib_device *device) goto err; for (i = 0; i <= e - s; ++i) - update_sm_ah(&sa_dev->port[i]); + update_sm_ah(&sa_dev->port[i].update_task); return; diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c index efe147d..db12cc0 100644 --- a/drivers/infiniband/core/uverbs_mem.c +++ b/drivers/infiniband/core/uverbs_mem.c @@ -179,9 +179,10 @@ void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) up_write(¤t->mm->mmap_sem); } -static void ib_umem_account(void *work_ptr) +static void ib_umem_account(struct work_struct *_work) { - struct ib_umem_account_work *work = work_ptr; + struct ib_umem_account_work *work = + container_of(_work, struct ib_umem_account_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->diff; @@ -216,7 +217,7 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) return; } - INIT_WORK(&work->work, ib_umem_account, work); + INIT_WORK(&work->work, ib_umem_account); work->mm = mm; work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index 413754b..8536aeb 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c @@ -214,9 +214,10 @@ struct ipath_user_pages_work { unsigned long num_pages; }; -static void user_pages_account(void *ptr) +static void user_pages_account(struct work_struct *_work) { - struct ipath_user_pages_work *work = ptr; + struct ipath_user_pages_work *work = + container_of(_work, struct ipath_user_pages_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->num_pages; @@ -242,7 +243,7 @@ void ipath_release_user_pages_on_close(struct page **p, size_t num_pages) goto bail; - INIT_WORK(&work->work, user_pages_account, work); + INIT_WORK(&work->work, user_pages_account); work->mm = mm; work->num_pages = num_pages; diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index cd044ea..e948158 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -57,7 +57,7 @@ static int catas_reset_disable; module_param_named(catas_reset_disable, catas_reset_disable, int, 0644); MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero"); -static void catas_reset(void *work_ptr) +static void catas_reset(struct work_struct *work) { struct mthca_dev *dev, *tmpdev; LIST_HEAD(tlist); @@ -203,7 +203,7 @@ void mthca_stop_catas_poll(struct mthca_dev *dev) int __init mthca_catas_init(void) { - INIT_WORK(&catas_work, catas_reset, NULL); + INIT_WORK(&catas_work, catas_reset); catas_wq = create_singlethread_workqueue("mthca_catas"); if (!catas_wq) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 0b8a79d..3b2ee0e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -136,11 +136,11 @@ struct ipoib_dev_priv { struct list_head multicast_list; struct rb_root multicast_tree; - struct work_struct pkey_task; - struct work_struct mcast_task; + struct delayed_work pkey_task; + struct delayed_work mcast_task; struct work_struct flush_task; struct work_struct restart_task; - struct work_struct ah_reap_task; + struct delayed_work ah_reap_task; struct ib_device *ca; u8 port; @@ -254,13 +254,13 @@ int ipoib_add_pkey_attr(struct net_device *dev); void ipoib_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_ah *address, u32 qpn); -void ipoib_reap_ah(void *dev_ptr); +void ipoib_reap_ah(struct work_struct *work); void ipoib_flush_paths(struct net_device *dev); struct ipoib_dev_priv *ipoib_intf_alloc(const char *format); int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port); -void ipoib_ib_dev_flush(void *dev); +void ipoib_ib_dev_flush(struct work_struct *work); void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); @@ -271,10 +271,10 @@ int ipoib_ib_dev_stop(struct net_device *dev); int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); void ipoib_dev_cleanup(struct net_device *dev); -void ipoib_mcast_join_task(void *dev_ptr); +void ipoib_mcast_join_task(struct work_struct *work); void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); -void ipoib_mcast_restart_task(void *dev_ptr); +void ipoib_mcast_restart_task(struct work_struct *work); int ipoib_mcast_start_thread(struct net_device *dev); int ipoib_mcast_stop_thread(struct net_device *dev, int flush); @@ -312,7 +312,7 @@ void ipoib_event(struct ib_event_handler *handler, int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey); int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey); -void ipoib_pkey_poll(void *dev); +void ipoib_pkey_poll(struct work_struct *work); int ipoib_pkey_dev_delay_open(struct net_device *dev); #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8bf5e9e..f10fba5d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -400,10 +400,11 @@ static void __ipoib_reap_ah(struct net_device *dev) spin_unlock_irq(&priv->tx_lock); } -void ipoib_reap_ah(void *dev_ptr) +void ipoib_reap_ah(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, ah_reap_task.work); + struct net_device *dev = priv->dev; __ipoib_reap_ah(dev); @@ -613,10 +614,11 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return 0; } -void ipoib_ib_dev_flush(void *_dev) +void ipoib_ib_dev_flush(struct work_struct *work) { - struct net_device *dev = (struct net_device *)_dev; - struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv; + struct ipoib_dev_priv *cpriv, *priv = + container_of(work, struct ipoib_dev_priv, flush_task); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) { ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); @@ -638,14 +640,14 @@ void ipoib_ib_dev_flush(void *_dev) */ if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { ipoib_ib_dev_up(dev); - ipoib_mcast_restart_task(dev); + ipoib_mcast_restart_task(&priv->restart_task); } mutex_lock(&priv->vlan_mutex); /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) - ipoib_ib_dev_flush(cpriv->dev); + ipoib_ib_dev_flush(&cpriv->flush_task); mutex_unlock(&priv->vlan_mutex); } @@ -672,10 +674,11 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) * change async notification is available. */ -void ipoib_pkey_poll(void *dev_ptr) +void ipoib_pkey_poll(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, pkey_task.work); + struct net_device *dev = priv->dev; ipoib_pkey_dev_check_presence(dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 85522da..71114a8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -933,11 +933,11 @@ static void ipoib_setup(struct net_device *dev) INIT_LIST_HEAD(&priv->dead_ahs); INIT_LIST_HEAD(&priv->multicast_list); - INIT_WORK(&priv->pkey_task, ipoib_pkey_poll, priv->dev); - INIT_WORK(&priv->mcast_task, ipoib_mcast_join_task, priv->dev); - INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush, priv->dev); - INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task, priv->dev); - INIT_WORK(&priv->ah_reap_task, ipoib_reap_ah, priv->dev); + INIT_DELAYED_WORK(&priv->pkey_task, ipoib_pkey_poll); + INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); + INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush); + INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); + INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); } struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3faa182..f0a4fac 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -399,7 +399,8 @@ static void ipoib_mcast_join_complete(int status, mcast->backoff = 1; mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, + &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); complete(&mcast->done); return; @@ -435,7 +436,8 @@ static void ipoib_mcast_join_complete(int status, if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { if (status == -ETIMEDOUT) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, + 0); else queue_delayed_work(ipoib_workqueue, &priv->mcast_task, mcast->backoff * HZ); @@ -517,10 +519,11 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, mcast->query_id = ret; } -void ipoib_mcast_join_task(void *dev_ptr) +void ipoib_mcast_join_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, mcast_task.work); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_MCAST_RUN, &priv->flags)) return; @@ -610,7 +613,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) mutex_lock(&mcast_mutex); if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); spin_lock_irq(&priv->lock); @@ -818,10 +821,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -void ipoib_mcast_restart_task(void *dev_ptr) +void ipoib_mcast_restart_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, restart_task); + struct net_device *dev = priv->dev; struct dev_mc_list *mclist; struct ipoib_mcast *mcast, *tmcast; LIST_HEAD(remove_list); diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 18a0000..693b770 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -48,7 +48,7 @@ static void iser_cq_tasklet_fn(unsigned long data); static void iser_cq_callback(struct ib_cq *cq, void *cq_context); -static void iser_comp_error_worker(void *data); +static void iser_comp_error_worker(struct work_struct *work); static void iser_cq_event_callback(struct ib_event *cause, void *context) { @@ -480,8 +480,7 @@ int iser_conn_init(struct iser_conn **ibconn) init_waitqueue_head(&ib_conn->wait); atomic_set(&ib_conn->post_recv_buf_count, 0); atomic_set(&ib_conn->post_send_buf_count, 0); - INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker, - ib_conn); + INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker); INIT_LIST_HEAD(&ib_conn->conn_list); spin_lock_init(&ib_conn->lock); @@ -754,9 +753,10 @@ int iser_post_send(struct iser_desc *tx_desc) return ret_val; } -static void iser_comp_error_worker(void *data) +static void iser_comp_error_worker(struct work_struct *work) { - struct iser_conn *ib_conn = data; + struct iser_conn *ib_conn = + container_of(work, struct iser_conn, comperror_work); /* getting here when the state is UP means that the conn is being * * terminated asynchronously from the iSCSI layer's perspective. */ diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4b09147..214f661 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -390,9 +390,10 @@ static void srp_disconnect_target(struct srp_target_port *target) wait_for_completion(&target->done); } -static void srp_remove_work(void *target_ptr) +static void srp_remove_work(struct work_struct *work) { - struct srp_target_port *target = target_ptr; + struct srp_target_port *target = + container_of(work, struct srp_target_port, work); spin_lock_irq(target->scsi_host->host_lock); if (target->state != SRP_TARGET_DEAD) { @@ -575,7 +576,7 @@ err: spin_lock_irq(target->scsi_host->host_lock); if (target->state == SRP_TARGET_CONNECTING) { target->state = SRP_TARGET_DEAD; - INIT_WORK(&target->work, srp_remove_work, target); + INIT_WORK(&target->work, srp_remove_work); schedule_work(&target->work); } spin_unlock_irq(target->scsi_host->host_lock); diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 979b93e..b7f049b 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -572,9 +572,9 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, * were in. */ static void -lkkbd_reinit (void *data) +lkkbd_reinit (struct work_struct *work) { - struct lkkbd *lk = data; + struct lkkbd *lk = container_of(work, struct lkkbd, tq); int division; unsigned char leds_on = 0; unsigned char leds_off = 0; @@ -651,7 +651,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) lk->serio = serio; lk->dev = input_dev; - INIT_WORK (&lk->tq, lkkbd_reinit, lk); + INIT_WORK (&lk->tq, lkkbd_reinit); lk->bell_volume = bell_volume; lk->keyclick_volume = keyclick_volume; lk->ctrlclick_volume = ctrlclick_volume; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index cac4781..6cd887c 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -208,9 +208,9 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) * were in. */ -static void sunkbd_reinit(void *data) +static void sunkbd_reinit(struct work_struct *work) { - struct sunkbd *sunkbd = data; + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); @@ -248,7 +248,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) sunkbd->serio = serio; sunkbd->dev = input_dev; init_waitqueue_head(&sunkbd->wait); - INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd); + INIT_WORK(&sunkbd->tq, sunkbd_reinit); snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys); serio_set_drvdata(serio, sunkbd); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 6f9b2c7..52bb222 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -888,9 +888,10 @@ static int psmouse_poll(struct psmouse *psmouse) * psmouse_resync() attempts to re-validate current protocol. */ -static void psmouse_resync(void *p) +static void psmouse_resync(struct work_struct *work) { - struct psmouse *psmouse = p, *parent = NULL; + struct psmouse *parent = NULL, *psmouse = + container_of(work, struct psmouse, resync_work); struct serio *serio = psmouse->ps2dev.serio; psmouse_ret_t rc = PSMOUSE_GOOD_DATA; int failed = 0, enabled = 0; @@ -1121,7 +1122,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) goto out; ps2_init(&psmouse->ps2dev, serio); - INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); + INIT_WORK(&psmouse->resync_work, psmouse_resync); psmouse->dev = input_dev; snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c index 6ae6eb3..946c38c 100644 --- a/drivers/isdn/act2000/capi.c +++ b/drivers/isdn/act2000/capi.c @@ -627,8 +627,10 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { } void -actcapi_dispatch(act2000_card *card) +actcapi_dispatch(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, rcv_tq); struct sk_buff *skb; actcapi_msg *msg; __u16 ccmd; diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h index 49f453c..e55f6a9 100644 --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h @@ -356,7 +356,7 @@ extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *); extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *); extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8); -extern void actcapi_dispatch(act2000_card *); +extern void actcapi_dispatch(struct work_struct *); #ifdef DEBUG_MSG extern void actcapi_debug_msg(struct sk_buff *skb, int); #else diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index d89dcde..90593e2 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -192,8 +192,11 @@ act2000_set_msn(act2000_card *card, char *eazmsn) } static void -act2000_transmit(struct act2000_card *card) +act2000_transmit(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, snd_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_send(card); @@ -207,8 +210,11 @@ act2000_transmit(struct act2000_card *card) } static void -act2000_receive(struct act2000_card *card) +act2000_receive(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, poll_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_receive(card); @@ -227,7 +233,7 @@ act2000_poll(unsigned long data) act2000_card * card = (act2000_card *)data; unsigned long flags; - act2000_receive(card); + act2000_receive(&card->poll_tq); spin_lock_irqsave(&card->lock, flags); mod_timer(&card->ptimer, jiffies+3); spin_unlock_irqrestore(&card->lock, flags); @@ -578,9 +584,9 @@ act2000_alloccard(int bus, int port, int irq, char *id) skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->ackq); - INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card); - INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card); - INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card); + INIT_WORK(&card->snd_tq, act2000_transmit); + INIT_WORK(&card->rcv_tq, actcapi_dispatch); + INIT_WORK(&card->poll_tq, act2000_receive); init_timer(&card->ptimer); card->interface.owner = THIS_MODULE; card->interface.channels = ACT2000_BCH; diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 8c4fcb9..783a255 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -208,9 +208,10 @@ static void notify_down(u32 contr) } } -static void notify_handler(void *data) +static void notify_handler(struct work_struct *work) { - struct capi_notifier *np = data; + struct capi_notifier *np = + container_of(work, struct capi_notifier, work); switch (np->cmd) { case KCI_CONTRUP: @@ -235,7 +236,7 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) if (!np) return -ENOMEM; - INIT_WORK(&np->work, notify_handler, np); + INIT_WORK(&np->work, notify_handler); np->cmd = cmd; np->controller = controller; np->applid = applid; @@ -248,10 +249,11 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) /* -------- Receiver ------------------------------------------ */ -static void recv_handler(void *_ap) +static void recv_handler(struct work_struct *work) { struct sk_buff *skb; - struct capi20_appl *ap = (struct capi20_appl *) _ap; + struct capi20_appl *ap = + container_of(work, struct capi20_appl, recv_work); if ((!ap) || (ap->release_in_progress)) return; @@ -527,7 +529,7 @@ u16 capi20_register(struct capi20_appl *ap) ap->callback = NULL; init_MUTEX(&ap->recv_sem); skb_queue_head_init(&ap->recv_queue); - INIT_WORK(&ap->recv_work, recv_handler, (void *)ap); + INIT_WORK(&ap->recv_work, recv_handler); ap->release_in_progress = 0; write_unlock_irqrestore(&application_lock, flags); diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index bec5901..3b19cae 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -232,9 +232,10 @@ Amd7930_new_ph(struct IsdnCardState *cs) static void -Amd7930_bh(struct IsdnCardState *cs) +Amd7930_bh(struct work_struct *work) { - + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -789,7 +790,7 @@ Amd7930_init(struct IsdnCardState *cs) void __devinit setup_Amd7930(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs); + INIT_WORK(&cs->tqueue, Amd7930_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 785b085..cede72c 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1137,7 +1137,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow cs->tx_skb = NULL; cs->tx_cnt = 0; cs->event = 0; - cs->tqueue.data = cs; skb_queue_head_init(&cs->rq); skb_queue_head_init(&cs->sq); @@ -1554,7 +1553,7 @@ static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); -static void hisax_bh(struct IsdnCardState *cs); +static void hisax_bh(struct work_struct *work); static void EChannel_proc_rcv(struct hisax_d_if *d_if); int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], @@ -1586,7 +1585,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; cs->cardmsg = hisax_cardmsg; - INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs); + INIT_WORK(&cs->tqueue, hisax_bh); cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { cs->bcs[i].BC_SetStack = hisax_bc_setstack; @@ -1618,8 +1617,10 @@ static void hisax_sched_event(struct IsdnCardState *cs, int event) schedule_work(&cs->tqueue); } -static void hisax_bh(struct IsdnCardState *cs) +static void hisax_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *st; int pr; diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index d852c9d..de9b1a4 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c @@ -1083,8 +1083,9 @@ tx_b_frame(struct hfc4s8s_btype *bch) /* bottom half handler for interrupt */ /*************************************/ static void -hfc4s8s_bh(hfc4s8s_hw * hw) +hfc4s8s_bh(struct work_struct *work) { + hfc4s8s_hw *hw = container_of(work, hfc4s8s_hw, tqueue); u_char b; struct hfc4s8s_l1 *l1p; volatile u_char *fifo_stat; @@ -1550,7 +1551,7 @@ setup_instance(hfc4s8s_hw * hw) goto out; } - INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw); + INIT_WORK(&hw->tqueue, hfc4s8s_bh); if (request_irq (hw->irq, hfc4s8s_interrupt, IRQF_SHARED, hw->card_name, hw)) { diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 6360e82..8d98644 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -549,10 +549,11 @@ setstack_2b(struct PStack *st, struct BCState *bcs) } static void -hfcd_bh(struct IsdnCardState *cs) +hfcd_bh(struct work_struct *work) { - if (!cs) - return; + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { switch (cs->dc.hfcd.ph_state) { case (0): @@ -1072,5 +1073,5 @@ set_cs_func(struct IsdnCardState *cs) cs->dbusytimer.function = (void *) hfc_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); + INIT_WORK(&cs->tqueue, hfcd_bh); } diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 93f60b5..5db0a85 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1506,8 +1506,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcpci_bh(struct IsdnCardState *cs) +hfcpci_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; // struct PStack *stptr; @@ -1722,7 +1724,7 @@ setup_hfcpci(struct IsdnCard *card) Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* At this point the needed PCI config is done */ /* fifos are still not enabled */ - INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); + INIT_WORK(&cs->tqueue, hfcpci_bh); cs->setstack_d = setstack_hfcpci; cs->BC_Send_Data = &hfcpci_send_data; cs->readisac = NULL; diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 954d153..4fd09d2 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -1251,8 +1251,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcsx_bh(struct IsdnCardState *cs) +hfcsx_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; if (!cs) @@ -1499,7 +1501,7 @@ setup_hfcsx(struct IsdnCard *card) cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); + INIT_WORK(&cs->tqueue, hfcsx_bh); cs->readisac = NULL; cs->writeisac = NULL; cs->readisacfifo = NULL; diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index da70692..682cac3 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -77,8 +77,10 @@ icc_new_ph(struct IsdnCardState *cs) } static void -icc_bh(struct IsdnCardState *cs) +icc_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_icc_ints(struct IsdnCardState *cs) void __devinit setup_icc(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs); + INIT_WORK(&cs->tqueue, icc_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 282f349..4e9f238 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -81,8 +81,10 @@ isac_new_ph(struct IsdnCardState *cs) } static void -isac_bh(struct IsdnCardState *cs) +isac_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_isac_ints(struct IsdnCardState *cs) void __devinit setup_isac(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs); + INIT_WORK(&cs->tqueue, isac_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 674af67..6f1a658 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -437,8 +437,10 @@ extern void BChannel_bh(struct BCState *); #define B_LL_OK 10 static void -isar_bh(struct BCState *bcs) +isar_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + BChannel_bh(bcs); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); @@ -1580,7 +1582,7 @@ isar_setup(struct IsdnCardState *cs) cs->bcs[i].mode = 0; cs->bcs[i].hw.isar.dpath = i + 1; modeisar(&cs->bcs[i], 0, 0); - INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]); + INIT_WORK(&cs->bcs[i].tqueue, isar_bh); } } diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index bab3568..a14204e 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -315,8 +315,10 @@ BChannel_proc_ack(struct BCState *bcs) } void -BChannel_bh(struct BCState *bcs) +BChannel_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + if (!bcs) return; if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event)) @@ -362,7 +364,7 @@ init_bcstate(struct IsdnCardState *cs, int bc) bcs->cs = cs; bcs->channel = bc; - INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + INIT_WORK(&bcs->tqueue, BChannel_bh); spin_lock_init(&bcs->aclock); bcs->BC_SetStack = NULL; bcs->BC_Close = NULL; diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 1655341..3aeceaf 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -101,8 +101,10 @@ W6692_new_ph(struct IsdnCardState *cs) } static void -W6692_bh(struct IsdnCardState *cs) +W6692_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -1070,7 +1072,7 @@ setup_w6692(struct IsdnCard *card) id_list[cs->subtyp].card_name, cs->irq, cs->hw.w6692.iobase); - INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs); + INIT_WORK(&cs->tqueue, W6692_bh); cs->readW6692 = &ReadW6692; cs->writeW6692 = &WriteW6692; cs->readisacfifo = &ReadISACfifo; diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 1f8d6ae6..2e4daeb 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -984,9 +984,9 @@ void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb) /* * called from tq_immediate */ -static void isdn_net_softint(void *private) +static void isdn_net_softint(struct work_struct *work) { - isdn_net_local *lp = private; + isdn_net_local *lp = container_of(work, isdn_net_local, tqueue); struct sk_buff *skb; spin_lock_bh(&lp->xmit_lock); @@ -2596,7 +2596,7 @@ isdn_net_new(char *name, struct net_device *master) netdev->local->netdev = netdev; netdev->local->next = netdev->local; - INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local); + INIT_WORK(&netdev->local->tqueue, isdn_net_softint); spin_lock_init(&netdev->local->xmit_lock); netdev->local->isdn_device = -1; diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 6ead5e1..1966f34 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -68,8 +68,6 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list); static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); -extern void pcbit_deliver(void * data); - int pcbit_init_dev(int board, int mem_base, int irq) { struct pcbit_dev *dev; @@ -129,7 +127,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) memset(dev->b2, 0, sizeof(struct pcbit_chan)); dev->b2->id = 1; - INIT_WORK(&dev->qdelivery, pcbit_deliver, dev); + INIT_WORK(&dev->qdelivery, pcbit_deliver); /* * interrupts diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index 937fd21..0c9f6df 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -67,7 +67,6 @@ extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, * Prototypes */ -void pcbit_deliver(void *data); static void pcbit_transmit(struct pcbit_dev *dev); static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); @@ -299,11 +298,12 @@ pcbit_transmit(struct pcbit_dev *dev) */ void -pcbit_deliver(void *data) +pcbit_deliver(struct work_struct *work) { struct frame_buf *frame; unsigned long flags, msg; - struct pcbit_dev *dev = (struct pcbit_dev *) data; + struct pcbit_dev *dev = + container_of(work, struct pcbit_dev, qdelivery); spin_lock_irqsave(&dev->lock, flags); diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h index 388bace..19c18e8 100644 --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -166,4 +166,6 @@ struct pcbit_ioctl { #define L2_RUNNING 5 #define L2_ERROR 6 +extern void pcbit_deliver(struct work_struct *work); + #endif diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index ade25b3..4871158 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -600,7 +600,7 @@ core_initcall(smu_late_init); * sysfs visibility */ -static void smu_expose_childs(void *unused) +static void smu_expose_childs(struct work_struct *unused) { struct device_node *np; @@ -610,7 +610,7 @@ static void smu_expose_childs(void *unused) &smu->of_dev->dev); } -static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); +static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); static int smu_platform_probe(struct of_device* dev, const struct of_device_id *match) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 08a40f4..ed2d4ef 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -458,11 +458,11 @@ static void dec_pending(struct crypt_io *io, int error) * interrupt context. */ static struct workqueue_struct *_kcryptd_workqueue; -static void kcryptd_do_work(void *data); +static void kcryptd_do_work(struct work_struct *work); static void kcryptd_queue_io(struct crypt_io *io) { - INIT_WORK(&io->work, kcryptd_do_work, io); + INIT_WORK(&io->work, kcryptd_do_work); queue_work(_kcryptd_workqueue, &io->work); } @@ -618,9 +618,9 @@ static void process_read_endio(struct crypt_io *io) dec_pending(io, crypt_convert(cc, &ctx)); } -static void kcryptd_do_work(void *data) +static void kcryptd_do_work(struct work_struct *work) { - struct crypt_io *io = data; + struct crypt_io *io = container_of(work, struct crypt_io, work); if (io->post_process) process_read_endio(io); diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index d754e0b..e77ee6f 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -104,8 +104,8 @@ typedef int (*action_fn) (struct pgpath *pgpath); static kmem_cache_t *_mpio_cache; struct workqueue_struct *kmultipathd; -static void process_queued_ios(void *data); -static void trigger_event(void *data); +static void process_queued_ios(struct work_struct *work); +static void trigger_event(struct work_struct *work); /*----------------------------------------------- @@ -173,8 +173,8 @@ static struct multipath *alloc_multipath(struct dm_target *ti) INIT_LIST_HEAD(&m->priority_groups); spin_lock_init(&m->lock); m->queue_io = 1; - INIT_WORK(&m->process_queued_ios, process_queued_ios, m); - INIT_WORK(&m->trigger_event, trigger_event, m); + INIT_WORK(&m->process_queued_ios, process_queued_ios); + INIT_WORK(&m->trigger_event, trigger_event); m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); if (!m->mpio_pool) { kfree(m); @@ -379,9 +379,10 @@ static void dispatch_queued_ios(struct multipath *m) } } -static void process_queued_ios(void *data) +static void process_queued_ios(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, process_queued_ios); struct hw_handler *hwh = &m->hw_handler; struct pgpath *pgpath = NULL; unsigned init_required = 0, must_queue = 1; @@ -421,9 +422,10 @@ out: * An event is triggered whenever a path is taken out of use. * Includes path failure and PG bypass. */ -static void trigger_event(void *data) +static void trigger_event(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, trigger_event); dm_table_event(m->ti->table); } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 48a653b..fc8cbb1 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -883,7 +883,7 @@ static void do_mirror(struct mirror_set *ms) do_writes(ms, &writes); } -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { struct mirror_set *ms; @@ -1269,7 +1269,7 @@ static int __init dm_mirror_init(void) dm_dirty_log_exit(); return r; } - INIT_WORK(&_kmirrord_work, do_work, NULL); + INIT_WORK(&_kmirrord_work, do_work); r = dm_register_target(&mirror_target); if (r < 0) { diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 5281e00..91c7aa1 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -40,7 +40,7 @@ #define SNAPSHOT_PAGES 256 struct workqueue_struct *ksnapd; -static void flush_queued_bios(void *data); +static void flush_queued_bios(struct work_struct *work); struct pending_exception { struct exception e; @@ -528,7 +528,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) } bio_list_init(&s->queued_bios); - INIT_WORK(&s->queued_bios_work, flush_queued_bios, s); + INIT_WORK(&s->queued_bios_work, flush_queued_bios); /* Add snapshot to the list of snapshots for this origin */ /* Exceptions aren't triggered till snapshot_resume() is called */ @@ -603,9 +603,10 @@ static void flush_bios(struct bio *bio) } } -static void flush_queued_bios(void *data) +static void flush_queued_bios(struct work_struct *work) { - struct dm_snapshot *s = (struct dm_snapshot *) data; + struct dm_snapshot *s = + container_of(work, struct dm_snapshot, queued_bios_work); struct bio *queued_bios; unsigned long flags; diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index f1db6ef..b3c0149 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -417,7 +417,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *)) /* * kcopyd does this every time it's woken up. */ -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { /* * The order that these are called is *very* important. @@ -628,7 +628,7 @@ static int kcopyd_init(void) } kcopyd_clients++; - INIT_WORK(&_kcopyd_work, do_work, NULL); + INIT_WORK(&_kcopyd_work, do_work); mutex_unlock(&kcopyd_init_lock); return 0; } diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 0689324..6e16680 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -63,7 +63,7 @@ struct flexcop_pci { unsigned long last_irq; - struct work_struct irq_check_work; + struct delayed_work irq_check_work; struct flexcop_device *fc_dev; }; @@ -97,9 +97,10 @@ static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi return 0; } -static void flexcop_pci_irq_check_work(void *data) +static void flexcop_pci_irq_check_work(struct work_struct *work) { - struct flexcop_pci *fc_pci = data; + struct flexcop_pci *fc_pci = + container_of(work, struct flexcop_pci, irq_check_work.work); struct flexcop_device *fc = fc_pci->fc_dev; flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); @@ -371,7 +372,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) goto err_fc_exit; - INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); + INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); return ret; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index ff7d4f56..dd0bcbe 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -127,7 +127,7 @@ struct cinergyt2 { struct dvbt_set_parameters_msg param; struct dvbt_get_status_msg status; - struct work_struct query_work; + struct delayed_work query_work; wait_queue_head_t poll_wq; int pending_fe_events; @@ -141,7 +141,7 @@ struct cinergyt2 { #ifdef ENABLE_RC struct input_dev *rc_input_dev; char phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; int rc_input_event; u32 rc_last_code; unsigned long last_event_jiffies; @@ -724,9 +724,10 @@ static struct dvb_device cinergyt2_fe_template = { #ifdef ENABLE_RC -static void cinergyt2_query_rc (void *data) +static void cinergyt2_query_rc (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, rc_query_work.work); char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; struct cinergyt2_rc_event rc_events[12]; int n, len, i; @@ -807,7 +808,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); cinergyt2->rc_input_event = KEY_MAX; cinergyt2->rc_last_code = ~0; - INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); input_dev->name = DRIVER_NAME " remote control"; input_dev->phys = cinergyt2->phys; @@ -848,9 +849,10 @@ static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } #endif /* ENABLE_RC */ -static void cinergyt2_query (void *data) +static void cinergyt2_query (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, query_work.work); char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; struct dvbt_get_status_msg *s = &cinergyt2->status; uint8_t lock_bits; @@ -894,7 +896,7 @@ static int cinergyt2_probe (struct usb_interface *intf, mutex_init(&cinergyt2->sem); init_waitqueue_head (&cinergyt2->poll_wq); - INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); cinergyt2->udev = interface_to_usbdev(intf); cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 8859ab7..ebf4dc5 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -127,6 +127,7 @@ struct dvb_net_priv { int in_use; struct net_device_stats stats; u16 pid; + struct net_device *net; struct dvb_net *host; struct dmx_demux *demux; struct dmx_section_feed *secfeed; @@ -1123,10 +1124,11 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) } -static void wq_set_multicast_list (void *data) +static void wq_set_multicast_list (struct work_struct *work) { - struct net_device *dev = data; - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, set_multicast_list_wq); + struct net_device *dev = priv->net; dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; @@ -1167,9 +1169,11 @@ static void dvb_net_set_multicast_list (struct net_device *dev) } -static void wq_restart_net_feed (void *data) +static void wq_restart_net_feed (struct work_struct *work) { - struct net_device *dev = data; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, restart_net_feed_wq); + struct net_device *dev = priv->net; if (netif_running(dev)) { dvb_net_feed_stop(dev); @@ -1276,6 +1280,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) dvbnet->device[if_num] = net; priv = net->priv; + priv->net = net; priv->demux = dvbnet->demux; priv->pid = pid; priv->rx_mode = RX_MODE_UNI; @@ -1284,8 +1289,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) priv->feedtype = feedtype; reset_ule(priv); - INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); - INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); + INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list); + INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed); mutex_init(&priv->mutex); net->base_addr = pid; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 0a3a0b6..794e447 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -13,9 +13,10 @@ * * TODO: Fix the repeat rate of the input device. */ -static void dvb_usb_read_remote_control(void *data) +static void dvb_usb_read_remote_control(struct work_struct *work) { - struct dvb_usb_device *d = data; + struct dvb_usb_device *d = + container_of(work, struct dvb_usb_device, rc_query_work.work); u32 event; int state; @@ -128,7 +129,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_register_device(d->rc_input_dev); - INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); + INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); info("schedule remote query interval to %d msecs.", d->props.rc_interval); schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 376c45a..0d721731 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -369,7 +369,7 @@ struct dvb_usb_device { /* remote control */ struct input_dev *rc_input_dev; char rc_phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; u32 last_event; int last_state; diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 41f4b8d..b12cec9 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c @@ -82,6 +82,8 @@ struct pp_cam_entry { struct pardevice *pdev; struct parport *port; struct work_struct cb_task; + void (*cb_func)(void *cbdata); + void *cb_data; int open_count; wait_queue_head_t wq_stream; /* image state flags */ @@ -130,6 +132,20 @@ static void cpia_parport_disable_irq( struct parport *port ) { #define PARPORT_CHUNK_SIZE PAGE_SIZE +static void cpia_pp_run_callback(struct work_struct *work) +{ + void (*cb_func)(void *cbdata); + void *cb_data; + struct pp_cam_entry *cam; + + cam = container_of(work, struct pp_cam_entry, cb_task); + cb_func = cam->cb_func; + cb_data = cam->cb_data; + work_release(work); + + cb_func(cb_data); +} + /**************************************************************************** * * CPiA-specific low-level parport functions for nibble uploads @@ -664,7 +680,9 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo int retval = 0; if(cam->port->irq != PARPORT_IRQ_NONE) { - INIT_WORK(&cam->cb_task, cb, cbdata); + cam->cb_func = cb; + cam->cb_data = cbdata; + INIT_WORK_NAR(&cam->cb_task, cpia_pp_run_callback); } else { retval = -1; } diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 57e1c02..e60a0a5 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -145,9 +145,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void cx88_ir_work(void *data) +static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = data; + struct cx88_IR *ir = container_of(work, struct cx88_IR, work); unsigned long timeout; cx88_ir_handle_key(ir); @@ -308,7 +308,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) core->ir = ir; if (ir->polling) { - INIT_WORK(&ir->work, cx88_ir_work, ir); + INIT_WORK(&ir->work, cx88_ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 1457b16..ab87e7b 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -268,9 +268,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void ir_work(void *data) +static void ir_work(struct work_struct *work) { - struct IR_i2c *ir = data; + struct IR_i2c *ir = container_of(work, struct IR_i2c, work); ir_key_poll(ir); mod_timer(&ir->timer, jiffies+HZ/10); } @@ -400,7 +400,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->input->name,ir->input->phys,adap->name); /* start polling via eventd */ - INIT_WORK(&ir->work, ir_work, ir); + INIT_WORK(&ir->work, ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index f129f31..cf12974 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -45,16 +45,21 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp) } -static void pvr2_context_poll(struct pvr2_context *mp) +static void pvr2_context_poll(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workpoll); pvr2_context_enter(mp); do { pvr2_hdw_poll(mp->hdw); } while (0); pvr2_context_exit(mp); } -static void pvr2_context_setup(struct pvr2_context *mp) +static void pvr2_context_setup(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workinit); + pvr2_context_enter(mp); do { if (!pvr2_hdw_dev_ok(mp->hdw)) break; pvr2_hdw_setup(mp->hdw); @@ -92,8 +97,8 @@ struct pvr2_context *pvr2_context_create( } mp->workqueue = create_singlethread_workqueue("pvrusb2"); - INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp); - INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp); + INIT_WORK(&mp->workinit, pvr2_context_setup); + INIT_WORK(&mp->workpoll, pvr2_context_poll); queue_work(mp->workqueue,&mp->workinit); done: return mp; diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index a81285c..8ba05c2 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -322,9 +322,9 @@ static void saa6588_timer(unsigned long data) schedule_work(&s->work); } -static void saa6588_work(void *data) +static void saa6588_work(struct work_struct *work) { - struct saa6588 *s = (struct saa6588 *)data; + struct saa6588 *s = container_of(work, struct saa6588, work); saa6588_i2c_poll(s); mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); @@ -417,7 +417,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) saa6588_configure(s); /* start polling via eventd */ - INIT_WORK(&s->work, saa6588_work, s); + INIT_WORK(&s->work, saa6588_work); init_timer(&s->timer); s->timer.function = saa6588_timer; s->timer.data = (unsigned long)s; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 65d0440..daaae87 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -343,9 +343,10 @@ static struct video_device saa7134_empress_template = .minor = -1, }; -static void empress_signal_update(void* data) +static void empress_signal_update(struct work_struct *work) { - struct saa7134_dev* dev = (struct saa7134_dev*) data; + struct saa7134_dev* dev = + container_of(work, struct saa7134_dev, empress_workqueue); if (dev->nosignal) { dprintk("no video signal\n"); @@ -378,7 +379,7 @@ static int empress_init(struct saa7134_dev *dev) "%s empress (%s)", dev->name, saa7134_boards[dev->board].name); - INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); + INIT_WORK(&dev->empress_workqueue, empress_signal_update); err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, empress_nr[dev->nr]); @@ -399,7 +400,7 @@ static int empress_init(struct saa7134_dev *dev) sizeof(struct saa7134_buf), dev); - empress_signal_update(dev); + empress_signal_update(&dev->empress_workqueue); return 0; } diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 1dd4917..ef2b55e 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1018,9 +1018,10 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) } static void -mptfc_setup_reset(void *arg) +mptfc_setup_reset(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_setup_reset_work); u64 pn; struct mptfc_rport_info *ri; @@ -1043,9 +1044,10 @@ mptfc_setup_reset(void *arg) } static void -mptfc_rescan_devices(void *arg) +mptfc_rescan_devices(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_rescan_work); int ii; u64 pn; struct mptfc_rport_info *ri; @@ -1154,8 +1156,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) } spin_lock_init(&ioc->fc_rescan_work_lock); - INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); - INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); + INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset); spin_lock_irqsave(&ioc->FreeQlock, flags); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 314c3a2..b7c4407 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -111,7 +111,8 @@ struct mpt_lan_priv { u32 total_received; struct net_device_stats stats; /* Per device statistics */ - struct work_struct post_buckets_task; + struct delayed_work post_buckets_task; + struct net_device *dev; unsigned long post_buckets_active; }; @@ -132,7 +133,7 @@ static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, static int mpt_lan_open(struct net_device *dev); static int mpt_lan_reset(struct net_device *dev); static int mpt_lan_close(struct net_device *dev); -static void mpt_lan_post_receive_buckets(void *dev_id); +static void mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv); static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority); static int mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg); @@ -345,7 +346,7 @@ mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; spin_unlock_irqrestore(&priv->rxfidx_lock, flags); } else { - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); netif_wake_queue(dev); } @@ -441,7 +442,7 @@ mpt_lan_open(struct net_device *dev) dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n")); - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n", IOC_AND_NETDEV_NAMES_s_s(dev)); @@ -854,7 +855,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { if (priority) { - schedule_work(&priv->post_buckets_task); + schedule_delayed_work(&priv->post_buckets_task, 0); } else { schedule_delayed_work(&priv->post_buckets_task, 1); dioprintk((KERN_INFO MYNAM ": post_buckets queued on " @@ -1188,10 +1189,9 @@ mpt_lan_receive_post_reply(struct net_device *dev, /* Simple SGE's only at the moment */ static void -mpt_lan_post_receive_buckets(void *dev_id) +mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) { - struct net_device *dev = dev_id; - struct mpt_lan_priv *priv = dev->priv; + struct net_device *dev = priv->dev; MPT_ADAPTER *mpt_dev = priv->mpt_dev; MPT_FRAME_HDR *mf; LANReceivePostRequest_t *pRecvReq; @@ -1335,6 +1335,13 @@ out: clear_bit(0, &priv->post_buckets_active); } +static void +mpt_lan_post_receive_buckets_work(struct work_struct *work) +{ + mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv, + post_buckets_task.work)); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static struct net_device * mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) @@ -1350,11 +1357,13 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv = netdev_priv(dev); + priv->dev = dev; priv->mpt_dev = mpt_dev; priv->pnum = pnum; - memset(&priv->post_buckets_task, 0, sizeof(struct work_struct)); - INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); + memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task)); + INIT_DELAYED_WORK(&priv->post_buckets_task, + mpt_lan_post_receive_buckets_work); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b752a47..4f0c530 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2006,9 +2006,10 @@ __mptsas_discovery_work(MPT_ADAPTER *ioc) *(Mutex LOCKED) */ static void -mptsas_discovery_work(void * arg) +mptsas_discovery_work(struct work_struct *work) { - struct mptsas_discovery_event *ev = arg; + struct mptsas_discovery_event *ev = + container_of(work, struct mptsas_discovery_event, work); MPT_ADAPTER *ioc = ev->ioc; mutex_lock(&ioc->sas_discovery_mutex); @@ -2068,9 +2069,9 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) * Work queue thread to clear the persitency table */ static void -mptsas_persist_clear_table(void * arg) +mptsas_persist_clear_table(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task); mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); } @@ -2093,9 +2094,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) * Work queue thread to handle SAS hotplug events */ static void -mptsas_hotplug_work(void *arg) +mptsas_hotplug_work(struct work_struct *work) { - struct mptsas_hotplug_event *ev = arg; + struct mptsas_hotplug_event *ev = + container_of(work, struct mptsas_hotplug_event, work); MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; @@ -2341,7 +2343,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, break; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->handle = le16_to_cpu(sas_event_data->DevHandle); ev->parent_handle = @@ -2366,7 +2368,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, * Persistent table is full. */ INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: @@ -2395,7 +2397,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, return; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; ev->event_type = MPTSAS_IGNORE_EVENT; @@ -2474,7 +2476,7 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) return; - INIT_WORK(&ev->work, mptsas_discovery_work, ev); + INIT_WORK(&ev->work, mptsas_discovery_work); ev->ioc = ioc; schedule_work(&ev->work); }; @@ -2511,8 +2513,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) break; case MPI_EVENT_PERSISTENT_TABLE_FULL: INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, - (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DISCOVERY: diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index e4cc3dd..f422c0d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -646,9 +646,10 @@ struct work_queue_wrapper { int disk; }; -static void mpt_work_wrapper(void *data) +static void mpt_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct Scsi_Host *shost = hd->ioc->sh; struct scsi_device *sdev; @@ -695,7 +696,7 @@ static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) disk); return; } - INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); + INIT_WORK(&wqw->work, mpt_work_wrapper); wqw->hd = hd; wqw->disk = disk; @@ -784,9 +785,10 @@ MODULE_DEVICE_TABLE(pci, mptspi_pci_table); * renegotiate for a given target */ static void -mptspi_dv_renegotiate_work(void *data) +mptspi_dv_renegotiate_work(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct scsi_device *sdev; @@ -804,7 +806,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd) if (!wqw) return; - INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw); + INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work); wqw->hd = hd; schedule_work(&wqw->work); diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 6413022..7fc7399 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -232,7 +232,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) break; } - INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); + INIT_WORK(&evt->work, drv->event); queue_work(drv->event_queue, &evt->work); return 1; } diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index a235064..9e529d8 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -371,8 +371,10 @@ static int i2o_exec_remove(struct device *dev) * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ -static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work) +static void i2o_exec_lct_modified(struct work_struct *_work) { + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); u32 change_ind = 0; struct i2o_controller *c = work->c; @@ -439,8 +441,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, work->c = c; - INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified, - work); + INIT_WORK(&work->work, i2o_exec_lct_modified); queue_work(i2o_exec_driver.event_queue, &work->work); return 1; } @@ -460,13 +461,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, /** * i2o_exec_event - Event handling function - * @evt: Event which occurs + * @work: Work item in occurring event * * Handles events send by the Executive device. At the moment does not do * anything useful. */ -static void i2o_exec_event(struct i2o_event *evt) +static void i2o_exec_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); + if (likely(evt->i2o_dev)) osm_debug("Event received from device: %d\n", evt->i2o_dev->lct_data.tid); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index eaba81b..70ae002 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -419,16 +419,18 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) /** * i2o_block_delayed_request_fn - delayed request queue function - * delayed_request: the delayed request with the queue to start + * @work: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */ -static void i2o_block_delayed_request_fn(void *delayed_request) +static void i2o_block_delayed_request_fn(struct work_struct *work) { - struct i2o_block_delayed_request *dreq = delayed_request; + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); struct request_queue *q = dreq->queue; unsigned long flags; @@ -538,8 +540,9 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, return 1; }; -static void i2o_block_event(struct i2o_event *evt) +static void i2o_block_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); osm_debug("event received\n"); kfree(evt); }; @@ -938,8 +941,8 @@ static void i2o_block_request_fn(struct request_queue *q) continue; dreq->queue = q; - INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, - dreq); + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 4fdaa5b..d9fdc95 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -96,7 +96,7 @@ struct i2o_block_request { /* I2O Block device delayed request */ struct i2o_block_delayed_request { - struct work_struct work; + struct delayed_work work; struct request_queue *queue; }; diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 1ba8754..2ab7add 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -33,9 +33,10 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) spin_unlock_irqrestore(&fm->lock, flags); } -static void tifm_7xx1_remove_media(void *adapter) +static void tifm_7xx1_remove_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_remover); unsigned long flags; int cnt; struct tifm_dev *sock; @@ -169,9 +170,10 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) return base_addr + ((sock_num + 1) << 10); } -static void tifm_7xx1_insert_media(void *adapter) +static void tifm_7xx1_insert_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_inserter); unsigned long flags; tifm_media_id media_id; char *card_name = "xx"; @@ -261,7 +263,7 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) spin_unlock_irqrestore(&fm->lock, flags); flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); pci_set_power_state(dev, PCI_D3hot); pci_disable_device(dev); @@ -328,8 +330,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->sockets) goto err_out_free; - INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media, fm); - INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media, fm); + INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media); + INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); @@ -384,7 +386,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev) flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); free_irq(dev->irq, fm); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 766bc544..21fd39e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1165,18 +1165,16 @@ static void mmc_setup(struct mmc_host *host) */ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { - if (delay) - mmc_schedule_delayed_work(&host->detect, delay); - else - mmc_schedule_work(&host->detect); + mmc_schedule_delayed_work(&host->detect, delay); } EXPORT_SYMBOL(mmc_detect_change); -static void mmc_rescan(void *data) +static void mmc_rescan(struct work_struct *work) { - struct mmc_host *host = data; + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); struct list_head *l, *n; unsigned char power_mode; @@ -1259,7 +1257,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_LIST_HEAD(&host->cards); - INIT_WORK(&host->detect, mmc_rescan, host); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); /* * By default, hosts do not support SGIO or large requests. @@ -1357,7 +1355,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - mmc_rescan(host); + mmc_rescan(&host->detect.work); return 0; } diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h index cd5e0ab..149affe 100644 --- a/drivers/mmc/mmc.h +++ b/drivers/mmc/mmc.h @@ -20,6 +20,6 @@ void mmc_remove_host_sysfs(struct mmc_host *host); void mmc_free_host_sysfs(struct mmc_host *host); int mmc_schedule_work(struct work_struct *work); -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay); +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); void mmc_flush_scheduled_work(void); #endif diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 10cc973..fd9a5fc 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -321,17 +321,9 @@ void mmc_free_host_sysfs(struct mmc_host *host) static struct workqueue_struct *workqueue; /* - * Internal function. Schedule work in the MMC work queue. - */ -int mmc_schedule_work(struct work_struct *work) -{ - return queue_work(workqueue, work); -} - -/* * Internal function. Schedule delayed work in the MMC work queue. */ -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay) +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) { return queue_delayed_work(workqueue, work, delay); } diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index 0fdc55b..e846499 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c @@ -99,7 +99,7 @@ struct tifm_sd { struct mmc_request *req; struct work_struct cmd_handler; - struct work_struct abort_handler; + struct delayed_work abort_handler; wait_queue_head_t can_eject; size_t written_blocks; @@ -496,9 +496,9 @@ err_out: mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd(void *data) +static void tifm_sd_end_cmd(struct work_struct *work) { - struct tifm_sd *host = data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -608,9 +608,9 @@ err_out: mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd_nodma(void *data) +static void tifm_sd_end_cmd_nodma(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -661,11 +661,14 @@ static void tifm_sd_end_cmd_nodma(void *data) mmc_request_done(mmc, mrq); } -static void tifm_sd_abort(void *data) +static void tifm_sd_abort(struct work_struct *work) { + struct tifm_sd *host = + container_of(work, struct tifm_sd, abort_handler.work); + printk(KERN_ERR DRIVER_NAME ": card failed to respond for a long period of time"); - tifm_eject(((struct tifm_sd*)data)->dev); + tifm_eject(host->dev); } static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) @@ -762,9 +765,9 @@ static struct mmc_host_ops tifm_sd_ops = { .get_ro = tifm_sd_ro }; -static void tifm_sd_register_host(void *data) +static void tifm_sd_register_host(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); unsigned long flags; @@ -772,8 +775,7 @@ static void tifm_sd_register_host(void *data) spin_lock_irqsave(&sock->lock, flags); host->flags |= HOST_REG; PREPARE_WORK(&host->cmd_handler, - no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, - data); + no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); spin_unlock_irqrestore(&sock->lock, flags); dev_dbg(&sock->dev, "adding host\n"); mmc_add_host(mmc); @@ -799,8 +801,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) host->dev = sock; host->clk_div = 61; init_waitqueue_head(&host->can_eject); - INIT_WORK(&host->cmd_handler, tifm_sd_register_host, host); - INIT_WORK(&host->abort_handler, tifm_sd_abort, host); + INIT_WORK(&host->cmd_handler, tifm_sd_register_host); + INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); tifm_set_drvdata(sock, mmc); sock->signal_irq = tifm_sd_signal_irq; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index d02ed51..931028f 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -594,7 +594,7 @@ struct rtl8139_private { u32 rx_config; struct rtl_extra_stats xstats; - struct work_struct thread; + struct delayed_work thread; struct mii_if_info mii; unsigned int regs_len; @@ -636,8 +636,8 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); +static void rtl8139_thread (struct work_struct *work); +static void rtl8139_tx_timeout_task(struct work_struct *work); static const struct ethtool_ops rtl8139_ethtool_ops; /* write MMIO register, with flush */ @@ -1010,7 +1010,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); spin_lock_init (&tp->lock); spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); tp->mii.dev = dev; tp->mii.mdio_read = mdio_read; tp->mii.mdio_write = mdio_write; @@ -1596,15 +1596,16 @@ static inline void rtl8139_thread_iter (struct net_device *dev, RTL_R8 (Config1)); } -static void rtl8139_thread (void *_data) +static void rtl8139_thread (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; unsigned long thr_delay = next_tick; if (tp->watchdog_fired) { tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); + rtl8139_tx_timeout_task(work); } else if (rtnl_trylock()) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); @@ -1646,10 +1647,11 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ } -static void rtl8139_tx_timeout_task (void *_data) +static void rtl8139_tx_timeout_task (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; void __iomem *ioaddr = tp->mmio_addr; int i; u8 tmp8; @@ -1695,7 +1697,7 @@ static void rtl8139_tx_timeout (struct net_device *dev) struct rtl8139_private *tp = netdev_priv(dev); if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 01b76d3a..b12cc45 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4339,9 +4339,9 @@ bnx2_open(struct net_device *dev) } static void -bnx2_reset_task(void *data) +bnx2_reset_task(struct work_struct *work) { - struct bnx2 *bp = data; + struct bnx2 *bp = container_of(work, struct bnx2, reset_task); if (!netif_running(bp->dev)) return; @@ -5630,7 +5630,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pdev = pdev; spin_lock_init(&bp->phy_lock); - INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); + INIT_WORK(&bp->reset_task, bnx2_reset_task); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); mem_len = MB_GET_CID_ADDR(17); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 521c5b7..fe08f38 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -4066,9 +4066,9 @@ static int cas_alloc_rxds(struct cas *cp) return 0; } -static void cas_reset_task(void *data) +static void cas_reset_task(struct work_struct *work) { - struct cas *cp = (struct cas *) data; + struct cas *cp = container_of(work, struct cas, reset_task); #if 0 int pending = atomic_read(&cp->reset_task_pending); #else @@ -5006,7 +5006,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, atomic_set(&cp->reset_task_pending_spare, 0); atomic_set(&cp->reset_task_pending_mtu, 0); #endif - INIT_WORK(&cp->reset_task, cas_reset_task, cp); + INIT_WORK(&cp->reset_task, cas_reset_task); /* Default link parameters */ if (link_mode >= 0 && link_mode <= 6) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 5d9dd14..8b1bedb 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -209,7 +209,7 @@ struct adapter { struct peespi *espi; struct port_info port[MAX_NPORTS]; - struct work_struct stats_update_task; + struct delayed_work stats_update_task; struct timer_list stats_update_timer; struct semaphore mib_mutex; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index ad7ff96..f607cc6 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -927,10 +927,11 @@ static void t1_netpoll(struct net_device *dev) * Periodic accumulation of MAC statistics. This is used only if the MAC * does not have any other way to prevent stats counter overflow. */ -static void mac_stats_task(void *data) +static void mac_stats_task(struct work_struct *work) { int i; - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, stats_update_task.work); for_each_port(adapter, i) { struct port_info *p = &adapter->port[i]; @@ -951,9 +952,10 @@ static void mac_stats_task(void *data) /* * Processes elmer0 external interrupts in process context. */ -static void ext_intr_task(void *data) +static void ext_intr_task(struct work_struct *work) { - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, ext_intr_handler_task); elmer0_ext_intr_handler(adapter); @@ -1087,9 +1089,9 @@ static int __devinit init_one(struct pci_dev *pdev, spin_lock_init(&adapter->async_lock); INIT_WORK(&adapter->ext_intr_handler_task, - ext_intr_task, adapter); - INIT_WORK(&adapter->stats_update_task, mac_stats_task, - adapter); + ext_intr_task); + INIT_DELAYED_WORK(&adapter->stats_update_task, + mac_stats_task); #ifdef work_struct init_timer(&adapter->stats_update_timer); adapter->stats_update_timer.function = mac_stats_timer; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 19ab344..e7737d0 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2102,9 +2102,10 @@ static void e100_tx_timeout(struct net_device *netdev) schedule_work(&nic->tx_timeout_task); } -static void e100_tx_timeout_task(struct net_device *netdev) +static void e100_tx_timeout_task(struct work_struct *work) { - struct nic *nic = netdev_priv(netdev); + struct nic *nic = container_of(work, struct nic, tx_timeout_task); + struct net_device *netdev = nic->netdev; DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", readb(&nic->csr->scb.status)); @@ -2637,8 +2638,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->blink_timer.function = e100_blink_led; nic->blink_timer.data = (unsigned long)nic; - INIT_WORK(&nic->tx_timeout_task, - (void (*)(void *))e100_tx_timeout_task, netdev); + INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); if((err = e100_alloc(nic))) { DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 6ad6961..83fa32f 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2224,11 +2224,12 @@ static int ehea_stop(struct net_device *dev) return ret; } -static void ehea_reset_port(void *data) +static void ehea_reset_port(struct work_struct *work) { int ret; - struct net_device *dev = data; - struct ehea_port *port = netdev_priv(dev); + struct ehea_port *port = + container_of(work, struct ehea_port, reset_task); + struct net_device *dev = port->netdev; port->resets++; down(&port->port_lock); @@ -2379,7 +2380,7 @@ static int ehea_setup_single_port(struct ehea_port *port, dev->tx_timeout = &ehea_tx_watchdog; dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; - INIT_WORK(&port->reset_task, ehea_reset_port, dev); + INIT_WORK(&port->reset_task, ehea_reset_port); ehea_set_ethtool_ops(dev); diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 1ed9ccc..3c33d6f 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -168,8 +168,9 @@ struct baycom_state { int magic; struct pardevice *pdev; + struct net_device *dev; unsigned int work_running; - struct work_struct run_work; + struct delayed_work run_work; unsigned int modem; unsigned int bitrate; unsigned char stat; @@ -659,16 +660,18 @@ static int receive(struct net_device *dev, int cnt) #define GETTICK(x) #endif /* __i386__ */ -static void epp_bh(struct net_device *dev) +static void epp_bh(struct work_struct *work) { + struct net_device *dev; struct baycom_state *bc; struct parport *pp; unsigned char stat; unsigned char tmp[2]; unsigned int time1 = 0, time2 = 0, time3 = 0; int cnt, cnt2; - - bc = netdev_priv(dev); + + bc = container_of(work, struct baycom_state, run_work.work); + dev = bc->dev; if (!bc->work_running) return; baycom_int_freq(bc); @@ -889,7 +892,7 @@ static int epp_open(struct net_device *dev) return -EBUSY; } dev->irq = /*pp->irq*/ 0; - INIT_WORK(&bc->run_work, (void *)(void *)epp_bh, dev); + INIT_DELAYED_WORK(&bc->run_work, epp_bh); bc->work_running = 1; bc->modem = EPP_CONVENTIONAL; if (eppconfig(bc)) @@ -1213,6 +1216,7 @@ static void __init baycom_epp_dev_setup(struct net_device *dev) /* * initialize part of the baycom_state struct */ + bc->dev = dev; bc->magic = BAYCOM_MAGIC; bc->cfg.fclk = 19666600; bc->cfg.bps = 9600; diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index b32c52e..f0c61f3 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -560,9 +560,9 @@ static inline int mcs_find_endpoints(struct mcs_cb *mcs, return ret; } -static void mcs_speed_work(void *arg) +static void mcs_speed_work(struct work_struct *work) { - struct mcs_cb *mcs = arg; + struct mcs_cb *mcs = container_of(work, struct mcs_cb, work); struct net_device *netdev = mcs->netdev; mcs_speed_change(mcs); @@ -927,7 +927,7 @@ static int mcs_probe(struct usb_interface *intf, irda_qos_bits_to_value(&mcs->qos); /* Speed change work initialisation*/ - INIT_WORK(&mcs->work, mcs_speed_work, mcs); + INIT_WORK(&mcs->work, mcs_speed_work); /* Override the network functions we need to use */ ndev->hard_start_xmit = mcs_hard_xmit; diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h index 9fa294a..2a57bc6 100644 --- a/drivers/net/irda/sir-dev.h +++ b/drivers/net/irda/sir-dev.h @@ -22,7 +22,7 @@ struct sir_fsm { struct semaphore sem; - struct work_struct work; + struct delayed_work work; unsigned state, substate; int param; int result; diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 3b5854d..17b0c3a 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -100,9 +100,9 @@ static int sirdev_tx_complete_fsm(struct sir_dev *dev) * Both must be unlocked/restarted on completion - but only on final exit. */ -static void sirdev_config_fsm(void *data) +static void sirdev_config_fsm(struct work_struct *work) { - struct sir_dev *dev = data; + struct sir_dev *dev = container_of(work, struct sir_dev, fsm.work.work); struct sir_fsm *fsm = &dev->fsm; int next_state; int ret = -1; @@ -309,8 +309,8 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par fsm->param = param; fsm->result = 0; - INIT_WORK(&fsm->work, sirdev_config_fsm, dev); - queue_work(irda_sir_wq, &fsm->work); + INIT_DELAYED_WORK(&fsm->work, sirdev_config_fsm); + queue_delayed_work(irda_sir_wq, &fsm->work, 0); return 0; } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 2284e2c..d6f4f18 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -166,7 +166,7 @@ struct veth_msg { struct veth_lpar_connection { HvLpIndex remote_lp; - struct work_struct statemachine_wq; + struct delayed_work statemachine_wq; struct veth_msg *msgs; int num_events; struct veth_cap_data local_caps; @@ -456,7 +456,7 @@ static struct kobj_type veth_port_ktype = { static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx) { - schedule_work(&cnx->statemachine_wq); + schedule_delayed_work(&cnx->statemachine_wq, 0); } static void veth_take_cap(struct veth_lpar_connection *cnx, @@ -638,9 +638,11 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) } /* FIXME: The gotos here are a bit dubious */ -static void veth_statemachine(void *p) +static void veth_statemachine(struct work_struct *work) { - struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)p; + struct veth_lpar_connection *cnx = + container_of(work, struct veth_lpar_connection, + statemachine_wq.work); int rlp = cnx->remote_lp; int rc; @@ -827,7 +829,7 @@ static int veth_init_connection(u8 rlp) cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); - INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); + INIT_DELAYED_WORK(&cnx->statemachine_wq, veth_statemachine); init_timer(&cnx->ack_timer); cnx->ack_timer.function = veth_timed_ack; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e09f575..d1ebb91 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -106,7 +106,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); void ixgb_set_ethtool_ops(struct net_device *netdev); static void ixgb_tx_timeout(struct net_device *dev); -static void ixgb_tx_timeout_task(struct net_device *dev); +static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); @@ -489,8 +489,7 @@ ixgb_probe(struct pci_dev *pdev, adapter->watchdog_timer.function = &ixgb_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))ixgb_tx_timeout_task, netdev); + INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) @@ -1493,9 +1492,10 @@ ixgb_tx_timeout(struct net_device *netdev) } static void -ixgb_tx_timeout_task(struct net_device *netdev) +ixgb_tx_timeout_task(struct work_struct *work) { - struct ixgb_adapter *adapter = netdev_priv(netdev); + struct ixgb_adapter *adapter = + container_of(work, struct ixgb_adapter, tx_timeout_task); adapter->tx_timeout_count++; ixgb_down(adapter, TRUE); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 806081b..98703e0 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2615,9 +2615,10 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) * This watchdog is used to check whether the board has suffered * from a parity error and needs to be recovered. */ -static void myri10ge_watchdog(void *arg) +static void myri10ge_watchdog(struct work_struct *work) { - struct myri10ge_priv *mgp = arg; + struct myri10ge_priv *mgp = + container_of(work, struct myri10ge_priv, watchdog_work); u32 reboot; int status; u16 cmd, vendor; @@ -2887,7 +2888,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long)mgp); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); - INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp); + INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); status = register_netdev(netdev); if (status != 0) { dev_err(&pdev->dev, "register_netdev failed: %d\n", status); diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index b0127c7..312e0e3 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -427,6 +427,7 @@ struct ns83820 { u8 __iomem *base; struct pci_dev *pci_dev; + struct net_device *ndev; #ifdef NS83820_VLAN_ACCEL_SUPPORT struct vlan_group *vlgrp; @@ -631,10 +632,10 @@ static void fastcall rx_refill_atomic(struct net_device *ndev) } /* REFILL */ -static inline void queue_refill(void *_dev) +static inline void queue_refill(struct work_struct *work) { - struct net_device *ndev = _dev; - struct ns83820 *dev = PRIV(ndev); + struct ns83820 *dev = container_of(work, struct ns83820, tq_refill); + struct net_device *ndev = dev->ndev; rx_refill(ndev, GFP_KERNEL); if (dev->rx_info.up) @@ -1841,6 +1842,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev = alloc_etherdev(sizeof(struct ns83820)); dev = PRIV(ndev); + dev->ndev = ndev; err = -ENOMEM; if (!dev) goto out; @@ -1853,7 +1855,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); - INIT_WORK(&dev->tq_refill, queue_refill, ndev); + INIT_WORK(&dev->tq_refill, queue_refill); tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev); err = pci_enable_device(pci_dev); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index f3914f58..5de8850 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -332,6 +332,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); */ typedef struct local_info_t { + struct net_device *dev; struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; @@ -353,7 +354,7 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); -static void xirc2ps_tx_timeout_task(void *data); +static void xirc2ps_tx_timeout_task(struct work_struct *work); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -567,6 +568,7 @@ xirc2ps_probe(struct pcmcia_device *link) if (!dev) return -ENOMEM; local = netdev_priv(dev); + local->dev = dev; local->p_dev = link; link->priv = dev; @@ -591,7 +593,7 @@ xirc2ps_probe(struct pcmcia_device *link) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev); + INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); #endif return xirc2ps_config(link); @@ -1344,9 +1346,11 @@ xirc2ps_interrupt(int irq, void *dev_id) /*====================================================================*/ static void -xirc2ps_tx_timeout_task(void *data) +xirc2ps_tx_timeout_task(struct work_struct *work) { - struct net_device *dev = data; + local_info_t *local = + container_of(work, local_info_t, tx_timeout_task); + struct net_device *dev = local->dev; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3af9fcf..a443976 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -394,7 +394,7 @@ out_unlock: EXPORT_SYMBOL(phy_start_aneg); -static void phy_change(void *data); +static void phy_change(struct work_struct *work); static void phy_timer(unsigned long data); /* phy_start_machine: @@ -549,7 +549,7 @@ int phy_start_interrupts(struct phy_device *phydev) { int err = 0; - INIT_WORK(&phydev->phy_queue, phy_change, phydev); + INIT_WORK(&phydev->phy_queue, phy_change); if (request_irq(phydev->irq, phy_interrupt, IRQF_SHARED, @@ -585,10 +585,11 @@ EXPORT_SYMBOL(phy_stop_interrupts); /* Scheduled by the phy_interrupt/timer to handle PHY changes */ -static void phy_change(void *data) +static void phy_change(struct work_struct *work) { int err; - struct phy_device *phydev = data; + struct phy_device *phydev = + container_of(work, struct phy_device, phy_queue); err = phy_disable_interrupts(phydev); diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 71afb27..6bb085f 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -138,9 +138,9 @@ static const unsigned int net_debug = NET_DEBUG; #define PLIP_NIBBLE_WAIT 3000 /* Bottom halves */ -static void plip_kick_bh(struct net_device *dev); -static void plip_bh(struct net_device *dev); -static void plip_timer_bh(struct net_device *dev); +static void plip_kick_bh(struct work_struct *work); +static void plip_bh(struct work_struct *work); +static void plip_timer_bh(struct work_struct *work); /* Interrupt handler */ static void plip_interrupt(int irq, void *dev_id); @@ -207,9 +207,10 @@ struct plip_local { struct net_local { struct net_device_stats enet_stats; + struct net_device *dev; struct work_struct immediate; - struct work_struct deferred; - struct work_struct timer; + struct delayed_work deferred; + struct delayed_work timer; struct plip_local snd_data; struct plip_local rcv_data; struct pardevice *pardev; @@ -306,11 +307,11 @@ plip_init_netdev(struct net_device *dev) nl->nibble = PLIP_NIBBLE_WAIT; /* Initialize task queue structures */ - INIT_WORK(&nl->immediate, (void (*)(void *))plip_bh, dev); - INIT_WORK(&nl->deferred, (void (*)(void *))plip_kick_bh, dev); + INIT_WORK(&nl->immediate, plip_bh); + INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh); if (dev->irq == -1) - INIT_WORK(&nl->timer, (void (*)(void *))plip_timer_bh, dev); + INIT_DELAYED_WORK(&nl->timer, plip_timer_bh); spin_lock_init(&nl->lock); } @@ -319,9 +320,10 @@ plip_init_netdev(struct net_device *dev) This routine is kicked by do_timer(). Request `plip_bh' to be invoked. */ static void -plip_kick_bh(struct net_device *dev) +plip_kick_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, deferred.work); if (nl->is_deferred) schedule_work(&nl->immediate); @@ -362,9 +364,9 @@ static const plip_func connection_state_table[] = /* Bottom half handler of PLIP. */ static void -plip_bh(struct net_device *dev) +plip_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = container_of(work, struct net_local, immediate); struct plip_local *snd = &nl->snd_data; struct plip_local *rcv = &nl->rcv_data; plip_func f; @@ -372,20 +374,21 @@ plip_bh(struct net_device *dev) nl->is_deferred = 0; f = connection_state_table[nl->connection]; - if ((r = (*f)(dev, nl, snd, rcv)) != OK - && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) { + if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK + && (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) { nl->is_deferred = 1; schedule_delayed_work(&nl->deferred, 1); } } static void -plip_timer_bh(struct net_device *dev) +plip_timer_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, timer.work); if (!(atomic_read (&nl->kill_timer))) { - plip_interrupt (-1, dev); + plip_interrupt (-1, nl->dev); schedule_delayed_work(&nl->timer, 1); } @@ -1284,6 +1287,7 @@ static void plip_attach (struct parport *port) } nl = netdev_priv(dev); + nl->dev = dev; nl->pardev = parport_register_device(port, name, plip_preempt, plip_wakeup, plip_interrupt, 0, dev); diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index ec640f6..d79d141 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2008,7 +2008,7 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) "%s: Another function issued a reset to the " "chip. ISR value = %x.\n", ndev->name, value); } - queue_work(qdev->workqueue, &qdev->reset_work); + queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0); spin_unlock(&qdev->adapter_lock); } else if (value & ISP_IMR_DISABLE_CMPL_INT) { ql_disable_interrupts(qdev); @@ -3182,11 +3182,13 @@ static void ql3xxx_tx_timeout(struct net_device *ndev) /* * Wake up the worker to process this event. */ - queue_work(qdev->workqueue, &qdev->tx_timeout_work); + queue_delayed_work(qdev->workqueue, &qdev->tx_timeout_work, 0); } -static void ql_reset_work(struct ql3_adapter *qdev) +static void ql_reset_work(struct work_struct *work) { + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, reset_work.work); struct net_device *ndev = qdev->ndev; u32 value; struct ql_tx_buf_cb *tx_cb; @@ -3278,9 +3280,12 @@ static void ql_reset_work(struct ql3_adapter *qdev) } } -static void ql_tx_timeout_work(struct ql3_adapter *qdev) +static void ql_tx_timeout_work(struct work_struct *work) { - ql_cycle_adapter(qdev,QL_DO_RESET); + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, tx_timeout_work.work); + + ql_cycle_adapter(qdev, QL_DO_RESET); } static void ql_get_board_info(struct ql3_adapter *qdev) @@ -3459,9 +3464,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, netif_stop_queue(ndev); qdev->workqueue = create_singlethread_workqueue(ndev->name); - INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev); - INIT_WORK(&qdev->tx_timeout_work, - (void (*)(void *))ql_tx_timeout_work, qdev); + INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work); + INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work); init_timer(&qdev->adapter_timer); qdev->adapter_timer.function = ql3xxx_timer; diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 65da2c0..ea94de7 100644 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1186,8 +1186,8 @@ struct ql3_adapter { u32 numPorts; struct net_device_stats stats; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct tx_timeout_work; + struct delayed_work reset_work; + struct delayed_work tx_timeout_work; u32 max_frame_size; }; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 27f90b2..1f9663a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -424,6 +424,7 @@ struct ring_info { struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device *dev; struct net_device_stats stats; /* statistics of net device */ spinlock_t lock; /* spin lock flag */ u32 msg_enable; @@ -455,7 +456,7 @@ struct rtl8169_private { void (*phy_reset_enable)(void __iomem *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); - struct work_struct task; + struct delayed_work task; unsigned wol_enabled : 1; }; @@ -1492,6 +1493,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); /* enable device (incl. PCI PM wakeup and hotplug setup) */ @@ -1764,7 +1766,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_free_rx; - INIT_WORK(&tp->task, NULL, dev); + INIT_DELAYED_WORK(&tp->task, NULL); rtl8169_hw_start(dev); @@ -2087,11 +2089,11 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) tp->cur_tx = tp->dirty_tx = 0; } -static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *)) +static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) { struct rtl8169_private *tp = netdev_priv(dev); - PREPARE_WORK(&tp->task, task, dev); + PREPARE_DELAYED_WORK(&tp->task, task); schedule_delayed_work(&tp->task, 4); } @@ -2110,9 +2112,11 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) netif_poll_enable(dev); } -static void rtl8169_reinit_task(void *_data) +static void rtl8169_reinit_task(struct work_struct *work) { - struct net_device *dev = _data; + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; int ret; if (netif_running(dev)) { @@ -2135,10 +2139,11 @@ static void rtl8169_reinit_task(void *_data) } } -static void rtl8169_reset_task(void *_data) +static void rtl8169_reset_task(struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8169_private *tp = netdev_priv(dev); + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; if (!netif_running(dev)) return; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 33569ec..250cdbe 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5872,9 +5872,9 @@ static void s2io_tasklet(unsigned long dev_addr) * Description: Sets the link status for the adapter */ -static void s2io_set_link(unsigned long data) +static void s2io_set_link(struct work_struct *work) { - nic_t *nic = (nic_t *) data; + nic_t *nic = container_of(work, nic_t, set_link_task); struct net_device *dev = nic->dev; XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64; @@ -6379,10 +6379,10 @@ static int s2io_card_up(nic_t * sp) * spin lock. */ -static void s2io_restart_nic(unsigned long data) +static void s2io_restart_nic(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; - nic_t *sp = dev->priv; + nic_t *sp = container_of(work, nic_t, rst_timer_task); + struct net_device *dev = sp->dev; s2io_card_down(sp); if (s2io_card_up(sp)) { @@ -6992,10 +6992,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->tx_timeout = &s2io_tx_watchdog; dev->watchdog_timeo = WATCH_DOG_TIMEOUT; - INIT_WORK(&sp->rst_timer_task, - (void (*)(void *)) s2io_restart_nic, dev); - INIT_WORK(&sp->set_link_task, - (void (*)(void *)) s2io_set_link, sp); + INIT_WORK(&sp->rst_timer_task, s2io_restart_nic); + INIT_WORK(&sp->set_link_task, s2io_set_link); pci_save_state(sp->pdev); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 12b719f..3b0bafd 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -1000,7 +1000,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id); static irqreturn_t s2io_isr(int irq, void *dev_id); static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); static const struct ethtool_ops netdev_ethtool_ops; -static void s2io_set_link(unsigned long data); +static void s2io_set_link(struct work_struct *work); static int s2io_set_swapper(nic_t * sp); static void s2io_card_down(nic_t *nic); static int s2io_card_up(nic_t *nic); diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index aaba458..b70ed79 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -280,6 +280,7 @@ enum sis190_feature { struct sis190_private { void __iomem *mmio_addr; struct pci_dev *pci_dev; + struct net_device *dev; struct net_device_stats stats; spinlock_t lock; u32 rx_buf_sz; @@ -897,10 +898,11 @@ static void sis190_hw_start(struct net_device *dev) netif_start_queue(dev); } -static void sis190_phy_task(void * data) +static void sis190_phy_task(struct work_struct *work) { - struct net_device *dev = data; - struct sis190_private *tp = netdev_priv(dev); + struct sis190_private *tp = + container_of(work, struct sis190_private, phy_task); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->mmio_addr; int phy_id = tp->mii_if.phy_id; u16 val; @@ -1047,7 +1049,7 @@ static int sis190_open(struct net_device *dev) if (rc < 0) goto err_free_rx_1; - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); sis190_request_timer(dev); @@ -1436,6 +1438,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT); rc = pci_enable_device(pdev); @@ -1798,7 +1801,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, sis190_init_rxfilter(dev); - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); dev->open = sis190_open; dev->stop = sis190_close; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b294903..3b67614 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1327,10 +1327,11 @@ static void xm_check_link(struct net_device *dev) * Since internal PHY is wired to a level triggered pin, can't * get an interrupt when carrier is detected. */ -static void xm_link_timer(void *arg) +static void xm_link_timer(struct work_struct *work) { - struct net_device *dev = arg; - struct skge_port *skge = netdev_priv(arg); + struct skge_port *skge = + container_of(work, struct skge_port, link_thread.work); + struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; @@ -3072,9 +3073,9 @@ static void skge_error_irq(struct skge_hw *hw) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(void *arg) +static void skge_extirq(struct work_struct *work) { - struct skge_hw *hw = arg; + struct skge_hw *hw = container_of(work, struct skge_hw, phy_work); int port; mutex_lock(&hw->phy_mutex); @@ -3456,7 +3457,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - INIT_WORK(&skge->link_thread, xm_link_timer, dev); + INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer); if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; @@ -3543,7 +3544,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, hw->pdev = pdev; mutex_init(&hw->phy_mutex); - INIT_WORK(&hw->phy_work, skge_extirq, hw); + INIT_WORK(&hw->phy_work, skge_extirq); spin_lock_init(&hw->hw_lock); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 537c0aa..23e5275 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2456,7 +2456,7 @@ struct skge_port { struct net_device_stats net_stats; - struct work_struct link_thread; + struct delayed_work link_thread; enum pause_control flow_control; enum pause_status flow_status; u8 rx_csum; diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 418138d..f88fcac 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1945,10 +1945,11 @@ spider_net_stop(struct net_device *netdev) * called as task when tx hangs, resets interface (if interface is up) */ static void -spider_net_tx_timeout_task(void *data) +spider_net_tx_timeout_task(struct work_struct *work) { - struct net_device *netdev = data; - struct spider_net_card *card = netdev_priv(netdev); + struct spider_net_card *card = + container_of(work, struct spider_net_card, tx_timeout_task); + struct net_device *netdev = card->netdev; if (!(netdev->flags & IFF_UP)) goto out; @@ -2122,7 +2123,7 @@ spider_net_alloc_card(void) card = netdev_priv(netdev); card->netdev = netdev; card->msg_enable = SPIDER_NET_DEFAULT_MSG; - INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev); + INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task); init_waitqueue_head(&card->waitq); atomic_set(&card->tx_timeout_task_counter, 0); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 253e96e..004d651 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2281,9 +2281,9 @@ static void gem_do_stop(struct net_device *dev, int wol) } } -static void gem_reset_task(void *data) +static void gem_reset_task(struct work_struct *work) { - struct gem *gp = (struct gem *) data; + struct gem *gp = container_of(work, struct gem, reset_task); mutex_lock(&gp->pm_mutex); @@ -3043,7 +3043,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->link_timer.function = gem_link_timer; gp->link_timer.data = (unsigned long) gp; - INIT_WORK(&gp->reset_task, gem_reset_task, gp); + INIT_WORK(&gp->reset_task, gem_reset_task); gp->lstate = link_down; gp->timer_ticks = 0; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c20bb99..d9123c9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3654,9 +3654,9 @@ static void tg3_poll_controller(struct net_device *dev) } #endif -static void tg3_reset_task(void *_data) +static void tg3_reset_task(struct work_struct *work) { - struct tg3 *tp = _data; + struct tg3 *tp = container_of(work, struct tg3, reset_task); unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -11734,7 +11734,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, #endif spin_lock_init(&tp->lock); spin_lock_init(&tp->indirect_lock); - INIT_WORK(&tp->reset_task, tg3_reset_task, tp); + INIT_WORK(&tp->reset_task, tg3_reset_task); tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index e14f5a0..f85f002 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -296,6 +296,7 @@ static void TLan_SetMulticastList( struct net_device *); static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd); static int TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent); static void TLan_tx_timeout( struct net_device *dev); +static void TLan_tx_timeout_work(struct work_struct *work); static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); static u32 TLan_HandleInvalid( struct net_device *, u16 ); @@ -562,6 +563,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, priv = netdev_priv(dev); priv->pciDev = pdev; + priv->dev = dev; /* Is this a PCI device? */ if (pdev) { @@ -634,7 +636,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, /* This will be used when we get an adapter error from * within our irq handler */ - INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev); + INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work); spin_lock_init(&priv->lock); @@ -1040,6 +1042,25 @@ static void TLan_tx_timeout(struct net_device *dev) } + /*************************************************************** + * TLan_tx_timeout_work + * + * Returns: nothing + * + * Params: + * work work item of device which timed out + * + **************************************************************/ + +static void TLan_tx_timeout_work(struct work_struct *work) +{ + TLanPrivateInfo *priv = + container_of(work, TLanPrivateInfo, tlan_tqueue); + + TLan_tx_timeout(priv->dev); +} + + /*************************************************************** * TLan_StartTx diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h index a44e2f2..41ce0b6 100644 --- a/drivers/net/tlan.h +++ b/drivers/net/tlan.h @@ -170,6 +170,7 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE]; typedef struct tlan_private_tag { struct net_device *nextDevice; struct pci_dev *pciDev; + struct net_device *dev; void *dmaStorage; dma_addr_t dmaStorageDMA; unsigned int dmaSize; diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index fa3a2bb..942b839 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -26,10 +26,11 @@ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list of available transceivers. */ -void t21142_media_task(void *data) +void t21142_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; int csr12 = ioread32(ioaddr + CSR12); int next_tick = 60*HZ; diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index 066e5d6..df326fe 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -18,10 +18,11 @@ #include "tulip.h" -void tulip_media_task(void *data) +void tulip_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; u32 csr12 = ioread32(ioaddr + CSR12); int next_tick = 2*HZ; diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index ad107f4..25f25da 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -44,7 +44,7 @@ struct tulip_chip_table { int valid_intrs; /* CSR7 interrupt enable settings */ int flags; void (*media_timer) (unsigned long); - void (*media_task) (void *); + work_func_t media_task; }; @@ -392,6 +392,7 @@ struct tulip_private { int csr12_shadow; int pad0; /* Used for 8-byte alignment */ struct work_struct media_work; + struct net_device *dev; }; @@ -406,7 +407,7 @@ struct eeprom_fixup { /* 21142.c */ extern u16 t21142_csr14[]; -void t21142_media_task(void *data); +void t21142_media_task(struct work_struct *work); void t21142_start_nway(struct net_device *dev); void t21142_lnk_change(struct net_device *dev, int csr5); @@ -444,7 +445,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5); void pnic_timer(unsigned long data); /* timer.c */ -void tulip_media_task(void *data); +void tulip_media_task(struct work_struct *work); void mxic_timer(unsigned long data); void comet_timer(unsigned long data); diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 0aee618..5a35354 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1367,6 +1367,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, * it is zeroed and aligned in alloc_etherdev */ tp = netdev_priv(dev); + tp->dev = dev; tp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct tulip_rx_desc) * RX_RING_SIZE + @@ -1389,7 +1390,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->timer.data = (unsigned long)dev; tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev); + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); dev->base_addr = (unsigned long)ioaddr; diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 931cbdf..b2a23ae 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -125,8 +125,8 @@ static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); static void cpc_tty_hangup(struct tty_struct *tty); -static void cpc_tty_rx_work(void *data); -static void cpc_tty_tx_work(void *data); +static void cpc_tty_rx_work(struct work_struct *work); +static void cpc_tty_tx_work(struct work_struct *work); static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len); static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char); @@ -261,8 +261,8 @@ void cpc_tty_init(pc300dev_t *pc300dev) cpc_tty->tty_minor = port + CPC_TTY_MINOR_START; cpc_tty->pc300dev = pc300dev; - INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty); - INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port); + INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work); + INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work); cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL; @@ -659,21 +659,23 @@ static void cpc_tty_hangup(struct tty_struct *tty) * o call the line disc. read * o free memory */ -static void cpc_tty_rx_work(void * data) +static void cpc_tty_rx_work(struct work_struct *work) { + st_cpc_tty_area *cpc_tty; unsigned long port; int i, j; - st_cpc_tty_area *cpc_tty; volatile st_cpc_rx_buf *buf; char flags=0,flg_rx=1; struct tty_ldisc *ld; if (cpc_tty_cnt == 0) return; - for (i=0; (i < 4) && flg_rx ; i++) { flg_rx = 0; - port = (unsigned long)data; + + cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work); + port = cpc_tty - cpc_tty_area; + for (j=0; j < CPC_TTY_NPORTS; j++) { cpc_tty = &cpc_tty_area[port]; @@ -882,9 +884,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) * o if need call line discipline wakeup * o call wake_up_interruptible */ -static void cpc_tty_tx_work(void *data) +static void cpc_tty_tx_work(struct work_struct *work) { - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; + st_cpc_tty_area *cpc_tty = + container_of(work, st_cpc_tty_area, tty_tx_work); struct tty_struct *tty; CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index d6a8bf0..fbc0c08 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -787,7 +787,7 @@ struct bcm43xx_private { struct tasklet_struct isr_tasklet; /* Periodic tasks */ - struct work_struct periodic_work; + struct delayed_work periodic_work; unsigned int periodic_state; struct work_struct restart_work; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a1b7838..728a9b7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3177,9 +3177,10 @@ static int estimate_periodic_work_badness(unsigned int state) return badness; } -static void bcm43xx_periodic_work_handler(void *d) +static void bcm43xx_periodic_work_handler(struct work_struct *work) { - struct bcm43xx_private *bcm = d; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, periodic_work.work); struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; @@ -3242,11 +3243,11 @@ void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - struct work_struct *work = &(bcm->periodic_work); + struct delayed_work *work = &bcm->periodic_work; assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); - schedule_work(work); + INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler); + schedule_delayed_work(work, 0); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3598,7 +3599,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_periodic_tasks_setup(bcm); /*FIXME: This should be handled by softmac instead. */ - schedule_work(&bcm->softmac->associnfo.work); + schedule_delayed_work(&bcm->softmac->associnfo.work, 0); out: mutex_unlock(&(bcm)->mutex); @@ -4149,9 +4150,10 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) /* Hard-reset the chip. Do not call this directly. * Use bcm43xx_controller_restart() */ -static void bcm43xx_chip_reset(void *_bcm) +static void bcm43xx_chip_reset(struct work_struct *work) { - struct bcm43xx_private *bcm = _bcm; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, restart_work); struct bcm43xx_phyinfo *phy; int err = -ENODEV; @@ -4178,7 +4180,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) return; printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); - INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset); schedule_work(&bcm->restart_work); } diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h index e663518..e89c890 100644 --- a/drivers/net/wireless/hostap/hostap.h +++ b/drivers/net/wireless/hostap/hostap.h @@ -35,7 +35,7 @@ int hostap_80211_get_hdrlen(u16 fc); struct net_device_stats *hostap_get_stats(struct net_device *dev); void hostap_setup_dev(struct net_device *dev, local_info_t *local, int main_dev); -void hostap_set_multicast_list_queue(void *data); +void hostap_set_multicast_list_queue(struct work_struct *work); int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked); int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked); void hostap_cleanup(local_info_t *local); diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index ba13125..08bc57a 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -49,10 +49,10 @@ MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs " static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta); static void hostap_event_expired_sta(struct net_device *dev, struct sta_info *sta); -static void handle_add_proc_queue(void *data); +static void handle_add_proc_queue(struct work_struct *work); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data); +static void handle_wds_oper_queue(struct work_struct *work); static void prism2_send_mgmt(struct net_device *dev, u16 type_subtype, char *body, int body_len, u8 *addr, u16 tx_cb_idx); @@ -807,7 +807,7 @@ void hostap_init_data(local_info_t *local) INIT_LIST_HEAD(&ap->sta_list); /* Initialize task queue structure for AP management */ - INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap); + INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue); ap->tx_callback_idx = hostap_tx_callback_register(local, hostap_ap_tx_cb, ap); @@ -815,7 +815,7 @@ void hostap_init_data(local_info_t *local) printk(KERN_WARNING "%s: failed to register TX callback for " "AP\n", local->dev->name); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local); + INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue); ap->tx_callback_auth = hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap); @@ -1062,9 +1062,10 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off, } -static void handle_add_proc_queue(void *data) +static void handle_add_proc_queue(struct work_struct *work) { - struct ap_data *ap = (struct ap_data *) data; + struct ap_data *ap = container_of(work, struct ap_data, + add_sta_proc_queue); struct sta_info *sta; char name[20]; struct add_sta_proc_data *entry, *prev; @@ -1952,9 +1953,11 @@ static void handle_pspoll(local_info_t *local, #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data) +static void handle_wds_oper_queue(struct work_struct *work) { - local_info_t *local = data; + struct ap_data *ap = container_of(work, struct ap_data, + wds_oper_queue); + local_info_t *local = ap->local; struct wds_oper_data *entry, *prev; spin_lock_bh(&local->lock); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ed00ebb..c19e686 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -1645,9 +1645,9 @@ static void prism2_schedule_reset(local_info_t *local) /* Called only as scheduled task after noticing card timeout in interrupt * context */ -static void handle_reset_queue(void *data) +static void handle_reset_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, reset_queue); printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name); prism2_hw_reset(local->dev); @@ -2896,9 +2896,10 @@ static void hostap_passive_scan(unsigned long data) /* Called only as a scheduled task when communications quality values should * be updated. */ -static void handle_comms_qual_update(void *data) +static void handle_comms_qual_update(struct work_struct *work) { - local_info_t *local = data; + local_info_t *local = + container_of(work, local_info_t, comms_qual_update); prism2_update_comms_qual(local->dev); } @@ -3050,9 +3051,9 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set) } -static void handle_set_tim_queue(void *data) +static void handle_set_tim_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, set_tim_queue); struct set_tim_data *entry; u16 val; @@ -3209,15 +3210,15 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, local->scan_channel_mask = 0xffff; /* Initialize task queue structures */ - INIT_WORK(&local->reset_queue, handle_reset_queue, local); + INIT_WORK(&local->reset_queue, handle_reset_queue); INIT_WORK(&local->set_multicast_list_queue, - hostap_set_multicast_list_queue, local->dev); + hostap_set_multicast_list_queue); - INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local); + INIT_WORK(&local->set_tim_queue, handle_set_tim_queue); INIT_LIST_HEAD(&local->set_tim_list); spin_lock_init(&local->set_tim_lock); - INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local); + INIT_WORK(&local->comms_qual_update, handle_comms_qual_update); /* Initialize tasklets for handling hardware IRQ related operations * outside hw IRQ handler */ diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c index 50f72d8..5fd2b1a 100644 --- a/drivers/net/wireless/hostap/hostap_info.c +++ b/drivers/net/wireless/hostap/hostap_info.c @@ -474,9 +474,9 @@ static void handle_info_queue_scanresults(local_info_t *local) /* Called only as scheduled task after receiving info frames (used to avoid * pending too much time in HW IRQ handler). */ -static void handle_info_queue(void *data) +static void handle_info_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, info_queue); if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info)) @@ -493,7 +493,7 @@ void hostap_info_init(local_info_t *local) { skb_queue_head_init(&local->info_list); #ifndef PRISM2_NO_STATION_MODES - INIT_WORK(&local->info_queue, handle_info_queue, local); + INIT_WORK(&local->info_queue, handle_info_queue); #endif /* PRISM2_NO_STATION_MODES */ } diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 53374fc..0796be9 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -767,14 +767,14 @@ static int prism2_set_mac_address(struct net_device *dev, void *p) /* TODO: to be further implemented as soon as Prism2 fully supports * GroupAddresses and correct documentation is available */ -void hostap_set_multicast_list_queue(void *data) +void hostap_set_multicast_list_queue(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; + local_info_t *local = + container_of(work, local_info_t, set_multicast_list_queue); + struct net_device *dev = local->dev; struct hostap_interface *iface; - local_info_t *local; iface = netdev_priv(dev); - local = iface->local; if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, local->is_promisc)) { printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 4e4eaa2..0f55437 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -316,7 +316,7 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw); static int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw); -static void ipw2100_wx_event_work(struct ipw2100_priv *priv); +static void ipw2100_wx_event_work(struct work_struct *work); static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev); static struct iw_handler_def ipw2100_wx_handler_def; @@ -679,7 +679,8 @@ static void schedule_reset(struct ipw2100_priv *priv) queue_delayed_work(priv->workqueue, &priv->reset_work, priv->reset_backoff * HZ); else - queue_work(priv->workqueue, &priv->reset_work); + queue_delayed_work(priv->workqueue, &priv->reset_work, + 0); if (priv->reset_backoff < MAX_RESET_BACKOFF) priv->reset_backoff++; @@ -1873,8 +1874,10 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } -static void ipw2100_reset_adapter(struct ipw2100_priv *priv) +static void ipw2100_reset_adapter(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, reset_work.work); unsigned long flags; union iwreq_data wrqu = { .ap_addr = { @@ -2071,9 +2074,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) return; if (priv->status & STATUS_SECURITY_UPDATED) - queue_work(priv->workqueue, &priv->security_work); + queue_delayed_work(priv->workqueue, &priv->security_work, 0); - queue_work(priv->workqueue, &priv->wx_event_work); + queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0); } static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) @@ -5524,8 +5527,11 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) return err; } -static void ipw2100_security_work(struct ipw2100_priv *priv) +static void ipw2100_security_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, security_work.work); + /* If we happen to have reconnected before we get a chance to * process this, then update the security settings--which causes * a disassociation to occur */ @@ -5748,7 +5754,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p) priv->reset_backoff = 0; mutex_unlock(&priv->action_mutex); - ipw2100_reset_adapter(priv); + ipw2100_reset_adapter(&priv->reset_work.work); return 0; done: @@ -5923,9 +5929,10 @@ static const struct ethtool_ops ipw2100_ethtool_ops = { .get_drvinfo = ipw_ethtool_get_drvinfo, }; -static void ipw2100_hang_check(void *adapter) +static void ipw2100_hang_check(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, hang_check.work); unsigned long flags; u32 rtc = 0xa5a5a5a5; u32 len = sizeof(rtc); @@ -5965,9 +5972,10 @@ static void ipw2100_hang_check(void *adapter) spin_unlock_irqrestore(&priv->low_lock, flags); } -static void ipw2100_rf_kill(void *adapter) +static void ipw2100_rf_kill(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, rf_kill.work); unsigned long flags; spin_lock_irqsave(&priv->low_lock, flags); @@ -6117,14 +6125,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->workqueue = create_workqueue(DRV_NAME); - INIT_WORK(&priv->reset_work, - (void (*)(void *))ipw2100_reset_adapter, priv); - INIT_WORK(&priv->security_work, - (void (*)(void *))ipw2100_security_work, priv); - INIT_WORK(&priv->wx_event_work, - (void (*)(void *))ipw2100_wx_event_work, priv); - INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv); - INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv); + INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter); + INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work); + INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); + INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); + INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -8290,8 +8295,10 @@ static struct iw_handler_def ipw2100_wx_handler_def = { .get_wireless_stats = ipw2100_wx_wireless_stats, }; -static void ipw2100_wx_event_work(struct ipw2100_priv *priv) +static void ipw2100_wx_event_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, wx_event_work.work); union iwreq_data wrqu; int len = ETH_ALEN; diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 55b7227..de7d384 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -583,11 +583,11 @@ struct ipw2100_priv { struct tasklet_struct irq_tasklet; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct security_work; - struct work_struct wx_event_work; - struct work_struct hang_check; - struct work_struct rf_kill; + struct delayed_work reset_work; + struct delayed_work security_work; + struct delayed_work wx_event_work; + struct delayed_work hang_check; + struct delayed_work rf_kill; u32 interrupts; int tx_interrupts; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 1f74281..587a091 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -187,9 +187,9 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); static void ipw_rx_queue_replenish(void *); static int ipw_up(struct ipw_priv *); -static void ipw_bg_up(void *); +static void ipw_bg_up(struct work_struct *work); static void ipw_down(struct ipw_priv *); -static void ipw_bg_down(void *); +static void ipw_bg_down(struct work_struct *work); static int ipw_config(struct ipw_priv *); static int init_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *prates); @@ -862,11 +862,12 @@ static void ipw_led_link_on(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_on(void *data) +static void ipw_bg_led_link_on(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_on.work); mutex_lock(&priv->mutex); - ipw_led_link_on(data); + ipw_led_link_on(priv); mutex_unlock(&priv->mutex); } @@ -906,11 +907,12 @@ static void ipw_led_link_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_off(void *data) +static void ipw_bg_led_link_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_off.work); mutex_lock(&priv->mutex); - ipw_led_link_off(data); + ipw_led_link_off(priv); mutex_unlock(&priv->mutex); } @@ -985,11 +987,12 @@ static void ipw_led_activity_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_activity_off(void *data) +static void ipw_bg_led_activity_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_act_off.work); mutex_lock(&priv->mutex); - ipw_led_activity_off(data); + ipw_led_activity_off(priv); mutex_unlock(&priv->mutex); } @@ -2228,11 +2231,12 @@ static void ipw_adapter_restart(void *adapter) } } -static void ipw_bg_adapter_restart(void *data) +static void ipw_bg_adapter_restart(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adapter_restart); mutex_lock(&priv->mutex); - ipw_adapter_restart(data); + ipw_adapter_restart(priv); mutex_unlock(&priv->mutex); } @@ -2249,11 +2253,12 @@ static void ipw_scan_check(void *data) } } -static void ipw_bg_scan_check(void *data) +static void ipw_bg_scan_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, scan_check.work); mutex_lock(&priv->mutex); - ipw_scan_check(data); + ipw_scan_check(priv); mutex_unlock(&priv->mutex); } @@ -3831,17 +3836,19 @@ static int ipw_disassociate(void *data) return 1; } -static void ipw_bg_disassociate(void *data) +static void ipw_bg_disassociate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, disassociate); mutex_lock(&priv->mutex); - ipw_disassociate(data); + ipw_disassociate(priv); mutex_unlock(&priv->mutex); } -static void ipw_system_config(void *data) +static void ipw_system_config(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, system_config); #ifdef CONFIG_IPW2200_PROMISCUOUS if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { @@ -4208,11 +4215,12 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_STATS_INTERVAL); } -static void ipw_bg_gather_stats(void *data) +static void ipw_bg_gather_stats(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, gather_stats.work); mutex_lock(&priv->mutex); - ipw_gather_stats(data); + ipw_gather_stats(priv); mutex_unlock(&priv->mutex); } @@ -4268,8 +4276,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, if (!(priv->status & STATUS_ROAMING)) { priv->status |= STATUS_ROAMING; if (!(priv->status & STATUS_SCANNING)) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return; } @@ -4607,8 +4615,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { priv->status |= STATUS_SCAN_FORCED; - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); break; } priv->status &= ~STATUS_SCAN_FORCED; @@ -4631,8 +4639,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, /* Don't schedule if we aborted the scan */ priv->status &= ~STATUS_ROAMING; } else if (priv->status & STATUS_SCAN_PENDING) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, @@ -5055,11 +5063,12 @@ static void ipw_rx_queue_replenish(void *data) ipw_rx_queue_restock(priv); } -static void ipw_bg_rx_queue_replenish(void *data) +static void ipw_bg_rx_queue_replenish(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rx_replenish); mutex_lock(&priv->mutex); - ipw_rx_queue_replenish(data); + ipw_rx_queue_replenish(priv); mutex_unlock(&priv->mutex); } @@ -5489,9 +5498,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, return 1; } -static void ipw_merge_adhoc_network(void *data) +static void ipw_merge_adhoc_network(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, merge_networks); struct ieee80211_network *network = NULL; struct ipw_network_match match = { .network = priv->assoc_network @@ -5948,11 +5958,12 @@ static void ipw_adhoc_check(void *data) priv->assoc_request.beacon_interval); } -static void ipw_bg_adhoc_check(void *data) +static void ipw_bg_adhoc_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adhoc_check.work); mutex_lock(&priv->mutex); - ipw_adhoc_check(data); + ipw_adhoc_check(priv); mutex_unlock(&priv->mutex); } @@ -6299,19 +6310,26 @@ done: return err; } -static int ipw_request_passive_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); +static void ipw_request_passive_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_passive_scan); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); } -static int ipw_request_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); +static void ipw_request_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); } -static void ipw_bg_abort_scan(void *data) +static void ipw_bg_abort_scan(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, abort_scan); mutex_lock(&priv->mutex); - ipw_abort_scan(data); + ipw_abort_scan(priv); mutex_unlock(&priv->mutex); } @@ -7084,9 +7102,10 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, /* * background support to run QoS activate functionality */ -static void ipw_bg_qos_activate(void *data) +static void ipw_bg_qos_activate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, qos_activate); if (priv == NULL) return; @@ -7394,11 +7413,12 @@ static void ipw_roam(void *data) priv->status &= ~STATUS_ROAMING; } -static void ipw_bg_roam(void *data) +static void ipw_bg_roam(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, roam); mutex_lock(&priv->mutex); - ipw_roam(data); + ipw_roam(priv); mutex_unlock(&priv->mutex); } @@ -7479,8 +7499,8 @@ static int ipw_associate(void *data) &priv->request_scan, SCAN_INTERVAL); else - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return 0; @@ -7491,11 +7511,12 @@ static int ipw_associate(void *data) return 1; } -static void ipw_bg_associate(void *data) +static void ipw_bg_associate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, associate); mutex_lock(&priv->mutex); - ipw_associate(data); + ipw_associate(priv); mutex_unlock(&priv->mutex); } @@ -9410,7 +9431,7 @@ static int ipw_wx_set_scan(struct net_device *dev, IPW_DEBUG_WX("Start scan\n"); - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); return 0; } @@ -10547,11 +10568,12 @@ static void ipw_rf_kill(void *adapter) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_rf_kill(void *data) +static void ipw_bg_rf_kill(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rf_kill.work); mutex_lock(&priv->mutex); - ipw_rf_kill(data); + ipw_rf_kill(priv); mutex_unlock(&priv->mutex); } @@ -10582,11 +10604,12 @@ static void ipw_link_up(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); } -static void ipw_bg_link_up(void *data) +static void ipw_bg_link_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_up); mutex_lock(&priv->mutex); - ipw_link_up(data); + ipw_link_up(priv); mutex_unlock(&priv->mutex); } @@ -10606,15 +10629,16 @@ static void ipw_link_down(struct ipw_priv *priv) if (!(priv->status & STATUS_EXIT_PENDING)) { /* Queue up another scan... */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); } } -static void ipw_bg_link_down(void *data) +static void ipw_bg_link_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_down); mutex_lock(&priv->mutex); - ipw_link_down(data); + ipw_link_down(priv); mutex_unlock(&priv->mutex); } @@ -10626,38 +10650,30 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) init_waitqueue_head(&priv->wait_command_queue); init_waitqueue_head(&priv->wait_state); - INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); - INIT_WORK(&priv->associate, ipw_bg_associate, priv); - INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv); - INIT_WORK(&priv->system_config, ipw_system_config, priv); - INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); - INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); - INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); - INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); - INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); - INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_request_scan, priv); - INIT_WORK(&priv->request_passive_scan, - (void (*)(void *))ipw_request_passive_scan, priv); - INIT_WORK(&priv->gather_stats, - (void (*)(void *))ipw_bg_gather_stats, priv); - INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); - INIT_WORK(&priv->roam, ipw_bg_roam, priv); - INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv); - INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv); - INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv); - INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on, - priv); - INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off, - priv); - INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off, - priv); - INIT_WORK(&priv->merge_networks, - (void (*)(void *))ipw_merge_adhoc_network, priv); + INIT_DELAYED_WORK(&priv->adhoc_check, ipw_bg_adhoc_check); + INIT_WORK(&priv->associate, ipw_bg_associate); + INIT_WORK(&priv->disassociate, ipw_bg_disassociate); + INIT_WORK(&priv->system_config, ipw_system_config); + INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish); + INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart); + INIT_DELAYED_WORK(&priv->rf_kill, ipw_bg_rf_kill); + INIT_WORK(&priv->up, ipw_bg_up); + INIT_WORK(&priv->down, ipw_bg_down); + INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); + INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); + INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); + INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); + INIT_WORK(&priv->roam, ipw_bg_roam); + INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check); + INIT_WORK(&priv->link_up, ipw_bg_link_up); + INIT_WORK(&priv->link_down, ipw_bg_link_down); + INIT_DELAYED_WORK(&priv->led_link_on, ipw_bg_led_link_on); + INIT_DELAYED_WORK(&priv->led_link_off, ipw_bg_led_link_off); + INIT_DELAYED_WORK(&priv->led_act_off, ipw_bg_led_activity_off); + INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network); #ifdef CONFIG_IPW2200_QOS - INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, - priv); + INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate); #endif /* CONFIG_IPW2200_QOS */ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) @@ -11190,7 +11206,8 @@ static int ipw_up(struct ipw_priv *priv) /* If configure to try and auto-associate, kick * off a scan. */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); return 0; } @@ -11211,11 +11228,12 @@ static int ipw_up(struct ipw_priv *priv) return -EIO; } -static void ipw_bg_up(void *data) +static void ipw_bg_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, up); mutex_lock(&priv->mutex); - ipw_up(data); + ipw_up(priv); mutex_unlock(&priv->mutex); } @@ -11282,11 +11300,12 @@ static void ipw_down(struct ipw_priv *priv) ipw_led_radio_off(priv); } -static void ipw_bg_down(void *data) +static void ipw_bg_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, down); mutex_lock(&priv->mutex); - ipw_down(data); + ipw_down(priv); mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index dad5eed..626a240 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1290,21 +1290,21 @@ struct ipw_priv { struct workqueue_struct *workqueue; - struct work_struct adhoc_check; + struct delayed_work adhoc_check; struct work_struct associate; struct work_struct disassociate; struct work_struct system_config; struct work_struct rx_replenish; - struct work_struct request_scan; + struct delayed_work request_scan; struct work_struct request_passive_scan; struct work_struct adapter_restart; - struct work_struct rf_kill; + struct delayed_work rf_kill; struct work_struct up; struct work_struct down; - struct work_struct gather_stats; + struct delayed_work gather_stats; struct work_struct abort_scan; struct work_struct roam; - struct work_struct scan_check; + struct delayed_work scan_check; struct work_struct link_up; struct work_struct link_down; @@ -1319,9 +1319,9 @@ struct ipw_priv { u32 led_ofdm_on; u32 led_ofdm_off; - struct work_struct led_link_on; - struct work_struct led_link_off; - struct work_struct led_act_off; + struct delayed_work led_link_on; + struct delayed_work led_link_off; + struct delayed_work led_act_off; struct work_struct merge_networks; struct ipw_cmd_log *cmdlog; diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 336caba..936c888 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -980,9 +980,11 @@ static void print_linkstatus(struct net_device *dev, u16 status) } /* Search scan results for requested BSSID, join it if found */ -static void orinoco_join_ap(struct net_device *dev) +static void orinoco_join_ap(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, join_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -1055,9 +1057,11 @@ static void orinoco_join_ap(struct net_device *dev) } /* Send new BSSID to userspace */ -static void orinoco_send_wevents(struct net_device *dev) +static void orinoco_send_wevents(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, wevent_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; union iwreq_data wrqu; int err; @@ -1864,9 +1868,11 @@ __orinoco_set_multicast_list(struct net_device *dev) /* This must be called from user context, without locks held - use * schedule_work() */ -static void orinoco_reset(struct net_device *dev) +static void orinoco_reset(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, reset_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -2434,9 +2440,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, priv->hw_unavailable = 1; /* orinoco_init() must clear this * before anything else touches the * hardware */ - INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); - INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); + INIT_WORK(&priv->reset_work, orinoco_reset); + INIT_WORK(&priv->join_work, orinoco_join_ap); + INIT_WORK(&priv->wevent_work, orinoco_send_wevents); netif_carrier_off(dev); priv->last_linkstatus = 0xffff; @@ -3608,7 +3614,7 @@ static int orinoco_ioctl_reset(struct net_device *dev, printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); /* Firmware reset */ - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); } else { printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); @@ -4154,7 +4160,7 @@ static int orinoco_ioctl_commit(struct net_device *dev, return 0; if (priv->broken_disableport) { - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); return 0; } diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 286325c..e7700b4 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -158,8 +158,9 @@ prism54_mib_init(islpci_private *priv) * schedule_work(), thus we can as well use sleeping semaphore * locking */ void -prism54_update_stats(islpci_private *priv) +prism54_update_stats(struct work_struct *work) { + islpci_private *priv = container_of(work, islpci_private, stats_work); char *data; int j; struct obj_bss bss, *bss2; @@ -2494,9 +2495,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, * interrupt context, no locks held. */ void -prism54_process_trap(void *data) +prism54_process_trap(struct work_struct *work) { - struct islpci_mgmtframe *frame = data; + struct islpci_mgmtframe *frame = + container_of(work, struct islpci_mgmtframe, ws); struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index 65f33ac..0802fa6 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -32,12 +32,12 @@ void prism54_mib_init(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); -void prism54_update_stats(islpci_private *); +void prism54_update_stats(struct work_struct *); void prism54_acl_init(struct islpci_acl *); void prism54_acl_clean(struct islpci_acl *); -void prism54_process_trap(void *); +void prism54_process_trap(struct work_struct *); void prism54_wpa_bss_ie_init(islpci_private *priv); void prism54_wpa_bss_ie_clean(islpci_private *priv); diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index ec1c00f..e35fcb2 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -861,11 +861,10 @@ islpci_setup(struct pci_dev *pdev) priv->state_off = 1; /* initialize workqueue's */ - INIT_WORK(&priv->stats_work, - (void (*)(void *)) prism54_update_stats, priv); + INIT_WORK(&priv->stats_work, prism54_update_stats); priv->stats_timestamp = 0; - INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake); priv->reset_task_pending = 0; /* allocate various memory areas */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index a8261d8..103a378 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -482,9 +482,9 @@ islpci_eth_receive(islpci_private *priv) } void -islpci_do_reset_and_wake(void *data) +islpci_do_reset_and_wake(struct work_struct *work) { - islpci_private *priv = (islpci_private *) data; + islpci_private *priv = container_of(work, islpci_private, reset_task); islpci_reset(priv, 1); netif_wake_queue(priv->ndev); priv->reset_task_pending = 0; diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h index bc9d7a6..99d37ed 100644 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ b/drivers/net/wireless/prism54/islpci_eth.h @@ -68,6 +68,6 @@ void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); int islpci_eth_transmit(struct sk_buff *, struct net_device *); int islpci_eth_receive(islpci_private *); void islpci_eth_tx_timeout(struct net_device *); -void islpci_do_reset_and_wake(void *data); +void islpci_do_reset_and_wake(struct work_struct *); #endif /* _ISL_GEN_H */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 2e061a8..656ec9f 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -387,7 +387,7 @@ islpci_mgt_receive(struct net_device *ndev) /* Create work to handle trap out of interrupt * context. */ - INIT_WORK(&frame->ws, prism54_process_trap, frame); + INIT_WORK(&frame->ws, prism54_process_trap); schedule_work(&frame->ws); } else { diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a7d29bd..5e4f4b7 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1090,9 +1090,10 @@ void zd_dump_rx_status(const struct rx_status *status) #define LINK_LED_WORK_DELAY HZ -static void link_led_handler(void *p) +static void link_led_handler(struct work_struct *work) { - struct zd_mac *mac = p; + struct zd_mac *mac = + container_of(work, struct zd_mac, housekeeping.link_led_work.work); struct zd_chip *chip = &mac->chip; struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev); int is_associated; @@ -1113,7 +1114,7 @@ static void link_led_handler(void *p) static void housekeeping_init(struct zd_mac *mac) { - INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac); + INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler); } static void housekeeping_enable(struct zd_mac *mac) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index b8ea3de..7957cac 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -121,7 +121,7 @@ enum mac_flags { }; struct housekeeping { - struct work_struct link_led_work; + struct delayed_work link_led_work; }; #define ZD_MAC_STATS_BUFFER_SIZE 16 diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index fc4bc9b..a83c3db 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -29,7 +29,7 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; -static void wq_sync_buffer(void *); +static void wq_sync_buffer(struct work_struct *work); #define DEFAULT_TIMER_EXPIRE (HZ / 10) static int work_enabled; @@ -65,7 +65,7 @@ int alloc_cpu_buffers(void) b->sample_received = 0; b->sample_lost_overflow = 0; b->cpu = i; - INIT_WORK(&b->work, wq_sync_buffer, b); + INIT_DELAYED_WORK(&b->work, wq_sync_buffer); } return 0; @@ -282,9 +282,10 @@ void oprofile_add_trace(unsigned long pc) * By using schedule_delayed_work_on and then schedule_delayed_work * we guarantee this will stay on the correct cpu */ -static void wq_sync_buffer(void * data) +static void wq_sync_buffer(struct work_struct *work) { - struct oprofile_cpu_buffer * b = data; + struct oprofile_cpu_buffer * b = + container_of(work, struct oprofile_cpu_buffer, work.work); if (b->cpu != smp_processor_id()) { printk("WQ on CPU%d, prefer CPU%d\n", smp_processor_id(), b->cpu); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 09abb80..49900d9 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -43,7 +43,7 @@ struct oprofile_cpu_buffer { unsigned long sample_lost_overflow; unsigned long backtrace_aborted; int cpu; - struct work_struct work; + struct delayed_work work; } ____cacheline_aligned; extern struct oprofile_cpu_buffer cpu_buffer[]; diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ea2087c..5075769 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -70,7 +70,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; char name[SLOT_NAME_SIZE]; - struct work_struct work; /* work for button event */ + struct delayed_work work; /* work for button event */ struct mutex lock; }; @@ -187,7 +187,7 @@ extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); -extern void queue_pushbutton_work(void *data); +extern void queue_pushbutton_work(struct work_struct *work); #ifdef CONFIG_ACPI diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 235c18a..4eac85b 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -159,7 +159,7 @@ static int init_slots(struct controller *ctrl) goto error_info; slot->number = sun; - INIT_WORK(&slot->work, queue_pushbutton_work, slot); + INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index c39901d..158ac78 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -36,7 +36,7 @@ #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(void *data); +static void interrupt_event_handler(struct work_struct *work); static int shpchp_enable_slot(struct slot *p_slot); static int shpchp_disable_slot(struct slot *p_slot); @@ -50,7 +50,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->event_type = event_type; info->p_slot = p_slot; - INIT_WORK(&info->work, interrupt_event_handler, info); + INIT_WORK(&info->work, interrupt_event_handler); schedule_work(&info->work); @@ -408,9 +408,10 @@ struct pushbutton_work_info { * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(struct work_struct *work) { - struct pushbutton_work_info *info = data; + struct pushbutton_work_info *info = + container_of(work, struct pushbutton_work_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); @@ -436,9 +437,9 @@ static void shpchp_pushbutton_thread(void *data) kfree(info); } -void queue_pushbutton_work(void *data) +void queue_pushbutton_work(struct work_struct *work) { - struct slot *p_slot = data; + struct slot *p_slot = container_of(work, struct slot, work.work); struct pushbutton_work_info *info; info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -447,7 +448,7 @@ void queue_pushbutton_work(void *data) return; } info->p_slot = p_slot; - INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + INIT_WORK(&info->work, shpchp_pushbutton_thread); mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -541,9 +542,9 @@ static void handle_button_press_event(struct slot *p_slot) } } -static void interrupt_event_handler(void *data) +static void interrupt_event_handler(struct work_struct *work) { - struct event_info *info = data; + struct event_info *info = container_of(work, struct event_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a20d84d..e469a46 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -698,9 +698,10 @@ static int pcmcia_card_add(struct pcmcia_socket *s) } -static void pcmcia_delayed_add_pseudo_device(void *data) +static void pcmcia_delayed_add_pseudo_device(struct work_struct *work) { - struct pcmcia_socket *s = data; + struct pcmcia_socket *s = + container_of(work, struct pcmcia_socket, device_add); pcmcia_device_add(s, 0); s->pcmcia_state.device_add_pending = 0; } @@ -1246,7 +1247,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, init_waitqueue_head(&socket->queue); #endif INIT_LIST_HEAD(&socket->devices_list); - INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket); + INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device); memset(&socket->pcmcia_state, 0, sizeof(u8)); socket->device_count = 0; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 583789c..dcf5f86 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -53,9 +53,10 @@ static int rtc_dev_open(struct inode *inode, struct file *file) * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void rtc_uie_task(void *data) +static void rtc_uie_task(struct work_struct *work) { - struct rtc_device *rtc = data; + struct rtc_device *rtc = + container_of(work, struct rtc_device, uie_task); struct rtc_time tm; int num = 0; int err; @@ -398,7 +399,7 @@ static int rtc_dev_add_device(struct class_device *class_dev, spin_lock_init(&rtc->irq_lock); init_waitqueue_head(&rtc->irq_queue); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc); + INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); #endif diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a6aa910..bb3cb33 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -849,7 +849,7 @@ static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; - INIT_WORK(&hostdata->coroutine, NCR5380_main, hostdata); + INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main); #ifdef NCR5380_STATS for (i = 0; i < 8; ++i) { @@ -1016,7 +1016,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* Run the coroutine if it isn't already running. */ /* Kick off command processing */ - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); return 0; } @@ -1033,9 +1033,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) * host lock and called routines may take the isa dma lock. */ -static void NCR5380_main(void *p) +static void NCR5380_main(struct work_struct *work) { - struct NCR5380_hostdata *hostdata = p; + struct NCR5380_hostdata *hostdata = + container_of(work, struct NCR5380_hostdata, coroutine.work); struct Scsi_Host *instance = hostdata->host; Scsi_Cmnd *tmp, *prev; int done; @@ -1221,7 +1222,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) } /* if BASR_IRQ */ spin_unlock_irqrestore(instance->host_lock, flags); if(!done) - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); } while (!done); return IRQ_HANDLED; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 1bc73de..713a108 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -271,7 +271,7 @@ struct NCR5380_hostdata { unsigned long time_expires; /* in jiffies, set prior to sleeping */ int select_time; /* timer in select for target response */ volatile Scsi_Cmnd *selecting; - struct work_struct coroutine; /* our co-routine */ + struct delayed_work coroutine; /* our co-routine */ #ifdef NCR5380_STATS unsigned timebase; /* Base for time calcs */ long time_read[8]; /* time to do reads */ @@ -298,7 +298,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id); #endif -static void NCR5380_main(void *ptr); +static void NCR5380_main(struct work_struct *work); static void NCR5380_print_options(struct Scsi_Host *instance); #ifdef NDEBUG static void NCR5380_print_phase(struct Scsi_Host *instance); diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 306f46b..0cec742 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1443,7 +1443,7 @@ static struct work_struct aha152x_tq; * Run service completions on the card with interrupts enabled. * */ -static void run(void) +static void run(struct work_struct *work) { struct aha152x_hostdata *hd; @@ -1499,7 +1499,7 @@ static irqreturn_t intr(int irqno, void *dev_id) HOSTDATA(shpnt)->service=1; /* Poke the BH handler */ - INIT_WORK(&aha152x_tq, (void *) run, NULL); + INIT_WORK(&aha152x_tq, run); schedule_work(&aha152x_tq); } DO_UNLOCK(flags); diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index e31f612..0464c18 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -36,7 +36,7 @@ typedef struct { int base_hi; /* Hi Base address for ECP-ISA chipset */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct imm_tq; /* Polling interrupt stuff */ + struct delayed_work imm_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned failed:1; /* Failure flag */ unsigned dp:1; /* Data phase present */ @@ -733,9 +733,9 @@ static int imm_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void imm_interrupt(void *data) +static void imm_interrupt(struct work_struct *work) { - imm_struct *dev = (imm_struct *) data; + imm_struct *dev = container_of(work, imm_struct, imm_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; struct Scsi_Host *host = cmd->device->host; unsigned long flags; @@ -745,7 +745,6 @@ static void imm_interrupt(void *data) return; } if (imm_engine(dev, cmd)) { - INIT_WORK(&dev->imm_tq, imm_interrupt, (void *) dev); schedule_delayed_work(&dev->imm_tq, 1); return; } @@ -953,8 +952,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); - schedule_work(&dev->imm_tq); + schedule_delayed_work(&dev->imm_tq, 0); imm_pb_claim(dev); @@ -1225,7 +1223,7 @@ static int __imm_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); + INIT_DELAYED_WORK(&dev->imm_tq, imm_interrupt); err = -ENOMEM; host = scsi_host_alloc(&imm_template, sizeof(imm_struct *)); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2dde821..d51c3e7 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2093,7 +2093,7 @@ static void ipr_release_dump(struct kref *kref) /** * ipr_worker_thread - Worker thread - * @data: ioa config struct + * @work: ioa config struct * * Called at task level from a work thread. This function takes care * of adding and removing device from the mid-layer as configuration @@ -2102,13 +2102,14 @@ static void ipr_release_dump(struct kref *kref) * Return value: * nothing **/ -static void ipr_worker_thread(void *data) +static void ipr_worker_thread(struct work_struct *work) { unsigned long lock_flags; struct ipr_resource_entry *res; struct scsi_device *sdev; struct ipr_dump *dump; - struct ipr_ioa_cfg *ioa_cfg = data; + struct ipr_ioa_cfg *ioa_cfg = + container_of(work, struct ipr_ioa_cfg, work_q); u8 bus, target, lun; int did_work; @@ -6926,7 +6927,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); INIT_LIST_HEAD(&ioa_cfg->free_res_q); INIT_LIST_HEAD(&ioa_cfg->used_res_q); - INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread, ioa_cfg); + INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); init_waitqueue_head(&ioa_cfg->reset_wait_q); ioa_cfg->sdt_state = INACTIVE; if (ipr_enable_cache) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 5d88621..e11b23c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -719,9 +719,10 @@ again: return rc; } -static void iscsi_xmitworker(void *data) +static void iscsi_xmitworker(struct work_struct *work) { - struct iscsi_conn *conn = data; + struct iscsi_conn *conn = + container_of(work, struct iscsi_conn, xmitwork); int rc; /* * serialize Xmit worker on a per-connection basis. @@ -1512,7 +1513,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) goto mgmtqueue_alloc_fail; - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + INIT_WORK(&conn->xmitwork, iscsi_xmitworker); /* allocate login_mtask used for the login/text sequences */ spin_lock_bh(&session->lock); diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index d977bd4..fb7df7b 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -647,10 +647,12 @@ void sas_unregister_domain_devices(struct asd_sas_port *port) * Discover process only interrogates devices in order to discover the * domain. */ -static void sas_discover_domain(void *data) +static void sas_discover_domain(struct work_struct *work) { int error = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -692,10 +694,12 @@ static void sas_discover_domain(void *data) current->pid, error); } -static void sas_revalidate_domain(void *data) +static void sas_revalidate_domain(struct work_struct *work) { int res = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -722,7 +726,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) BUG_ON(ev >= DISC_NUM_EVENTS); sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, - &disc->disc_work[ev], port->ha->core.shost); + &disc->disc_work[ev].work, port->ha->core.shost); return 0; } @@ -737,13 +741,15 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) { int i; - static void (*sas_event_fns[DISC_NUM_EVENTS])(void *) = { + static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, }; spin_lock_init(&disc->disc_event_lock); disc->pending = 0; - for (i = 0; i < DISC_NUM_EVENTS; i++) - INIT_WORK(&disc->disc_work[i], sas_event_fns[i], port); + for (i = 0; i < DISC_NUM_EVENTS; i++) { + INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]); + disc->disc_work[i].port = port; + } } diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 19110ed..d83392e 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) BUG_ON(event >= HA_NUM_EVENTS); sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, - &sas_ha->ha_events[event], sas_ha->core.shost); + &sas_ha->ha_events[event].work, sas_ha->core.shost); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) @@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, - &phy->port_events[event], ha->core.shost); + &phy->port_events[event].work, ha->core.shost); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) @@ -51,12 +51,12 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, - &phy->phy_events[event], ha->core.shost); + &phy->phy_events[event].work, ha->core.shost); } int sas_init_events(struct sas_ha_struct *sas_ha) { - static void (*sas_ha_event_fns[HA_NUM_EVENTS])(void *) = { + static const work_func_t sas_ha_event_fns[HA_NUM_EVENTS] = { [HAE_RESET] = sas_hae_reset, }; @@ -64,8 +64,10 @@ int sas_init_events(struct sas_ha_struct *sas_ha) spin_lock_init(&sas_ha->event_lock); - for (i = 0; i < HA_NUM_EVENTS; i++) - INIT_WORK(&sas_ha->ha_events[i], sas_ha_event_fns[i], sas_ha); + for (i = 0; i < HA_NUM_EVENTS; i++) { + INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]); + sas_ha->ha_events[i].ha = sas_ha; + } sas_ha->notify_ha_event = notify_ha_event; sas_ha->notify_port_event = notify_port_event; diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index c836a23..7b4e916 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -65,9 +65,11 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr) /* ---------- HA events ---------- */ -void sas_hae_reset(void *data) +void sas_hae_reset(struct work_struct *work) { - struct sas_ha_struct *ha = data; + struct sas_ha_event *ev = + container_of(work, struct sas_ha_event, work); + struct sas_ha_struct *ha = ev->ha; sas_begin_event(HAE_RESET, &ha->event_lock, &ha->pending); diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index bffcee4..137d7e4 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -60,11 +60,11 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha); void sas_deform_port(struct asd_sas_phy *phy); -void sas_porte_bytes_dmaed(void *); -void sas_porte_broadcast_rcvd(void *); -void sas_porte_link_reset_err(void *); -void sas_porte_timer_event(void *); -void sas_porte_hard_reset(void *); +void sas_porte_bytes_dmaed(struct work_struct *work); +void sas_porte_broadcast_rcvd(struct work_struct *work); +void sas_porte_link_reset_err(struct work_struct *work); +void sas_porte_timer_event(struct work_struct *work); +void sas_porte_hard_reset(struct work_struct *work); int sas_notify_lldd_dev_found(struct domain_device *); void sas_notify_lldd_dev_gone(struct domain_device *); @@ -75,7 +75,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); -void sas_hae_reset(void *); +void sas_hae_reset(struct work_struct *work); static inline void sas_queue_event(int event, spinlock_t *lock, unsigned long *pending, diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c index 9340cdb..b459c4b 100644 --- a/drivers/scsi/libsas/sas_phy.c +++ b/drivers/scsi/libsas/sas_phy.c @@ -30,9 +30,11 @@ /* ---------- Phy events ---------- */ -static void sas_phye_loss_of_signal(void *data) +static void sas_phye_loss_of_signal(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, &phy->phy_events_pending); @@ -40,18 +42,22 @@ static void sas_phye_loss_of_signal(void *data) sas_deform_port(phy); } -static void sas_phye_oob_done(void *data) +static void sas_phye_oob_done(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_OOB_DONE, &phy->ha->event_lock, &phy->phy_events_pending); phy->error = 0; } -static void sas_phye_oob_error(void *data) +static void sas_phye_oob_error(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct asd_sas_port *port = phy->port; struct sas_internal *i = @@ -80,9 +86,11 @@ static void sas_phye_oob_error(void *data) } } -static void sas_phye_spinup_hold(void *data) +static void sas_phye_spinup_hold(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); @@ -100,14 +108,14 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) { int i; - static void (*sas_phy_event_fns[PHY_NUM_EVENTS])(void *) = { + static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = { [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal, [PHYE_OOB_DONE] = sas_phye_oob_done, [PHYE_OOB_ERROR] = sas_phye_oob_error, [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold, }; - static void (*sas_port_event_fns[PORT_NUM_EVENTS])(void *) = { + static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = { [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed, [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd, [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err, @@ -122,13 +130,18 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) phy->error = 0; INIT_LIST_HEAD(&phy->port_phy_el); - for (k = 0; k < PORT_NUM_EVENTS; k++) - INIT_WORK(&phy->port_events[k], sas_port_event_fns[k], - phy); + for (k = 0; k < PORT_NUM_EVENTS; k++) { + INIT_WORK(&phy->port_events[k].work, + sas_port_event_fns[k]); + phy->port_events[k].phy = phy; + } + + for (k = 0; k < PHY_NUM_EVENTS; k++) { + INIT_WORK(&phy->phy_events[k].work, + sas_phy_event_fns[k]); + phy->phy_events[k].phy = phy; + } - for (k = 0; k < PHY_NUM_EVENTS; k++) - INIT_WORK(&phy->phy_events[k], sas_phy_event_fns[k], - phy); phy->port = NULL; phy->ha = sas_ha; spin_lock_init(&phy->frame_rcvd_lock); diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 253cdcf..971c37c 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -181,9 +181,11 @@ void sas_deform_port(struct asd_sas_phy *phy) /* ---------- SAS port events ---------- */ -void sas_porte_bytes_dmaed(void *data) +void sas_porte_bytes_dmaed(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock, &phy->port_events_pending); @@ -191,11 +193,13 @@ void sas_porte_bytes_dmaed(void *data) sas_form_port(phy); } -void sas_porte_broadcast_rcvd(void *data) +void sas_porte_broadcast_rcvd(struct work_struct *work) { + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; unsigned long flags; u32 prim; - struct asd_sas_phy *phy = data; sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock, &phy->port_events_pending); @@ -208,9 +212,11 @@ void sas_porte_broadcast_rcvd(void *data) sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN); } -void sas_porte_link_reset_err(void *data) +void sas_porte_link_reset_err(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, &phy->port_events_pending); @@ -218,9 +224,11 @@ void sas_porte_link_reset_err(void *data) sas_deform_port(phy); } -void sas_porte_timer_event(void *data) +void sas_porte_timer_event(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, &phy->port_events_pending); @@ -228,9 +236,11 @@ void sas_porte_timer_event(void *data) sas_deform_port(phy); } -void sas_porte_hard_reset(void *data) +void sas_porte_hard_reset(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, &phy->port_events_pending); diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 89a2a9f..584ba4d 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -31,7 +31,7 @@ typedef struct { int base; /* Actual port address */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct ppa_tq; /* Polling interrupt stuff */ + struct delayed_work ppa_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned long recon_tmo; /* How many usecs to wait for reconnection (6th bit) */ unsigned int failed:1; /* Failure flag */ @@ -627,9 +627,9 @@ static int ppa_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void ppa_interrupt(void *data) +static void ppa_interrupt(struct work_struct *work) { - ppa_struct *dev = (ppa_struct *) data; + ppa_struct *dev = container_of(work, ppa_struct, ppa_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; if (!cmd) { @@ -637,7 +637,6 @@ static void ppa_interrupt(void *data) return; } if (ppa_engine(dev, cmd)) { - dev->ppa_tq.data = (void *) dev; schedule_delayed_work(&dev->ppa_tq, 1); return; } @@ -822,8 +821,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - dev->ppa_tq.data = dev; - schedule_work(&dev->ppa_tq); + schedule_delayed_work(&dev->ppa_tq, 0); ppa_pb_claim(dev); @@ -1086,7 +1084,7 @@ static int __ppa_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev); + INIT_DELAYED_WORK(&dev->ppa_tq, ppa_interrupt); err = -ENOMEM; host = scsi_host_alloc(&ppa_template, sizeof(ppa_struct *)); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5b8db61..bbbc9d0 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1011,9 +1011,10 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, * the mid-level tries to sleep when it reaches the driver threshold * "host->can_queue". This can cause a panic if we were in our interrupt code. **/ -static void qla4xxx_do_dpc(void *data) +static void qla4xxx_do_dpc(struct work_struct *work) { - struct scsi_qla_host *ha = (struct scsi_qla_host *) data; + struct scsi_qla_host *ha = + container_of(work, struct scsi_qla_host, dpc_work); struct ddb_entry *ddb_entry, *dtemp; DEBUG2(printk("scsi%ld: %s: DPC handler waking up.\n", @@ -1315,7 +1316,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ret = -ENODEV; goto probe_failed; } - INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc, ha); + INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); ret = request_irq(pdev->irq, qla4xxx_intr_handler, SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 38c215a..3571ce8 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -241,9 +241,9 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) #define FC_MGMTSRVR_PORTID 0x00000a -static void fc_timeout_deleted_rport(void *data); -static void fc_timeout_fail_rport_io(void *data); -static void fc_scsi_scan_rport(void *data); +static void fc_timeout_deleted_rport(struct work_struct *work); +static void fc_timeout_fail_rport_io(struct work_struct *work); +static void fc_scsi_scan_rport(struct work_struct *work); /* * Attribute counts pre object type... @@ -1613,7 +1613,7 @@ fc_flush_work(struct Scsi_Host *shost) * 1 on success / 0 already queued / < 0 for error **/ static int -fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, +fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work, unsigned long delay) { if (unlikely(!fc_host_devloss_work_q(shost))) { @@ -1625,9 +1625,6 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, return -EINVAL; } - if (delay == 0) - return queue_work(fc_host_devloss_work_q(shost), work); - return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay); } @@ -1712,12 +1709,13 @@ EXPORT_SYMBOL(fc_remove_host); * fc_starget_delete - called to delete the scsi decendents of an rport * (target and all sdevs) * - * @data: remote port to be operated on. + * @work: remote port to be operated on. **/ static void -fc_starget_delete(void *data) +fc_starget_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, stgt_delete_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1751,12 +1749,13 @@ fc_starget_delete(void *data) /** * fc_rport_final_delete - finish rport termination and delete it. * - * @data: remote port to be deleted. + * @work: remote port to be deleted. **/ static void -fc_rport_final_delete(void *data) +fc_rport_final_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, rport_delete_work); struct device *dev = &rport->dev; struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1770,7 +1769,7 @@ fc_rport_final_delete(void *data) /* Delete SCSI target and sdevs */ if (rport->scsi_target_id != -1) - fc_starget_delete(data); + fc_starget_delete(&rport->stgt_delete_work); else if (i->f->dev_loss_tmo_callbk) i->f->dev_loss_tmo_callbk(rport); else if (i->f->terminate_rport_io) @@ -1829,11 +1828,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel, rport->channel = channel; rport->fast_io_fail_tmo = -1; - INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); - INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport); - INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); - INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport); - INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport); + INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport); + INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io); + INIT_WORK(&rport->scan_work, fc_scsi_scan_rport); + INIT_WORK(&rport->stgt_delete_work, fc_starget_delete); + INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete); spin_lock_irqsave(shost->host_lock, flags); @@ -1963,7 +1962,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } if (match) { - struct work_struct *work = + struct delayed_work *work = &rport->dev_loss_work; memcpy(&rport->node_name, &ids->node_name, @@ -2267,12 +2266,13 @@ EXPORT_SYMBOL(fc_remote_port_rolechg); * was a SCSI target (thus was blocked), and failed * to return in the alloted time. * - * @data: rport target that failed to reappear in the alloted time. + * @work: rport target that failed to reappear in the alloted time. **/ static void -fc_timeout_deleted_rport(void *data) +fc_timeout_deleted_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, dev_loss_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; @@ -2366,15 +2366,16 @@ fc_timeout_deleted_rport(void *data) * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a * disconnected SCSI target. * - * @data: rport to terminate io on. + * @work: rport to terminate io on. * * Notes: Only requests the failure of the io, not that all are flushed * prior to returning. **/ static void -fc_timeout_fail_rport_io(void *data) +fc_timeout_fail_rport_io(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, fail_io_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -2387,12 +2388,13 @@ fc_timeout_fail_rport_io(void *data) /** * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. * - * @data: remote port to be scanned. + * @work: remote port to be scanned. **/ static void -fc_scsi_scan_rport(void *data) +fc_scsi_scan_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, scan_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9b25124..9c22f13 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -234,9 +234,11 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, return 0; } -static void session_recovery_timedout(void *data) +static void session_recovery_timedout(struct work_struct *work) { - struct iscsi_cls_session *session = data; + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, + recovery_work.work); dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " "out after %d secs\n", session->recovery_tmo); @@ -276,7 +278,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, session->transport = transport; session->recovery_tmo = 120; - INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->host_list); INIT_LIST_HEAD(&session->sess_list); diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 9f070f0..3fded48 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -964,9 +964,10 @@ struct work_queue_wrapper { }; static void -spi_dv_device_work_wrapper(void *data) +spi_dv_device_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct scsi_device *sdev = wqw->sdev; kfree(wqw); @@ -1006,7 +1007,7 @@ spi_schedule_dv_device(struct scsi_device *sdev) return; } - INIT_WORK(&wqw->work, spi_dv_device_work_wrapper, wqw); + INIT_WORK(&wqw->work, spi_dv_device_work_wrapper); wqw->sdev = sdev; schedule_work(&wqw->work); diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index a23862e..08c1c57 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -265,9 +265,10 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ -static void bitbang_work(void *_bitbang) +static void bitbang_work(struct work_struct *work) { - struct spi_bitbang *bitbang = _bitbang; + struct spi_bitbang *bitbang = + container_of(work, struct spi_bitbang, work); unsigned long flags; spin_lock_irqsave(&bitbang->lock, flags); @@ -456,7 +457,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) if (!bitbang->master || !bitbang->chipselect) return -EINVAL; - INIT_WORK(&bitbang->work, bitbang_work, bitbang); + INIT_WORK(&bitbang->work, bitbang_work); spin_lock_init(&bitbang->lock); INIT_LIST_HEAD(&bitbang->queue); diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index e656563..3dfa3e4 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -158,7 +158,7 @@ struct cxacru_data { const struct cxacru_modem_type *modem_type; int line_status; - struct work_struct poll_work; + struct delayed_work poll_work; /* contol handles */ struct mutex cm_serialize; @@ -347,7 +347,7 @@ static int cxacru_card_status(struct cxacru_data *instance) return 0; } -static void cxacru_poll_status(struct cxacru_data *instance); +static void cxacru_poll_status(struct work_struct *work); static int cxacru_atm_start(struct usbatm_data *usbatm_instance, struct atm_dev *atm_dev) @@ -376,12 +376,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, } /* Start status polling */ - cxacru_poll_status(instance); + cxacru_poll_status(&instance->poll_work.work); return 0; } -static void cxacru_poll_status(struct cxacru_data *instance) +static void cxacru_poll_status(struct work_struct *work) { + struct cxacru_data *instance = + container_of(work, struct cxacru_data, poll_work.work); u32 buf[CXINF_MAX] = {}; struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; @@ -720,7 +722,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, mutex_init(&instance->cm_serialize); - INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); + INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status); usbatm_instance->driver_data = instance; diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c870c80..7ed34bb 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -142,7 +142,7 @@ struct speedtch_instance_data { struct speedtch_params params; /* set in probe, constant afterwards */ - struct work_struct status_checker; + struct delayed_work status_checker; unsigned char last_status; @@ -498,8 +498,11 @@ static int speedtch_start_synchro(struct speedtch_instance_data *instance) return ret; } -static void speedtch_check_status(struct speedtch_instance_data *instance) +static void speedtch_check_status(struct work_struct *work) { + struct speedtch_instance_data *instance = + container_of(work, struct speedtch_instance_data, + status_checker.work); struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; unsigned char *buf = instance->scratch_buffer; @@ -576,7 +579,7 @@ static void speedtch_status_poll(unsigned long data) { struct speedtch_instance_data *instance = (void *)data; - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); /* The following check is racy, but the race is harmless */ if (instance->poll_delay < MAX_POLL_DELAY) @@ -596,7 +599,7 @@ static void speedtch_resubmit_int(unsigned long data) if (int_urb) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); if (!ret) - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); else { atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); @@ -640,7 +643,7 @@ static void speedtch_handle_int(struct urb *int_urb) if ((int_urb = instance->int_urb)) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); if (ret < 0) { atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); goto fail; @@ -855,7 +858,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); - INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); + INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status); instance->status_checker.timer.function = speedtch_status_poll; instance->status_checker.timer.data = (unsigned long)instance; diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index f6b9f7e..e39bb09 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -658,9 +658,9 @@ static int request_dsp(struct uea_softc *sc) /* * The uea_load_page() function must be called within a process context */ -static void uea_load_page(void *xsc) +static void uea_load_page(struct work_struct *work) { - struct uea_softc *sc = xsc; + struct uea_softc *sc = container_of(work, struct uea_softc, task); u16 pageno = sc->pageno; u16 ovl = sc->ovl; struct block_info bi; @@ -1352,7 +1352,7 @@ static int uea_boot(struct uea_softc *sc) uea_enters(INS_TO_USBDEV(sc)); - INIT_WORK(&sc->task, uea_load_page, sc); + INIT_WORK(&sc->task, uea_load_page); init_waitqueue_head(&sc->sync_q); init_waitqueue_head(&sc->cmv_ack_wait); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9a9012f..6408e10 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -421,9 +421,9 @@ static void acm_write_bulk(struct urb *urb) schedule_work(&acm->work); } -static void acm_softint(void *private) +static void acm_softint(struct work_struct *work) { - struct acm *acm = private; + struct acm *acm = container_of(work, struct acm, work); dbg("Entering acm_softint."); if (!ACM_READY(acm)) @@ -927,7 +927,7 @@ skip_normal_probe: acm->rx_buflimit = num_rx_buf; acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; - INIT_WORK(&acm->work, acm_softint, acm); + INIT_WORK(&acm->work, acm_softint); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ba165af..ad0ffbe 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -167,9 +167,10 @@ static void set_port_led( #define LED_CYCLE_PERIOD ((2*HZ)/3) -static void led_work (void *__hub) +static void led_work (struct work_struct *work) { - struct usb_hub *hub = __hub; + struct usb_hub *hub = + container_of(work, struct usb_hub, leds.work); struct usb_device *hdev = hub->hdev; unsigned i; unsigned changed = 0; @@ -351,9 +352,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) * talking to TTs must queue control transfers (not just bulk and iso), so * both can talk to the same hub concurrently. */ -static void hub_tt_kevent (void *arg) +static void hub_tt_kevent (struct work_struct *work) { - struct usb_hub *hub = arg; + struct usb_hub *hub = + container_of(work, struct usb_hub, tt.kevent); unsigned long flags; spin_lock_irqsave (&hub->tt.lock, flags); @@ -641,7 +643,7 @@ static int hub_configure(struct usb_hub *hub, spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); - INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); + INIT_WORK (&hub->tt.kevent, hub_tt_kevent); switch (hdev->descriptor.bDeviceProtocol) { case 0: break; @@ -880,7 +882,7 @@ descriptor_error: INIT_LIST_HEAD(&hub->event_list); hub->intfdev = &intf->dev; hub->hdev = hdev; - INIT_WORK(&hub->leds, led_work, hub); + INIT_DELAYED_WORK(&hub->leds, led_work); usb_set_intfdata (intf, hub); @@ -2281,7 +2283,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } } kfree(qual); @@ -2455,7 +2457,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_AMBER_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } status = -ENOTCONN; /* Don't retry */ goto loop_disable; diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 0f8e82a..035d3ef3 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -230,7 +230,7 @@ struct usb_hub { unsigned has_indicators:1; enum hub_led_mode indicator[USB_MAXCHILDREN]; - struct work_struct leds; + struct delayed_work leds; }; #endif /* __LINUX_HUB_H */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7729c07..89572bc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1501,9 +1501,10 @@ struct set_config_request { }; /* Worker routine for usb_driver_set_configuration() */ -static void driver_set_config_work(void *_req) +static void driver_set_config_work(struct work_struct *work) { - struct set_config_request *req = _req; + struct set_config_request *req = + container_of(work, struct set_config_request, work); usb_lock_device(req->udev); usb_set_configuration(req->udev, req->config); @@ -1541,7 +1542,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) return -ENOMEM; req->udev = udev; req->config = config; - INIT_WORK(&req->work, driver_set_config_work, req); + INIT_WORK(&req->work, driver_set_config_work); usb_get_dev(udev); if (!schedule_work(&req->work)) { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 467cb02..ab2f68f 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -210,9 +210,10 @@ static void ksuspend_usb_cleanup(void) #ifdef CONFIG_USB_SUSPEND /* usb_autosuspend_work - callback routine to autosuspend a USB device */ -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) { - struct usb_device *udev = _udev; + struct usb_device *udev = + container_of(work, struct usb_device, autosuspend.work); usb_pm_lock(udev); udev->auto_pm = 1; @@ -222,7 +223,7 @@ static void usb_autosuspend_work(void *_udev) #else -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) {} #endif @@ -304,7 +305,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) #ifdef CONFIG_PM mutex_init(&dev->pm_mutex); - INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); + INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); #endif return dev; } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 1c17d26..107119c 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1833,9 +1833,9 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) spin_unlock_irqrestore(&dev->req_lock, flags); } -static void eth_work (void *_dev) +static void eth_work (struct work_struct *work) { - struct eth_dev *dev = _dev; + struct eth_dev *dev = container_of(work, struct eth_dev, work); if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { if (netif_running (dev->net)) @@ -2398,7 +2398,7 @@ autoconf_fail: dev = netdev_priv(net); spin_lock_init (&dev->lock); spin_lock_init (&dev->req_lock); - INIT_WORK (&dev->work, eth_work, dev); + INIT_WORK (&dev->work, eth_work); INIT_LIST_HEAD (&dev->tx_reqs); INIT_LIST_HEAD (&dev->rx_reqs); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 32c635e..4f95a24 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -163,7 +163,7 @@ struct u132_endp { u16 queue_next; struct urb *urb_list[ENDP_QUEUE_SIZE]; struct list_head urb_more; - struct work_struct scheduler; + struct delayed_work scheduler; }; struct u132_ring { unsigned in_use:1; @@ -171,7 +171,7 @@ struct u132_ring { u8 number; struct u132 *u132; struct u132_endp *curr_endp; - struct work_struct scheduler; + struct delayed_work scheduler; }; #define OHCI_QUIRK_AMD756 0x01 #define OHCI_QUIRK_SUPERIO 0x02 @@ -198,7 +198,7 @@ struct u132 { u32 hc_roothub_portstatus[MAX_ROOT_PORTS]; int flags; unsigned long next_statechange; - struct work_struct monitor; + struct delayed_work monitor; int num_endpoints; struct u132_addr addr[MAX_U132_ADDRS]; struct u132_udev udev[MAX_U132_UDEVS]; @@ -314,7 +314,7 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, if (delta > 0) { if (queue_delayed_work(workqueue, &ring->scheduler, delta)) return; - } else if (queue_work(workqueue, &ring->scheduler)) + } else if (queue_delayed_work(workqueue, &ring->scheduler, 0)) return; kref_put(&u132->kref, u132_hcd_delete); return; @@ -393,12 +393,8 @@ static inline void u132_endp_init_kref(struct u132 *u132, static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &endp->scheduler, delta)) - kref_get(&endp->kref); - } else if (queue_work(workqueue, &endp->scheduler)) - kref_get(&endp->kref); - return; + if (queue_delayed_work(workqueue, &endp->scheduler, delta)) + kref_get(&endp->kref); } static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp) @@ -414,24 +410,14 @@ static inline void u132_monitor_put_kref(struct u132 *u132) static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) { - kref_get(&u132->kref); - } - } else if (queue_work(workqueue, &u132->monitor)) - kref_get(&u132->kref); - return; + if (queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_get(&u132->kref); } static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) - return; - } else if (queue_work(workqueue, &u132->monitor)) - return; - kref_put(&u132->kref, u132_hcd_delete); - return; + if (!queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_put(&u132->kref, u132_hcd_delete); } static void u132_monitor_cancel_work(struct u132 *u132) @@ -493,9 +479,9 @@ static int read_roothub_info(struct u132 *u132) return 0; } -static void u132_hcd_monitor_work(void *data) +static void u132_hcd_monitor_work(struct work_struct *work) { - struct u132 *u132 = data; + struct u132 *u132 = container_of(work, struct u132, monitor.work); if (u132->going > 1) { dev_err(&u132->platform_dev->dev, "device has been removed %d\n" , u132->going); @@ -1319,15 +1305,14 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, } } -static void u132_hcd_ring_work_scheduler(void *data); -static void u132_hcd_endp_work_scheduler(void *data); /* * this work function is only executed from the work queue * */ -static void u132_hcd_ring_work_scheduler(void *data) +static void u132_hcd_ring_work_scheduler(struct work_struct *work) { - struct u132_ring *ring = data; + struct u132_ring *ring = + container_of(work, struct u132_ring, scheduler.work); struct u132 *u132 = ring->u132; down(&u132->scheduler_lock); if (ring->in_use) { @@ -1386,10 +1371,11 @@ static void u132_hcd_ring_work_scheduler(void *data) } } -static void u132_hcd_endp_work_scheduler(void *data) +static void u132_hcd_endp_work_scheduler(struct work_struct *work) { struct u132_ring *ring; - struct u132_endp *endp = data; + struct u132_endp *endp = + container_of(work, struct u132_endp, scheduler.work); struct u132 *u132 = endp->u132; down(&u132->scheduler_lock); ring = endp->ring; @@ -1947,7 +1933,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -2036,7 +2022,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); endp->dequeueing = 0; @@ -2121,7 +2107,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -3100,10 +3086,10 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) ring->number = rings + 1; ring->length = 0; ring->curr_endp = NULL; - INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler, - (void *)ring); + INIT_DELAYED_WORK(&ring->scheduler, + u132_hcd_ring_work_scheduler); } down(&u132->sw_lock); - INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132); + INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work); while (ports-- > 0) { struct u132_port *port = &u132->port[ports]; port->u132 = u132; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6d08a3b..ebc9e82 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -969,9 +969,10 @@ static void hid_retry_timeout(unsigned long _hid) } /* Workqueue routine to reset the device */ -static void hid_reset(void *_hid) +static void hid_reset(struct work_struct *work) { - struct hid_device *hid = (struct hid_device *) _hid; + struct hid_device *hid = + container_of(work, struct hid_device, reset_work); int rc_lock, rc; dev_dbg(&hid->intf->dev, "resetting device\n"); @@ -2015,7 +2016,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) init_waitqueue_head(&hid->wait); - INIT_WORK(&hid->reset_work, hid_reset, hid); + INIT_WORK(&hid->reset_work, hid_reset); setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); spin_lock_init(&hid->inlock); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 9b591b8..e4e2cf2 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -156,9 +156,9 @@ struct usb_ftdi { struct usb_device *udev; struct usb_interface *interface; struct usb_class_driver *class; - struct work_struct status_work; - struct work_struct command_work; - struct work_struct respond_work; + struct delayed_work status_work; + struct delayed_work command_work; + struct delayed_work respond_work; struct u132_platform_data platform_data; struct resource resources[0]; struct platform_device platform_dev; @@ -210,23 +210,14 @@ static void ftdi_elan_init_kref(struct usb_ftdi *ftdi) static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - return; - } else if (queue_work(status_queue, &ftdi->status_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - kref_get(&ftdi->kref); - } else if (queue_work(status_queue, &ftdi->status_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) @@ -237,25 +228,14 @@ static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - return; - } else if (queue_work(command_queue, &ftdi->command_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(command_queue, &ftdi->command_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) @@ -267,25 +247,14 @@ static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) static void ftdi_response_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - return; - } else if (queue_work(respond_queue, &ftdi->respond_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(respond_queue, &ftdi->respond_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_response_cancel_work(struct usb_ftdi *ftdi) @@ -475,9 +444,11 @@ static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_command_work(void *data) +static void ftdi_elan_command_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, command_work.work); + if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -500,9 +471,10 @@ static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_respond_work(void *data) +static void ftdi_elan_respond_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, respond_work.work); if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -534,9 +506,10 @@ static void ftdi_elan_respond_work(void *data) * after the FTDI has been synchronized * */ -static void ftdi_elan_status_work(void *data) +static void ftdi_elan_status_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, status_work.work); int work_delay_in_msec = 0; if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); @@ -2691,12 +2664,9 @@ static int ftdi_elan_probe(struct usb_interface *interface, ftdi->class = NULL; dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a" "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber); - INIT_WORK(&ftdi->status_work, ftdi_elan_status_work, - (void *)ftdi); - INIT_WORK(&ftdi->command_work, ftdi_elan_command_work, - (void *)ftdi); - INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work, - (void *)ftdi); + INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work); + INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work); + INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work); ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); return 0; } else { diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index abb4dcd..33e716c 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -81,8 +81,8 @@ struct interfacekit { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; - struct work_struct do_resubmit; + struct delayed_work do_notify; + struct delayed_work do_resubmit; unsigned long input_events; unsigned long sensor_events; }; @@ -374,7 +374,7 @@ static void interfacekit_irq(struct urb *urb) } if (kit->input_events || kit->sensor_events) - schedule_work(&kit->do_notify); + schedule_delayed_work(&kit->do_notify, 0); resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); @@ -384,9 +384,10 @@ resubmit: kit->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct interfacekit *kit = data; + struct interfacekit *kit = + container_of(work, struct interfacekit, do_notify.work); int i; char sysfs_file[8]; @@ -405,9 +406,11 @@ static void do_notify(void *data) } } -static void do_resubmit(void *data) +static void do_resubmit(struct work_struct *work) { - set_outputs(data); + struct interfacekit *kit = + container_of(work, struct interfacekit, do_resubmit.work); + set_outputs(kit); } #define show_set_output(value) \ @@ -575,8 +578,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic kit->udev = usb_get_dev(dev); kit->intf = intf; - INIT_WORK(&kit->do_notify, do_notify, kit); - INIT_WORK(&kit->do_resubmit, do_resubmit, kit); + INIT_DELAYED_WORK(&kit->do_notify, do_notify); + INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, interfacekit_irq, kit, endpoint->bInterval); diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 5c780ca..0385ffc 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -41,7 +41,7 @@ struct motorcontrol { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; + struct delayed_work do_notify; unsigned long input_events; unsigned long speed_events; unsigned long exceed_events; @@ -148,7 +148,7 @@ static void motorcontrol_irq(struct urb *urb) set_bit(1, &mc->exceed_events); if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_work(&mc->do_notify); + schedule_delayed_work(&mc->do_notify, 0); resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); @@ -159,9 +159,10 @@ resubmit: mc->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct motorcontrol *mc = data; + struct motorcontrol *mc = + container_of(work, struct motorcontrol, do_notify.work); int i; char sysfs_file[8]; @@ -348,7 +349,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic mc->udev = usb_get_dev(dev); mc->intf = intf; mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_WORK(&mc->do_notify, do_notify, mc); + INIT_DELAYED_WORK(&mc->do_notify, do_notify); usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, motorcontrol_irq, mc, endpoint->bInterval); diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 7c906a4..fa78326 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -222,7 +222,7 @@ struct kaweth_device int suspend_lowmem_ctrl; int linkstate; int opened; - struct work_struct lowmem_work; + struct delayed_work lowmem_work; struct usb_device *dev; struct net_device *net; @@ -530,9 +530,10 @@ resubmit: kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); } -static void kaweth_resubmit_tl(void *d) +static void kaweth_resubmit_tl(struct work_struct *work) { - struct kaweth_device *kaweth = (struct kaweth_device *)d; + struct kaweth_device *kaweth = + container_of(work, struct kaweth_device, lowmem_work.work); if (IS_BLOCKED(kaweth->status)) return; @@ -1126,7 +1127,7 @@ err_fw: /* kaweth is zeroed as part of alloc_netdev */ - INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); + INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); SET_MODULE_OWNER(netdev); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 33abbd2..78cf6f0 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -1280,9 +1280,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) static struct workqueue_struct *pegasus_workqueue = NULL; #define CARRIER_CHECK_DELAY (2 * HZ) -static void check_carrier(void *data) +static void check_carrier(struct work_struct *work) { - pegasus_t *pegasus = data; + pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work); set_carrier(pegasus->net); if (!(pegasus->flags & PEGASUS_UNPLUG)) { queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, @@ -1318,7 +1318,7 @@ static int pegasus_probe(struct usb_interface *intf, tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); - INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus); + INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier); pegasus->intf = intf; pegasus->usb = dev; diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index 0064380..98f6898 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -95,7 +95,7 @@ typedef struct pegasus { int dev_index; int intr_interval; struct tasklet_struct rx_tl; - struct work_struct carrier_check; + struct delayed_work carrier_check; struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; struct sk_buff *rx_pool[RX_SKBS]; struct sk_buff *rx_skb; diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 760b532..79b5474 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -782,9 +782,10 @@ static struct ethtool_ops usbnet_ethtool_ops = { * especially now that control transfers can be queued. */ static void -kevent (void *data) +kevent (struct work_struct *work) { - struct usbnet *dev = data; + struct usbnet *dev = + container_of(work, struct usbnet, kevent); int status; /* usb_clear_halt() needs a thread context */ @@ -1146,7 +1147,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) skb_queue_head_init (&dev->done); dev->bh.func = usbnet_bh; dev->bh.data = (unsigned long) dev; - INIT_WORK (&dev->kevent, kevent, dev); + INIT_WORK (&dev->kevent, kevent); dev->delay.function = usbnet_bh; dev->delay.data = (unsigned long) dev; init_timer (&dev->delay); diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 8122755..2a4ac9b 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -92,6 +92,7 @@ struct aircable_private { struct circ_buf *rx_buf; /* read buffer */ int rx_flags; /* for throttilng */ struct work_struct rx_work; /* work cue for the receiving line */ + struct usb_serial_port *port; /* USB port with which associated */ }; /* Private methods */ @@ -251,10 +252,11 @@ static void aircable_send(struct usb_serial_port *port) schedule_work(&port->work); } -static void aircable_read(void *params) +static void aircable_read(struct work_struct *work) { - struct usb_serial_port *port = params; - struct aircable_private *priv = usb_get_serial_port_data(port); + struct aircable_private *priv = + container_of(work, struct aircable_private, rx_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty; unsigned char *data; int count; @@ -348,7 +350,8 @@ static int aircable_attach (struct usb_serial *serial) } priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); - INIT_WORK(&priv->rx_work, aircable_read, port); + priv->port = port; + INIT_WORK(&priv->rx_work, aircable_read); usb_set_serial_port_data(serial->port[0], priv); @@ -515,7 +518,7 @@ static void aircable_read_bulk_callback(struct urb *urb) package_length - shift); } } - aircable_read(port); + aircable_read(&priv->rx_work); } /* Schedule the next read _if_ we are still open */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index bdb5810..fd159b0 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -430,13 +430,14 @@ struct digi_port { int dp_in_close; /* close in progress */ wait_queue_head_t dp_close_wait; /* wait queue for close */ struct work_struct dp_wakeup_work; + struct usb_serial_port *dp_port; }; /* Local Function Declarations */ static void digi_wakeup_write( struct usb_serial_port *port ); -static void digi_wakeup_write_lock(void *); +static void digi_wakeup_write_lock(struct work_struct *work); static int digi_write_oob_command( struct usb_serial_port *port, unsigned char *buf, int count, int interruptible ); static int digi_write_inb_command( struct usb_serial_port *port, @@ -598,11 +599,12 @@ static inline long cond_wait_interruptible_timeout_irqrestore( * on writes. */ -static void digi_wakeup_write_lock(void *arg) +static void digi_wakeup_write_lock(struct work_struct *work) { - struct usb_serial_port *port = arg; + struct digi_port *priv = + container_of(work, struct digi_port, dp_wakeup_work); + struct usb_serial_port *port = priv->dp_port; unsigned long flags; - struct digi_port *priv = usb_get_serial_port_data(port); spin_lock_irqsave( &priv->dp_port_lock, flags ); @@ -1702,8 +1704,8 @@ dbg( "digi_startup: TOP" ); init_waitqueue_head( &priv->dp_flush_wait ); priv->dp_in_close = 0; init_waitqueue_head( &priv->dp_close_wait ); - INIT_WORK(&priv->dp_wakeup_work, - digi_wakeup_write_lock, serial->port[i]); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = serial->port[i]; /* initialize write wait queue for this port */ init_waitqueue_head( &serial->port[i]->write_wait ); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c186b4e..88ed5c1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -559,7 +559,8 @@ struct ftdi_private { 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; + struct delayed_work rx_work; + struct usb_serial_port *port; int rx_processed; unsigned long rx_bytes; @@ -593,7 +594,7 @@ static int ftdi_write_room (struct usb_serial_port *port); static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); -static void ftdi_process_read (void *param); +static void ftdi_process_read (struct work_struct *work); static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); @@ -1201,7 +1202,8 @@ static int ftdi_sio_attach (struct usb_serial *serial) port->read_urb->transfer_buffer_length = BUFSZ; } - INIT_WORK(&priv->rx_work, ftdi_process_read, port); + INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); + priv->port = port; /* Free port's existing write urb and transfer buffer. */ if (port->write_urb) { @@ -1641,17 +1643,18 @@ static void ftdi_read_bulk_callback (struct urb *urb) priv->rx_bytes += countread; spin_unlock_irqrestore(&priv->rx_lock, flags); - ftdi_process_read(port); + ftdi_process_read(&priv->rx_work.work); } /* ftdi_read_bulk_callback */ -static void ftdi_process_read (void *param) +static void ftdi_process_read (struct work_struct *work) { /* ftdi_process_read */ - struct usb_serial_port *port = (struct usb_serial_port*)param; + struct ftdi_private *priv = + container_of(work, struct ftdi_private, rx_work.work); + struct usb_serial_port *port = priv->port; struct urb *urb; struct tty_struct *tty; - struct ftdi_private *priv; char error_flag; unsigned char *data; @@ -2180,7 +2183,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&priv->rx_lock, flags); if (actually_throttled) - schedule_work(&priv->rx_work); + schedule_delayed_work(&priv->rx_work, 0); } static int __init ftdi_init (void) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 9090051..e09a0bf 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -120,6 +120,8 @@ struct keyspan_pda_private { int tx_throttled; struct work_struct wakeup_work; struct work_struct unthrottle_work; + struct usb_serial *serial; + struct usb_serial_port *port; }; @@ -175,9 +177,11 @@ static struct usb_device_id id_table_fake_xircom [] = { }; #endif -static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) +static void keyspan_pda_wakeup_write(struct work_struct *work) { - + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, wakeup_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty = port->tty; /* wake up port processes */ @@ -187,8 +191,11 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) tty_wakeup(tty); } -static void keyspan_pda_request_unthrottle( struct usb_serial *serial ) +static void keyspan_pda_request_unthrottle(struct work_struct *work) { + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, unthrottle_work); + struct usb_serial *serial = priv->serial; int result; dbg(" request_unthrottle"); @@ -765,11 +772,10 @@ static int keyspan_pda_startup (struct usb_serial *serial) return (1); /* error */ usb_set_serial_port_data(serial->port[0], priv); init_waitqueue_head(&serial->port[0]->write_wait); - INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write, - (void *)(serial->port[0])); - INIT_WORK(&priv->unthrottle_work, - (void *)keyspan_pda_request_unthrottle, - (void *)(serial)); + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); + INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); + priv->serial = serial; + priv->port = serial->port[0]; return (0); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8006e51..2cfba84 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -533,9 +533,10 @@ void usb_serial_port_softint(struct usb_serial_port *port) schedule_work(&port->work); } -static void usb_serial_port_work(void *private) +static void usb_serial_port_work(struct work_struct *work) { - struct usb_serial_port *port = private; + struct usb_serial_port *port = + container_of(work, struct usb_serial_port, work); struct tty_struct *tty; dbg("%s - port %d", __FUNCTION__, port->number); @@ -799,7 +800,7 @@ int usb_serial_probe(struct usb_interface *interface, port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_work, port); + INIT_WORK(&port->work, usb_serial_port_work); serial->port[i] = port; } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 4d1cd7a..154c7d2 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -227,6 +227,7 @@ struct whiteheat_private { struct list_head rx_urbs_submitted; struct list_head rx_urb_q; struct work_struct rx_work; + struct usb_serial_port *port; struct list_head tx_urbs_free; struct list_head tx_urbs_submitted; }; @@ -241,7 +242,7 @@ static void command_port_read_callback(struct urb *urb); static int start_port_read(struct usb_serial_port *port); static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head); static struct list_head *list_first(struct list_head *head); -static void rx_data_softint(void *private); +static void rx_data_softint(struct work_struct *work); static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); @@ -424,7 +425,8 @@ static int whiteheat_attach (struct usb_serial *serial) spin_lock_init(&info->lock); info->flags = 0; info->mcr = 0; - INIT_WORK(&info->rx_work, rx_data_softint, port); + INIT_WORK(&info->rx_work, rx_data_softint); + info->port = port; INIT_LIST_HEAD(&info->rx_urbs_free); INIT_LIST_HEAD(&info->rx_urbs_submitted); @@ -949,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&info->lock, flags); if (actually_throttled) - rx_data_softint(port); + rx_data_softint(&info->rx_work); return; } @@ -1400,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head) } -static void rx_data_softint(void *private) +static void rx_data_softint(struct work_struct *work) { - struct usb_serial_port *port = (struct usb_serial_port *)private; - struct whiteheat_private *info = usb_get_serial_port_data(port); + struct whiteheat_private *info = + container_of(work, struct whiteheat_private, rx_work); + struct usb_serial_port *port = info->port; struct tty_struct *tty = port->tty; struct whiteheat_urb_wrap *wrap; struct urb *urb; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 302174b..31f476a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -383,9 +383,9 @@ static void fbcon_update_softback(struct vc_data *vc) softback_top = 0; } -static void fb_flashcursor(void *private) +static void fb_flashcursor(struct work_struct *work) { - struct fb_info *info = private; + struct fb_info *info = container_of(work, struct fb_info, queue); struct fbcon_ops *ops = info->fbcon_par; struct display *p; struct vc_data *vc = NULL; @@ -442,7 +442,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info) if ((!info->queue.func || info->queue.func == fb_flashcursor) && !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) { if (!info->queue.func) - INIT_WORK(&info->queue, fb_flashcursor, info); + INIT_WORK(&info->queue, fb_flashcursor); init_timer(&ops->cursor_timer); ops->cursor_timer.function = cursor_timer_handler; diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 90a79c7..944273c 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c @@ -110,8 +110,8 @@ struct v9fs_mux_rpc { }; static int v9fs_poll_proc(void *); -static void v9fs_read_work(void *); -static void v9fs_write_work(void *); +static void v9fs_read_work(struct work_struct *work); +static void v9fs_write_work(struct work_struct *work); static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, poll_table * p); static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); @@ -297,8 +297,8 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, m->rbuf = NULL; m->wpos = m->wsize = 0; m->wbuf = NULL; - INIT_WORK(&m->rq, v9fs_read_work, m); - INIT_WORK(&m->wq, v9fs_write_work, m); + INIT_WORK(&m->rq, v9fs_read_work); + INIT_WORK(&m->wq, v9fs_write_work); m->wsched = 0; memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); m->poll_task = NULL; @@ -458,13 +458,13 @@ static int v9fs_poll_proc(void *a) /** * v9fs_write_work - called when a transport can send some data */ -static void v9fs_write_work(void *a) +static void v9fs_write_work(struct work_struct *work) { int n, err; struct v9fs_mux_data *m; struct v9fs_req *req; - m = a; + m = container_of(work, struct v9fs_mux_data, wq); if (m->err < 0) { clear_bit(Wworksched, &m->wsched); @@ -564,7 +564,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) /** * v9fs_read_work - called when there is some data to be read from a transport */ -static void v9fs_read_work(void *a) +static void v9fs_read_work(struct work_struct *work) { int n, err; struct v9fs_mux_data *m; @@ -572,7 +572,7 @@ static void v9fs_read_work(void *a) struct v9fs_fcall *rcall; char *rbuf; - m = a; + m = container_of(work, struct v9fs_mux_data, rq); if (m->err < 0) return; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 78fe0fa..55f5333 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -35,7 +35,7 @@ struct greedy { struct gfs2_holder gr_gh; - struct work_struct gr_work; + struct delayed_work gr_work; }; struct gfs2_gl_hash_bucket { @@ -1368,9 +1368,9 @@ static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state, glops->go_xmote_th(gl, state, flags); } -static void greedy_work(void *data) +static void greedy_work(struct work_struct *work) { - struct greedy *gr = data; + struct greedy *gr = container_of(work, struct greedy, gr_work.work); struct gfs2_holder *gh = &gr->gr_gh; struct gfs2_glock *gl = gh->gh_gl; const struct gfs2_glock_operations *glops = gl->gl_ops; @@ -1422,7 +1422,7 @@ int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time) gfs2_holder_init(gl, 0, 0, gh); set_bit(HIF_GREEDY, &gh->gh_iflags); - INIT_WORK(&gr->gr_work, greedy_work, gr); + INIT_DELAYED_WORK(&gr->gr_work, greedy_work); set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); schedule_delayed_work(&gr->gr_work, time); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 42e3bef..72dad55 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -577,12 +577,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; - INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc, server); - INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server); + INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); + INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { - INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server); - INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server); + INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); + INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 11c2b25..e496d8b 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -350,9 +350,10 @@ static void info_server(struct ncp_server *server, unsigned int id, const void * } } -void ncpdgram_rcv_proc(void *s) +void ncpdgram_rcv_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); struct socket* sock; sock = server->ncp_sock; @@ -468,9 +469,10 @@ static void __ncpdgram_timeout_proc(struct ncp_server *server) } } -void ncpdgram_timeout_proc(void *s) +void ncpdgram_timeout_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, timeout_tq); mutex_lock(&server->rcv.creq_mutex); __ncpdgram_timeout_proc(server); mutex_unlock(&server->rcv.creq_mutex); @@ -652,18 +654,20 @@ skipdata:; } } -void ncp_tcp_rcv_proc(void *s) +void ncp_tcp_rcv_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); mutex_lock(&server->rcv.creq_mutex); __ncptcp_rcv_proc(server); mutex_unlock(&server->rcv.creq_mutex); } -void ncp_tcp_tx_proc(void *s) +void ncp_tcp_tx_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, tx.tq); mutex_lock(&server->rcv.creq_mutex); __ncptcp_try_send(server); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 293b649..e431e93 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1829,9 +1829,8 @@ out: } static struct workqueue_struct *laundry_wq; -static struct work_struct laundromat_work; -static void laundromat_main(void *); -static DECLARE_WORK(laundromat_work, laundromat_main, NULL); +static void laundromat_main(struct work_struct *); +static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); __be32 nfsd4_renew(clientid_t *clid) @@ -1940,7 +1939,7 @@ nfs4_laundromat(void) } void -laundromat_main(void *not_used) +laundromat_main(struct work_struct *not_used) { time_t t; diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f43bc5f..0b2ad16 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1205,10 +1205,12 @@ int ocfs2_flush_truncate_log(struct ocfs2_super *osb) return status; } -static void ocfs2_truncate_log_worker(void *data) +static void ocfs2_truncate_log_worker(struct work_struct *work) { int status; - struct ocfs2_super *osb = data; + struct ocfs2_super *osb = + container_of(work, struct ocfs2_super, + osb_truncate_log_wq.work); mlog_entry_void(); @@ -1441,7 +1443,8 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) /* ocfs2_truncate_log_shutdown keys on the existence of * osb->osb_tl_inode so we don't set any of the osb variables * until we're sure all is well. */ - INIT_WORK(&osb->osb_truncate_log_wq, ocfs2_truncate_log_worker, osb); + INIT_DELAYED_WORK(&osb->osb_truncate_log_wq, + ocfs2_truncate_log_worker); osb->osb_tl_bh = tl_bh; osb->osb_tl_inode = tl_inode; diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 305cba3..4cd9a95 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -141,7 +141,7 @@ struct o2hb_region { * recognizes a node going up and down in one iteration */ u64 hr_generation; - struct work_struct hr_write_timeout_work; + struct delayed_work hr_write_timeout_work; unsigned long hr_last_timeout_start; /* Used during o2hb_check_slot to hold a copy of the block @@ -156,9 +156,11 @@ struct o2hb_bio_wait_ctxt { int wc_error; }; -static void o2hb_write_timeout(void *arg) +static void o2hb_write_timeout(struct work_struct *work) { - struct o2hb_region *reg = arg; + struct o2hb_region *reg = + container_of(work, struct o2hb_region, + hr_write_timeout_work.work); mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u " "milliseconds\n", reg->hr_dev_name, @@ -1404,7 +1406,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, goto out; } - INIT_WORK(®->hr_write_timeout_work, o2hb_write_timeout, reg); + INIT_DELAYED_WORK(®->hr_write_timeout_work, o2hb_write_timeout); /* * A node is considered live after it has beat LIVE_THRESHOLD diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c index 7bba98f..4705d65 100644 --- a/fs/ocfs2/cluster/quorum.c +++ b/fs/ocfs2/cluster/quorum.c @@ -88,7 +88,7 @@ void o2quo_disk_timeout(void) o2quo_fence_self(); } -static void o2quo_make_decision(void *arg) +static void o2quo_make_decision(struct work_struct *work) { int quorum; int lowest_hb, lowest_reachable = 0, fence = 0; @@ -306,7 +306,7 @@ void o2quo_init(void) struct o2quo_state *qs = &o2quo_state; spin_lock_init(&qs->qs_lock); - INIT_WORK(&qs->qs_work, o2quo_make_decision, NULL); + INIT_WORK(&qs->qs_work, o2quo_make_decision); } void o2quo_exit(void) diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index b650efa..9b3209d 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -140,11 +140,11 @@ static int o2net_sys_err_translations[O2NET_ERR_MAX] = [O2NET_ERR_DIED] = -EHOSTDOWN,}; /* can't quite avoid *all* internal declarations :/ */ -static void o2net_sc_connect_completed(void *arg); -static void o2net_rx_until_empty(void *arg); -static void o2net_shutdown_sc(void *arg); +static void o2net_sc_connect_completed(struct work_struct *work); +static void o2net_rx_until_empty(struct work_struct *work); +static void o2net_shutdown_sc(struct work_struct *work); static void o2net_listen_data_ready(struct sock *sk, int bytes); -static void o2net_sc_send_keep_req(void *arg); +static void o2net_sc_send_keep_req(struct work_struct *work); static void o2net_idle_timer(unsigned long data); static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); @@ -308,10 +308,10 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node) o2nm_node_get(node); sc->sc_node = node; - INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed, sc); - INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty, sc); - INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc, sc); - INIT_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req, sc); + INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed); + INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty); + INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc); + INIT_DELAYED_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req); init_timer(&sc->sc_idle_timeout); sc->sc_idle_timeout.function = o2net_idle_timer; @@ -342,7 +342,7 @@ static void o2net_sc_queue_work(struct o2net_sock_container *sc, sc_put(sc); } static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, - struct work_struct *work, + struct delayed_work *work, int delay) { sc_get(sc); @@ -350,7 +350,7 @@ static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, sc_put(sc); } static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc, - struct work_struct *work) + struct delayed_work *work) { if (cancel_delayed_work(work)) sc_put(sc); @@ -564,9 +564,11 @@ static void o2net_ensure_shutdown(struct o2net_node *nn, * ourselves as state_change couldn't get the nn_lock and call set_nn_state * itself. */ -static void o2net_shutdown_sc(void *arg) +static void o2net_shutdown_sc(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_shutdown_work); struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); sclog(sc, "shutting down\n"); @@ -1201,9 +1203,10 @@ out: /* this work func is triggerd by data ready. it reads until it can read no * more. it interprets 0, eof, as fatal. if data_ready hits while we're doing * our work the work struct will be marked and we'll be called again. */ -static void o2net_rx_until_empty(void *arg) +static void o2net_rx_until_empty(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, sc_rx_work); int ret; do { @@ -1249,9 +1252,11 @@ static int o2net_set_nodelay(struct socket *sock) /* called when a connect completes and after a sock is accepted. the * rx path will see the response and mark the sc valid */ -static void o2net_sc_connect_completed(void *arg) +static void o2net_sc_connect_completed(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_connect_work); mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n", (unsigned long long)O2NET_PROTOCOL_VERSION, @@ -1262,9 +1267,11 @@ static void o2net_sc_connect_completed(void *arg) } /* this is called as a work_struct func. */ -static void o2net_sc_send_keep_req(void *arg) +static void o2net_sc_send_keep_req(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_keepalive_work.work); o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req)); sc_put(sc); @@ -1314,14 +1321,15 @@ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) * having a connect attempt fail, etc. This centralizes the logic which decides * if a connect attempt should be made or if we should give up and all future * transmit attempts should fail */ -static void o2net_start_connect(void *arg) +static void o2net_start_connect(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_work.work); struct o2net_sock_container *sc = NULL; struct o2nm_node *node = NULL, *mynode = NULL; struct socket *sock = NULL; struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; - int ret = 0; + int ret = 0, stop; /* if we're greater we initiate tx, otherwise we accept */ if (o2nm_this_node() <= o2net_num_from_nn(nn)) @@ -1342,10 +1350,9 @@ static void o2net_start_connect(void *arg) spin_lock(&nn->nn_lock); /* see if we already have one pending or have given up */ - if (nn->nn_sc || nn->nn_persistent_error) - arg = NULL; + stop = (nn->nn_sc || nn->nn_persistent_error); spin_unlock(&nn->nn_lock); - if (arg == NULL) /* *shrug*, needed some indicator */ + if (stop) goto out; nn->nn_last_connect_attempt = jiffies; @@ -1421,9 +1428,10 @@ out: return; } -static void o2net_connect_expired(void *arg) +static void o2net_connect_expired(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_expired.work); spin_lock(&nn->nn_lock); if (!nn->nn_sc_valid) { @@ -1436,9 +1444,10 @@ static void o2net_connect_expired(void *arg) spin_unlock(&nn->nn_lock); } -static void o2net_still_up(void *arg) +static void o2net_still_up(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_still_up.work); o2quo_hb_still_up(o2net_num_from_nn(nn)); } @@ -1644,9 +1653,9 @@ out: return ret; } -static void o2net_accept_many(void *arg) +static void o2net_accept_many(struct work_struct *work) { - struct socket *sock = arg; + struct socket *sock = o2net_listen_sock; while (o2net_accept_one(sock) == 0) cond_resched(); } @@ -1700,7 +1709,7 @@ static int o2net_open_listening_sock(__be16 port) write_unlock_bh(&sock->sk->sk_callback_lock); o2net_listen_sock = sock; - INIT_WORK(&o2net_listen_work, o2net_accept_many, sock); + INIT_WORK(&o2net_listen_work, o2net_accept_many); sock->sk->sk_reuse = 1; ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); @@ -1819,9 +1828,10 @@ int o2net_init(void) struct o2net_node *nn = o2net_nn_from_num(i); spin_lock_init(&nn->nn_lock); - INIT_WORK(&nn->nn_connect_work, o2net_start_connect, nn); - INIT_WORK(&nn->nn_connect_expired, o2net_connect_expired, nn); - INIT_WORK(&nn->nn_still_up, o2net_still_up, nn); + INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); + INIT_DELAYED_WORK(&nn->nn_connect_expired, + o2net_connect_expired); + INIT_DELAYED_WORK(&nn->nn_still_up, o2net_still_up); /* until we see hb from a node we'll return einval */ nn->nn_persistent_error = -ENOTCONN; init_waitqueue_head(&nn->nn_sc_wq); diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index 4b46aac..daebbd3 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h @@ -86,18 +86,18 @@ struct o2net_node { * connect attempt fails and so can be self-arming. shutdown is * careful to first mark the nn such that no connects will be attempted * before canceling delayed connect work and flushing the queue. */ - struct work_struct nn_connect_work; + struct delayed_work nn_connect_work; unsigned long nn_last_connect_attempt; /* this is queued as nodes come up and is canceled when a connection is * established. this expiring gives up on the node and errors out * transmits */ - struct work_struct nn_connect_expired; + struct delayed_work nn_connect_expired; /* after we give up on a socket we wait a while before deciding * that it is still heartbeating and that we should do some * quorum work */ - struct work_struct nn_still_up; + struct delayed_work nn_still_up; }; struct o2net_sock_container { @@ -129,7 +129,7 @@ struct o2net_sock_container { struct work_struct sc_shutdown_work; struct timer_list sc_idle_timeout; - struct work_struct sc_keepalive_work; + struct delayed_work sc_keepalive_work; unsigned sc_handshake_ok:1; diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index fa96818..6b6ff76 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -153,7 +153,7 @@ static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned * called functions that cannot be directly called from the * net message handlers for some reason, usually because * they need to send net messages of their own. */ -void dlm_dispatch_work(void *data); +void dlm_dispatch_work(struct work_struct *work); struct dlm_lock_resource; struct dlm_work_item; diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 8d1065f..637646e 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -1296,7 +1296,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, spin_lock_init(&dlm->work_lock); INIT_LIST_HEAD(&dlm->work_list); - INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work, dlm); + INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work); kref_init(&dlm->dlm_refs); dlm->dlm_state = DLM_CTXT_NEW; diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 9d950d7..fb3e2b0 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -153,9 +153,10 @@ static inline void dlm_reset_recovery(struct dlm_ctxt *dlm) } /* Worker function used during recovery. */ -void dlm_dispatch_work(void *data) +void dlm_dispatch_work(struct work_struct *work) { - struct dlm_ctxt *dlm = (struct dlm_ctxt *)data; + struct dlm_ctxt *dlm = + container_of(work, struct dlm_ctxt, dispatched_work); LIST_HEAD(tmp_list); struct list_head *iter, *iter2; struct dlm_work_item *item; diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c index eead48b..7d2f578 100644 --- a/fs/ocfs2/dlm/userdlm.c +++ b/fs/ocfs2/dlm/userdlm.c @@ -171,15 +171,14 @@ static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres) BUG(); } -static void user_dlm_unblock_lock(void *opaque); +static void user_dlm_unblock_lock(struct work_struct *work); static void __user_dlm_queue_lockres(struct user_lock_res *lockres) { if (!(lockres->l_flags & USER_LOCK_QUEUED)) { user_dlm_grab_inode_ref(lockres); - INIT_WORK(&lockres->l_work, user_dlm_unblock_lock, - lockres); + INIT_WORK(&lockres->l_work, user_dlm_unblock_lock); queue_work(user_dlm_worker, &lockres->l_work); lockres->l_flags |= USER_LOCK_QUEUED; @@ -279,10 +278,11 @@ static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres) iput(inode); } -static void user_dlm_unblock_lock(void *opaque) +static void user_dlm_unblock_lock(struct work_struct *work) { int new_level, status; - struct user_lock_res *lockres = (struct user_lock_res *) opaque; + struct user_lock_res *lockres = + container_of(work, struct user_lock_res, l_work); struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); mlog(0, "processing lockres %.*s\n", lockres->l_namelen, diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index fd9734d..d95ee27 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -911,11 +911,12 @@ struct ocfs2_la_recovery_item { * NOTE: This function can and will sleep on recovery of other nodes * during cluster locking, just like any other ocfs2 process. */ -void ocfs2_complete_recovery(void *data) +void ocfs2_complete_recovery(struct work_struct *work) { int ret; - struct ocfs2_super *osb = data; - struct ocfs2_journal *journal = osb->journal; + struct ocfs2_journal *journal = + container_of(work, struct ocfs2_journal, j_recovery_work); + struct ocfs2_super *osb = journal->j_osb; struct ocfs2_dinode *la_dinode, *tl_dinode; struct ocfs2_la_recovery_item *item; struct list_head *p, *n; diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 2f3a6ac..5be161a 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -172,7 +172,7 @@ static inline void ocfs2_handle_set_sync(struct ocfs2_journal_handle *handle, in } /* Exported only for the journal struct init code in super.c. Do not call. */ -void ocfs2_complete_recovery(void *data); +void ocfs2_complete_recovery(struct work_struct *work); /* * Journal Control: diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 0462a7f..9b1bad1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -283,7 +283,7 @@ struct ocfs2_super /* Truncate log info */ struct inode *osb_tl_inode; struct buffer_head *osb_tl_bh; - struct work_struct osb_truncate_log_wq; + struct delayed_work osb_truncate_log_wq; struct ocfs2_node_map osb_recovering_orphan_dirs; unsigned int *osb_orphan_wipes; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 76b46eb..9a80890 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1365,7 +1365,7 @@ static int ocfs2_initialize_super(struct super_block *sb, spin_lock_init(&journal->j_lock); journal->j_trans_id = (unsigned long) 1; INIT_LIST_HEAD(&journal->j_la_cleanups); - INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery, osb); + INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); journal->j_state = OCFS2_JOURNAL_FREE; /* get some pseudo constants for clustersize bits */ diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 85ce232..cd1bb75 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -104,7 +104,7 @@ static int release_journal_dev(struct super_block *super, struct reiserfs_journal *journal); static int dirty_one_transaction(struct super_block *s, struct reiserfs_journal_list *jl); -static void flush_async_commits(void *p); +static void flush_async_commits(struct work_struct *work); static void queue_log_writer(struct super_block *s); /* values for join in do_journal_begin_r */ @@ -2836,7 +2836,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, if (reiserfs_mounted_fs_count <= 1) commit_wq = create_workqueue("reiserfs"); - INIT_WORK(&journal->j_work, flush_async_commits, p_s_sb); + INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); + journal->j_work_sb = p_s_sb; return 0; free_and_return: free_journal_ram(p_s_sb); @@ -3447,10 +3448,11 @@ int journal_end_sync(struct reiserfs_transaction_handle *th, /* ** writeback the pending async commits to disk */ -static void flush_async_commits(void *p) +static void flush_async_commits(struct work_struct *work) { - struct super_block *p_s_sb = p; - struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); + struct reiserfs_journal *journal = + container_of(work, struct reiserfs_journal, j_work.work); + struct super_block *p_s_sb = journal->j_work_sb; struct reiserfs_journal_list *jl; struct list_head *entry; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 09360cf..8e6b56f 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -149,9 +149,10 @@ xfs_destroy_ioend( */ STATIC void xfs_end_bio_delalloc( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); xfs_destroy_ioend(ioend); } @@ -161,9 +162,10 @@ xfs_end_bio_delalloc( */ STATIC void xfs_end_bio_written( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); xfs_destroy_ioend(ioend); } @@ -176,9 +178,10 @@ xfs_end_bio_written( */ STATIC void xfs_end_bio_unwritten( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); bhv_vnode_t *vp = ioend->io_vnode; xfs_off_t offset = ioend->io_offset; size_t size = ioend->io_size; @@ -220,11 +223,11 @@ xfs_alloc_ioend( ioend->io_size = 0; if (type == IOMAP_UNWRITTEN) - INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten); else if (type == IOMAP_DELAY) - INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc); else - INIT_WORK(&ioend->io_work, xfs_end_bio_written, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_written); return ioend; } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index d338284..eef4a0b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -994,9 +994,10 @@ xfs_buf_wait_unpin( STATIC void xfs_buf_iodone_work( - void *v) + struct work_struct *work) { - xfs_buf_t *bp = (xfs_buf_t *)v; + xfs_buf_t *bp = + container_of(work, xfs_buf_t, b_iodone_work); if (bp->b_iodone) (*(bp->b_iodone))(bp); @@ -1017,10 +1018,10 @@ xfs_buf_ioend( if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) { if (schedule) { - INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work, bp); + INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work); queue_work(xfslogd_workqueue, &bp->b_iodone_work); } else { - xfs_buf_iodone_work(bp); + xfs_buf_iodone_work(&bp->b_iodone_work); } } else { up(&bp->b_iodonesema); diff --git a/include/linux/connector.h b/include/linux/connector.h index 4c02119..3ea1cd5 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -133,7 +133,7 @@ struct cn_callback_data { struct cn_callback_entry { struct list_head callback_entry; struct cn_callback *cb; - struct work_struct work; + struct delayed_work work; struct cn_queue_dev *pdev; struct cn_callback_id id; @@ -170,7 +170,7 @@ void cn_queue_free_dev(struct cn_queue_dev *dev); int cn_cb_equal(struct cb_id *, struct cb_id *); -void cn_queue_wrapper(void *data); +void cn_queue_wrapper(struct work_struct *work); extern int cn_already_initialized; diff --git a/include/linux/i2o.h b/include/linux/i2o.h index c115e9e..1fb02e1 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -461,7 +461,7 @@ struct i2o_driver { int (*reply) (struct i2o_controller *, u32, struct i2o_message *); /* Event handler */ - void (*event) (struct i2o_event *); + work_func_t event; struct workqueue_struct *event_queue; /* Event queue */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 587264a..8b08ef3 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -110,7 +110,7 @@ struct mmc_host { struct mmc_card *card_busy; /* the MMC card claiming host */ struct mmc_card *card_selected; /* the selected MMC card */ - struct work_struct detect; + struct delayed_work detect; unsigned long private[0] ____cacheline_aligned; }; diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h index b089d95..a503052 100644 --- a/include/linux/ncp_fs_sb.h +++ b/include/linux/ncp_fs_sb.h @@ -127,10 +127,10 @@ struct ncp_server { } unexpected_packet; }; -extern void ncp_tcp_rcv_proc(void *server); -extern void ncp_tcp_tx_proc(void *server); -extern void ncpdgram_rcv_proc(void *server); -extern void ncpdgram_timeout_proc(void *server); +extern void ncp_tcp_rcv_proc(struct work_struct *work); +extern void ncp_tcp_tx_proc(struct work_struct *work); +extern void ncpdgram_rcv_proc(struct work_struct *work); +extern void ncpdgram_timeout_proc(struct work_struct *work); extern void ncpdgram_timeout_call(unsigned long server); extern void ncp_tcp_data_ready(struct sock* sk, int len); extern void ncp_tcp_write_space(struct sock* sk); diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 73e0bec..6610103 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -249,7 +249,8 @@ struct reiserfs_journal { int j_errno; /* when flushing ordered buffers, throttle new ordered writers */ - struct work_struct j_work; + struct delayed_work j_work; + struct super_block *j_work_sb; atomic_t j_async_throttle; }; diff --git a/include/linux/relay.h b/include/linux/relay.h index 24accb4..0e3d91b 100644 --- a/include/linux/relay.h +++ b/include/linux/relay.h @@ -38,7 +38,7 @@ struct rchan_buf size_t subbufs_consumed; /* count of sub-buffers consumed */ struct rchan *chan; /* associated channel */ wait_queue_head_t read_wait; /* reader wait queue */ - struct work_struct wake_readers; /* reader wake-up work struct */ + struct delayed_work wake_readers; /* reader wake-up work struct */ struct dentry *dentry; /* channel file dentry */ struct kref kref; /* channel buffer refcount */ struct page **page_array; /* array of current buffer pages */ diff --git a/include/linux/usb.h b/include/linux/usb.h index 5482bfb..06ce7a6 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -382,7 +382,7 @@ struct usb_device { int pm_usage_cnt; /* usage counter for autosuspend */ #ifdef CONFIG_PM - struct work_struct autosuspend; /* for delayed autosuspends */ + struct delayed_work autosuspend; /* for delayed autosuspends */ struct mutex pm_mutex; /* protects PM operations */ unsigned auto_pm:1; /* autosuspend/resume in progress */ diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 617b672..8911927 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h @@ -108,8 +108,8 @@ struct ieee80211softmac_assoc_info { /* Scan retries remaining */ int scan_retry; - struct work_struct work; - struct work_struct timeout; + struct delayed_work work; + struct delayed_work timeout; }; struct ieee80211softmac_bss_info { diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c6d93bb..60b6844 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1030,7 +1030,7 @@ void sctp_inq_init(struct sctp_inq *); void sctp_inq_free(struct sctp_inq *); void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet); struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); -void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *); +void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t); /* This is the structure we use to hold outbound chunks. You push * chunks in and they automatically pop out the other end as bundled diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9582e84..9ccc036 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -200,9 +200,14 @@ struct domain_device { void *lldd_dev; }; +struct sas_discovery_event { + struct work_struct work; + struct asd_sas_port *port; +}; + struct sas_discovery { spinlock_t disc_event_lock; - struct work_struct disc_work[DISC_NUM_EVENTS]; + struct sas_discovery_event disc_work[DISC_NUM_EVENTS]; unsigned long pending; u8 fanout_sas_addr[8]; u8 eeds_a[8]; @@ -248,14 +253,19 @@ struct asd_sas_port { void *lldd_port; /* not touched by the sas class code */ }; +struct asd_sas_event { + struct work_struct work; + struct asd_sas_phy *phy; +}; + /* The phy pretty much is controlled by the LLDD. * The class only reads those fields. */ struct asd_sas_phy { /* private: */ /* protected by ha->event_lock */ - struct work_struct port_events[PORT_NUM_EVENTS]; - struct work_struct phy_events[PHY_NUM_EVENTS]; + struct asd_sas_event port_events[PORT_NUM_EVENTS]; + struct asd_sas_event phy_events[PHY_NUM_EVENTS]; unsigned long port_events_pending; unsigned long phy_events_pending; @@ -307,10 +317,15 @@ struct scsi_core { int queue_thread_kill; }; +struct sas_ha_event { + struct work_struct work; + struct sas_ha_struct *ha; +}; + struct sas_ha_struct { /* private: */ spinlock_t event_lock; - struct work_struct ha_events[HA_NUM_EVENTS]; + struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; struct scsi_core core; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index fd35232..798f7c7 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -206,9 +206,9 @@ struct fc_rport { /* aka fc_starget_attrs */ u8 flags; struct list_head peers; struct device dev; - struct work_struct dev_loss_work; + struct delayed_work dev_loss_work; struct work_struct scan_work; - struct work_struct fail_io_work; + struct delayed_work fail_io_work; struct work_struct stgt_delete_work; struct work_struct rport_delete_work; } __attribute__((aligned(sizeof(unsigned long)))); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 4b95c89..d5c218d 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -176,7 +176,7 @@ struct iscsi_cls_session { /* recovery fields */ int recovery_tmo; - struct work_struct recovery_work; + struct delayed_work recovery_work; int target_id; diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 4c43521..3372039 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -511,7 +511,7 @@ struct snd_ac97 { #ifdef CONFIG_SND_AC97_POWER_SAVE unsigned int power_up; /* power states */ struct workqueue_struct *power_workq; - struct work_struct power_work; + struct delayed_work power_work; #endif struct device dev; }; diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h index 11702aa..2ee0616 100644 --- a/include/sound/ak4114.h +++ b/include/sound/ak4114.h @@ -182,7 +182,7 @@ struct ak4114 { unsigned char rcs0; unsigned char rcs1; struct workqueue_struct *workqueue; - struct work_struct work; + struct delayed_work work; void *change_callback_private; void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1); }; diff --git a/kernel/relay.c b/kernel/relay.c index f04bbdb..2b92e8e 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -308,9 +308,10 @@ static struct rchan_callbacks default_channel_callbacks = { * reason waking is deferred is that calling directly from write * causes problems if you're writing from say the scheduler. */ -static void wakeup_readers(void *private) +static void wakeup_readers(struct work_struct *work) { - struct rchan_buf *buf = private; + struct rchan_buf *buf = + container_of(work, struct rchan_buf, wake_readers.work); wake_up_interruptible(&buf->read_wait); } @@ -328,7 +329,7 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) if (init) { init_waitqueue_head(&buf->read_wait); kref_init(&buf->kref); - INIT_WORK(&buf->wake_readers, NULL, NULL); + INIT_DELAYED_WORK(&buf->wake_readers, NULL); } else { cancel_delayed_work(&buf->wake_readers); flush_scheduled_work(); @@ -549,7 +550,8 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) buf->padding[old_subbuf]; smp_mb(); if (waitqueue_active(&buf->read_wait)) { - PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); + PREPARE_DELAYED_WORK(&buf->wake_readers, + wakeup_readers); schedule_delayed_work(&buf->wake_readers, 1); } } diff --git a/mm/swap.c b/mm/swap.c index 2e0e871..d9a3770 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -216,7 +216,7 @@ void lru_add_drain(void) } #ifdef CONFIG_NUMA -static void lru_add_drain_per_cpu(void *dummy) +static void lru_add_drain_per_cpu(struct work_struct *dummy) { lru_add_drain(); } @@ -226,7 +226,7 @@ static void lru_add_drain_per_cpu(void *dummy) */ int lru_add_drain_all(void) { - return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL); + return schedule_on_each_cpu(lru_add_drain_per_cpu); } #else diff --git a/net/atm/lec.c b/net/atm/lec.c index 66c57c1..e801fff 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1458,7 +1458,7 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr, #define LEC_ARP_REFRESH_INTERVAL (3*HZ) -static void lec_arp_check_expire(void *data); +static void lec_arp_check_expire(struct work_struct *work); static void lec_arp_expire_arp(unsigned long data); /* @@ -1481,7 +1481,7 @@ static void lec_arp_init(struct lec_priv *priv) INIT_HLIST_HEAD(&priv->lec_no_forward); INIT_HLIST_HEAD(&priv->mcast_fwds); spin_lock_init(&priv->lec_arp_lock); - INIT_WORK(&priv->lec_arp_work, lec_arp_check_expire, priv); + INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire); schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL); } @@ -1879,10 +1879,11 @@ static void lec_arp_expire_vcc(unsigned long data) * to ESI_FORWARD_DIRECT. This causes the flush period to end * regardless of the progress of the flush protocol. */ -static void lec_arp_check_expire(void *data) +static void lec_arp_check_expire(struct work_struct *work) { unsigned long flags; - struct lec_priv *priv = data; + struct lec_priv *priv = + container_of(work, struct lec_priv, lec_arp_work.work); struct hlist_node *node, *next; struct lec_arp_table *entry; unsigned long now; diff --git a/net/atm/lec.h b/net/atm/lec.h index 877f509..984e8e6 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -92,7 +92,7 @@ struct lec_priv { spinlock_t lec_arp_lock; struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ struct atm_vcc *lecd; - struct work_struct lec_arp_work; /* C10 */ + struct delayed_work lec_arp_work; /* C10 */ unsigned int maximum_unknown_frame_count; /* * Within the period of time defined by this variable, the client will send diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 3eeeb7a..d4c9356 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -237,9 +237,9 @@ static void bt_release(struct device *dev) kfree(data); } -static void add_conn(void *data) +static void add_conn(struct work_struct *work) { - struct hci_conn *conn = data; + struct hci_conn *conn = container_of(work, struct hci_conn, work); int i; if (device_register(&conn->dev) < 0) { @@ -272,14 +272,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) dev_set_drvdata(&conn->dev, conn); - INIT_WORK(&conn->work, add_conn, (void *) conn); + INIT_WORK(&conn->work, add_conn); schedule_work(&conn->work); } -static void del_conn(void *data) +static void del_conn(struct work_struct *work) { - struct hci_conn *conn = data; + struct hci_conn *conn = container_of(work, struct hci_conn, work); device_del(&conn->dev); } @@ -287,7 +287,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - INIT_WORK(&conn->work, del_conn, (void *) conn); + INIT_WORK(&conn->work, del_conn); schedule_work(&conn->work); } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f753c40..55bb263 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -77,12 +77,16 @@ static int port_cost(struct net_device *dev) * Called from work queue to allow for calling functions that * might sleep (such as speed check), and to debounce. */ -static void port_carrier_check(void *arg) +static void port_carrier_check(struct work_struct *work) { - struct net_device *dev = arg; struct net_bridge_port *p; + struct net_device *dev; struct net_bridge *br; + dev = container_of(work, struct net_bridge_port, + carrier_check.work)->dev; + work_release(work); + rtnl_lock(); p = dev->br_port; if (!p) @@ -276,7 +280,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->port_no = index; br_init_port(p); p->state = BR_STATE_DISABLED; - INIT_WORK(&p->carrier_check, port_carrier_check, dev); + INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check); br_stp_port_timer_init(p); kobject_init(&p->kobj); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 74258d8..3a534e9 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -82,7 +82,7 @@ struct net_bridge_port struct timer_list hold_timer; struct timer_list message_age_timer; struct kobject kobj; - struct work_struct carrier_check; + struct delayed_work carrier_check; struct rcu_head rcu; }; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6589adb..63f24c9 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -56,7 +56,7 @@ static atomic_t trapped; static void zap_completion_queue(void); static void arp_reply(struct sk_buff *skb); -static void queue_process(void *p) +static void queue_process(struct work_struct *work) { unsigned long flags; struct sk_buff *skb; @@ -77,7 +77,7 @@ static void queue_process(void *p) } } -static DECLARE_WORK(send_queue, queue_process, NULL); +static DECLARE_WORK(send_queue, queue_process); void netpoll_queue(struct sk_buff *skb) { diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 9045438..36db5be 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -31,8 +31,7 @@ struct inet_timewait_death_row dccp_death_row = { .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0, (unsigned long)&dccp_death_row), .twkill_work = __WORK_INITIALIZER(dccp_death_row.twkill_work, - inet_twdr_twkill_work, - &dccp_death_row), + inet_twdr_twkill_work), /* Short-time timewait calendar */ .twcal_hand = -1, diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index cf51c87..08386c1 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -58,9 +58,11 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft } void -ieee80211softmac_assoc_timeout(void *d) +ieee80211softmac_assoc_timeout(struct work_struct *work) { - struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_device *mac = + container_of(work, struct ieee80211softmac_device, + associnfo.timeout.work); struct ieee80211softmac_network *n; mutex_lock(&mac->associnfo.mutex); @@ -186,9 +188,11 @@ ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void /* This function is called to handle userspace requests (asynchronously) */ void -ieee80211softmac_assoc_work(void *d) +ieee80211softmac_assoc_work(struct work_struct *work) { - struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_device *mac = + container_of(work, struct ieee80211softmac_device, + associnfo.work.work); struct ieee80211softmac_network *found = NULL; struct ieee80211_network *net = NULL, *best = NULL; int bssvalid; @@ -412,7 +416,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, network->authenticated = 0; /* we don't want to do this more than once ... */ network->auth_desynced_once = 1; - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); break; } default: @@ -446,7 +450,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, ieee80211softmac_disassoc(mac); /* try to reassociate */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } @@ -466,7 +470,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 4cef39e..2ae1833 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -26,7 +26,7 @@ #include "ieee80211softmac_priv.h" -static void ieee80211softmac_auth_queue(void *data); +static void ieee80211softmac_auth_queue(struct work_struct *work); /* Queues an auth request to the desired AP */ int @@ -54,14 +54,14 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, auth->mac = mac; auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT; auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST; - INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth); + INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue); /* Lock (for list) */ spin_lock_irqsave(&mac->lock, flags); /* add to list */ list_add_tail(&auth->list, &mac->auth_queue); - schedule_work(&auth->work); + schedule_delayed_work(&auth->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; @@ -70,14 +70,15 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, /* Sends an auth request to the desired AP and handles timeouts */ static void -ieee80211softmac_auth_queue(void *data) +ieee80211softmac_auth_queue(struct work_struct *work) { struct ieee80211softmac_device *mac; struct ieee80211softmac_auth_queue_item *auth; struct ieee80211softmac_network *net; unsigned long flags; - auth = (struct ieee80211softmac_auth_queue_item *)data; + auth = container_of(work, struct ieee80211softmac_auth_queue_item, + work.work); net = auth->net; mac = auth->mac; @@ -118,9 +119,11 @@ ieee80211softmac_auth_queue(void *data) /* Sends a response to an auth challenge (for shared key auth). */ static void -ieee80211softmac_auth_challenge_response(void *_aq) +ieee80211softmac_auth_challenge_response(struct work_struct *work) { - struct ieee80211softmac_auth_queue_item *aq = _aq; + struct ieee80211softmac_auth_queue_item *aq = + container_of(work, struct ieee80211softmac_auth_queue_item, + work.work); /* Send our response */ ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); @@ -228,8 +231,8 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) * we have obviously already sent the initial auth * request. */ cancel_delayed_work(&aq->work); - INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq); - schedule_work(&aq->work); + INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response); + schedule_delayed_work(&aq->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; case IEEE80211SOFTMAC_AUTH_SHARED_PASS: @@ -392,6 +395,6 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de ieee80211softmac_deauth_from_net(mac, net); /* let's try to re-associate */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index f34fa2e..b901565 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -73,10 +73,12 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { static void -ieee80211softmac_notify_callback(void *d) +ieee80211softmac_notify_callback(struct work_struct *work) { - struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; - kfree(d); + struct ieee80211softmac_event *pevent = + container_of(work, struct ieee80211softmac_event, work.work); + struct ieee80211softmac_event event = *pevent; + kfree(pevent); event.fun(event.mac->dev, event.event_type, event.context); } @@ -99,7 +101,7 @@ ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, return -ENOMEM; eventptr->event_type = event; - INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr); + INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback); eventptr->fun = fun; eventptr->context = context; eventptr->mac = mac; @@ -170,7 +172,7 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve /* User may have subscribed to ANY event, so * we tell them which event triggered it. */ eventptr->event_type = event; - schedule_work(&eventptr->work); + schedule_delayed_work(&eventptr->work, 0); } } } diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 33aff4f..256207b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -58,8 +58,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) 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); + INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work); + INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout); softmac->start_scan = ieee80211softmac_start_scan_implementation; softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; softmac->stop_scan = ieee80211softmac_stop_scan_implementation; diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h index 0642e09..c0dbe07 100644 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -78,7 +78,7 @@ /* private definitions and prototypes */ /*** prototypes from _scan.c */ -void ieee80211softmac_scan(void *sm); +void ieee80211softmac_scan(struct work_struct *work); /* for internal use if scanning is needed */ int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac); void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac); @@ -149,7 +149,7 @@ int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *au int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth); /*** prototypes from _assoc.c */ -void ieee80211softmac_assoc_work(void *d); +void ieee80211softmac_assoc_work(struct work_struct *work); int ieee80211softmac_handle_assoc_response(struct net_device * dev, struct ieee80211_assoc_response * resp, struct ieee80211_network * network); @@ -157,7 +157,7 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev, struct ieee80211_disassoc * disassoc); int ieee80211softmac_handle_reassoc_req(struct net_device * dev, struct ieee80211_reassoc_request * reassoc); -void ieee80211softmac_assoc_timeout(void *d); +void ieee80211softmac_assoc_timeout(struct work_struct *work); void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason); void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac); @@ -207,7 +207,7 @@ struct ieee80211softmac_auth_queue_item { struct ieee80211softmac_device *mac; /* SoftMAC device */ u8 retry; /* Retry limit */ u8 state; /* Auth State */ - struct work_struct work; /* Work queue */ + struct delayed_work work; /* Work queue */ }; /* scanning information */ @@ -219,7 +219,8 @@ struct ieee80211softmac_scaninfo { stop:1; u8 skip_flags; struct completion finished; - struct work_struct softmac_scan; + struct delayed_work softmac_scan; + struct ieee80211softmac_device *mac; }; /* private event struct */ @@ -227,7 +228,7 @@ struct ieee80211softmac_event { struct list_head list; int event_type; void *event_context; - struct work_struct work; + struct delayed_work work; notify_function_ptr fun; void *context; struct ieee80211softmac_device *mac; diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index d31cf77..a832607 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -91,12 +91,14 @@ ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm) /* internal scanning implementation follows */ -void ieee80211softmac_scan(void *d) +void ieee80211softmac_scan(struct work_struct *work) { int invalid_channel; u8 current_channel_idx; - struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d; - struct ieee80211softmac_scaninfo *si = sm->scaninfo; + struct ieee80211softmac_scaninfo *si = + container_of(work, struct ieee80211softmac_scaninfo, + softmac_scan.work); + struct ieee80211softmac_device *sm = si->mac; unsigned long flags; while (!(si->stop) && (si->current_channel_idx < si->number_channels)) { @@ -146,7 +148,8 @@ static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee802 struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC); if (unlikely(!info)) return NULL; - INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac); + INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan); + info->mac = mac; init_completion(&info->finished); return info; } @@ -189,7 +192,7 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->started = 1; sm->scaninfo->stop = 0; INIT_COMPLETION(sm->scaninfo->finished); - schedule_work(&sm->scaninfo->softmac_scan); + schedule_delayed_work(&sm->scaninfo->softmac_scan, 0); spin_unlock_irqrestore(&sm->lock, flags); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 23068a8..2ffaebd 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -122,7 +122,7 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ - schedule_work(&sm->associnfo.work); + schedule_delayed_work(&sm->associnfo.work, 0); out: mutex_unlock(&sm->associnfo.mutex); @@ -356,7 +356,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, /* force reassociation */ mac->associnfo.bssvalid = 0; if (mac->associnfo.associated) - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is no longer fixed */ mac->associnfo.bssfixed = 0; @@ -373,7 +373,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, /* tell the other code that this bssid should be used no matter what */ mac->associnfo.bssfixed = 1; /* queue associate if new bssid or (old one again and not associated) */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); } out: diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index f261616..9b93338 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -221,10 +221,10 @@ static void update_defense_level(void) * Timer for checking the defense */ #define DEFENSE_TIMER_PERIOD 1*HZ -static void defense_work_handler(void *data); -static DECLARE_WORK(defense_work, defense_work_handler, NULL); +static void defense_work_handler(struct work_struct *work); +static DECLARE_DELAYED_WORK(defense_work, defense_work_handler); -static void defense_work_handler(void *data) +static void defense_work_handler(struct work_struct *work) { update_defense_level(); if (atomic_read(&ip_vs_dropentry)) diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index d50a020..262bda8 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -61,7 +61,7 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty); static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch); static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout); static void ircomm_tty_hangup(struct tty_struct *tty); -static void ircomm_tty_do_softint(void *private_); +static void ircomm_tty_do_softint(struct work_struct *work); static void ircomm_tty_shutdown(struct ircomm_tty_cb *self); static void ircomm_tty_stop(struct tty_struct *tty); @@ -389,7 +389,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) self->flow = FLOW_STOP; self->line = line; - INIT_WORK(&self->tqueue, ircomm_tty_do_softint, self); + INIT_WORK(&self->tqueue, ircomm_tty_do_softint); self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; self->close_delay = 5*HZ/10; @@ -594,15 +594,16 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty) } /* - * Function ircomm_tty_do_softint (private_) + * Function ircomm_tty_do_softint (work) * * We use this routine to give the write wakeup to the user at at a * safe time (as fast as possible after write have completed). This * can be compared to the Tx interrupt. */ -static void ircomm_tty_do_softint(void *private_) +static void ircomm_tty_do_softint(struct work_struct *work) { - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_; + struct ircomm_tty_cb *self = + container_of(work, struct ircomm_tty_cb, tqueue); struct tty_struct *tty; unsigned long flags; struct sk_buff *skb, *ctrl_skb; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ed0445f..8812469 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -61,7 +61,7 @@ #include /* Forward declarations for internal functions. */ -static void sctp_assoc_bh_rcv(struct sctp_association *asoc); +static void sctp_assoc_bh_rcv(struct work_struct *work); /* 1st Level Abstractions. */ @@ -269,9 +269,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a /* Create an input queue. */ sctp_inq_init(&asoc->base.inqueue); - sctp_inq_set_th_handler(&asoc->base.inqueue, - (void (*)(void *))sctp_assoc_bh_rcv, - asoc); + sctp_inq_set_th_handler(&asoc->base.inqueue, sctp_assoc_bh_rcv); /* Create an output queue. */ sctp_outq_init(asoc, &asoc->outqueue); @@ -944,8 +942,11 @@ out: } /* Do delayed input processing. This is scheduled by sctp_rcv(). */ -static void sctp_assoc_bh_rcv(struct sctp_association *asoc) +static void sctp_assoc_bh_rcv(struct work_struct *work) { + struct sctp_association *asoc = + container_of(work, struct sctp_association, + base.inqueue.immediate); struct sctp_endpoint *ep; struct sctp_chunk *chunk; struct sock *sk; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 9b6b394..a2b5537 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -61,7 +61,7 @@ #include /* Forward declarations for internal helpers. */ -static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep); +static void sctp_endpoint_bh_rcv(struct work_struct *work); /* * Initialize the base fields of the endpoint structure. @@ -85,8 +85,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, sctp_inq_init(&ep->base.inqueue); /* Set its top-half handler */ - sctp_inq_set_th_handler(&ep->base.inqueue, - (void (*)(void *))sctp_endpoint_bh_rcv, ep); + sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv); /* Initialize the bind addr area */ sctp_bind_addr_init(&ep->base.bind_addr, 0); @@ -311,8 +310,11 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, /* Do delayed input processing. This is scheduled by sctp_rcv(). * This may be called on BH or task time. */ -static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep) +static void sctp_endpoint_bh_rcv(struct work_struct *work) { + struct sctp_endpoint *ep = + container_of(work, struct sctp_endpoint, + base.inqueue.immediate); struct sctp_association *asoc; struct sock *sk; struct sctp_transport *transport; diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index cf6deed..71b0746 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -54,7 +54,7 @@ void sctp_inq_init(struct sctp_inq *queue) queue->in_progress = NULL; /* Create a task for delivering data. */ - INIT_WORK(&queue->immediate, NULL, NULL); + INIT_WORK(&queue->immediate, NULL); queue->malloced = 0; } @@ -97,7 +97,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) * on the BH related data structures. */ list_add_tail(&chunk->list, &q->in_chunk_list); - q->immediate.func(q->immediate.data); + q->immediate.func(&q->immediate); } /* Extract a chunk from an SCTP inqueue. @@ -205,9 +205,8 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) * The intent is that this routine will pull stuff out of the * inqueue and process it. */ -void sctp_inq_set_th_handler(struct sctp_inq *q, - void (*callback)(void *), void *arg) +void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback) { - INIT_WORK(&q->immediate, callback, arg); + INIT_WORK(&q->immediate, callback); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7736b23..ba924d4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -358,7 +358,7 @@ static void xfrm_policy_gc_kill(struct xfrm_policy *policy) xfrm_pol_put(policy); } -static void xfrm_policy_gc_task(void *data) +static void xfrm_policy_gc_task(struct work_struct *work) { struct xfrm_policy *policy; struct hlist_node *entry, *tmp; @@ -546,7 +546,7 @@ static inline int xfrm_byidx_should_resize(int total) static DEFINE_MUTEX(hash_resize_mutex); -static void xfrm_hash_resize(void *__unused) +static void xfrm_hash_resize(struct work_struct *__unused) { int dir, total; @@ -563,7 +563,7 @@ static void xfrm_hash_resize(void *__unused) mutex_unlock(&hash_resize_mutex); } -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); +static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); /* Generate new index... KAME seems to generate them ordered by cost * of an absolute inpredictability of ordering of rules. This will not pass. */ @@ -2080,7 +2080,7 @@ static void __init xfrm_policy_init(void) panic("XFRM: failed to allocate bydst hash\n"); } - INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL); + INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); register_netdevice_notifier(&xfrm_dev_notifier); } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 899de9e..40c5271 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -115,7 +115,7 @@ static unsigned long xfrm_hash_new_size(void) static DEFINE_MUTEX(hash_resize_mutex); -static void xfrm_hash_resize(void *__unused) +static void xfrm_hash_resize(struct work_struct *__unused) { struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; unsigned long nsize, osize; @@ -168,7 +168,7 @@ out_unlock: mutex_unlock(&hash_resize_mutex); } -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); +static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); DECLARE_WAIT_QUEUE_HEAD(km_waitq); EXPORT_SYMBOL(km_waitq); @@ -207,7 +207,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) kfree(x); } -static void xfrm_state_gc_task(void *data) +static void xfrm_state_gc_task(struct work_struct *data) { struct xfrm_state *x; struct hlist_node *entry, *tmp; @@ -1568,6 +1568,6 @@ void __init xfrm_state_init(void) panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); - INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); + INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task); } diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h index 3a61f31..ee64f5d 100644 --- a/sound/aoa/aoa-gpio.h +++ b/sound/aoa/aoa-gpio.h @@ -59,10 +59,10 @@ struct gpio_methods { }; struct gpio_notification { + struct delayed_work work; notify_func_t notify; void *data; void *gpio_private; - struct work_struct work; struct mutex mutex; }; diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c index 40eb47e..2b03bc7 100644 --- a/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/sound/aoa/core/snd-aoa-gpio-feature.c @@ -195,9 +195,10 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) ftr_gpio_set_lineout(rt, (s>>2)&1); } -static void ftr_handle_notify(void *data) +static void ftr_handle_notify(struct work_struct *work) { - struct gpio_notification *notif = data; + struct gpio_notification *notif = + container_of(work, struct gpio_notification, work.work); mutex_lock(¬if->mutex); if (notif->notify) @@ -253,12 +254,9 @@ static void ftr_gpio_init(struct gpio_runtime *rt) ftr_gpio_all_amps_off(rt); rt->implementation_private = 0; - INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, - &rt->headphone_notify); - INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, - &rt->line_in_notify); - INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, - &rt->line_out_notify); + INIT_DELAYED_WORK(&rt->headphone_notify.work, ftr_handle_notify); + INIT_DELAYED_WORK(&rt->line_in_notify.work, ftr_handle_notify); + INIT_DELAYED_WORK(&rt->line_out_notify.work, ftr_handle_notify); mutex_init(&rt->headphone_notify.mutex); mutex_init(&rt->line_in_notify.mutex); mutex_init(&rt->line_out_notify.mutex); @@ -287,7 +285,7 @@ static irqreturn_t ftr_handle_notify_irq(int xx, void *data) { struct gpio_notification *notif = data; - schedule_work(¬if->work); + schedule_delayed_work(¬if->work, 0); return IRQ_HANDLED; } diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c index 2836c32..5ca2220 100644 --- a/sound/aoa/core/snd-aoa-gpio-pmf.c +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -69,9 +69,10 @@ static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) pmf_gpio_set_lineout(rt, (s>>2)&1); } -static void pmf_handle_notify(void *data) +static void pmf_handle_notify(struct work_struct *work) { - struct gpio_notification *notif = data; + struct gpio_notification *notif = + container_of(work, struct gpio_notification, work.work); mutex_lock(¬if->mutex); if (notif->notify) @@ -83,12 +84,9 @@ static void pmf_gpio_init(struct gpio_runtime *rt) { pmf_gpio_all_amps_off(rt); rt->implementation_private = 0; - INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, - &rt->headphone_notify); - INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, - &rt->line_in_notify); - INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, - &rt->line_out_notify); + INIT_DELAYED_WORK(&rt->headphone_notify.work, pmf_handle_notify); + INIT_DELAYED_WORK(&rt->line_in_notify.work, pmf_handle_notify); + INIT_DELAYED_WORK(&rt->line_out_notify.work, pmf_handle_notify); mutex_init(&rt->headphone_notify.mutex); mutex_init(&rt->line_in_notify.mutex); mutex_init(&rt->line_out_notify.mutex); @@ -129,7 +127,7 @@ static void pmf_handle_notify_irq(void *data) { struct gpio_notification *notif = data; - schedule_work(¬if->work); + schedule_delayed_work(¬if->work, 0); } static int pmf_set_notify(struct gpio_runtime *rt, diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 12ffffc..d2f2c50 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -35,7 +35,7 @@ MODULE_LICENSE("GPL"); #define AK4114_ADDR 0x00 /* fixed address */ -static void ak4114_stats(void *); +static void ak4114_stats(struct work_struct *work); static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) { @@ -158,7 +158,7 @@ void snd_ak4114_reinit(struct ak4114 *chip) reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); /* bring up statistics / event queing */ chip->init = 0; - INIT_WORK(&chip->work, ak4114_stats, chip); + INIT_DELAYED_WORK(&chip->work, ak4114_stats); queue_delayed_work(chip->workqueue, &chip->work, HZ / 10); } @@ -561,9 +561,9 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) return res; } -static void ak4114_stats(void *data) +static void ak4114_stats(struct work_struct *work) { - struct ak4114 *chip = (struct ak4114 *)data; + struct ak4114 *chip = container_of(work, struct ak4114, work.work); if (chip->init) return; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 6577b23..7abcb10 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1927,9 +1927,10 @@ static int snd_ac97_dev_disconnect(struct snd_device *device) static struct snd_ac97_build_ops null_build_ops; #ifdef CONFIG_SND_AC97_POWER_SAVE -static void do_update_power(void *data) +static void do_update_power(struct work_struct *work) { - update_power_regs(data); + update_power_regs( + container_of(work, struct snd_ac97, power_work.work)); } #endif @@ -1989,7 +1990,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, mutex_init(&ac97->page_mutex); #ifdef CONFIG_SND_AC97_POWER_SAVE ac97->power_workq = create_workqueue("ac97"); - INIT_WORK(&ac97->power_work, do_update_power, ac97); + INIT_DELAYED_WORK(&ac97->power_work, do_update_power); #endif #ifdef CONFIG_PCI diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9c3d7ac..71482c1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -272,10 +272,11 @@ EXPORT_SYMBOL(snd_hda_queue_unsol_event); /* * process queueud unsolicited events */ -static void process_unsol_events(void *data) +static void process_unsol_events(struct work_struct *work) { - struct hda_bus *bus = data; - struct hda_bus_unsolicited *unsol = bus->unsol; + struct hda_bus_unsolicited *unsol = + container_of(work, struct hda_bus_unsolicited, work); + struct hda_bus *bus = unsol->bus; struct hda_codec *codec; unsigned int rp, caddr, res; @@ -314,7 +315,8 @@ static int init_unsol_queue(struct hda_bus *bus) kfree(unsol); return -ENOMEM; } - INIT_WORK(&unsol->work, process_unsol_events, bus); + INIT_WORK(&unsol->work, process_unsol_events); + unsol->bus = bus; bus->unsol = unsol; return 0; } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index f9416c3..9ca1baf 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -206,6 +206,7 @@ struct hda_bus_unsolicited { /* workqueue */ struct workqueue_struct *workq; struct work_struct work; + struct hda_bus *bus; }; /* diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 2fbe1d1..8f074c7 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -942,10 +942,11 @@ static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int } static struct work_struct device_change; +static struct snd_pmac *device_change_chip; -static void device_change_handler(void *self) +static void device_change_handler(struct work_struct *work) { - struct snd_pmac *chip = self; + struct snd_pmac *chip = device_change_chip; struct pmac_tumbler *mix; int headphone, lineout; @@ -1417,7 +1418,8 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) chip->resume = tumbler_resume; #endif - INIT_WORK(&device_change, device_change_handler, (void *)chip); + INIT_WORK(&device_change, device_change_handler); + device_change_chip = chip; #ifdef PMAC_SUPPORT_AUTOMUTE if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) -- cgit v0.10.2 From dea22214790d1306f3a3444db13d2c726037b189 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 7 Nov 2006 17:28:55 -0800 Subject: [PATCH] aic94xx: handle REQ_DEVICE_RESET This patch implements a REQ_DEVICE_RESET handler for the aic94xx driver. Like the earlier REQ_TASK_ABORT patch, this patch defers the device reset to the Scsi_Host's workqueue, which has the added benefit of ensuring that the device reset does not happen at the same time that the abort tmfs are being processed. After the phy reset, the busted drive should go away and be re-detected later, which is indeed what I've seen on both a x260 and a x206m. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 1911c5d..a014418 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -343,6 +343,27 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } } +/* hard reset a phy later */ +static void do_phy_reset_later(void *data) +{ + struct sas_phy *sas_phy = data; + int error; + + ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, + sas_phy->identify.phy_identifier); + /* Reset device port */ + error = sas_phy_reset(sas_phy, 1); + if (error) + ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n", + __FUNCTION__, sas_phy->identify.phy_identifier, error); +} + +static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) +{ + INIT_WORK(&sas_phy->reset_work, do_phy_reset_later, sas_phy); + queue_work(shost->work_q, &sas_phy->reset_work); +} + /* start up the ABORT TASK tmf... */ static void task_kill_later(struct asd_ascb *ascb) { @@ -402,7 +423,9 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, goto out; } case REQ_DEVICE_RESET: { - struct asd_ascb *a, *b; + struct Scsi_Host *shost = sas_ha->core.shost; + struct sas_phy *dev_phy; + struct asd_ascb *a; u16 conn_handle; conn_handle = *((u16*)(&dl->status_block[1])); @@ -412,17 +435,31 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, dl->status_block[3]); /* Kill all pending tasks and reset the device */ - list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { - struct sas_task *task = a->uldd_task; - struct domain_device *dev = task->dev; + dev_phy = NULL; + list_for_each_entry(a, &asd_ha->seq.pend_q, list) { + struct sas_task *task; + struct domain_device *dev; u16 x; - x = *((u16*)(&dev->lldd_dev)); - if (x == conn_handle) + task = a->uldd_task; + if (!task) + continue; + dev = task->dev; + + x = (u16)dev->lldd_dev; + if (x == conn_handle) { + dev_phy = dev->port->phy; task_kill_later(a); + } } - /* FIXME: Reset device port (huh?) */ + /* Reset device port */ + if (!dev_phy) { + ASD_DPRINTK("%s: No pending commands; can't reset.\n", + __FUNCTION__); + goto out; + } + phy_reset_later(dev_phy, shost); goto out; } case SIGNAL_NCQ_ERROR: diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index a2b479a..0fb347b 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -144,7 +144,7 @@ static int sas_get_linkerrors(struct sas_phy *phy) return sas_smp_get_phy_events(phy); } -static int sas_phy_reset(struct sas_phy *phy, int hard_reset) +int sas_phy_reset(struct sas_phy *phy, int hard_reset) { int ret; enum phy_func reset_type; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index c5fd375..e064aac 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -865,3 +865,4 @@ EXPORT_SYMBOL_GPL(sas_change_queue_depth); EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); EXPORT_SYMBOL_GPL(sas_task_abort); +EXPORT_SYMBOL_GPL(sas_phy_reset); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index a1fc20a..29f6e1a 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -597,6 +597,7 @@ struct sas_domain_function_template { extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); +int sas_phy_reset(struct sas_phy *phy, int hard_reset); extern int sas_queuecommand(struct scsi_cmnd *, void (*scsi_done)(struct scsi_cmnd *)); extern int sas_target_alloc(struct scsi_target *); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 5302437..59633a82d 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -73,6 +73,8 @@ struct sas_phy { /* for the list of phys belonging to a port */ struct list_head port_siblings; + + struct work_struct reset_work; }; #define dev_to_phy(d) \ -- cgit v0.10.2 From 7b4feee973ca7be63345b92a987ef7ef879b179b Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 14 Nov 2006 18:02:07 -0800 Subject: [PATCH] aic94xx: delete ascb timers when freeing queues When the aic94xx driver creates ascbs, each ascb is initialized with a timeout timer. If there are any ascbs left over when the driver is being torn down, these timers need to be deleted. In particular, we seem to hit this case when ascbs are issued yet never end up on the done list. Right now there's a sequencer bug that results in this happening every so often. CONTROL PHY commands are typically sent when things are really messed up with the sequencer; however, any other leftover ascb should produce loud warnings. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 99743ca..3a5bbba 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -724,6 +724,15 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha) list_for_each_safe(pos, n, &pending) { struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list); + /* + * Delete unexpired ascb timers. This may happen if we issue + * a CONTROL PHY scb to an adapter and rmmod before the scb + * times out. Apparently we don't wait for the CONTROL PHY + * to complete, so it doesn't matter if we kill the timer. + */ + del_timer_sync(&ascb->timer); + WARN_ON(ascb->scb->header.opcode != CONTROL_PHY); + list_del_init(pos); ASD_DPRINTK("freeing from pending\n"); asd_ascb_free(ascb); -- cgit v0.10.2 From f26b90440cd74c78fe10c9bd5160809704a9627c Mon Sep 17 00:00:00 2001 From: David C Somayajulu Date: Wed, 15 Nov 2006 16:41:09 -0800 Subject: [PATCH] qla4xxx: bug fix: driver hardware semaphore needs to be grabbed before soft reset On qla4xxx, the driver needs to grab the drvr semaphore provided by the hardware, prior to issuing a reset. This patches takes care of a couple of places where it was not being done. In addition there is minor clean up. Signed-off-by: David Somayajulu Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 1b221ff..eeefdcb 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -8,6 +8,7 @@ #ifndef __QLA4x_GBL_H #define __QLA4x_GBL_H +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index bb3a1c1..9e81b81 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -978,7 +978,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) return status; } -static int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) { #define QL4_LOCK_DRVR_WAIT 300 #define QL4_LOCK_DRVR_SLEEP 100 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5b8db61..bab434e 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -919,18 +919,11 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, if (status == QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", ha->host_no, __func__)); - status = qla4xxx_soft_reset(ha); - } - /* FIXMEkaren: Do we want to keep interrupts enabled and process - AENs after soft reset */ - - /* If firmware (SOFT) reset failed, or if all outstanding - * commands have not returned, then do a HARD reset. - */ - if (status == QLA_ERROR) { - DEBUG2(printk("scsi%ld: %s - Performing hard reset..\n", - ha->host_no, __func__)); - status = qla4xxx_hard_reset(ha); + qla4xxx_flush_active_srbs(ha); + if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) + status = qla4xxx_soft_reset(ha); + else + status = QLA_ERROR; } /* Flush any pending ddb changed AENs */ @@ -1016,13 +1009,9 @@ static void qla4xxx_do_dpc(void *data) struct scsi_qla_host *ha = (struct scsi_qla_host *) data; struct ddb_entry *ddb_entry, *dtemp; - DEBUG2(printk("scsi%ld: %s: DPC handler waking up.\n", - ha->host_no, __func__)); - - DEBUG2(printk("scsi%ld: %s: ha->flags = 0x%08lx\n", - ha->host_no, __func__, ha->flags)); - DEBUG2(printk("scsi%ld: %s: ha->dpc_flags = 0x%08lx\n", - ha->host_no, __func__, ha->dpc_flags)); + DEBUG2(printk("scsi%ld: %s: DPC handler waking up." + "flags = 0x%08lx, dpc_flags = 0x%08lx\n", + ha->host_no, __func__, ha->flags, ha->dpc_flags)); /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) @@ -1032,16 +1021,8 @@ static void qla4xxx_do_dpc(void *data) test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { - if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) - /* - * dg 09/23 Never initialize ddb list - * once we up and running - * qla4xxx_recover_adapter(ha, - * REBUILD_DDB_LIST); - */ - qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); - - if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) + if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags)) qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { @@ -1122,7 +1103,8 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) destroy_workqueue(ha->dpc_thread); /* Issue Soft Reset to put firmware in unknown state */ - qla4xxx_soft_reset(ha); + if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) + qla4xxx_soft_reset(ha); /* Remove timer thread, if present */ if (ha->timer_active) diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index b3fe7e6..d05048b 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,9 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.00.05b9-k" - -#define QL4_DRIVER_MAJOR_VER 5 -#define QL4_DRIVER_MINOR_VER 0 -#define QL4_DRIVER_PATCH_VER 5 -#define QL4_DRIVER_BETA_VER 9 +#define QLA4XXX_DRIVER_VERSION "5.00.06-k" -- cgit v0.10.2 From b42172fc7b569a0ef2b0fa38d71382969074c0e2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Nov 2006 09:32:06 -0800 Subject: Don't call "note_interrupt()" with irq descriptor lock held This reverts commit f72fa707604c015a6625e80f269506032d5430dc, and solves the problem that it tried to fix by simply making "__do_IRQ()" call the note_interrupt() function without the lock held, the way everybody else does. It should be noted that all interrupt handling code must never allow the descriptor actors to be entered "recursively" (that's why we do all the magic IRQ_PENDING stuff in the first place), so there actually is exclusion at that much higher level, even in the absense of locking. Acked-by: Vivek Goyal Acked-by:Pavel Emelianov Cc: Andrew Morton Cc: Ingo Molnar Cc: Adrian Bunk Signed-off-by: Linus Torvalds diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 42aa6f1..a681912 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -231,10 +231,10 @@ fastcall unsigned int __do_IRQ(unsigned int irq) spin_unlock(&desc->lock); action_ret = handle_IRQ_event(irq, action); - - spin_lock(&desc->lock); if (!noirqdebug) note_interrupt(irq, desc, action_ret); + + spin_lock(&desc->lock); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 9c7e2e4..543ea2e 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -147,11 +147,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (unlikely(irqfixup)) { /* Don't punish working computers */ if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) { - int ok; - - spin_unlock(&desc->lock); - ok = misrouted_irq(irq); - spin_lock(&desc->lock); + int ok = misrouted_irq(irq); if (action_ret == IRQ_NONE) desc->irqs_unhandled -= ok; } -- cgit v0.10.2 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 diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index d1ede7d..aceece7 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 v0.10.2 From e138a5d2356729b8752e88520cc1525fae9794ac Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 22 Nov 2006 11:54:15 -0600 Subject: [SCSI] aic94xx: fix pointer to integer conversion warning Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index a014418..52c6ea4 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -446,7 +446,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, continue; dev = task->dev; - x = (u16)dev->lldd_dev; + x = (unsigned long)dev->lldd_dev; if (x == conn_handle) { dev_phy = dev->port->phy; task_kill_later(a); -- cgit v0.10.2 From d915058f48745c0d5c4582566e5aa63867264f81 Mon Sep 17 00:00:00 2001 From: David C Somayajulu Date: Wed, 15 Nov 2006 17:38:40 -0800 Subject: [SCSI] qla4xxx: add support for qla4032 This patch provides the following: 1. adds support for the next version of Qlogic's iSCSI HBA, qla4032 (PCI Device ID 4032). 2. removes dead code related to topcat chip and renames qla4010_soft_reset to qla4xxx_soft_reset (minor changes). Signed-off-by: David Somayajulu Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index 752031f..7b4e077 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c @@ -71,7 +71,7 @@ void __dump_registers(struct scsi_qla_host *ha) readw(&ha->reg->u1.isp4010.nvram)); } - else if (is_qla4022(ha)) { + else if (is_qla4022(ha) | is_qla4032(ha)) { printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", (uint8_t) offsetof(struct isp_reg, u1.isp4022.intr_mask), @@ -119,7 +119,7 @@ void __dump_registers(struct scsi_qla_host *ha) readw(&ha->reg->u2.isp4010.port_err_status)); } - else if (is_qla4022(ha)) { + else if (is_qla4022(ha) | is_qla4032(ha)) { printk(KERN_INFO "Page 0 Registers:\n"); printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", (uint8_t) offsetof(struct isp_reg, diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a7f6c7b..4249e52 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -40,7 +40,11 @@ #ifndef PCI_DEVICE_ID_QLOGIC_ISP4022 #define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022 -#endif /* */ +#endif + +#ifndef PCI_DEVICE_ID_QLOGIC_ISP4032 +#define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 +#endif #define QLA_SUCCESS 0 #define QLA_ERROR 1 @@ -277,7 +281,6 @@ struct scsi_qla_host { #define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ #define AF_LINK_UP 8 /* 0x00000100 */ -#define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */ #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ #define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ #define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ @@ -317,16 +320,17 @@ struct scsi_qla_host { /* NVRAM registers */ struct eeprom_data *nvram; spinlock_t hardware_lock ____cacheline_aligned; - spinlock_t list_lock; uint32_t eeprom_cmd_data; /* Counters for general statistics */ + uint64_t isr_count; uint64_t adapter_error_count; uint64_t device_error_count; uint64_t total_io_count; uint64_t total_mbytes_xferred; uint64_t link_failure_count; uint64_t invalid_crc_count; + uint32_t bytes_xfered; uint32_t spurious_int_count; uint32_t aborted_io_count; uint32_t io_timeout_count; @@ -438,6 +442,11 @@ static inline int is_qla4022(struct scsi_qla_host *ha) return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022; } +static inline int is_qla4032(struct scsi_qla_host *ha) +{ + return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; +} + static inline int adapter_up(struct scsi_qla_host *ha) { return (test_bit(AF_ONLINE, &ha->flags) != 0) && @@ -451,58 +460,58 @@ static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost) static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u1.isp4022.semaphore : - &ha->reg->u1.isp4010.nvram); + return (is_qla4010(ha) ? + &ha->reg->u1.isp4010.nvram : + &ha->reg->u1.isp4022.semaphore); } static inline void __iomem* isp_nvram(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u1.isp4022.nvram : - &ha->reg->u1.isp4010.nvram); + return (is_qla4010(ha) ? + &ha->reg->u1.isp4010.nvram : + &ha->reg->u1.isp4022.nvram); } static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.ext_hw_conf : - &ha->reg->u2.isp4010.ext_hw_conf); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.ext_hw_conf : + &ha->reg->u2.isp4022.p0.ext_hw_conf); } static inline void __iomem* isp_port_status(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_status : - &ha->reg->u2.isp4010.port_status); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_status : + &ha->reg->u2.isp4022.p0.port_status); } static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_ctrl : - &ha->reg->u2.isp4010.port_ctrl); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_ctrl : + &ha->reg->u2.isp4022.p0.port_ctrl); } static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_err_status : - &ha->reg->u2.isp4010.port_err_status); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_err_status : + &ha->reg->u2.isp4022.p0.port_err_status); } static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.gp_out : - &ha->reg->u2.isp4010.gp_out); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.gp_out : + &ha->reg->u2.isp4022.p0.gp_out); } static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2 : - offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2); + return (is_qla4010(ha) ? + offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2 : + offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2); } int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); @@ -511,59 +520,59 @@ int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); static inline int ql4xxx_lock_flash(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, + QL4010_FLASH_SEM_BITS); + else return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 13); - else - return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, - QL4010_FLASH_SEM_BITS); } static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); } static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, + QL4010_NVRAM_SEM_BITS); + else return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 10); - else - return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, - QL4010_NVRAM_SEM_BITS); } static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); } static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, + QL4010_DRVR_SEM_BITS); + else return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 1); - else - return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, - QL4010_DRVR_SEM_BITS); } static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); } /*---------------------------------------------------------------------------*/ diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 427489d..4eea8c5 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -296,7 +296,6 @@ static inline uint32_t clr_rmask(uint32_t val) /* ISP Semaphore definitions */ /* ISP General Purpose Output definitions */ -#define GPOR_TOPCAT_RESET 0x00000004 /* shadow registers (DMA'd from HA to system memory. read only) */ struct shadow_regs { @@ -339,10 +338,13 @@ union external_hw_config_reg { /* Mailbox command definitions */ #define MBOX_CMD_ABOUT_FW 0x0009 #define MBOX_CMD_LUN_RESET 0x0016 +#define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E #define MBOX_CMD_GET_FW_STATUS 0x001F #define MBOX_CMD_SET_ISNS_SERVICE 0x0021 #define ISNS_DISABLE 0 #define ISNS_ENABLE 1 +#define MBOX_CMD_COPY_FLASH 0x0024 +#define MBOX_CMD_WRITE_FLASH 0x0025 #define MBOX_CMD_READ_FLASH 0x0026 #define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031 #define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056 @@ -360,10 +362,13 @@ union external_hw_config_reg { #define DDB_DS_SESSION_FAILED 0x06 #define DDB_DS_LOGIN_IN_PROCESS 0x07 #define MBOX_CMD_GET_FW_STATE 0x0069 +#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A +#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 /* Mailbox 1 */ #define FW_STATE_READY 0x0000 #define FW_STATE_CONFIG_WAIT 0x0001 +#define FW_STATE_WAIT_LOGIN 0x0002 #define FW_STATE_ERROR 0x0004 #define FW_STATE_DHCP_IN_PROGRESS 0x0008 diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index eeefdcb..2122967 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -76,4 +76,4 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; extern int ql4xdontresethba; -#endif /* _QLA4x_GBL_H */ +#endif /* _QLA4x_GBL_H */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 9e81b81..cc210f2 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -259,10 +259,16 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) "seconds expired= %d\n", ha->host_no, __func__, ha->firmware_state, ha->addl_fw_state, timeout_count)); + if (is_qla4032(ha) && + !(ha->addl_fw_state & FW_ADDSTATE_LINK_UP) && + (timeout_count < ADAPTER_INIT_TOV - 5)) { + break; + } + msleep(1000); } /* end of for */ - if (timeout_count <= 0) + if (timeout_count == 0) DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", ha->host_no, __func__)); @@ -806,32 +812,6 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha, return QLA_SUCCESS; } -/** - * qla4010_get_topcat_presence - check if it is QLA4040 TopCat Chip - * @ha: Pointer to host adapter structure. - * - **/ -static int qla4010_get_topcat_presence(struct scsi_qla_host *ha) -{ - unsigned long flags; - uint16_t topcat; - - if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) - return QLA_ERROR; - spin_lock_irqsave(&ha->hardware_lock, flags); - topcat = rd_nvram_word(ha, offsetof(struct eeprom_data, - isp4010.topcat)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if ((topcat & TOPCAT_MASK) == TOPCAT_PRESENT) - set_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); - else - clear_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); - ql4xxx_unlock_nvram(ha); - return QLA_SUCCESS; -} - - static int qla4xxx_config_nvram(struct scsi_qla_host *ha) { unsigned long flags; @@ -866,7 +846,7 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) /* set defaults */ if (is_qla4010(ha)) extHwConfig.Asuint32_t = 0x1912; - else if (is_qla4022(ha)) + else if (is_qla4022(ha) | is_qla4032(ha)) extHwConfig.Asuint32_t = 0x0023; } DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n", @@ -927,7 +907,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) spin_lock_irqsave(&ha->hardware_lock, flags); writel(jiffies, &ha->reg->mailbox[7]); - if (is_qla4022(ha)) + if (is_qla4022(ha) | is_qla4032(ha)) writel(set_rmask(NVR_WRITE_ENABLE), &ha->reg->u1.isp4022.nvram); @@ -1018,12 +998,7 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) int soft_reset = 1; int config_chip = 0; - if (is_qla4010(ha)){ - if (qla4010_get_topcat_presence(ha) != QLA_SUCCESS) - return QLA_ERROR; - } - - if (is_qla4022(ha)) + if (is_qla4022(ha) | is_qla4032(ha)) ql4xxx_set_mac_number(ha); if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 0d61797..6375eb0 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h @@ -38,7 +38,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index) static inline void __qla4xxx_enable_intrs(struct scsi_qla_host *ha) { - if (is_qla4022(ha)) { + if (is_qla4022(ha) | is_qla4032(ha)) { writel(set_rmask(IMR_SCSI_INTR_ENABLE), &ha->reg->u1.isp4022.intr_mask); readl(&ha->reg->u1.isp4022.intr_mask); @@ -52,7 +52,7 @@ __qla4xxx_enable_intrs(struct scsi_qla_host *ha) static inline void __qla4xxx_disable_intrs(struct scsi_qla_host *ha) { - if (is_qla4022(ha)) { + if (is_qla4022(ha) | is_qla4032(ha)) { writel(clr_rmask(IMR_SCSI_INTR_ENABLE), &ha->reg->u1.isp4022.intr_mask); readl(&ha->reg->u1.isp4022.intr_mask); diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index c0a254b..d41ce38 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -294,6 +294,12 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) cmd_entry->control_flags = CF_WRITE; else if (cmd->sc_data_direction == DMA_FROM_DEVICE) cmd_entry->control_flags = CF_READ; + + ha->bytes_xfered += cmd->request_bufflen; + if (ha->bytes_xfered & ~0xFFFFF){ + ha->total_mbytes_xferred += ha->bytes_xfered >> 20; + ha->bytes_xfered &= 0xFFFFF; + } } /* Set tagged queueing control flags */ diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 1e28332..ef975e0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -627,6 +627,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); + ha->isr_count++; /* * Repeatedly service interrupts up to a maximum of * MAX_REQS_SERVICED_PER_INTR diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index e3957ca..fc50203 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c @@ -9,13 +9,13 @@ static inline int eeprom_size(struct scsi_qla_host *ha) { - return is_qla4022(ha) ? FM93C86A_SIZE_16 : FM93C66A_SIZE_16; + return is_qla4010(ha) ? FM93C66A_SIZE_16 : FM93C86A_SIZE_16; } static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha) { - return is_qla4022(ha) ? FM93C86A_NO_ADDR_BITS_16 : - FM93C56A_NO_ADDR_BITS_16; + return is_qla4010(ha) ? FM93C56A_NO_ADDR_BITS_16 : + FM93C86A_NO_ADDR_BITS_16 ; } static inline int eeprom_no_data_bits(struct scsi_qla_host *ha) diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index 08e2aed..b47b4fc 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h @@ -134,9 +134,7 @@ struct eeprom_data { u16 phyConfig; /* x36 */ #define PHY_CONFIG_PHY_ADDR_MASK 0x1f #define PHY_CONFIG_ENABLE_FW_MANAGEMENT_MASK 0x20 - u16 topcat; /* x38 */ -#define TOPCAT_PRESENT 0x0100 -#define TOPCAT_MASK 0xFF00 + u16 reserved_56; /* x38 */ #define EEPROM_UNUSED_1_SIZE 2 u8 unused_1[EEPROM_UNUSED_1_SIZE]; /* x3A */ diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index bab434e..db9d88e 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -708,10 +708,10 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) } /** - * qla4010_soft_reset - performs soft reset. + * qla4xxx_soft_reset - performs soft reset. * @ha: Pointer to host adapter structure. **/ -static int qla4010_soft_reset(struct scsi_qla_host *ha) +int qla4xxx_soft_reset(struct scsi_qla_host *ha) { uint32_t max_wait_time; unsigned long flags = 0; @@ -817,29 +817,6 @@ static int qla4010_soft_reset(struct scsi_qla_host *ha) } /** - * qla4xxx_topcat_reset - performs hard reset of TopCat Chip. - * @ha: Pointer to host adapter structure. - **/ -static int qla4xxx_topcat_reset(struct scsi_qla_host *ha) -{ - unsigned long flags; - - ql4xxx_lock_nvram(ha); - spin_lock_irqsave(&ha->hardware_lock, flags); - writel(set_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); - readl(isp_gp_out(ha)); - mdelay(1); - - writel(clr_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); - readl(isp_gp_out(ha)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - mdelay(2523); - - ql4xxx_unlock_nvram(ha); - return QLA_SUCCESS; -} - -/** * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. * @ha: Pointer to host adapter structure. * @@ -867,26 +844,6 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) } /** - * qla4xxx_hard_reset - performs HBA Hard Reset - * @ha: Pointer to host adapter structure. - **/ -static int qla4xxx_hard_reset(struct scsi_qla_host *ha) -{ - /* The QLA4010 really doesn't have an equivalent to a hard reset */ - qla4xxx_flush_active_srbs(ha); - if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { - int status = QLA_ERROR; - - if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && - (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && - (qla4010_soft_reset(ha) == QLA_SUCCESS)) - status = QLA_SUCCESS; - return status; - } else - return qla4010_soft_reset(ha); -} - -/** * qla4xxx_recover_adapter - recovers adapter after a fatal error * @ha: Pointer to host adapter structure. * @renew_ddb_list: Indicates what to do with the adapter's ddb list @@ -1243,7 +1200,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, init_waitqueue_head(&ha->mailbox_wait_queue); spin_lock_init(&ha->hardware_lock); - spin_lock_init(&ha->list_lock); /* Allocate dma buffers */ if (qla4xxx_mem_alloc(ha)) { @@ -1450,27 +1406,6 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t in } /** - * qla4xxx_soft_reset - performs a SOFT RESET of hba. - * @ha: Pointer to host adapter structure. - **/ -int qla4xxx_soft_reset(struct scsi_qla_host *ha) -{ - - DEBUG2(printk(KERN_WARNING "scsi%ld: %s: chip reset!\n", ha->host_no, - __func__)); - if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { - int status = QLA_ERROR; - - if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && - (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && - (qla4010_soft_reset(ha) == QLA_SUCCESS) ) - status = QLA_SUCCESS; - return status; - } else - return qla4010_soft_reset(ha); -} - -/** * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware * @ha: actual ha whose done queue will contain the comd returned by firmware. * @cmd: Scsi Command to wait on. @@ -1668,6 +1603,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + { + .vendor = PCI_VENDOR_ID_QLOGIC, + .device = PCI_DEVICE_ID_QLOGIC_ISP4032, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, {0, 0}, }; MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index d05048b..454e19c 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.00.06-k" +#define QLA4XXX_DRIVER_VERSION "5.00.07-k" -- cgit v0.10.2 From b448de473139e40a9ecc4e34946ffec5a65807ec Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:23:49 +0100 Subject: [SCSI] megaraid_sas: make 2 functions static This patch makes two needlessly global functions static. Signed-off-by: Adrian Bunk Acked-by: "Patro, Sumant" Signed-off-by: James Bottomley diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 7e4262f..046223b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -517,7 +517,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, * Returns the number of frames required for numnber of sge's (sge_count) */ -u32 megasas_get_frame_count(u8 sge_count) +static u32 megasas_get_frame_count(u8 sge_count) { int num_cnt; int sge_bytes; @@ -1733,7 +1733,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance, * * Tasklet to complete cmds */ -void megasas_complete_cmd_dpc(unsigned long instance_addr) +static void megasas_complete_cmd_dpc(unsigned long instance_addr) { u32 producer; u32 consumer; -- cgit v0.10.2 From 7feb6b3fbb48ceaceb7a66a9784106abef48e454 Mon Sep 17 00:00:00 2001 From: David C Somayajulu Date: Mon, 20 Nov 2006 16:20:22 -0800 Subject: [SCSI] qla4xxx: fix for timing issue for nvram accesses. This patch fixes a timing issue related to nvram accesses in qla4xxx driver for some cpu/slot speed combination. Signed-off-by: David Somayajulu Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index fc50203..58afd13 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c @@ -7,6 +7,13 @@ #include "ql4_def.h" +static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha) +{ + writel(cmd, isp_nvram(ha)); + readl(isp_nvram(ha)); + udelay(1); +} + static inline int eeprom_size(struct scsi_qla_host *ha) { return is_qla4010(ha) ? FM93C66A_SIZE_16 : FM93C86A_SIZE_16; @@ -28,8 +35,7 @@ static int fm93c56a_select(struct scsi_qla_host * ha) DEBUG5(printk(KERN_ERR "fm93c56a_select:\n")); ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000; - writel(ha->eeprom_cmd_data, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data, ha); return 1; } @@ -41,12 +47,13 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) int previousBit; /* Clock in a zero, then do the start bit. */ - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, ha); + + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | + AUBURN_EEPROM_CLK_FALL, ha); + mask = 1 << (FM93C56A_CMD_BITS - 1); /* Force the previous data bit to be different. */ @@ -60,14 +67,14 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) * If the bit changed, then change the DO state to * match. */ - writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); previousBit = dataBit; } - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_FALL, ha); + cmd = cmd << 1; } mask = 1 << (eeprom_no_addr_bits(ha) - 1); @@ -82,14 +89,15 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) * If the bit changed, then change the DO state to * match. */ - writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); + previousBit = dataBit; } - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_FALL, ha); + addr = addr << 1; } return 1; @@ -98,8 +106,7 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) static int fm93c56a_deselect(struct scsi_qla_host * ha) { ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000; - writel(ha->eeprom_cmd_data, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data, ha); return 1; } @@ -112,12 +119,13 @@ static int fm93c56a_datain(struct scsi_qla_host * ha, unsigned short *value) /* Read the data bits * The first bit is a dummy. Clock right over it. */ for (i = 0; i < eeprom_no_data_bits(ha); i++) { - writel(ha->eeprom_cmd_data | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - dataBit = - (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; + eeprom_cmd(ha->eeprom_cmd_data | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | + AUBURN_EEPROM_CLK_FALL, ha); + + dataBit = (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; + data = (data << 1) | dataBit; } -- cgit v0.10.2 From 73d98ff0fa8d9074792b7273f57d9f92810104c6 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:27:58 -0600 Subject: [SCSI] ipr: SATA reset - wait for host reset completion If an ipr adapter hits a fatal microcode error requiring a reset while a SATA device is going through EH, it can result in a command getting issued to the ipr adapter while it is getting reset, which can cause PCI bus errors. Wait for any outstanding adapter reset to finish prior to issuing a SATA device reset. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2dde821..c983f0f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3573,6 +3573,12 @@ static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes) ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + while(ioa_cfg->in_reset_reload) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + } + res = sata_port->res; if (res) { rc = ipr_device_reset(ioa_cfg, res); @@ -4776,6 +4782,12 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc) unsigned long flags; spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + while(ioa_cfg->in_reset_reload) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + } + list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { if (ipr_cmd->qc == qc) { ipr_device_reset(ioa_cfg, sata_port->res); -- cgit v0.10.2 From 04d9768ff8847b0ae8c41ac3cfb3c5bb2e31699a Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:04 -0600 Subject: [SCSI] ipr: Stop issuing cancel all to disk arrays The ipr disk array devices do not support a cancel all requests primitive, so change the ipr driver to never send it. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index c983f0f..244173a 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3776,7 +3776,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) */ if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) return FAILED; - if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res))) + if (!res || !ipr_is_gscsi(res)) return FAILED; list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { -- cgit v0.10.2 From 60e7486b190998745b548599c843f090d5624ae3 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:10 -0600 Subject: [SCSI] ipr: PCI IDs for new SAS adapters Adds PCI IDs for some new ipr SAS adapters. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 244173a..f1e01b6 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -98,7 +98,7 @@ static DEFINE_SPINLOCK(ipr_driver_lock); /* This table describes the differences between DMA controller chips */ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { - { /* Gemstone, Citrine, and Obsidian */ + { /* Gemstone, Citrine, Obsidian, and Obsidian-E */ .mailbox = 0x0042C, .cache_line_size = 0x20, { @@ -135,6 +135,7 @@ static const struct ipr_chip_t ipr_chip[] = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } }; @@ -7363,12 +7364,24 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, @@ -7378,6 +7391,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 6d03528..7566925 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -54,6 +54,8 @@ */ #define IPR_NUM_BASE_CMD_BLKS 100 +#define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339 + #define IPR_SUBS_DEV_ID_2780 0x0264 #define IPR_SUBS_DEV_ID_5702 0x0266 #define IPR_SUBS_DEV_ID_5703 0x0278 @@ -66,7 +68,11 @@ #define IPR_SUBS_DEV_ID_571F 0x02D5 #define IPR_SUBS_DEV_ID_572A 0x02C1 #define IPR_SUBS_DEV_ID_572B 0x02C2 +#define IPR_SUBS_DEV_ID_572F 0x02C3 #define IPR_SUBS_DEV_ID_575B 0x030D +#define IPR_SUBS_DEV_ID_575C 0x0338 +#define IPR_SUBS_DEV_ID_57B7 0x0360 +#define IPR_SUBS_DEV_ID_57B8 0x02C2 #define IPR_NAME "ipr" -- cgit v0.10.2 From efbbdd846d41221396c094ff6df35246bdcf889e Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:16 -0600 Subject: [SCSI] ipr: Set default ipr Kconfig values Both SCSI_IPR_TRACE and SCSI_IPR_DUMP should be defaulted to yes when SCSI_IPR is enabled. Signed-off-by: Brian King Signed-off-by: James Bottomley diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 9540eb8..5881464 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1026,6 +1026,7 @@ config SCSI_IPR config SCSI_IPR_TRACE bool "enable driver internal trace" depends on SCSI_IPR + default y help If you say Y here, the driver will trace all commands issued to the adapter. Performance impact is minimal. Trace can be @@ -1034,6 +1035,7 @@ config SCSI_IPR_TRACE config SCSI_IPR_DUMP bool "enable adapter dump support" depends on SCSI_IPR + default y help If you say Y here, the driver will support adapter crash dump. If you enable this support, the iprdump daemon can be used -- cgit v0.10.2 From 7402ecef94f416dcf03af7435c404a4079683d96 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:23 -0600 Subject: [SCSI] ipr: Remove ipr_scsi_timed_out Remove ipr's usage of the scsi transport eh_timed_out for handling SATA timeouts. This was only needed in order to set some flags on the qc prior to calling ata_do_eh. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f1e01b6..e32c3f8 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -79,7 +79,6 @@ #include #include #include -#include #include "ipr.h" /* @@ -3643,6 +3642,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { if (ipr_cmd->scsi_cmd) ipr_cmd->done = ipr_scsi_eh_done; + if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { + ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; + ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; + } } } @@ -4655,40 +4658,6 @@ static const char * ipr_ioa_info(struct Scsi_Host *host) return buffer; } -/** - * ipr_scsi_timed_out - Handle scsi command timeout - * @scsi_cmd: scsi command struct - * - * Return value: - * EH_NOT_HANDLED - **/ -enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg; - struct ipr_cmnd *ipr_cmd; - unsigned long flags; - - ENTER; - spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); - ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata; - - list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { - if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) { - ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; - ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; - break; - } - } - - spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); - LEAVE; - return EH_NOT_HANDLED; -} - -static struct scsi_transport_template ipr_transport_template = { - .eh_timed_out = ipr_scsi_timed_out -}; - static struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "IPR", @@ -7030,7 +6999,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); - host->transportt = &ipr_transport_template; ata_host_init(&ioa_cfg->ata_host, &pdev->dev, sata_port_info.flags, &ipr_sata_ops); -- cgit v0.10.2 From 9d66bdf81f97673b6e330a26438fcaea38c26cd5 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:29 -0600 Subject: [SCSI] ipr: Remove debug trace points from dump code Remove some debug trace points that clutter up the log when ipr debugging is turned on. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e32c3f8..e53cfbd 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2969,7 +2969,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) struct ipr_dump *dump; unsigned long lock_flags = 0; - ENTER; dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); if (!dump) { @@ -2996,7 +2995,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - LEAVE; return 0; } -- cgit v0.10.2 From 49dc6a18185c12bae4980d17512fbe54ca6bae54 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:35 -0600 Subject: [SCSI] ipr: Add support for logging SAS fabric errors Adds support for logging SAS fabric errors logged by the ipr firmware. Signed-off-by: Brian King Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e53cfbd..94345e7 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1321,6 +1321,219 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, offsetof(struct ipr_hostrcb_type_07_error, data))); } +static const struct { + u8 active; + char *desc; +} path_active_desc[] = { + { IPR_PATH_NO_INFO, "Path" }, + { IPR_PATH_ACTIVE, "Active path" }, + { IPR_PATH_NOT_ACTIVE, "Inactive path" } +}; + +static const struct { + u8 state; + char *desc; +} path_state_desc[] = { + { IPR_PATH_STATE_NO_INFO, "has no path state information available" }, + { IPR_PATH_HEALTHY, "is healthy" }, + { IPR_PATH_DEGRADED, "is degraded" }, + { IPR_PATH_FAILED, "is failed" } +}; + +/** + * ipr_log_fabric_path - Log a fabric path error + * @hostrcb: hostrcb struct + * @fabric: fabric descriptor + * + * Return value: + * none + **/ +static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, + struct ipr_hostrcb_fabric_desc *fabric) +{ + int i, j; + u8 path_state = fabric->path_state; + u8 active = path_state & IPR_PATH_ACTIVE_MASK; + u8 state = path_state & IPR_PATH_STATE_MASK; + + for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { + if (path_active_desc[i].active != active) + continue; + + for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { + if (path_state_desc[j].state != state) + continue; + + if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port); + } else if (fabric->cascaded_expander == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->phy); + } else if (fabric->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->cascaded_expander); + } else { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->cascaded_expander, fabric->phy); + } + return; + } + } + + ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state, + fabric->ioa_port, fabric->cascaded_expander, fabric->phy); +} + +static const struct { + u8 type; + char *desc; +} path_type_desc[] = { + { IPR_PATH_CFG_IOA_PORT, "IOA port" }, + { IPR_PATH_CFG_EXP_PORT, "Expander port" }, + { IPR_PATH_CFG_DEVICE_PORT, "Device port" }, + { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" } +}; + +static const struct { + u8 status; + char *desc; +} path_status_desc[] = { + { IPR_PATH_CFG_NO_PROB, "Functional" }, + { IPR_PATH_CFG_DEGRADED, "Degraded" }, + { IPR_PATH_CFG_FAILED, "Failed" }, + { IPR_PATH_CFG_SUSPECT, "Suspect" }, + { IPR_PATH_NOT_DETECTED, "Missing" }, + { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" } +}; + +static const char *link_rate[] = { + "unknown", + "disabled", + "phy reset problem", + "spinup hold", + "port selector", + "unknown", + "unknown", + "unknown", + "1.5Gbps", + "3.0Gbps", + "unknown", + "unknown", + "unknown", + "unknown", + "unknown", + "unknown" +}; + +/** + * ipr_log_path_elem - Log a fabric path element. + * @hostrcb: hostrcb struct + * @cfg: fabric path element struct + * + * Return value: + * none + **/ +static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, + struct ipr_hostrcb_config_element *cfg) +{ + int i, j; + u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; + u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; + + if (type == IPR_PATH_CFG_NOT_EXIST) + return; + + for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { + if (path_type_desc[i].type != type) + continue; + + for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { + if (path_status_desc[j].status != status) + continue; + + if (type == IPR_PATH_CFG_IOA_PORT) { + ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n", + path_status_desc[j].desc, path_type_desc[i].desc, + cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else { + if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n", + path_status_desc[j].desc, path_type_desc[i].desc, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else if (cfg->cascaded_expander == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else if (cfg->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->cascaded_expander, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else { + ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } + } + return; + } + } + + ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s " + "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); +} + +/** + * ipr_log_fabric_error - Log a fabric error. + * @ioa_cfg: ioa config struct + * @hostrcb: hostrcb struct + * + * Return value: + * none + **/ +static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, + struct ipr_hostrcb *hostrcb) +{ + struct ipr_hostrcb_type_20_error *error; + struct ipr_hostrcb_fabric_desc *fabric; + struct ipr_hostrcb_config_element *cfg; + int i, add_len; + + error = &hostrcb->hcam.u.error.u.type_20_error; + error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; + ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); + + add_len = be32_to_cpu(hostrcb->hcam.length) - + (offsetof(struct ipr_hostrcb_error, u) + + offsetof(struct ipr_hostrcb_type_20_error, desc)); + + for (i = 0, fabric = error->desc; i < error->num_entries; i++) { + ipr_log_fabric_path(hostrcb, fabric); + for_each_fabric_cfg(fabric, cfg) + ipr_log_path_elem(hostrcb, cfg); + + add_len -= be16_to_cpu(fabric->length); + fabric = (struct ipr_hostrcb_fabric_desc *) + ((unsigned long)fabric + be16_to_cpu(fabric->length)); + } + + ipr_log_hex_data((u32 *)fabric, add_len); +} + /** * ipr_log_generic_error - Log an adapter error. * @ioa_cfg: ioa config struct @@ -1394,13 +1607,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, if (!ipr_error_table[error_index].log_hcam) return; - if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { - ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, - "%s\n", ipr_error_table[error_index].error); - } else { - dev_err(&ioa_cfg->pdev->dev, "%s\n", - ipr_error_table[error_index].error); - } + ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error); /* Set indication we have logged an error */ ioa_cfg->errors_logged++; @@ -1437,6 +1644,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, case IPR_HOST_RCB_OVERLAY_ID_17: ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); break; + case IPR_HOST_RCB_OVERLAY_ID_20: + ipr_log_fabric_error(ioa_cfg, hostrcb); + break; case IPR_HOST_RCB_OVERLAY_ID_1: case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: default: @@ -6812,6 +7022,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) ioa_cfg->hostrcb[i]->hostrcb_dma = ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); + ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg; list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 7566925..44b15e4 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -737,6 +737,64 @@ struct ipr_hostrcb_type_17_error { u32 data[476]; }__attribute__((packed, aligned (4))); +struct ipr_hostrcb_config_element { + u8 type_status; +#define IPR_PATH_CFG_TYPE_MASK 0xF0 +#define IPR_PATH_CFG_NOT_EXIST 0x00 +#define IPR_PATH_CFG_IOA_PORT 0x10 +#define IPR_PATH_CFG_EXP_PORT 0x20 +#define IPR_PATH_CFG_DEVICE_PORT 0x30 +#define IPR_PATH_CFG_DEVICE_LUN 0x40 + +#define IPR_PATH_CFG_STATUS_MASK 0x0F +#define IPR_PATH_CFG_NO_PROB 0x00 +#define IPR_PATH_CFG_DEGRADED 0x01 +#define IPR_PATH_CFG_FAILED 0x02 +#define IPR_PATH_CFG_SUSPECT 0x03 +#define IPR_PATH_NOT_DETECTED 0x04 +#define IPR_PATH_INCORRECT_CONN 0x05 + + u8 cascaded_expander; + u8 phy; + u8 link_rate; +#define IPR_PHY_LINK_RATE_MASK 0x0F + + __be32 wwid[2]; +}__attribute__((packed, aligned (4))); + +struct ipr_hostrcb_fabric_desc { + __be16 length; + u8 ioa_port; + u8 cascaded_expander; + u8 phy; + u8 path_state; +#define IPR_PATH_ACTIVE_MASK 0xC0 +#define IPR_PATH_NO_INFO 0x00 +#define IPR_PATH_ACTIVE 0x40 +#define IPR_PATH_NOT_ACTIVE 0x80 + +#define IPR_PATH_STATE_MASK 0x0F +#define IPR_PATH_STATE_NO_INFO 0x00 +#define IPR_PATH_HEALTHY 0x01 +#define IPR_PATH_DEGRADED 0x02 +#define IPR_PATH_FAILED 0x03 + + __be16 num_entries; + struct ipr_hostrcb_config_element elem[1]; +}__attribute__((packed, aligned (4))); + +#define for_each_fabric_cfg(fabric, cfg) \ + for (cfg = (fabric)->elem; \ + cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \ + cfg++) + +struct ipr_hostrcb_type_20_error { + u8 failure_reason[64]; + u8 reserved[3]; + u8 num_entries; + struct ipr_hostrcb_fabric_desc desc[1]; +}__attribute__((packed, aligned (4))); + struct ipr_hostrcb_error { __be32 failing_dev_ioasc; struct ipr_res_addr failing_dev_res_addr; @@ -753,6 +811,7 @@ struct ipr_hostrcb_error { struct ipr_hostrcb_type_13_error type_13_error; struct ipr_hostrcb_type_14_error type_14_error; struct ipr_hostrcb_type_17_error type_17_error; + struct ipr_hostrcb_type_20_error type_20_error; } u; }__attribute__((packed, aligned (4))); @@ -792,6 +851,7 @@ struct ipr_hcam { #define IPR_HOST_RCB_OVERLAY_ID_14 0x14 #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 +#define IPR_HOST_RCB_OVERLAY_ID_20 0x20 #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF u8 reserved1[3]; @@ -811,6 +871,7 @@ struct ipr_hostrcb { struct ipr_hcam hcam; dma_addr_t hostrcb_dma; struct list_head queue; + struct ipr_ioa_cfg *ioa_cfg; }; /* IPR smart dump table structures */ @@ -1289,6 +1350,17 @@ struct ipr_ucode_image_header { } \ } +#define ipr_hcam_err(hostrcb, fmt, ...) \ +{ \ + if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \ + ipr_ra_err((hostrcb)->ioa_cfg, \ + (hostrcb)->hcam.u.error.failing_dev_res_addr, \ + fmt, ##__VA_ARGS__); \ + } else { \ + dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \ + } \ +} + #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ __FILE__, __FUNCTION__, __LINE__) -- cgit v0.10.2 From ac719abab0fbe2b83dc99351f6605645aef814ab Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:42 -0600 Subject: [SCSI] ipr: Reduce default error log size Since the default error log size has increased on SAS adapters, prevent ipr from logging this additional data unless requested to do so by the user set log level in order to prevent flooding the logs. Signed-off-by: Brian King Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 94345e7..3c32e08 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1249,19 +1249,23 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_log_hex_data - Log additional hex IOA error data. + * @ioa_cfg: ioa config struct * @data: IOA error data * @len: data length * * Return value: * none **/ -static void ipr_log_hex_data(u32 *data, int len) +static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len) { int i; if (len == 0) return; + if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL) + len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP); + for (i = 0; i < len / 4; i += 4) { ipr_err("%08X: %08X %08X %08X %08X\n", i*4, be32_to_cpu(data[i]), @@ -1290,7 +1294,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err("%s\n", error->failure_reason); ipr_err("Remote Adapter VPD:\n"); ipr_log_ext_vpd(&error->vpd); - ipr_log_hex_data(error->data, + ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_17_error, data))); @@ -1315,7 +1319,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err("%s\n", error->failure_reason); ipr_err("Remote Adapter VPD:\n"); ipr_log_vpd(&error->vpd); - ipr_log_hex_data(error->data, + ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_07_error, data))); @@ -1531,7 +1535,7 @@ static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, ((unsigned long)fabric + be16_to_cpu(fabric->length)); } - ipr_log_hex_data((u32 *)fabric, add_len); + ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); } /** @@ -1545,7 +1549,7 @@ static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb) { - ipr_log_hex_data(hostrcb->hcam.u.raw.data, + ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data, be32_to_cpu(hostrcb->hcam.length)); } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 44b15e4..397e502 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -104,6 +104,7 @@ #define IPR_IOASC_IOA_WAS_RESET 0x10000001 #define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002 +#define IPR_DEFAULT_MAX_ERROR_DUMP 984 #define IPR_NUM_LOG_HCAMS 2 #define IPR_NUM_CFG_CHG_HCAMS 2 #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) -- cgit v0.10.2 From bd705f2d43d34c0309dfa48117bed7167024247b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 21 Nov 2006 10:28:48 -0600 Subject: [SCSI] ipr: Make ipr_ioctl static This patch makes ipr_ioctl static. Signed-off-by: Adrian Bunk Signed-off-by: Brian King Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 3c32e08..2d83fbb 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4837,7 +4837,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, * Return value: * 0 on success / other on failure **/ -int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { struct ipr_resource_entry *res; -- cgit v0.10.2 From 51d23da95c3b71ce70587af8fc8244a05722c191 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 21 Nov 2006 10:28:55 -0600 Subject: [SCSI] ipr: Driver version 2.3.0 Bump driver version. Signed-off-by: James Bottomley diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 397e502..9f62a1d 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.2.0" -#define IPR_DRIVER_DATE "(September 25, 2006)" +#define IPR_DRIVER_VERSION "2.3.0" +#define IPR_DRIVER_DATE "(November 8, 2006)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding -- cgit v0.10.2 From 33524b70e8f3dd55a4ba78ad81742c7814e7b0ed Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 21 Nov 2006 10:40:08 -0800 Subject: [SCSI] aacraid: Detect Blinkled at startup Received from Mark Salyzyn: Blinkled at startup is useful for catching Adapters in a lot of pain, in a BlinkLED assert, quickly; rather than waiting several minutes for commands to timeout. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 19e42ac..0fd462a 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -518,6 +518,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, */ unsigned long count = 36000000L; /* 3 minutes */ while (down_trylock(&fibptr->event_wait)) { + int blink; if (--count == 0) { spin_lock_irqsave(q->lock, qflags); q->numpending--; @@ -530,6 +531,14 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } return -ETIMEDOUT; } + if ((blink = aac_adapter_check_health(dev)) > 0) { + if (wait == -1) { + printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n" + "Usually a result of a serious unrecoverable hardware problem\n", + blink); + } + return -EFAULT; + } udelay(5); } } else if (down_interruptible(&fibptr->event_wait)) { -- cgit v0.10.2 From d18b448fc2caf0d719bd4bd34fb1856be89c8ef7 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 21 Nov 2006 10:40:31 -0800 Subject: [SCSI] aacraid: Abort management FIBs Received from Mark Salyzyn: Add code to abort outstanding management ioctl fibs when the blinkLED recovery is performed. This code is 'clunky' and does not have any real feedback in that the reset could progress before the user application has gotten it's notification of command completion. We put a schedule() call to delay just the right amount for most cases, because we tried a spin and still managed to find cases where we would spin forever waiting for the management application to acknowledge the impending doom surrounding the cause of the BlinkLED. Will cause an oops in the context of the management application if we proceed too quickly. I view this as the lesser of many evils since currently if there are outstanding management ioctls during a need to reset/recover the adapter, the management application just locks up and waits forever. The best practices fix for this problem not going to be simple or easy (at least the fixes I imagine today); and we found a balance between the needs of the driver to proceed, and the applications that locked or confused that would hold back the driver. I just do not like the idea of a kernel oops in an application to deal with low priority, sluggish or misbehaving applications. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 0fd462a..4893a6d 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1102,6 +1102,20 @@ static int _aac_reset_adapter(struct aac_dev *aac) goto out; } + /* + * Loop through the fibs, close the synchronous FIBS + */ + for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { + struct fib *fib = &aac->fibs[index]; + if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && + (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) { + unsigned long flagv; + spin_lock_irqsave(&fib->event_lock, flagv); + up(&fib->event_wait); + spin_unlock_irqrestore(&fib->event_lock, flagv); + schedule(); + } + } index = aac->cardtype; /* -- cgit v0.10.2 From 902762831c0068ba0c8c8fca801e505a9881aa01 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 21 Nov 2006 10:40:50 -0800 Subject: [SCSI] aacraid: Driver version update Received from Mark Salyzyn: Version patch, update to reflect a rough estimate of the Adaptec build (2423) that coincides with the sources on kernel.org. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index eb3ed91..4f8b4c5 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -11,8 +11,8 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2409 -# define AAC_DRIVER_BRANCH "-mh2" +# define AAC_DRIVER_BUILD 2423 +# define AAC_DRIVER_BRANCH "-mh3" #endif #define MAXIMUM_NUM_CONTAINERS 32 -- cgit v0.10.2 From 21db1882f79a1ad5977cae6766376a63f60ec414 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 22 Nov 2006 13:24:52 -0700 Subject: [SCSI] Add Kconfig option for asynchronous SCSI scanning Without this patch, the user has to add a kernel command line parameter to get asynchronous SCSI scanning. Now they can select the default at compile time and still override it at boot time if they need to. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5881464..8442be1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -216,6 +216,23 @@ config SCSI_LOGGING there should be no noticeable performance impact as long as you have logging turned off. +config SCSI_SCAN_ASYNC + bool "Asynchronous SCSI scanning" + depends on SCSI + help + The SCSI subsystem can probe for devices while the rest of the + system continues booting, and even probe devices on different + busses in parallel, leading to a significant speed-up. + If you have built SCSI as modules, enabling this option can + be a problem as the devices may not have been found by the + time your system expects them to have been. You can load the + scsi_wait_scan module to ensure that all scans have completed. + If you build your SCSI drivers into the kernel, then everything + will work fine if you say Y here. + + You can override this choice by specifying scsi_mod.scan="sync" + or "async" on the kernel's command line. + menu "SCSI Transports" depends on SCSI diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index aa1b1e0..d91d268 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -89,7 +89,13 @@ module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); -static char scsi_scan_type[6] = "sync"; +#ifdef CONFIG_SCSI_SCAN_ASYNC +#define SCSI_SCAN_TYPE_DEFAULT "async" +#else +#define SCSI_SCAN_TYPE_DEFAULT "sync" +#endif + +static char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); MODULE_PARM_DESC(scan, "sync, async or none"); -- cgit v0.10.2 From 93b45af5c6b9d41bbe9da11442291ac4eefc15b4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 22 Nov 2006 13:24:53 -0700 Subject: [SCSI] fix missing check for no scanning Drivers that called scsi_scan_target() instead of scsi_scan_host() were still adding devices; this needs to be under the control of userspace, not the driver. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d91d268..3ccaa4b 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1549,6 +1549,9 @@ void scsi_scan_target(struct device *parent, unsigned int channel, { struct Scsi_Host *shost = dev_to_shost(parent); + if (strncmp(scsi_scan_type, "none", 4) == 0) + return; + if (!shost->async_scan) scsi_complete_async_scans(); -- cgit v0.10.2 From 1aa8fab2acf1cb8b341131b726773fcff0abc707 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 22 Nov 2006 13:24:54 -0700 Subject: [SCSI] Make scsi_scan_host work for drivers which find their own targets If a driver can find its own targets, it can now fill in scan_finished and (optionally) scan_start in the scsi_host_template. Then, when it calls scsi_scan_host(), it will be called back (from a thread if asynchronous discovery is enabled), first to start the scan, and then at intervals to check if the scan is completed. Also make scsi_prep_async_scan and scsi_finish_async_scan static. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 3ccaa4b..4d65614 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1642,7 +1642,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) * that other asynchronous scans started after this one won't affect the * ordering of the discovered devices. */ -struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) +static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) { struct async_scan_data *data; @@ -1686,7 +1686,7 @@ struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) * This function announces all the devices it has found to the rest * of the system. */ -void scsi_finish_async_scan(struct async_scan_data *data) +static void scsi_finish_async_scan(struct async_scan_data *data) { struct Scsi_Host *shost; @@ -1719,12 +1719,25 @@ void scsi_finish_async_scan(struct async_scan_data *data) kfree(data); } -static int do_scan_async(void *_data) +static void do_scsi_scan_host(struct Scsi_Host *shost) { - struct async_scan_data *data = _data; - scsi_scan_host_selected(data->shost, SCAN_WILD_CARD, SCAN_WILD_CARD, + if (shost->hostt->scan_finished) { + unsigned long start = jiffies; + if (shost->hostt->scan_start) + shost->hostt->scan_start(shost); + + while (!shost->hostt->scan_finished(shost, jiffies - start)) + msleep(10); + } else { + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, SCAN_WILD_CARD, 0); + } +} +static int do_scan_async(void *_data) +{ + struct async_scan_data *data = _data; + do_scsi_scan_host(data->shost); scsi_finish_async_scan(data); return 0; } @@ -1742,10 +1755,10 @@ void scsi_scan_host(struct Scsi_Host *shost) data = scsi_prep_async_scan(shost); if (!data) { - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, - SCAN_WILD_CARD, 0); + do_scsi_scan_host(shost); return; } + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index e618e711..6d8945d 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -241,6 +241,24 @@ struct scsi_host_template { void (* target_destroy)(struct scsi_target *); /* + * If a host has the ability to discover targets on its own instead + * of scanning the entire bus, it can fill in this function and + * call scsi_scan_host(). This function will be called periodically + * until it returns 1 with the scsi_host and the elapsed time of + * the scan in jiffies. + * + * Status: OPTIONAL + */ + int (* scan_finished)(struct Scsi_Host *, unsigned long); + + /* + * If the host wants to be called before the scan starts, but + * after the midlayer has set up ready for the scan, it can fill + * in this function. + */ + void (* scan_start)(struct Scsi_Host *); + + /* * fill in this function to allow the queue depth of this host * to be changeable (on a per device basis). returns either * the current queue depth setting (may be different from what -- cgit v0.10.2 From d19044c32baadeb80e135027124a9e845c6f057c Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 22 Nov 2006 08:22:19 -0800 Subject: [SCSI] qla2xxx: defer topology discovery to DPC thread during initialization. Modify intialization semantics: - perform basic hardware configuration only (as usual) - allocate resources - load and execute firmware - defer link (transport) negotiations to the DPC thread - again the code in qla2x00_initialize_adapter() to stall probe() completion was needed for legacy-style scanning. - DPC thread stalls until probe() complete. - before probe() completes, set DPC flags to perform loop-resync logic (similar to what's done during cable-insertion/removal). Benefits: user does not have to wait 20+ seconds in case the FC cable is unplugged during driver load, code consolidation (removal of redundant link negotiation logic during initialize_adaoter()), and finilly, the driver no longer needs to defer the fc_remote_port_add() calls to hold off lun-scanning prior to returning from the probe() function. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 08cb5e3..a823f0b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -59,9 +59,6 @@ int qla2x00_initialize_adapter(scsi_qla_host_t *ha) { int rval; - uint8_t restart_risc = 0; - uint8_t retry; - uint32_t wait_time; /* Clear adapter flags. */ ha->flags.online = 0; @@ -104,87 +101,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); - retry = 10; - /* - * Try to configure the loop. - */ - do { - restart_risc = 0; - - /* If firmware needs to be loaded */ - if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { - if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { - rval = qla2x00_setup_chip(ha); - } - } - - if (rval == QLA_SUCCESS && - (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { -check_fw_ready_again: - /* - * Wait for a successful LIP up to a maximum - * of (in seconds): RISC login timeout value, - * RISC retry count value, and port down retry - * value OR a minimum of 4 seconds OR If no - * cable, only 5 seconds. - */ - rval = qla2x00_fw_ready(ha); - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - - /* Issue a marker after FW becomes ready. */ - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - - /* - * Wait at most MAX_TARGET RSCNs for a stable - * link. - */ - wait_time = 256; - do { - clear_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags); - rval = qla2x00_configure_loop(ha); - - if (test_and_clear_bit(ISP_ABORT_NEEDED, - &ha->dpc_flags)) { - restart_risc = 1; - break; - } - - /* - * If loop state change while we were - * discoverying devices then wait for - * LIP to complete - */ - - if (atomic_read(&ha->loop_state) != - LOOP_READY && retry--) { - goto check_fw_ready_again; - } - wait_time--; - } while (!atomic_read(&ha->loop_down_timer) && - retry && - wait_time && - (test_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags))); - - if (wait_time == 0) - rval = QLA_FUNCTION_FAILED; - } else if (ha->device_flags & DFLG_NO_CABLE) - /* If no cable, then all is good. */ - rval = QLA_SUCCESS; - } - } while (restart_risc && retry--); - - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - ha->marker_needed = 0; - - ha->flags.online = 1; - } else { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); + if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { + rval = ha->isp_ops.chip_diag(ha); + if (rval) + return (rval); + rval = qla2x00_setup_chip(ha); + if (rval) + return (rval); } + rval = qla2x00_init_rings(ha); return (rval); } @@ -2208,8 +2133,7 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) atomic_set(&fcport->state, FCS_ONLINE); - if (ha->flags.init_done) - qla2x00_reg_remote_port(ha, fcport); + qla2x00_reg_remote_port(ha, fcport); } void diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3eb4cd2..1cc8feb 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1377,10 +1377,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; - unsigned long wait_switch = 0; char pci_info[20]; char fw_str[30]; - fc_port_t *fcport; struct scsi_host_template *sht; if (pci_enable_device(pdev)) @@ -1631,24 +1629,15 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.enable_intrs(ha); - /* v2.19.5b6 */ - /* - * Wait around max loop_reset_delay secs for the devices to come - * on-line. We don't want Linux scanning before we are ready. - * - */ - for (wait_switch = jiffies + (ha->loop_reset_delay * HZ); - time_before(jiffies,wait_switch) && - !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) - && (ha->device_flags & SWITCH_FOUND) ;) { - - qla2x00_check_fabric_devices(ha); - - msleep(10); - } - pci_set_drvdata(pdev, ha); + + /* Start link scan. */ + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(RSCN_UPDATE, &ha->dpc_flags); ha->flags.init_done = 1; + ha->flags.online = 1; + num_hosts++; ret = scsi_add_host(host, &pdev->dev); @@ -1669,10 +1658,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str)); - /* Go with fc_rport registration. */ - list_for_each_entry(fcport, &ha->fcports, list) - qla2x00_reg_remote_port(ha, fcport); - return 0; probe_failed: -- cgit v0.10.2 From 1e99e33ad94aa363e01cdfc2fc9df93338907fe6 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 22 Nov 2006 08:24:48 -0800 Subject: [SCSI] qla2xxx: add asynchronous scsi scanning support. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 1cc8feb..cbe0cad 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -95,6 +95,8 @@ MODULE_PARM_DESC(ql2xqfullrampup, */ static int qla2xxx_slave_configure(struct scsi_device * device); static int qla2xxx_slave_alloc(struct scsi_device *); +static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time); +static void qla2xxx_scan_start(struct Scsi_Host *); static void qla2xxx_slave_destroy(struct scsi_device *); static int qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)); @@ -124,6 +126,8 @@ static struct scsi_host_template qla2x00_driver_template = { .slave_alloc = qla2xxx_slave_alloc, .slave_destroy = qla2xxx_slave_destroy, + .scan_finished = qla2xxx_scan_finished, + .scan_start = qla2xxx_scan_start, .change_queue_depth = qla2x00_change_queue_depth, .change_queue_type = qla2x00_change_queue_type, .this_id = -1, @@ -1366,6 +1370,29 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); } +static void +qla2xxx_scan_start(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(RSCN_UPDATE, &ha->dpc_flags); +} + +static int +qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + + if (!ha->host) + return 1; + if (time > ha->loop_reset_delay * HZ) + return 1; + + return atomic_read(&ha->loop_state) == LOOP_READY; +} + /* * PCI driver interface */ @@ -1631,10 +1658,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, ha); - /* Start link scan. */ - set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); - set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); - set_bit(RSCN_UPDATE, &ha->dpc_flags); ha->flags.init_done = 1; ha->flags.online = 1; @@ -1644,6 +1667,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto probe_failed; + scsi_scan_host(host); + qla2x00_alloc_sysfs_attr(ha); qla2x00_init_host_attr(ha); -- cgit v0.10.2 From 105ef9a0af1469a9dd906839dd4628aa9c013f58 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 21 Nov 2006 22:57:23 +0100 Subject: [ARM] 3942/1: ARM: comment: consistent_sync should not be called directly /* * Note: Drivers should NOT use this function directly, as it will break * platforms with CONFIG_DMABOUNCE. * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ Signed-off-by: Dan Williams Signed-off-by: Russell King diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 50e6b6b..b797217 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -476,6 +476,9 @@ core_initcall(consistent_init); /* * Make an area consistent for devices. + * Note: Drivers should NOT use this function directly, as it will break + * platforms with CONFIG_DMABOUNCE. + * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ void consistent_sync(void *vaddr, size_t size, int direction) { diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index 55eb4dc..6666177 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -12,6 +12,10 @@ * uncached, unwrite-buffered mapped memory space for use with DMA * devices. This is the "generic" version. The PCI specific version * is in pci.h + * + * Note: Drivers should NOT use this function directly, as it will break + * platforms with CONFIG_DMABOUNCE. + * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ extern void consistent_sync(void *kaddr, size_t size, int rw); -- cgit v0.10.2 From 21f37bc3e51fac4f7a226a6d110c4c316af0d22d Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Tue, 21 Nov 2006 01:20:31 +0100 Subject: [ARM] 3941/1: [Jornada7xx] - Addition to MAINTAINERS Adding myself to the MAINTAINERS file. Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King diff --git a/MAINTAINERS b/MAINTAINERS index a5508f9..e182992 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -353,6 +353,12 @@ P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +ARM/HP JORNADA 7XX MACHINE SUPPORT +P: Kristoffer Ericson +M: kristoffer_e1@hotmail.com +W: www.jlime.com +S: Maintained + ARM/TOSA MACHINE SUPPORT P: Dirk Opfer M: dirk@opfer-online.de -- cgit v0.10.2 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 diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c392001..5ff457b 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 aceece7..555b3a8 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 v0.10.2 From eb4828750852b84703f64747b3bedf6394d629ef Mon Sep 17 00:00:00 2001 From: Thiemo Seufer Date: Thu, 16 Nov 2006 22:13:54 +0000 Subject: [MIPS] Hack for SB1 cache issues Removing flush_icache_page a while ago broke SB1 which was using an empty flush_data_cache_page function. This glues things well enough so a more efficient but also more intrusive solution can be found later. Signed-Off-By: Thiemo Seufer Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index d0ddb4a..3a8afd4 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include @@ -242,6 +243,25 @@ void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsign __attribute__((alias("local_sb1_flush_cache_page"))); #endif +#ifdef CONFIG_SMP +static void sb1_flush_cache_data_page_ipi(void *info) +{ + unsigned long start = (unsigned long)info; + + __sb1_writeback_inv_dcache_range(start, start + PAGE_SIZE); +} + +static void sb1_flush_cache_data_page(unsigned long addr) +{ + if (in_atomic()) + __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE); + else + on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1); +} +#else +void sb1_flush_cache_data_page(unsigned long) + __attribute__((alias("local_sb1_flush_cache_data_page"))); +#endif /* * Invalidate all caches on this CPU @@ -481,7 +501,7 @@ void sb1_cache_init(void) flush_cache_sigtramp = sb1_flush_cache_sigtramp; local_flush_data_cache_page = (void *) sb1_nop; - flush_data_cache_page = (void *) sb1_nop; + flush_data_cache_page = sb1_flush_cache_data_page; /* Full flush */ __flush_cache_all = sb1___flush_cache_all; -- cgit v0.10.2 From ec7080d185a9b79581bf1dbe300e877719c0b1a9 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Wed, 22 Nov 2006 14:51:32 +0100 Subject: [PATCH] make au1xxx-ide compile again The Au1xx IDE controller driver doesn't compile: CC drivers/ide/mips/au1xxx-ide.o /linux-2.6.19-rc6-work/drivers/ide/mips/au1xxx-ide.c:480: error: conflicting types for 'auide_ddma_tx_callback' include2/asm/mach-au1x00/au1xxx_ide.h:174: error: previous declaration of 'auide_ddma_tx_callback' was here /linux-2.6.19-rc6-work/drivers/ide/mips/au1xxx-ide.c:486: error: conflicting types for 'auide_ddma_rx_callback' include2/asm/mach-au1x00/au1xxx_ide.h:176: error: previous declaration of 'auide_ddma_rx_callback' was here Signed-off-by: Manuel Lauss Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h index 301e713..e9fa252 100644 --- a/include/asm-mips/mach-au1x00/au1xxx_ide.h +++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h @@ -170,10 +170,8 @@ int __init auide_probe(void); static int auide_dma_host_on(ide_drive_t *drive); static int auide_dma_lostirq(ide_drive_t *drive); static int auide_dma_on(ide_drive_t *drive); - static void auide_ddma_tx_callback(int irq, void *param, - struct pt_regs *regs); - static void auide_ddma_rx_callback(int irq, void *param, - struct pt_regs *regs); + static void auide_ddma_tx_callback(int irq, void *param); + static void auide_ddma_rx_callback(int irq, void *param); static int auide_dma_off_quietly(ide_drive_t *drive); #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ -- cgit v0.10.2 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 diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 7ba5e49..6fd174a 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 v0.10.2 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 diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index 05fffb9..68fe863 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 v0.10.2 From 1abbfb412b1610ec3a7ec0164108cee01191d9f5 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Thu, 23 Nov 2006 12:01:41 +0000 Subject: [PATCH] x86_64: fix bad page state in process 'swapper' find_min_pfn_for_node() and find_min_pfn_with_active_regions() both depend on a sorted early_node_map[]. However, sort_node_map() is being called after fin_min_pfn_with_active_regions() in free_area_init_nodes(). In most cases, this is ok, but on at least one x86_64, the SRAT table caused the E820 ranges to be registered out of order. This gave the wrong values for the min PFN range resulting in some pages not being initialised. This patch sorts the early_node_map in find_min_pfn_for_node(). It has been boot tested on x86, x86_64, ppc64 and ia64. Signed-off-by: Mel Gorman Acked-by: Andre Noll Signed-off-by: Linus Torvalds diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bf2f6cf..aa6fcc7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2612,6 +2612,9 @@ unsigned long __init find_min_pfn_for_node(unsigned long nid) { int i; + /* Regions in the early_node_map can be in any order */ + sort_node_map(); + /* Assuming a sorted map, the first range found has the starting pfn */ for_each_active_range_index_in_nid(i, nid) return early_node_map[i].start_pfn; @@ -2680,9 +2683,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]); } - /* Regions in the early_node_map can be in any order */ - sort_node_map(); - /* Print out the zone ranges */ printk("Zone PFN ranges:\n"); for (i = 0; i < MAX_NR_ZONES; i++) -- cgit v0.10.2 From ed7b1f6d6ea1054ea4fe293a7fd8015fc3803d93 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 23 Nov 2006 23:34:49 -0500 Subject: Input: serio - make serio_register_driver() return errors Perform actual driver registration right in serio_register_driver() instead of offloading it to kseriod and return proper error code to callers if driver registration fails. Note that driver <-> port matching is still done by kseriod to speed up boot process since probing for PS/2 mice and keyboards is pretty slow. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index cd55ddb..8c71704 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -44,7 +44,7 @@ EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_child_port); -EXPORT_SYMBOL(__serio_register_driver); +EXPORT_SYMBOL(serio_register_driver); EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_close); @@ -61,10 +61,10 @@ static LIST_HEAD(serio_list); static struct bus_type serio_bus; -static void serio_add_driver(struct serio_driver *drv); static void serio_add_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio); +static void serio_attach_driver(struct serio_driver *drv); static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) { @@ -168,10 +168,10 @@ static void serio_find_driver(struct serio *serio) */ enum serio_event_type { - SERIO_RESCAN, - SERIO_RECONNECT, + SERIO_RESCAN_PORT, + SERIO_RECONNECT_PORT, SERIO_REGISTER_PORT, - SERIO_REGISTER_DRIVER, + SERIO_ATTACH_DRIVER, }; struct serio_event { @@ -186,11 +186,12 @@ static LIST_HEAD(serio_event_list); static DECLARE_WAIT_QUEUE_HEAD(serio_wait); static struct task_struct *serio_task; -static void serio_queue_event(void *object, struct module *owner, - enum serio_event_type event_type) +static int serio_queue_event(void *object, struct module *owner, + enum serio_event_type event_type) { unsigned long flags; struct serio_event *event; + int retval = 0; spin_lock_irqsave(&serio_event_lock, flags); @@ -209,24 +210,34 @@ static void serio_queue_event(void *object, struct module *owner, } } - if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { - if (!try_module_get(owner)) { - printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); - kfree(event); - goto out; - } - - event->type = event_type; - event->object = object; - event->owner = owner; + event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); + if (!event) { + printk(KERN_ERR + "serio: Not enough memory to queue event %d\n", + event_type); + retval = -ENOMEM; + goto out; + } - list_add_tail(&event->node, &serio_event_list); - wake_up(&serio_wait); - } else { - printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type); + if (!try_module_get(owner)) { + printk(KERN_WARNING + "serio: Can't get module reference, dropping event %d\n", + event_type); + kfree(event); + retval = -EINVAL; + goto out; } + + event->type = event_type; + event->object = object; + event->owner = owner; + + list_add_tail(&event->node, &serio_event_list); + wake_up(&serio_wait); + out: spin_unlock_irqrestore(&serio_event_lock, flags); + return retval; } static void serio_free_event(struct serio_event *event) @@ -304,17 +315,17 @@ static void serio_handle_event(void) serio_add_port(event->object); break; - case SERIO_RECONNECT: + case SERIO_RECONNECT_PORT: serio_reconnect_port(event->object); break; - case SERIO_RESCAN: + case SERIO_RESCAN_PORT: serio_disconnect_port(event->object); serio_find_driver(event->object); break; - case SERIO_REGISTER_DRIVER: - serio_add_driver(event->object); + case SERIO_ATTACH_DRIVER: + serio_attach_driver(event->object); break; default: @@ -666,12 +677,12 @@ static void serio_disconnect_port(struct serio *serio) void serio_rescan(struct serio *serio) { - serio_queue_event(serio, NULL, SERIO_RESCAN); + serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); } void serio_reconnect(struct serio *serio) { - serio_queue_event(serio, NULL, SERIO_RECONNECT); + serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); } /* @@ -766,22 +777,52 @@ static int serio_driver_remove(struct device *dev) return 0; } -static void serio_add_driver(struct serio_driver *drv) +static void serio_attach_driver(struct serio_driver *drv) { int error; - error = driver_register(&drv->driver); + error = driver_attach(&drv->driver); if (error) - printk(KERN_ERR - "serio: driver_register() failed for %s, error: %d\n", + printk(KERN_WARNING + "serio: driver_attach() failed for %s with error %d\n", drv->driver.name, error); } -void __serio_register_driver(struct serio_driver *drv, struct module *owner) +int serio_register_driver(struct serio_driver *drv) { + int manual_bind = drv->manual_bind; + int error; + drv->driver.bus = &serio_bus; - serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); + /* + * Temporarily disable automatic binding because probing + * takes long time and we are better off doing it in kseriod + */ + drv->manual_bind = 1; + + error = driver_register(&drv->driver); + if (error) { + printk(KERN_ERR + "serio: driver_register() failed for %s, error: %d\n", + drv->driver.name, error); + return error; + } + + /* + * Restore original bind mode and let kseriod bind the + * driver to free ports + */ + if (!manual_bind) { + drv->manual_bind = 0; + error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); + if (error) { + driver_unregister(&drv->driver); + return error; + } + } + + return 0; } void serio_unregister_driver(struct serio_driver *drv) diff --git a/include/linux/serio.h b/include/linux/serio.h index 8f52228..0f478a8 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -86,12 +86,7 @@ static inline void serio_register_port(struct serio *serio) void serio_unregister_port(struct serio *serio); void serio_unregister_child_port(struct serio *serio); -void __serio_register_driver(struct serio_driver *drv, struct module *owner); -static inline void serio_register_driver(struct serio_driver *drv) -{ - __serio_register_driver(drv, THIS_MODULE); -} - +int serio_register_driver(struct serio_driver *drv); void serio_unregister_driver(struct serio_driver *drv); static inline int serio_write(struct serio *serio, unsigned char data) -- cgit v0.10.2 From 153a9df01c0d1ecdc56161c7a0f830325145dd64 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 23 Nov 2006 23:35:10 -0500 Subject: Input: handle serio_register_driver() errors Signed-off-by: Akinobu Mita Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 706e0ae..3393a37 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -467,13 +467,21 @@ int iforce_init_device(struct iforce *iforce) static int __init iforce_init(void) { + int err = 0; + #ifdef CONFIG_JOYSTICK_IFORCE_USB - usb_register(&iforce_usb_driver); + err = usb_register(&iforce_usb_driver); + if (err) + return err; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 - serio_register_driver(&iforce_serio_drv); + err = serio_register_driver(&iforce_serio_drv); +#ifdef CONFIG_JOYSTICK_IFORCE_USB + if (err) + usb_deregister(&iforce_usb_driver); #endif - return 0; +#endif + return err; } static void __exit iforce_exit(void) diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index d512b0a..4112789 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -231,8 +231,7 @@ static struct serio_driver magellan_drv = { static int __init magellan_init(void) { - serio_register_driver(&magellan_drv); - return 0; + return serio_register_driver(&magellan_drv); } static void __exit magellan_exit(void) diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 9b35973..08bf113 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -300,8 +300,7 @@ static struct serio_driver spaceball_drv = { static int __init spaceball_init(void) { - serio_register_driver(&spaceball_drv); - return 0; + return serio_register_driver(&spaceball_drv); } static void __exit spaceball_exit(void) diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index ea9d51e..c9c7921 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -246,8 +246,7 @@ static struct serio_driver spaceorb_drv = { static int __init spaceorb_init(void) { - serio_register_driver(&spaceorb_drv); - return 0; + return serio_register_driver(&spaceorb_drv); } static void __exit spaceorb_exit(void) diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index b51a4a4..ecb0916 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -216,8 +216,7 @@ static struct serio_driver stinger_drv = { static int __init stinger_init(void) { - serio_register_driver(&stinger_drv); - return 0; + return serio_register_driver(&stinger_drv); } static void __exit stinger_exit(void) diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 3c1c83e..9cf17d6 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -269,8 +269,7 @@ static struct serio_driver twidjoy_drv = { static int __init twidjoy_init(void) { - serio_register_driver(&twidjoy_drv); - return 0; + return serio_register_driver(&twidjoy_drv); } static void __exit twidjoy_exit(void) diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 1e4828b..29d339a 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -224,8 +224,7 @@ static struct serio_driver warrior_drv = { static int __init warrior_init(void) { - serio_register_driver(&warrior_drv); - return 0; + return serio_register_driver(&warrior_drv); } static void __exit warrior_exit(void) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 73c6946..498e64a 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -1389,8 +1389,7 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) static int __init atkbd_init(void) { - serio_register_driver(&atkbd_drv); - return 0; + return serio_register_driver(&atkbd_drv); } static void __exit atkbd_exit(void) diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index e774dd3..7cc9728 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -381,8 +381,7 @@ struct serio_driver hil_kbd_serio_drv = { static int __init hil_kbd_init(void) { - serio_register_driver(&hil_kbd_serio_drv); - return 0; + return serio_register_driver(&hil_kbd_serio_drv); } static void __exit hil_kbd_exit(void) diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 0067c1f..1789785 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -758,8 +758,7 @@ static struct serio_driver lkkbd_drv = { static int __init lkkbd_init (void) { - serio_register_driver(&lkkbd_drv); - return 0; + return serio_register_driver(&lkkbd_drv); } static void __exit diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 33e8139..aa29b50 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -169,8 +169,7 @@ static struct serio_driver nkbd_drv = { static int __init nkbd_init(void) { - serio_register_driver(&nkbd_drv); - return 0; + return serio_register_driver(&nkbd_drv); } static void __exit nkbd_exit(void) diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index e60937d..f7b5c5b 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -173,8 +173,7 @@ static struct serio_driver skbd_drv = { static int __init skbd_init(void) { - serio_register_driver(&skbd_drv); - return 0; + return serio_register_driver(&skbd_drv); } static void __exit skbd_exit(void) diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index d1b62f7..d6ab6d4 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -352,8 +352,7 @@ static struct serio_driver sunkbd_drv = { static int __init sunkbd_init(void) { - serio_register_driver(&sunkbd_drv); - return 0; + return serio_register_driver(&sunkbd_drv); } static void __exit sunkbd_exit(void) diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index b53f716..a820934 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -174,8 +174,7 @@ static struct serio_driver xtkbd_drv = { static int __init xtkbd_init(void) { - serio_register_driver(&xtkbd_drv); - return 0; + return serio_register_driver(&xtkbd_drv); } static void __exit xtkbd_exit(void) diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index 4f2b503..bfb174f 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -417,8 +417,7 @@ static struct serio_driver hil_ptr_serio_driver = { static int __init hil_ptr_init(void) { - serio_register_driver(&hil_ptr_serio_driver); - return 0; + return serio_register_driver(&hil_ptr_serio_driver); } static void __exit hil_ptr_exit(void) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 58beca9..e626b1e 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1524,15 +1524,19 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) static int __init psmouse_init(void) { + int err; + kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); if (!kpsmoused_wq) { printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); return -ENOMEM; } - serio_register_driver(&psmouse_drv); + err = serio_register_driver(&psmouse_drv); + if (err) + destroy_workqueue(kpsmoused_wq); - return 0; + return err; } static void __exit psmouse_exit(void) diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 10b51e7..a85d747 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -351,8 +351,7 @@ static struct serio_driver sermouse_drv = { static int __init sermouse_init(void) { - serio_register_driver(&sermouse_drv); - return 0; + return serio_register_driver(&sermouse_drv); } static void __exit sermouse_exit(void) diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index ffd0d66..c3d64fc 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -574,8 +574,7 @@ static struct serio_driver vsxxxaa_drv = { static int __init vsxxxaa_init (void) { - serio_register_driver(&vsxxxaa_drv); - return 0; + return serio_register_driver(&vsxxxaa_drv); } static void __exit diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index ba2a203..0e343a6 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -389,8 +389,7 @@ static struct serio_driver serio_raw_drv = { static int __init serio_raw_init(void) { - serio_register_driver(&serio_raw_drv); - return 0; + return serio_register_driver(&serio_raw_drv); } static void __exit serio_raw_exit(void) diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 913e1b7..9d61cd1 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -397,8 +397,7 @@ static struct serio_driver elo_drv = { static int __init elo_init(void) { - serio_register_driver(&elo_drv); - return 0; + return serio_register_driver(&elo_drv); } static void __exit elo_exit(void) diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 44f397f..9157eb1 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -194,8 +194,7 @@ static struct serio_driver gunze_drv = { static int __init gunze_init(void) { - serio_register_driver(&gunze_drv); - return 0; + return serio_register_driver(&gunze_drv); } static void __exit gunze_exit(void) diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index d9e61ee..c4116d4 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -478,8 +478,7 @@ static struct serio_driver h3600ts_drv = { static int __init h3600ts_init(void) { - serio_register_driver(&h3600ts_drv); - return 0; + return serio_register_driver(&h3600ts_drv); } static void __exit h3600ts_exit(void) diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index c66b399..c3c2d73 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -208,8 +208,7 @@ static struct serio_driver mtouch_drv = { static int __init mtouch_init(void) { - serio_register_driver(&mtouch_drv); - return 0; + return serio_register_driver(&mtouch_drv); } static void __exit mtouch_exit(void) diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 6c7d0c2..bd27679 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -171,8 +171,7 @@ static struct serio_driver pm_drv = { static int __init pm_init(void) { - serio_register_driver(&pm_drv); - return 0; + return serio_register_driver(&pm_drv); } static void __exit pm_exit(void) diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index c74f74e..35ba46c 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -182,8 +182,7 @@ static struct serio_driver tr_drv = { static int __init tr_init(void) { - serio_register_driver(&tr_drv); - return 0; + return serio_register_driver(&tr_drv); } static void __exit tr_exit(void) diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 9911820..4dc073d 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -189,8 +189,7 @@ static struct serio_driver tw_drv = { static int __init tw_init(void) { - serio_register_driver(&tw_drv); - return 0; + return serio_register_driver(&tw_drv); } static void __exit tw_exit(void) -- cgit v0.10.2 From f9705fcb9887fcff364a0c8dffbac693aa221d4f Mon Sep 17 00:00:00 2001 From: Nicolas Bellido Date: Fri, 24 Nov 2006 00:42:50 -0500 Subject: Input: add driver for keyboard on AAED-2000 development board (ARM) The keyboard is connected via GPIOs to the processor, and scanned using a column sample register. The hardware provides no debouncing mechanism, so the state of the keys is read KBDSCAN_STABLE_COUNT times before being reported to the input layer. The status of the keys needs to be polled because there is no interrupt hooked to the lines. A workqueue is used for this. Signed-off-by: Nicolas Bellido Y Ortega Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 81a333f..049f2f5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -203,4 +203,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_AAED2000 + tristate "AAED-2000 keyboard" + depends on MACH_AAED2000 + default y + help + Say Y here to enable the keyboard on the Agilent AAED-2000 + development board. + + To compile this driver as a module, choose M here: the + module will be called aaed2000_kbd. + endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 4c79e7b..5687979 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o +obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c new file mode 100644 index 0000000..65fcb6a --- /dev/null +++ b/drivers/input/keyboard/aaed2000_kbd.c @@ -0,0 +1,203 @@ +/* + * Keyboard driver for the AAED-2000 dev board + * + * Copyright (c) 2006 Nicolas Bellido Y Ortega + * + * Based on corgikbd.c + * + * 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 + +#define KB_ROWS 12 +#define KB_COLS 8 +#define KB_ROWMASK(r) (1 << (r)) +#define SCANCODE(r,c) (((c) * KB_ROWS) + (r)) +#define NR_SCANCODES (KB_COLS * KB_ROWS) + +#define SCAN_INTERVAL (50) /* ms */ +#define KB_ACTIVATE_DELAY (20) /* us */ + +static unsigned char aaedkbd_keycode[NR_SCANCODES] = { + KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0, + KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0, + KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0, + KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, + KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK, + KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB, + KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE, + 0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL +}; + +struct aaedkbd { + unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; + struct input_dev *input; + struct work_struct workq; + int kbdscan_state[KB_COLS]; + int kbdscan_count[KB_COLS]; +}; + +#define KBDSCAN_STABLE_COUNT 2 + +static void aaedkbd_report_col(struct aaedkbd *aaedkbd, + unsigned int col, unsigned int rowd) +{ + unsigned int scancode, pressed; + unsigned int row; + + for (row = 0; row < KB_ROWS; row++) { + scancode = SCANCODE(row, col); + pressed = rowd & KB_ROWMASK(row); + + input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed); + } +} + +/* Scan the hardware keyboard and push any changes up through the input layer */ +static void aaedkbd_work(void *data) +{ + struct aaedkbd *aaedkbd = data; + unsigned int col, rowd; + + col = 0; + do { + AAEC_GPIO_KSCAN = col + 8; + udelay(KB_ACTIVATE_DELAY); + rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN; + + if (rowd != aaedkbd->kbdscan_state[col]) { + aaedkbd->kbdscan_count[col] = 0; + aaedkbd->kbdscan_state[col] = rowd; + } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) { + aaedkbd_report_col(aaedkbd, col, rowd); + col++; + } + } while (col < KB_COLS); + + AAEC_GPIO_KSCAN = 0x07; + input_sync(aaedkbd->input); + + schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); +} + +static int aaedkbd_open(struct input_dev *indev) +{ + struct aaedkbd *aaedkbd = indev->private; + + schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); + + return 0; +} + +static void aaedkbd_close(struct input_dev *indev) +{ + struct aaedkbd *aaedkbd = indev->private; + + cancel_delayed_work(&aaedkbd->workq); + flush_scheduled_work(); +} + +static int __devinit aaedkbd_probe(struct platform_device *pdev) +{ + struct aaedkbd *aaedkbd; + struct input_dev *input_dev; + int i; + int error; + + aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!aaedkbd || !input_dev) { + error = -ENOMEM; + goto fail; + } + + platform_set_drvdata(pdev, aaedkbd); + + aaedkbd->input = input_dev; + + /* Init keyboard rescan workqueue */ + INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd); + + memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); + + input_dev->name = "AAED-2000 Keyboard"; + input_dev->phys = "aaedkbd/input0"; + input_dev->id.bustype = BUS_HOST; + input_dev->id.vendor = 0x0001; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &pdev->dev; + input_dev->private = aaedkbd; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + input_dev->keycode = aaedkbd->keycode; + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode); + + for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++) + set_bit(aaedkbd->keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); + + input_dev->open = aaedkbd_open; + input_dev->close = aaedkbd_close; + + error = input_register_device(aaedkbd->input); + if (error) + goto fail; + + return 0; + + fail: kfree(aaedkbd); + input_free_device(input_dev); + return error; +} + +static int __devexit aaedkbd_remove(struct platform_device *pdev) +{ + struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); + + input_unregister_device(aaedkbd->input); + kfree(aaedkbd); + + return 0; +} + +static struct platform_driver aaedkbd_driver = { + .probe = aaedkbd_probe, + .remove = __devexit_p(aaedkbd_remove), + .driver = { + .name = "aaed2000-keyboard", + }, +}; + +static int __init aaedkbd_init(void) +{ + return platform_driver_register(&aaedkbd_driver); +} + +static void __exit aaedkbd_exit(void) +{ + platform_driver_unregister(&aaedkbd_driver); +} + +module_init(aaedkbd_init); +module_exit(aaedkbd_exit); + +MODULE_AUTHOR("Nicolas Bellido Y Ortega"); +MODULE_DESCRIPTION("AAED-2000 Keyboard Driver"); +MODULE_LICENSE("GPLv2"); -- cgit v0.10.2 From e4477d2d1bc3e6c76e83926f7fa8c8f94ba42615 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 24 Nov 2006 00:43:09 -0500 Subject: Input: add to kernel-api docbook Add input subsystem to kernel-api docbook. Enhance some function and parameter comments. Signed-off-by: Randy Dunlap Signed-off-by: Dmitry Torokhov diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index a166675..a1af278 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -533,4 +533,12 @@ X!Idrivers/video/console/fonts.c --> + + + Input Subsystem +!Iinclude/linux/input.h +!Edrivers/input/input.c +!Edrivers/input/ff-core.c +!Edrivers/input/ff-memless.c + diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 35656ca..783b341 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -203,7 +203,7 @@ static int erase_effect(struct input_dev *dev, int effect_id, } /** - * input_ff_erase - erase an effect from device + * input_ff_erase - erase a force-feedback effect from device * @dev: input device to erase effect from * @effect_id: id of the ffect to be erased * @file: purported owner of the request @@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(input_ff_create); /** * input_ff_free() - frees force feedback portion of input device - * @dev: input device supporintg force feedback + * @dev: input device supporting force feedback * * This function is only needed in error path as input core will * automatically free force feedback structures when device is diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index cd8b729..eba18b6 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -460,7 +460,7 @@ static void ml_ff_destroy(struct ff_device *ff) } /** - * input_ff_create_memless() - create memoryless FF device + * input_ff_create_memless() - create memoryless force-feedback device * @dev: input device supporting force-feedback * @data: driver-specific data to be passed into @play_effect * @play_effect: driver-specific method for playing FF effect diff --git a/include/linux/input.h b/include/linux/input.h index c38507b..4e61158 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -663,7 +663,7 @@ struct input_absinfo { #define BUS_GSC 0x1A /* - * Values describing the status of an effect + * Values describing the status of a force-feedback effect */ #define FF_STATUS_STOPPED 0x00 #define FF_STATUS_PLAYING 0x01 @@ -680,7 +680,7 @@ struct input_absinfo { */ /** - * struct ff_replay - defines scheduling of the effect + * struct ff_replay - defines scheduling of the force-feedback effect * @length: duration of the effect * @delay: delay before effect should start playing */ @@ -690,7 +690,7 @@ struct ff_replay { }; /** - * struct ff_trigger - defines what triggers the effect + * struct ff_trigger - defines what triggers the force-feedback effect * @button: number of the button triggering the effect * @interval: controls how soon the effect can be re-triggered */ @@ -700,7 +700,7 @@ struct ff_trigger { }; /** - * struct ff_envelope - generic effect envelope + * struct ff_envelope - generic force-feedback effect envelope * @attack_length: duration of the attack (ms) * @attack_level: level at the beginning of the attack * @fade_length: duration of fade (ms) @@ -719,7 +719,7 @@ struct ff_envelope { }; /** - * struct ff_constant_effect - defines parameters of a constant effect + * struct ff_constant_effect - defines parameters of a constant force-feedback effect * @level: strength of the effect; may be negative * @envelope: envelope data */ @@ -729,7 +729,7 @@ struct ff_constant_effect { }; /** - * struct ff_ramp_effect - defines parameters of a ramp effect + * struct ff_ramp_effect - defines parameters of a ramp force-feedback effect * @start_level: beginning strength of the effect; may be negative * @end_level: final strength of the effect; may be negative * @envelope: envelope data @@ -741,7 +741,7 @@ struct ff_ramp_effect { }; /** - * struct ff_condition_effect - defines a spring or friction effect + * struct ff_condition_effect - defines a spring or friction force-feedback effect * @right_saturation: maximum level when joystick moved all way to the right * @left_saturation: same for the left side * @right_coeff: controls how fast the force grows when the joystick moves @@ -762,7 +762,7 @@ struct ff_condition_effect { }; /** - * struct ff_periodic_effect - defines parameters of a periodic effect + * struct ff_periodic_effect - defines parameters of a periodic force-feedback effect * @waveform: kind of the effect (wave) * @period: period of the wave (ms) * @magnitude: peak value @@ -793,7 +793,7 @@ struct ff_periodic_effect { }; /** - * struct ff_rumble_effect - defines parameters of a periodic effect + * struct ff_rumble_effect - defines parameters of a periodic force-feedback effect * @strong_magnitude: magnitude of the heavy motor * @weak_magnitude: magnitude of the light one * -- cgit v0.10.2 From 4bdbd2807deeccc0793d57fb5120d7a53f2c0b3c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 24 Nov 2006 00:43:22 -0500 Subject: Input: handle errors from input_register_device in drivers/macintosh Signed-off-by: Dmitry Torokhov diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 5066e7a..1c7d6f2 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -689,7 +689,6 @@ adbhid_input_register(int id, int default_id, int original_handler_id, if (!hid || !input_dev) { err = -ENOMEM; goto fail; - } sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id); @@ -807,7 +806,9 @@ adbhid_input_register(int id, int default_id, int original_handler_id, input_dev->keycode = hid->keycode; - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) + goto fail; if (default_id == ADB_KEYBOARD) { /* HACK WARNING!! This should go away as soon there is an utility @@ -820,7 +821,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id, return 0; fail: input_free_device(input_dev); - kfree(hid); + if (hid) { + kfree(hid->keycode); + kfree(hid); + } adbhid[id] = NULL; return err; } diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c index 6b129ee..ee6b4ca 100644 --- a/drivers/macintosh/mac_hid.c +++ b/drivers/macintosh/mac_hid.c @@ -106,6 +106,8 @@ EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons); static int emumousebtn_input_register(void) { + int ret; + emumousebtn = input_allocate_device(); if (!emumousebtn) return -ENOMEM; @@ -120,9 +122,11 @@ static int emumousebtn_input_register(void) emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_register_device(emumousebtn); + ret = input_register_device(emumousebtn); + if (ret) + input_free_device(emumousebtn); - return 0; + return ret; } int __init mac_hid_init(void) -- cgit v0.10.2 From 84ad58e4efcf80c154f693d4cc8f5c913511b760 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 19 Nov 2006 18:53:43 -0800 Subject: [SCSI] initio: fix section mismatches with HOTPLUG=n WARNING: drivers/scsi/initio.o - Section mismatch: reference to .init.data: from .text between 'i91u_detect' (at offset 0x26e8) and 'i91uSCBPost' WARNING: drivers/scsi/initio.o - Section mismatch: reference to .init.data:i91u_pci_devices from .text between 'i91u_detect' (at offset 0x26ef) and 'i91uSCBPost' Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index afed293..f160357 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -170,7 +170,7 @@ static int setup_debug = 0; static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); /* PCI Devices supported by this driver */ -static struct pci_device_id i91u_pci_devices[] __devinitdata = { +static struct pci_device_id i91u_pci_devices[] = { { 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}, -- cgit v0.10.2 From b58d91547fb17c65ad621f3f98b1f2c228c812a5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 16 Nov 2006 19:24:10 +0900 Subject: [SCSI] export scsi-ml functions needed by tgt_scsi_lib and its LLDs This patch contains the needed changes to the scsi-ml for the target mode support. Note, per the last review we moved almost all the fields we added to the scsi_cmnd to our internal data structure which we are going to try and kill off when we can replace it with support from other parts of the kernel. The one field we left on was the offset variable. This is needed to handle the case where the target gets request that is so large that it cannot execute it in one dma operation. So max_secotors or a segment limit may limit the size of the transfer. In this case our tgt core code will break up the command into managable transfers and send them to the LLD one at a time. The offset is then used to tell the LLD where in the command we are at. Is there another field on the scsi_cmd for that? Signed-off-by: Mike Christie Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 2ffdc9e..38c3a29 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -263,6 +263,10 @@ static void scsi_host_dev_release(struct device *dev) kthread_stop(shost->ehandler); if (shost->work_q) destroy_workqueue(shost->work_q); + if (shost->uspace_req_q) { + kfree(shost->uspace_req_q->queuedata); + scsi_free_queue(shost->uspace_req_q); + } scsi_destroy_command_freelist(shost); if (shost->bqt) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 780d6dc..fafc00d 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -156,8 +156,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { static DEFINE_MUTEX(host_cmd_pool_mutex); -static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, - gfp_t gfp_mask) +struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) { struct scsi_cmnd *cmd; @@ -178,6 +177,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, return cmd; } +EXPORT_SYMBOL_GPL(__scsi_get_command); /* * Function: scsi_get_command() @@ -214,9 +214,29 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) put_device(&dev->sdev_gendev); return cmd; -} +} EXPORT_SYMBOL(scsi_get_command); +void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, + struct device *dev) +{ + unsigned long flags; + + /* changing locks here, don't need to restore the irq state */ + spin_lock_irqsave(&shost->free_list_lock, flags); + if (unlikely(list_empty(&shost->free_list))) { + list_add(&cmd->list, &shost->free_list); + cmd = NULL; + } + spin_unlock_irqrestore(&shost->free_list_lock, flags); + + if (likely(cmd != NULL)) + kmem_cache_free(shost->cmd_pool->slab, cmd); + + put_device(dev); +} +EXPORT_SYMBOL(__scsi_put_command); + /* * Function: scsi_put_command() * @@ -231,26 +251,15 @@ EXPORT_SYMBOL(scsi_get_command); void scsi_put_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; unsigned long flags; - + /* serious error if the command hasn't come from a device list */ spin_lock_irqsave(&cmd->device->list_lock, flags); BUG_ON(list_empty(&cmd->list)); list_del_init(&cmd->list); - spin_unlock(&cmd->device->list_lock); - /* changing locks here, don't need to restore the irq state */ - spin_lock(&shost->free_list_lock); - if (unlikely(list_empty(&shost->free_list))) { - list_add(&cmd->list, &shost->free_list); - cmd = NULL; - } - spin_unlock_irqrestore(&shost->free_list_lock, flags); + spin_unlock_irqrestore(&cmd->device->list_lock, flags); - if (likely(cmd != NULL)) - kmem_cache_free(shost->cmd_pool->slab, cmd); - - put_device(&sdev->sdev_gendev); + __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); } EXPORT_SYMBOL(scsi_put_command); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2f12f9f..fb616c6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -704,7 +704,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, return NULL; } -static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) +struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) { struct scsi_host_sg_pool *sgp; struct scatterlist *sgl; @@ -745,7 +745,9 @@ static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_m return sgl; } -static void scsi_free_sgtable(struct scatterlist *sgl, int index) +EXPORT_SYMBOL(scsi_alloc_sgtable); + +void scsi_free_sgtable(struct scatterlist *sgl, int index) { struct scsi_host_sg_pool *sgp; @@ -755,6 +757,8 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index) mempool_free(sgl, sgp->pool); } +EXPORT_SYMBOL(scsi_free_sgtable); + /* * Function: scsi_release_buffers() * @@ -1567,29 +1571,40 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_calculate_bounce_limit); -struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) +struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, + request_fn_proc *request_fn) { - struct Scsi_Host *shost = sdev->host; struct request_queue *q; - q = blk_init_queue(scsi_request_fn, NULL); + q = blk_init_queue(request_fn, NULL); if (!q) return NULL; - blk_queue_prep_rq(q, scsi_prep_fn); - blk_queue_max_hw_segments(q, shost->sg_tablesize); blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); - blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); - blk_queue_softirq_done(q, scsi_softirq_done); if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; } +EXPORT_SYMBOL(__scsi_alloc_queue); + +struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) +{ + struct request_queue *q; + + q = __scsi_alloc_queue(sdev->host, scsi_request_fn); + if (!q) + return NULL; + + blk_queue_prep_rq(q, scsi_prep_fn); + blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); + blk_queue_softirq_done(q, scsi_softirq_done); + return q; +} void scsi_free_queue(struct request_queue *q) { diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index be117f8..d6948d0 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -8,6 +8,7 @@ struct request; struct scatterlist; +struct Scsi_Host; struct scsi_device; @@ -72,6 +73,9 @@ struct scsi_cmnd { unsigned short use_sg; /* Number of pieces of scatter-gather */ unsigned short sglist_len; /* size of malloc'd scatter-gather list */ + /* offset in cmd we are at (for multi-transfer tgt cmds) */ + unsigned offset; + unsigned underflow; /* Return error if less than this amount is transferred */ @@ -119,7 +123,10 @@ struct scsi_cmnd { }; extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); +extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); +extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, + struct device *); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); @@ -128,4 +135,7 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t *offset, size_t *len); extern void scsi_kunmap_atomic_sg(void *virt); +extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t); +extern void scsi_free_sgtable(struct scatterlist *, int); + #endif /* _SCSI_SCSI_CMND_H */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 6d8945d..7f1f411 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -7,6 +7,7 @@ #include #include +struct request_queue; struct block_device; struct completion; struct module; @@ -124,6 +125,39 @@ struct scsi_host_template { void (*done)(struct scsi_cmnd *)); /* + * The transfer functions are used to queue a scsi command to + * the LLD. When the driver is finished processing the command + * the done callback is invoked. + * + * return values: see queuecommand + * + * If the LLD accepts the cmd, it should set the result to an + * appropriate value when completed before calling the done function. + * + * STATUS: REQUIRED FOR TARGET DRIVERS + */ + /* TODO: rename */ + int (* transfer_response)(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); + /* + * This is called to inform the LLD to transfer cmd->request_bufflen + * bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg + * speciefies the number of scatterlist entried in the command + * and cmd->request_buffer contains the scatterlist. + * + * If the command cannot be processed in one transfer_data call + * becuase a scatterlist within the LLD's limits cannot be + * created then transfer_data will be called multiple times. + * It is initially called from process context, and later + * calls are from the interrup context. + */ + int (* transfer_data)(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); + + /* Used as callback for the completion of task management request. */ + int (* tsk_mgmt_response)(u64 mid, int result); + + /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default * routine that is present that should work in most cases. For those @@ -589,6 +623,12 @@ struct Scsi_Host { */ unsigned int max_host_blocked; + /* + * q used for scsi_tgt msgs, async events or any other requests that + * need to be processed in userspace + */ + struct request_queue *uspace_req_q; + /* legacy crap */ unsigned long base; unsigned long io_port; @@ -687,6 +727,9 @@ extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *); struct class_container; + +extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, + void (*) (struct request_queue *)); /* * These two functions are used to allocate and free a pseudo device * which will connect to the host adapter itself rather than any -- cgit v0.10.2 From 5a55c2596f55e3a60f7502d0dfcfa0d20241e5ac Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 16 Nov 2006 19:24:13 +0900 Subject: [SCSI] scsi tgt: scsi target lib functionality The core scsi target lib functions. TODO: - mv md/dm-bio-list.h to linux/bio-list.h so md and us do not have to do that weird include. - convert scsi_tgt_cmd's work struct to James's execute code. And try to kill our scsi_tgt_cmd. - add host state checking. We do refcouting so hotplug is partially supported, but we need to add state checking to make it easier on the LLD. Signed-off-by: Mike Christie Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c new file mode 100644 index 0000000..39da5cd --- /dev/null +++ b/drivers/scsi/scsi_tgt_lib.c @@ -0,0 +1,742 @@ +/* + * SCSI target lib functions + * + * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 FUJITA Tomonori + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../drivers/md/dm-bio-list.h> + +#include "scsi_tgt_priv.h" + +static struct workqueue_struct *scsi_tgtd; +static kmem_cache_t *scsi_tgt_cmd_cache; + +/* + * TODO: this struct will be killed when the block layer supports large bios + * and James's work struct code is in + */ +struct scsi_tgt_cmd { + /* TODO replace work with James b's code */ + struct work_struct work; + /* TODO replace the lists with a large bio */ + struct bio_list xfer_done_list; + struct bio_list xfer_list; + + struct list_head hash_list; + struct request *rq; + u64 tag; + + void *buffer; + unsigned bufflen; +}; + +#define TGT_HASH_ORDER 4 +#define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER) + +struct scsi_tgt_queuedata { + struct Scsi_Host *shost; + struct list_head cmd_hash[1 << TGT_HASH_ORDER]; + spinlock_t cmd_hash_lock; +}; + +/* + * Function: scsi_host_get_command() + * + * Purpose: Allocate and setup a scsi command block and blk request + * + * Arguments: shost - scsi host + * data_dir - dma data dir + * gfp_mask- allocator flags + * + * Returns: The allocated scsi command structure. + * + * This should be called by target LLDs to get a command. + */ +struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, + enum dma_data_direction data_dir, + gfp_t gfp_mask) +{ + int write = (data_dir == DMA_TO_DEVICE); + struct request *rq; + struct scsi_cmnd *cmd; + struct scsi_tgt_cmd *tcmd; + + /* Bail if we can't get a reference to the device */ + if (!get_device(&shost->shost_gendev)) + return NULL; + + tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC); + if (!tcmd) + goto put_dev; + + rq = blk_get_request(shost->uspace_req_q, write, gfp_mask); + if (!rq) + goto free_tcmd; + + cmd = __scsi_get_command(shost, gfp_mask); + if (!cmd) + goto release_rq; + + memset(cmd, 0, sizeof(*cmd)); + cmd->sc_data_direction = data_dir; + cmd->jiffies_at_alloc = jiffies; + cmd->request = rq; + + rq->special = cmd; + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_flags |= REQ_TYPE_BLOCK_PC; + rq->end_io_data = tcmd; + + bio_list_init(&tcmd->xfer_list); + bio_list_init(&tcmd->xfer_done_list); + tcmd->rq = rq; + + return cmd; + +release_rq: + blk_put_request(rq); +free_tcmd: + kmem_cache_free(scsi_tgt_cmd_cache, tcmd); +put_dev: + put_device(&shost->shost_gendev); + return NULL; + +} +EXPORT_SYMBOL_GPL(scsi_host_get_command); + +/* + * Function: scsi_host_put_command() + * + * Purpose: Free a scsi command block + * + * Arguments: shost - scsi host + * cmd - command block to free + * + * Returns: Nothing. + * + * Notes: The command must not belong to any lists. + */ +void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + struct request_queue *q = shost->uspace_req_q; + struct request *rq = cmd->request; + struct scsi_tgt_cmd *tcmd = rq->end_io_data; + unsigned long flags; + + kmem_cache_free(scsi_tgt_cmd_cache, tcmd); + + spin_lock_irqsave(q->queue_lock, flags); + __blk_put_request(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); + + __scsi_put_command(shost, cmd, &shost->shost_gendev); +} +EXPORT_SYMBOL_GPL(scsi_host_put_command); + +static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) +{ + struct bio *bio; + + /* must call bio_endio in case bio was bounced */ + while ((bio = bio_list_pop(&tcmd->xfer_done_list))) { + bio_endio(bio, bio->bi_size, 0); + bio_unmap_user(bio); + } + + while ((bio = bio_list_pop(&tcmd->xfer_list))) { + bio_endio(bio, bio->bi_size, 0); + bio_unmap_user(bio); + } +} + +static void cmd_hashlist_del(struct scsi_cmnd *cmd) +{ + struct request_queue *q = cmd->request->q; + struct scsi_tgt_queuedata *qdata = q->queuedata; + unsigned long flags; + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + list_del(&tcmd->hash_list); + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); +} + +static void scsi_tgt_cmd_destroy(void *data) +{ + struct scsi_cmnd *cmd = data; + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + + dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction, + rq_data_dir(cmd->request)); + /* + * We fix rq->cmd_flags here since when we told bio_map_user + * to write vm for WRITE commands, blk_rq_bio_prep set + * rq_data_dir the flags to READ. + */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) + cmd->request->cmd_flags |= REQ_RW; + else + cmd->request->cmd_flags &= ~REQ_RW; + + scsi_unmap_user_pages(tcmd); + scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); +} + +static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, + u64 tag) +{ + struct scsi_tgt_queuedata *qdata = rq->q->queuedata; + unsigned long flags; + struct list_head *head; + + tcmd->tag = tag; + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + head = &qdata->cmd_hash[cmd_hashfn(tag)]; + list_add(&tcmd->hash_list, head); + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); +} + +/* + * scsi_tgt_alloc_queue - setup queue used for message passing + * shost: scsi host + * + * This should be called by the LLD after host allocation. + * And will be released when the host is released. + */ +int scsi_tgt_alloc_queue(struct Scsi_Host *shost) +{ + struct scsi_tgt_queuedata *queuedata; + struct request_queue *q; + int err, i; + + /* + * Do we need to send a netlink event or should uspace + * just respond to the hotplug event? + */ + q = __scsi_alloc_queue(shost, NULL); + if (!q) + return -ENOMEM; + + queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL); + if (!queuedata) { + err = -ENOMEM; + goto cleanup_queue; + } + queuedata->shost = shost; + q->queuedata = queuedata; + + /* + * this is a silly hack. We should probably just queue as many + * command as is recvd to userspace. uspace can then make + * sure we do not overload the HBA + */ + q->nr_requests = shost->hostt->can_queue; + /* + * We currently only support software LLDs so this does + * not matter for now. Do we need this for the cards we support? + * If so we should make it a host template value. + */ + blk_queue_dma_alignment(q, 0); + shost->uspace_req_q = q; + + for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++) + INIT_LIST_HEAD(&queuedata->cmd_hash[i]); + spin_lock_init(&queuedata->cmd_hash_lock); + + return 0; + +cleanup_queue: + blk_cleanup_queue(q); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue); + +void scsi_tgt_free_queue(struct Scsi_Host *shost) +{ + int i; + unsigned long flags; + struct request_queue *q = shost->uspace_req_q; + struct scsi_cmnd *cmd; + struct scsi_tgt_queuedata *qdata = q->queuedata; + struct scsi_tgt_cmd *tcmd, *n; + LIST_HEAD(cmds); + + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + + for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) { + list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i], + hash_list) { + list_del(&tcmd->hash_list); + list_add(&tcmd->hash_list, &cmds); + } + } + + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); + + while (!list_empty(&cmds)) { + tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list); + list_del(&tcmd->hash_list); + cmd = tcmd->rq->special; + + shost->hostt->eh_abort_handler(cmd); + scsi_tgt_cmd_destroy(cmd); + } +} +EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); + +struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata; + return queue->shost; +} +EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); + +/* + * scsi_tgt_queue_command - queue command for userspace processing + * @cmd: scsi command + * @scsilun: scsi lun + * @tag: unique value to identify this command for tmf + */ +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, + u64 tag) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + int err; + + init_scsi_tgt_cmd(cmd->request, tcmd, tag); + err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); + if (err) + cmd_hashlist_del(cmd); + + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_queue_command); + +/* + * This is run from a interrpt handler normally and the unmap + * needs process context so we must queue + */ +static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + + dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); + + scsi_tgt_uspace_send_status(cmd, tcmd->tag); + INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy, cmd); + queue_work(scsi_tgtd, &tcmd->work); +} + +static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + int err; + + dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); + + err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done); + switch (err) { + case SCSI_MLQUEUE_HOST_BUSY: + case SCSI_MLQUEUE_DEVICE_BUSY: + return -EAGAIN; + } + + return 0; +} + +static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + int err; + + err = __scsi_tgt_transfer_response(cmd); + if (!err) + return; + + cmd->result = DID_BUS_BUSY << 16; + err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); + if (err <= 0) + /* the eh will have to pick this up */ + printk(KERN_ERR "Could not send cmd %p status\n", cmd); +} + +static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) +{ + struct request *rq = cmd->request; + struct scsi_tgt_cmd *tcmd = rq->end_io_data; + int count; + + cmd->use_sg = rq->nr_phys_segments; + cmd->request_buffer = scsi_alloc_sgtable(cmd, gfp_mask); + if (!cmd->request_buffer) + return -ENOMEM; + + cmd->request_bufflen = rq->data_len; + + dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg, + rq_data_dir(rq)); + count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer); + if (likely(count <= cmd->use_sg)) { + cmd->use_sg = count; + return 0; + } + + eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg); + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); + return -EINVAL; +} + +/* TODO: test this crap and replace bio_map_user with new interface maybe */ +static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, + int rw) +{ + struct request_queue *q = cmd->request->q; + struct request *rq = cmd->request; + void *uaddr = tcmd->buffer; + unsigned int len = tcmd->bufflen; + struct bio *bio; + int err; + + while (len > 0) { + dprintk("%lx %u\n", (unsigned long) uaddr, len); + bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw); + if (IS_ERR(bio)) { + err = PTR_ERR(bio); + dprintk("fail to map %lx %u %d %x\n", + (unsigned long) uaddr, len, err, cmd->cmnd[0]); + goto unmap_bios; + } + + uaddr += bio->bi_size; + len -= bio->bi_size; + + /* + * The first bio is added and merged. We could probably + * try to add others using scsi_merge_bio() but for now + * we keep it simple. The first bio should be pretty large + * (either hitting the 1 MB bio pages limit or a queue limit) + * already but for really large IO we may want to try and + * merge these. + */ + if (!rq->bio) { + blk_rq_bio_prep(q, rq, bio); + rq->data_len = bio->bi_size; + } else + /* put list of bios to transfer in next go around */ + bio_list_add(&tcmd->xfer_list, bio); + } + + cmd->offset = 0; + err = scsi_tgt_init_cmd(cmd, GFP_KERNEL); + if (err) + goto unmap_bios; + + return 0; + +unmap_bios: + if (rq->bio) { + bio_unmap_user(rq->bio); + while ((bio = bio_list_pop(&tcmd->xfer_list))) + bio_unmap_user(bio); + } + + return err; +} + +static int scsi_tgt_transfer_data(struct scsi_cmnd *); + +static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + struct bio *bio; + int err; + + /* should we free resources here on error ? */ + if (cmd->result) { +send_uspace_err: + err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); + if (err <= 0) + /* the tgt uspace eh will have to pick this up */ + printk(KERN_ERR "Could not send cmd %p status\n", cmd); + return; + } + + dprintk("cmd %p request_bufflen %u bufflen %u\n", + cmd, cmd->request_bufflen, tcmd->bufflen); + + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); + bio_list_add(&tcmd->xfer_done_list, cmd->request->bio); + + tcmd->buffer += cmd->request_bufflen; + cmd->offset += cmd->request_bufflen; + + if (!tcmd->xfer_list.head) { + scsi_tgt_transfer_response(cmd); + return; + } + + dprintk("cmd2 %p request_bufflen %u bufflen %u\n", + cmd, cmd->request_bufflen, tcmd->bufflen); + + bio = bio_list_pop(&tcmd->xfer_list); + BUG_ON(!bio); + + blk_rq_bio_prep(cmd->request->q, cmd->request, bio); + cmd->request->data_len = bio->bi_size; + err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC); + if (err) { + cmd->result = DID_ERROR << 16; + goto send_uspace_err; + } + + if (scsi_tgt_transfer_data(cmd)) { + cmd->result = DID_NO_CONNECT << 16; + goto send_uspace_err; + } +} + +static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd) +{ + int err; + struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd); + + err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done); + switch (err) { + case SCSI_MLQUEUE_HOST_BUSY: + case SCSI_MLQUEUE_DEVICE_BUSY: + return -EAGAIN; + default: + return 0; + } +} + +static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, + unsigned len) +{ + char __user *p = (char __user *) uaddr; + + if (copy_from_user(cmd->sense_buffer, p, + min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) { + printk(KERN_ERR "Could not copy the sense buffer\n"); + return -EIO; + } + return 0; +} + +static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + int err; + + err = shost->hostt->eh_abort_handler(cmd); + if (err) + eprintk("fail to abort %p\n", cmd); + + scsi_tgt_cmd_destroy(cmd); + return err; +} + +static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) +{ + struct scsi_tgt_queuedata *qdata = q->queuedata; + struct request *rq = NULL; + struct list_head *head; + struct scsi_tgt_cmd *tcmd; + unsigned long flags; + + head = &qdata->cmd_hash[cmd_hashfn(tag)]; + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + list_for_each_entry(tcmd, head, hash_list) { + if (tcmd->tag == tag) { + rq = tcmd->rq; + list_del(&tcmd->hash_list); + break; + } + } + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); + + return rq; +} + +int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, + unsigned long uaddr, u8 rw) +{ + struct Scsi_Host *shost; + struct scsi_cmnd *cmd; + struct request *rq; + struct scsi_tgt_cmd *tcmd; + int err = 0; + + dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag, + result, len, uaddr, rw); + + /* TODO: replace with a O(1) alg */ + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return -EINVAL; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag); + if (!rq) { + printk(KERN_ERR "Could not find tag %llu\n", + (unsigned long long) tag); + err = -EINVAL; + goto done; + } + cmd = rq->special; + + dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd, + result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]); + + if (result == TASK_ABORTED) { + scsi_tgt_abort_cmd(shost, cmd); + goto done; + } + /* + * store the userspace values here, the working values are + * in the request_* values + */ + tcmd = cmd->request->end_io_data; + tcmd->buffer = (void *)uaddr; + tcmd->bufflen = len; + cmd->result = result; + + if (!tcmd->bufflen || cmd->request_buffer) { + err = __scsi_tgt_transfer_response(cmd); + goto done; + } + + /* + * TODO: Do we need to handle case where request does not + * align with LLD. + */ + err = scsi_map_user_pages(rq->end_io_data, cmd, rw); + if (err) { + eprintk("%p %d\n", cmd, err); + err = -EAGAIN; + goto done; + } + + /* userspace failure */ + if (cmd->result) { + if (status_byte(cmd->result) == CHECK_CONDITION) + scsi_tgt_copy_sense(cmd, uaddr, len); + err = __scsi_tgt_transfer_response(cmd); + goto done; + } + /* ask the target LLD to transfer the data to the buffer */ + err = scsi_tgt_transfer_data(cmd); + +done: + scsi_host_put(shost); + return err; +} + +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, + struct scsi_lun *scsilun, void *data) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, + tag, scsilun, data); + if (err < 0) + eprintk("The task management request lost!\n"); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); + +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) +{ + struct Scsi_Host *shost; + int err = -EINVAL; + + dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); + + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return err; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + err = shost->hostt->tsk_mgmt_response(mid, result); +done: + scsi_host_put(shost); + return err; +} + +static int __init scsi_tgt_init(void) +{ + int err; + + scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd", + sizeof(struct scsi_tgt_cmd), + 0, 0, NULL, NULL); + if (!scsi_tgt_cmd_cache) + return -ENOMEM; + + scsi_tgtd = create_workqueue("scsi_tgtd"); + if (!scsi_tgtd) { + err = -ENOMEM; + goto free_kmemcache; + } + + err = scsi_tgt_if_init(); + if (err) + goto destroy_wq; + + return 0; + +destroy_wq: + destroy_workqueue(scsi_tgtd); +free_kmemcache: + kmem_cache_destroy(scsi_tgt_cmd_cache); + return err; +} + +static void __exit scsi_tgt_exit(void) +{ + destroy_workqueue(scsi_tgtd); + scsi_tgt_if_exit(); + kmem_cache_destroy(scsi_tgt_cmd_cache); +} + +module_init(scsi_tgt_init); +module_exit(scsi_tgt_exit); + +MODULE_DESCRIPTION("SCSI target core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h new file mode 100644 index 0000000..84488c5 --- /dev/null +++ b/drivers/scsi/scsi_tgt_priv.h @@ -0,0 +1,25 @@ +struct scsi_cmnd; +struct scsi_lun; +struct Scsi_Host; +struct task_struct; + +/* tmp - will replace with SCSI logging stuff */ +#define eprintk(fmt, args...) \ +do { \ + printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ +} while (0) + +#define dprintk(fmt, args...) +/* #define dprintk eprintk */ + +extern void scsi_tgt_if_exit(void); +extern int scsi_tgt_if_init(void); + +extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, + u64 tag); +extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); +extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, + unsigned long uaddr, u8 rw); +extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, + struct scsi_lun *scsilun, void *data); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h new file mode 100644 index 0000000..4f44279 --- /dev/null +++ b/include/scsi/scsi_tgt.h @@ -0,0 +1,19 @@ +/* + * SCSI target definitions + */ + +#include + +struct Scsi_Host; +struct scsi_cmnd; +struct scsi_lun; + +extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); +extern int scsi_tgt_alloc_queue(struct Scsi_Host *); +extern void scsi_tgt_free_queue(struct Scsi_Host *); +extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); +extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, + void *); +extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, + enum dma_data_direction, gfp_t); +extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); -- cgit v0.10.2 From 97f78759ea1cb7d27b61095582de78b8e7486e85 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 16 Nov 2006 19:24:16 +0900 Subject: [SCSI] scsi tgt: scsi target user and kernel communication interface The user-space daemon and tgt kernel module need bi-directional kernel/user high-performance interface, however, mainline provides no standard interface like that. This patch adds shared memory interface between kernel and user spaces like some other drivers do by using own character device. The user-space daemon and tgt kernel module creates shared memory via mmap and use it like ring buffer. poll (kernel to user) and write (user to kernel) system calls are used for notification. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c new file mode 100644 index 0000000..28fd222 --- /dev/null +++ b/drivers/scsi/scsi_tgt_if.c @@ -0,0 +1,350 @@ +/* + * SCSI target kernel/user interface functions + * + * Copyright (C) 2005 FUJITA Tomonori + * Copyright (C) 2005 Mike Christie + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi_tgt_priv.h" + +struct tgt_ring { + u32 tr_idx; + unsigned long tr_pages[TGT_RING_PAGES]; + spinlock_t tr_lock; +}; + +/* tx_ring : kernel->user, rx_ring : user->kernel */ +static struct tgt_ring tx_ring, rx_ring; +static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait); + +static inline void tgt_ring_idx_inc(struct tgt_ring *ring) +{ + if (ring->tr_idx == TGT_MAX_EVENTS - 1) + ring->tr_idx = 0; + else + ring->tr_idx++; +} + +static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx) +{ + u32 pidx, off; + + pidx = idx / TGT_EVENT_PER_PAGE; + off = idx % TGT_EVENT_PER_PAGE; + + return (struct tgt_event *) + (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off); +} + +static int tgt_uspace_send_event(u32 type, struct tgt_event *p) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &tx_ring; + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&ring->tr_lock, flags); + + ev = tgt_head_event(ring, ring->tr_idx); + if (!ev->hdr.status) + tgt_ring_idx_inc(ring); + else + err = -BUSY; + + spin_unlock_irqrestore(&ring->tr_lock, flags); + + if (err) + return err; + + memcpy(ev, p, sizeof(*ev)); + ev->hdr.type = type; + mb(); + ev->hdr.status = 1; + + flush_dcache_page(virt_to_page(ev)); + + wake_up_interruptible(&tgt_poll_wait); + + return 0; +} + +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.cmd_req.host_no = shost->host_no; + ev.p.cmd_req.data_len = cmd->request_bufflen; + memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); + memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); + ev.p.cmd_req.attribute = cmd->tag; + ev.p.cmd_req.tag = tag; + + dprintk("%p %d %u %x %llx\n", cmd, shost->host_no, + ev.p.cmd_req.data_len, cmd->tag, + (unsigned long long) ev.p.cmd_req.tag); + + err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.cmd_done.host_no = shost->host_no; + ev.p.cmd_done.tag = tag; + ev.p.cmd_done.result = cmd->result; + + dprintk("%p %d %llu %u %x\n", cmd, shost->host_no, + (unsigned long long) ev.p.cmd_req.tag, + ev.p.cmd_req.data_len, cmd->tag); + + err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, + struct scsi_lun *scsilun, void *data) +{ + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.tsk_mgmt_req.host_no = host_no; + ev.p.tsk_mgmt_req.function = function; + ev.p.tsk_mgmt_req.tag = tag; + memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); + ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data; + + dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag, + (unsigned long long) ev.p.tsk_mgmt_req.mid); + + err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +static int event_recv_msg(struct tgt_event *ev) +{ + int err = 0; + + switch (ev->hdr.type) { + case TGT_UEVENT_CMD_RSP: + err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, + ev->p.cmd_rsp.tag, + ev->p.cmd_rsp.result, + ev->p.cmd_rsp.len, + ev->p.cmd_rsp.uaddr, + ev->p.cmd_rsp.rw); + break; + case TGT_UEVENT_TSK_MGMT_RSP: + err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, + ev->p.tsk_mgmt_rsp.mid, + ev->p.tsk_mgmt_rsp.result); + break; + default: + eprintk("unknown type %d\n", ev->hdr.type); + err = -EINVAL; + } + + return err; +} + +static ssize_t tgt_write(struct file *file, const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &rx_ring; + + while (1) { + ev = tgt_head_event(ring, ring->tr_idx); + /* do we need this? */ + flush_dcache_page(virt_to_page(ev)); + + if (!ev->hdr.status) + break; + + tgt_ring_idx_inc(ring); + event_recv_msg(ev); + ev->hdr.status = 0; + }; + + return count; +} + +static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &tx_ring; + unsigned long flags; + unsigned int mask = 0; + u32 idx; + + poll_wait(file, &tgt_poll_wait, wait); + + spin_lock_irqsave(&ring->tr_lock, flags); + + idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1; + ev = tgt_head_event(ring, idx); + if (ev->hdr.status) + mask |= POLLIN | POLLRDNORM; + + spin_unlock_irqrestore(&ring->tr_lock, flags); + + return mask; +} + +static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr, + struct tgt_ring *ring) +{ + int i, err; + + for (i = 0; i < TGT_RING_PAGES; i++) { + struct page *page = virt_to_page(ring->tr_pages[i]); + err = vm_insert_page(vma, addr, page); + if (err) + return err; + addr += PAGE_SIZE; + } + + return 0; +} + +static int tgt_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long addr; + int err; + + if (vma->vm_pgoff) + return -EINVAL; + + if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) { + eprintk("mmap size must be %lu, not %lu \n", + TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start); + return -EINVAL; + } + + addr = vma->vm_start; + err = uspace_ring_map(vma, addr, &tx_ring); + if (err) + return err; + err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring); + + return err; +} + +static int tgt_open(struct inode *inode, struct file *file) +{ + tx_ring.tr_idx = rx_ring.tr_idx = 0; + + return 0; +} + +static struct file_operations tgt_fops = { + .owner = THIS_MODULE, + .open = tgt_open, + .poll = tgt_poll, + .write = tgt_write, + .mmap = tgt_mmap, +}; + +static struct miscdevice tgt_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "tgt", + .fops = &tgt_fops, +}; + +static void tgt_ring_exit(struct tgt_ring *ring) +{ + int i; + + for (i = 0; i < TGT_RING_PAGES; i++) + free_page(ring->tr_pages[i]); +} + +static int tgt_ring_init(struct tgt_ring *ring) +{ + int i; + + spin_lock_init(&ring->tr_lock); + + for (i = 0; i < TGT_RING_PAGES; i++) { + ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL); + if (!ring->tr_pages[i]) { + eprintk("out of memory\n"); + return -ENOMEM; + } + } + + return 0; +} + +void scsi_tgt_if_exit(void) +{ + tgt_ring_exit(&tx_ring); + tgt_ring_exit(&rx_ring); + misc_deregister(&tgt_miscdev); +} + +int scsi_tgt_if_init(void) +{ + int err; + + err = tgt_ring_init(&tx_ring); + if (err) + return err; + + err = tgt_ring_init(&rx_ring); + if (err) + goto free_tx_ring; + + err = misc_register(&tgt_miscdev); + if (err) + goto free_rx_ring; + + return 0; +free_rx_ring: + tgt_ring_exit(&rx_ring); +free_tx_ring: + tgt_ring_exit(&tx_ring); + + return err; +} diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h new file mode 100644 index 0000000..46d5e70 --- /dev/null +++ b/include/scsi/scsi_tgt_if.h @@ -0,0 +1,90 @@ +/* + * SCSI target kernel/user interface + * + * Copyright (C) 2005 FUJITA Tomonori + * Copyright (C) 2005 Mike Christie + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#ifndef __SCSI_TARGET_IF_H +#define __SCSI_TARGET_IF_H + +/* user -> kernel */ +#define TGT_UEVENT_CMD_RSP 0x0001 +#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 + +/* kernel -> user */ +#define TGT_KEVENT_CMD_REQ 0x1001 +#define TGT_KEVENT_CMD_DONE 0x1002 +#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 + +struct tgt_event_hdr { + uint16_t version; + uint16_t status; + uint16_t type; + uint16_t len; +} __attribute__ ((aligned (sizeof(uint64_t)))); + +struct tgt_event { + struct tgt_event_hdr hdr; + + union { + /* user-> kernel */ + struct { + int host_no; + uint32_t len; + int result; + aligned_u64 uaddr; + uint8_t rw; + aligned_u64 tag; + } cmd_rsp; + struct { + int host_no; + aligned_u64 mid; + int result; + } tsk_mgmt_rsp; + + + /* kernel -> user */ + struct { + int host_no; + uint32_t data_len; + uint8_t scb[16]; + uint8_t lun[8]; + int attribute; + aligned_u64 tag; + } cmd_req; + struct { + int host_no; + aligned_u64 tag; + int result; + } cmd_done; + struct { + int host_no; + int function; + aligned_u64 tag; + uint8_t lun[8]; + aligned_u64 mid; + } tsk_mgmt_req; + } p; +} __attribute__ ((aligned (sizeof(uint64_t)))); + +#define TGT_RING_SIZE (1UL << 16) +#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT) +#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event)) +#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES) + +#endif -- cgit v0.10.2 From 0d2db302f95747908123e56fa8659c7eb2eb7498 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 16 Nov 2006 19:24:18 +0900 Subject: [SCSI] scsi-ml: Makefile and Kconfig changes for tgt Makefile and Kconfig for tgt. Signed-off-by: Mike Christie Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8442be1..1301d52 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -29,6 +29,13 @@ config SCSI However, do not compile this as a module if your root file system (the one containing the directory /) is located on a SCSI device. +config SCSI_TGT + tristate "SCSI target support" + depends on SCSI && EXPERIMENTAL + ---help--- + If you want to use SCSI target mode drivers enable this option. + If you choose M, the module will be called scsi_tgt. + config SCSI_NETLINK bool default n diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index a0a77fd..8f86c1b 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -21,6 +21,7 @@ CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM subdir-$(CONFIG_PCMCIA) += pcmcia obj-$(CONFIG_SCSI) += scsi_mod.o +obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o @@ -151,6 +152,8 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o +scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o + sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ -- cgit v0.10.2 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 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a20d84d..21d83a8 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 v0.10.2 From a26d79ca81d6e46c445c8db87a89740c9b4d17e9 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 25 Nov 2006 11:09:18 -0800 Subject: [PATCH] initramfs: handle more than one source dir or file list Fix bug 7401. Handle more than one source dir or file list to the initramfs gen scripts. The Kconfig help for INITRAMFS_SOURCE claims that you can specify multiple space-separated sources in order to allow unprivileged users to build an image. There are two bugs in the current implementation that prevent this from working. First, we pass "file1 dir2" to the gen_initramfs_list.sh script, which it obviously can't open. Second, gen_initramfs_list.sh -l outputs multiple definitions for deps_initramfs -- one for each argument. Signed-off-by: Thomas Chou Cc: Sam Ravnborg Acked-by: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 331c079..4c723fd 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -158,7 +158,7 @@ unknown_option() { } list_header() { - echo "deps_initramfs := \\" + : } header() { @@ -227,6 +227,7 @@ arg="$1" case "$arg" in "-l") # files included in initramfs - used by kbuild dep_list="list_" + echo "deps_initramfs := \\" shift ;; "-o") # generate gzipped cpio image named $1 diff --git a/usr/Makefile b/usr/Makefile index e338e7b..382702a 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -20,7 +20,7 @@ $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE hostprogs-y := gen_init_cpio initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \ - $(CONFIG_INITRAMFS_SOURCE),-d) + $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d) ramfs-args := \ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) -- cgit v0.10.2 From 2d51013ed2f2b6a5d2369b7fbbd989df1f6369e2 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Sat, 25 Nov 2006 11:09:20 -0800 Subject: [PATCH] fuse: fix Oops in lookup Fix bug in certain error paths of lookup routines. The request object was reused for sending FORGET, which is illegal. This bug could cause an Oops in 2.6.18. In earlier versions it might silently corrupt memory, but this is very unlikely. These error paths are never triggered by libfuse, so this wasn't noticed even with the 2.6.18 kernel, only with a filesystem using the raw kernel interface. Thanks to Russ Cox for the bug report and test filesystem. Signed-off-by: Miklos Szeredi Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index cfc8f81..c71a6c0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -138,6 +138,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) struct fuse_entry_out outarg; struct fuse_conn *fc; struct fuse_req *req; + struct fuse_req *forget_req; struct dentry *parent; /* Doesn't hurt to "reset" the validity timeout */ @@ -152,25 +153,33 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) if (IS_ERR(req)) return 0; + forget_req = fuse_get_req(fc); + if (IS_ERR(forget_req)) { + fuse_put_request(fc, req); + return 0; + } + parent = dget_parent(entry); fuse_lookup_init(req, parent->d_inode, entry, &outarg); request_send(fc, req); dput(parent); err = req->out.h.error; + fuse_put_request(fc, req); /* Zero nodeid is same as -ENOENT */ if (!err && !outarg.nodeid) err = -ENOENT; if (!err) { struct fuse_inode *fi = get_fuse_inode(inode); if (outarg.nodeid != get_node_id(inode)) { - fuse_send_forget(fc, req, outarg.nodeid, 1); + fuse_send_forget(fc, forget_req, + outarg.nodeid, 1); return 0; } spin_lock(&fc->lock); fi->nlookup ++; spin_unlock(&fc->lock); } - fuse_put_request(fc, req); + fuse_put_request(fc, forget_req); if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) return 0; @@ -221,6 +230,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct inode *inode = NULL; struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_req *req; + struct fuse_req *forget_req; if (entry->d_name.len > FUSE_NAME_MAX) return ERR_PTR(-ENAMETOOLONG); @@ -229,9 +239,16 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, if (IS_ERR(req)) return ERR_PTR(PTR_ERR(req)); + forget_req = fuse_get_req(fc); + if (IS_ERR(forget_req)) { + fuse_put_request(fc, req); + return ERR_PTR(PTR_ERR(forget_req)); + } + fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); err = req->out.h.error; + fuse_put_request(fc, req); /* Zero nodeid is same as -ENOENT, but with valid timeout */ if (!err && outarg.nodeid && (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode))) @@ -240,11 +257,11 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { - fuse_send_forget(fc, req, outarg.nodeid, 1); + fuse_send_forget(fc, forget_req, outarg.nodeid, 1); return ERR_PTR(-ENOMEM); } } - fuse_put_request(fc, req); + fuse_put_request(fc, forget_req); if (err && err != -ENOENT) return ERR_PTR(err); @@ -388,6 +405,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct fuse_entry_out outarg; struct inode *inode; int err; + struct fuse_req *forget_req; + + forget_req = fuse_get_req(fc); + if (IS_ERR(forget_req)) { + fuse_put_request(fc, req); + return PTR_ERR(forget_req); + } req->in.h.nodeid = get_node_id(dir); req->out.numargs = 1; @@ -395,24 +419,24 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, req->out.args[0].value = &outarg; request_send(fc, req); err = req->out.h.error; - if (err) { - fuse_put_request(fc, req); - return err; - } + fuse_put_request(fc, req); + if (err) + goto out_put_forget_req; + err = -EIO; if (invalid_nodeid(outarg.nodeid)) - goto out_put_request; + goto out_put_forget_req; if ((outarg.attr.mode ^ mode) & S_IFMT) - goto out_put_request; + goto out_put_forget_req; inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { - fuse_send_forget(fc, req, outarg.nodeid, 1); + fuse_send_forget(fc, forget_req, outarg.nodeid, 1); return -ENOMEM; } - fuse_put_request(fc, req); + fuse_put_request(fc, forget_req); if (S_ISDIR(inode->i_mode)) { struct dentry *alias; @@ -434,8 +458,8 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, fuse_invalidate_attr(dir); return 0; - out_put_request: - fuse_put_request(fc, req); + out_put_forget_req: + fuse_put_request(fc, forget_req); return err; } -- cgit v0.10.2 From 701e054e0c2db82359f0454c7ed4fd24346d52eb Mon Sep 17 00:00:00 2001 From: Vasily Tarasov Date: Sat, 25 Nov 2006 11:09:22 -0800 Subject: [PATCH] mounstats NULL pointer dereference OpenVZ developers team has encountered the following problem in 2.6.19-rc6 kernel. After some seconds of running script while [[ 1 ]] do find /proc -name mountstats | xargs cat done this Oops appears: BUG: unable to handle kernel NULL pointer dereference at virtual address 00000010 printing eip: c01a6b70 *pde = 00000000 Oops: 0000 [#1] SMP Modules linked in: xt_length ipt_ttl xt_tcpmss ipt_TCPMSS iptable_mangle iptable_filter xt_multiport xt_limit ipt_tos ipt_REJECT ip_tables x_tables parport_pc lp parport sunrpc af_packet thermal processor fan button battery asus_acpi ac ohci_hcd ehci_hcd usbcore i2c_nforce2 i2c_core tg3 floppy pata_amd ide_cd cdrom sata_nv libata CPU: 1 EIP: 0060:[] Not tainted VLI EFLAGS: 00010246 (2.6.19-rc6 #2) EIP is at mountstats_open+0x70/0xf0 eax: 00000000 ebx: e6247030 ecx: e62470f8 edx: 00000000 esi: 00000000 edi: c01a6b00 ebp: c33b83c0 esp: f4105eb4 ds: 007b es: 007b ss: 0068 Process cat (pid: 6044, ti=f4105000 task=f4104a70 task.ti=f4105000) Stack: c33b83c0 c04ee940 f46a4a80 c33b83c0 e4df31b4 c01a6b00 f4105000 c0169231 e4df31b4 c33b83c0 c33b83c0 f4105f20 00000003 f4105000 c0169445 f2503cf0 f7f8c4c0 00008000 c33b83c0 00000000 00008000 c0169350 f4105f20 00008000 Call Trace: [] mountstats_open+0x0/0xf0 [] __dentry_open+0x181/0x250 [] nameidata_to_filp+0x35/0x50 [] do_filp_open+0x50/0x60 [] seq_read+0xc6/0x300 [] get_unused_fd+0x31/0xc0 [] do_sys_open+0x63/0x110 [] sys_open+0x27/0x30 [] sysenter_past_esp+0x56/0x79 ======================= Code: 45 74 8b 54 24 20 89 44 24 08 8b 42 f0 31 d2 e8 47 cb f8 ff 85 c0 89 c3 74 51 8d 80 a0 04 00 00 e8 46 06 2c 00 8b 83 48 04 00 00 <8b> 78 10 85 ff 74 03 f0 ff 07 b0 01 86 83 a0 04 00 00 f0 ff 4b EIP: [] mountstats_open+0x70/0xf0 SS:ESP 0068:f4105eb4 The problem is that task->nsproxy can be equal NULL for some time during task exit. This patch fixes the BUG. Signed-off-by: Vasily Tarasov Cc: Herbert Poetzl Cc: "Serge E. Hallyn" Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 8df27401..795319c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -442,7 +442,8 @@ static int mountstats_open(struct inode *inode, struct file *file) if (task) { task_lock(task); - namespace = task->nsproxy->namespace; + if (task->nsproxy) + namespace = task->nsproxy->namespace; if (namespace) get_namespace(namespace); task_unlock(task); diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index f6baecd..971d1c6 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h @@ -45,8 +45,10 @@ static inline void exit_task_namespaces(struct task_struct *p) { struct nsproxy *ns = p->nsproxy; if (ns) { - put_nsproxy(ns); + task_lock(p); p->nsproxy = NULL; + task_unlock(p); + put_nsproxy(ns); } } #endif -- cgit v0.10.2 From 4d8ebddcc525a5800dab5880946cecffe73e9dca Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 25 Nov 2006 11:09:26 -0800 Subject: [PATCH] debugfs: add header file debugfs needs include/linux/kobject.h for . Signed-off-by: Randy Dunlap Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index a736d44..137d76c 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include -- cgit v0.10.2 From 7531d8faa85f8880db433027bf2b04950e49baeb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 25 Nov 2006 11:09:26 -0800 Subject: [PATCH] Documentation/rtc.txt updates (for rtc class) This updates the RTC documentation to summarize the two APIs now available: the old PC/AT one, and the new RTC class drivers. It also updates the included "rtctest.c" file to better meet Linux style guidelines, and to work with the new RTC drivers. Signed-off-by: David Brownell Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt index 2a58f98..7cf1ec5 100644 --- a/Documentation/rtc.txt +++ b/Documentation/rtc.txt @@ -1,12 +1,49 @@ - Real Time Clock Driver for Linux - ================================ + Real Time Clock (RTC) Drivers for Linux + ======================================= + +When Linux developers talk about a "Real Time Clock", they usually mean +something that tracks wall clock time and is battery backed so that it +works even with system power off. Such clocks will normally not track +the local time zone or daylight savings time -- unless they dual boot +with MS-Windows -- but will instead be set to Coordinated Universal Time +(UTC, formerly "Greenwich Mean Time"). + +The newest non-PC hardware tends to just count seconds, like the time(2) +system call reports, but RTCs also very commonly represent time using +the Gregorian calendar and 24 hour time, as reported by gmtime(3). + +Linux has two largely-compatible userspace RTC API families you may +need to know about: + + * /dev/rtc ... is the RTC provided by PC compatible systems, + so it's not very portable to non-x86 systems. + + * /dev/rtc0, /dev/rtc1 ... are part of a framework that's + supported by a wide variety of RTC chips on all systems. + +Programmers need to understand that the PC/AT functionality is not +always available, and some systems can do much more. That is, the +RTCs use the same API to make requests in both RTC frameworks (using +different filenames of course), but the hardware may not offer the +same functionality. For example, not every RTC is hooked up to an +IRQ, so they can't all issue alarms; and where standard PC RTCs can +only issue an alarm up to 24 hours in the future, other hardware may +be able to schedule one any time in the upcoming century. + + + Old PC/AT-Compatible driver: /dev/rtc + -------------------------------------- All PCs (even Alpha machines) have a Real Time Clock built into them. Usually they are built into the chipset of the computer, but some may actually have a Motorola MC146818 (or clone) on the board. This is the clock that keeps the date and time while your computer is turned off. +ACPI has standardized that MC146818 functionality, and extended it in +a few ways (enabling longer alarm periods, and wake-from-hibernate). +That functionality is NOT exposed in the old driver. + However it can also be used to generate signals from a slow 2Hz to a relatively fast 8192Hz, in increments of powers of two. These signals are reported by interrupt number 8. (Oh! So *that* is what IRQ 8 is @@ -63,223 +100,331 @@ Rather than write 50 pages describing the ioctl() and so on, it is perhaps more useful to include a small test program that demonstrates how to use them, and demonstrates the features of the driver. This is probably a lot more useful to people interested in writing applications -that will be using this driver. +that will be using this driver. See the code at the end of this document. + +(The original /dev/rtc driver was written by Paul Gortmaker.) + + + New portable "RTC Class" drivers: /dev/rtcN + -------------------------------------------- + +Because Linux supports many non-ACPI and non-PC platforms, some of which +have more than one RTC style clock, it needed a more portable solution +than expecting a single battery-backed MC146818 clone on every system. +Accordingly, a new "RTC Class" framework has been defined. It offers +three different userspace interfaces: + + * /dev/rtcN ... much the same as the older /dev/rtc interface + + * /sys/class/rtc/rtcN ... sysfs attributes support readonly + access to some RTC attributes. + + * /proc/driver/rtc ... the first RTC (rtc0) may expose itself + using a procfs interface. More information is (currently) shown + here than through sysfs. + +The RTC Class framework supports a wide variety of RTCs, ranging from those +integrated into embeddable system-on-chip (SOC) processors to discrete chips +using I2C, SPI, or some other bus to communicate with the host CPU. There's +even support for PC-style RTCs ... including the features exposed on newer PCs +through ACPI. + +The new framework also removes the "one RTC per system" restriction. For +example, maybe the low-power battery-backed RTC is a discrete I2C chip, but +a high functionality RTC is integrated into the SOC. That system might read +the system clock from the discrete RTC, but use the integrated one for all +other tasks, because of its greater functionality. + +The ioctl() calls supported by /dev/rtc are also supported by the RTC class +framework. However, because the chips and systems are not standardized, +some PC/AT functionality might not be provided. And in the same way, some +newer features -- including those enabled by ACPI -- are exposed by the +RTC class framework, but can't be supported by the older driver. + + * RTC_RD_TIME, RTC_SET_TIME ... every RTC supports at least reading + time, returning the result as a Gregorian calendar date and 24 hour + wall clock time. To be most useful, this time may also be updated. + + * RTC_AIE_ON, RTC_AIE_OFF, RTC_ALM_SET, RTC_ALM_READ ... when the RTC + is connected to an IRQ line, it can often issue an alarm IRQ up to + 24 hours in the future. + + * RTC_WKALM_SET, RTC_WKALM_READ ... RTCs that can issue alarms beyond + the next 24 hours use a slightly more powerful API, which supports + setting the longer alarm time and enabling its IRQ using a single + request (using the same model as EFI firmware). + + * RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, it probably + also offers update IRQs whenever the "seconds" counter changes. + If needed, the RTC framework can emulate this mechanism. + + * RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... another + feature often accessible with an IRQ line is a periodic IRQ, issued + at settable frequencies (usually 2^N Hz). + +In many cases, the RTC alarm can be a system wake event, used to force +Linux out of a low power sleep state (or hibernation) back to a fully +operational state. For example, a system could enter a deep power saving +state until it's time to execute some scheduled tasks. - Paul Gortmaker -------------------- 8< ---------------- 8< ----------------------------- /* - * Real Time Clock Driver Test/Example Program + * Real Time Clock Driver Test/Example Program * - * Compile with: - * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest + * Compile with: + * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest * - * Copyright (C) 1996, Paul Gortmaker. + * Copyright (C) 1996, Paul Gortmaker. * - * Released under the GNU General Public License, version 2, - * included herein by reference. + * Released under the GNU General Public License, version 2, + * included herein by reference. * */ #include -#include #include #include #include #include #include #include +#include #include -int main(void) { - -int i, fd, retval, irqcount = 0; -unsigned long tmp, data; -struct rtc_time rtc_tm; -fd = open ("/dev/rtc", O_RDONLY); +/* + * This expects the new RTC class driver framework, working with + * clocks that will often not be clones of what the PC-AT had. + * Use the command line to specify another RTC if you need one. + */ +static const char default_rtc[] = "/dev/rtc0"; + + +int main(int argc, char **argv) +{ + int i, fd, retval, irqcount = 0; + unsigned long tmp, data; + struct rtc_time rtc_tm; + const char *rtc = default_rtc; + + switch (argc) { + case 2: + rtc = argv[1]; + /* FALLTHROUGH */ + case 1: + break; + default: + fprintf(stderr, "usage: rtctest [rtcdev]\n"); + return 1; + } -if (fd == -1) { - perror("/dev/rtc"); - exit(errno); -} + fd = open(rtc, O_RDONLY); -fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n"); + if (fd == -1) { + perror(rtc); + exit(errno); + } -/* Turn on update interrupts (one per second) */ -retval = ioctl(fd, RTC_UIE_ON, 0); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} + fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n"); -fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading /dev/rtc:"); -fflush(stderr); -for (i=1; i<6; i++) { - /* This read will block */ - retval = read(fd, &data, sizeof(unsigned long)); + /* Turn on update interrupts (one per second) */ + retval = ioctl(fd, RTC_UIE_ON, 0); if (retval == -1) { - perror("read"); + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Update IRQs not supported.\n"); + goto test_READ; + } + perror("ioctl"); exit(errno); } - fprintf(stderr, " %d",i); + + fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:", + rtc); fflush(stderr); - irqcount++; -} + for (i=1; i<6; i++) { + /* This read will block */ + retval = read(fd, &data, sizeof(unsigned long)); + if (retval == -1) { + perror("read"); + exit(errno); + } + fprintf(stderr, " %d",i); + fflush(stderr); + irqcount++; + } -fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:"); -fflush(stderr); -for (i=1; i<6; i++) { - struct timeval tv = {5, 0}; /* 5 second timeout on select */ - fd_set readfds; + fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:"); + fflush(stderr); + for (i=1; i<6; i++) { + struct timeval tv = {5, 0}; /* 5 second timeout on select */ + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + /* The select will wait until an RTC interrupt happens. */ + retval = select(fd+1, &readfds, NULL, NULL, &tv); + if (retval == -1) { + perror("select"); + exit(errno); + } + /* This read won't block unlike the select-less case above. */ + retval = read(fd, &data, sizeof(unsigned long)); + if (retval == -1) { + perror("read"); + exit(errno); + } + fprintf(stderr, " %d",i); + fflush(stderr); + irqcount++; + } - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - /* The select will wait until an RTC interrupt happens. */ - retval = select(fd+1, &readfds, NULL, NULL, &tv); + /* Turn off update interrupts */ + retval = ioctl(fd, RTC_UIE_OFF, 0); if (retval == -1) { - perror("select"); + perror("ioctl"); exit(errno); } - /* This read won't block unlike the select-less case above. */ - retval = read(fd, &data, sizeof(unsigned long)); + +test_READ: + /* Read the RTC time/date */ + retval = ioctl(fd, RTC_RD_TIME, &rtc_tm); if (retval == -1) { - perror("read"); + perror("ioctl"); exit(errno); } - fprintf(stderr, " %d",i); - fflush(stderr); - irqcount++; -} - -/* Turn off update interrupts */ -retval = ioctl(fd, RTC_UIE_OFF, 0); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} - -/* Read the RTC time/date */ -retval = ioctl(fd, RTC_RD_TIME, &rtc_tm); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} - -fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n", - rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, - rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); - -/* Set the alarm to 5 sec in the future, and check for rollover */ -rtc_tm.tm_sec += 5; -if (rtc_tm.tm_sec >= 60) { - rtc_tm.tm_sec %= 60; - rtc_tm.tm_min++; -} -if (rtc_tm.tm_min == 60) { - rtc_tm.tm_min = 0; - rtc_tm.tm_hour++; -} -if (rtc_tm.tm_hour == 24) - rtc_tm.tm_hour = 0; - -retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} - -/* Read the current alarm settings */ -retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} - -fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n", - rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); -/* Enable alarm interrupts */ -retval = ioctl(fd, RTC_AIE_ON, 0); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} + fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n", + rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); -fprintf(stderr, "Waiting 5 seconds for alarm..."); -fflush(stderr); -/* This blocks until the alarm ring causes an interrupt */ -retval = read(fd, &data, sizeof(unsigned long)); -if (retval == -1) { - perror("read"); - exit(errno); -} -irqcount++; -fprintf(stderr, " okay. Alarm rang.\n"); - -/* Disable alarm interrupts */ -retval = ioctl(fd, RTC_AIE_OFF, 0); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} + /* Set the alarm to 5 sec in the future, and check for rollover */ + rtc_tm.tm_sec += 5; + if (rtc_tm.tm_sec >= 60) { + rtc_tm.tm_sec %= 60; + rtc_tm.tm_min++; + } + if (rtc_tm.tm_min == 60) { + rtc_tm.tm_min = 0; + rtc_tm.tm_hour++; + } + if (rtc_tm.tm_hour == 24) + rtc_tm.tm_hour = 0; -/* Read periodic IRQ rate */ -retval = ioctl(fd, RTC_IRQP_READ, &tmp); -if (retval == -1) { - perror("ioctl"); - exit(errno); -} -fprintf(stderr, "\nPeriodic IRQ rate was %ldHz.\n", tmp); + retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); + if (retval == -1) { + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Alarm IRQs not supported.\n"); + goto test_PIE; + } + perror("ioctl"); + exit(errno); + } -fprintf(stderr, "Counting 20 interrupts at:"); -fflush(stderr); + /* Read the current alarm settings */ + retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); + if (retval == -1) { + perror("ioctl"); + exit(errno); + } -/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */ -for (tmp=2; tmp<=64; tmp*=2) { + fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n", + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); - retval = ioctl(fd, RTC_IRQP_SET, tmp); + /* Enable alarm interrupts */ + retval = ioctl(fd, RTC_AIE_ON, 0); if (retval == -1) { perror("ioctl"); exit(errno); } - fprintf(stderr, "\n%ldHz:\t", tmp); + fprintf(stderr, "Waiting 5 seconds for alarm..."); fflush(stderr); + /* This blocks until the alarm ring causes an interrupt */ + retval = read(fd, &data, sizeof(unsigned long)); + if (retval == -1) { + perror("read"); + exit(errno); + } + irqcount++; + fprintf(stderr, " okay. Alarm rang.\n"); - /* Enable periodic interrupts */ - retval = ioctl(fd, RTC_PIE_ON, 0); + /* Disable alarm interrupts */ + retval = ioctl(fd, RTC_AIE_OFF, 0); if (retval == -1) { perror("ioctl"); exit(errno); } - for (i=1; i<21; i++) { - /* This blocks */ - retval = read(fd, &data, sizeof(unsigned long)); +test_PIE: + /* Read periodic IRQ rate */ + retval = ioctl(fd, RTC_IRQP_READ, &tmp); + if (retval == -1) { + /* not all RTCs support periodic IRQs */ + if (errno == ENOTTY) { + fprintf(stderr, "\nNo periodic IRQ support\n"); + return 0; + } + perror("ioctl"); + exit(errno); + } + fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp); + + fprintf(stderr, "Counting 20 interrupts at:"); + fflush(stderr); + + /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */ + for (tmp=2; tmp<=64; tmp*=2) { + + retval = ioctl(fd, RTC_IRQP_SET, tmp); if (retval == -1) { - perror("read"); - exit(errno); + /* not all RTCs can change their periodic IRQ rate */ + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Periodic IRQ rate is fixed\n"); + goto done; + } + perror("ioctl"); + exit(errno); } - fprintf(stderr, " %d",i); + + fprintf(stderr, "\n%ldHz:\t", tmp); fflush(stderr); - irqcount++; - } - /* Disable periodic interrupts */ - retval = ioctl(fd, RTC_PIE_OFF, 0); - if (retval == -1) { - perror("ioctl"); - exit(errno); + /* Enable periodic interrupts */ + retval = ioctl(fd, RTC_PIE_ON, 0); + if (retval == -1) { + perror("ioctl"); + exit(errno); + } + + for (i=1; i<21; i++) { + /* This blocks */ + retval = read(fd, &data, sizeof(unsigned long)); + if (retval == -1) { + perror("read"); + exit(errno); + } + fprintf(stderr, " %d",i); + fflush(stderr); + irqcount++; + } + + /* Disable periodic interrupts */ + retval = ioctl(fd, RTC_PIE_OFF, 0); + if (retval == -1) { + perror("ioctl"); + exit(errno); + } } -} -fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n"); -fprintf(stderr, "\nTyping \"cat /proc/interrupts\" will show %d more events on IRQ 8.\n\n", - irqcount); +done: + fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n"); -close(fd); -return 0; + close(fd); -} /* end main */ + return 0; +} -- cgit v0.10.2 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 diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 579cd66..4783ec6 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 583789c..3109865 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 v0.10.2 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 diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4783ec6..6f11f6d 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 bd61e99..5c8addc 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 3109865..814b9e1 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 78552e6..001eb11 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 bc4bd24..6ef9c62 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 v0.10.2 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 diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2a86632..a44fe4e 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 v0.10.2 From 533221fbaf001692d5db646f84f7d033fac78cc7 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 25 Nov 2006 11:09:30 -0800 Subject: [PATCH] reiserfs: fmt bugfix One reiserfs_warning() call uses %lu, but doesn't supply what to print. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index b67ce93..ac14318 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -74,7 +74,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) igrab(inode); reiserfs_warning(inode->i_sb, "pinning inode %lu because the " - "preallocation can't be freed"); + "preallocation can't be freed", + inode->i_ino); goto out; } } -- cgit v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index 68ad11a..002fde4 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 v0.10.2 From f12aa7045280836307e9bbdb1c676c4a94e2b3d3 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Sat, 25 Nov 2006 11:09:31 -0800 Subject: [PATCH] qconf: fix uninitialsied member Fixes a segfault reported by Randy. Cc: Randy Dunlap Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 393f374..338bdea 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1259,6 +1259,7 @@ void ConfigSearchWindow::search(void) * Construct the complete config widget */ ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) { QMenuBar* menu; bool ok; -- cgit v0.10.2 From c154348f00834911c49aa63dfb48bd50d1a07d93 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Sat, 25 Nov 2006 11:09:32 -0800 Subject: [PATCH] fix menuconfig colours with TERM=vt100 On Mon, 13 Nov 2006, Phil Oester wrote: > In commit 350b5b76384e77bcc58217f00455fdbec5cac594, the default menuconfig > color scheme was changed to bluetitle. This breaks the highlighting > of the selected item for me with TERM=vt100. The only way I can see > which item is selected is via: > > make MENUCONFIG_COLOR=mono menuconfig > > Which restores the pre-2.6.19 white on black highlighting. Fix. Cc: Phil Oester Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index ebc781b..d54440f 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c @@ -221,16 +221,14 @@ static void init_dialog_colors(void) */ static void color_setup(const char *theme) { - if (set_theme(theme)) { - if (has_colors()) { /* Terminal supports color? */ - start_color(); - init_dialog_colors(); - } - } - else - { + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else set_mono_theme(); - } } /* -- cgit v0.10.2 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 diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 244f7eb..cfad09a 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 v0.10.2 From 753ca4f312a4b26940e4731b4fa5dbbbbcc77e97 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 25 Nov 2006 11:09:34 -0800 Subject: [PATCH] fix copy_process() error check The return value of copy_process() should be checked by IS_ERR(). Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 3da978e..8cdd3e7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1315,9 +1315,8 @@ struct task_struct * __devinit fork_idle(int cpu) struct pt_regs regs; task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, 0); - if (!task) - return ERR_PTR(-ENOMEM); - init_idle(task, cpu); + if (!IS_ERR(task)) + init_idle(task, cpu); return task; } -- cgit v0.10.2 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 diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 2444a0e..244d30a 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 v0.10.2 From ee3ce191e8eaa4cc15c51a28b34143b36404c4f5 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 25 Nov 2006 11:09:36 -0800 Subject: [PATCH] Enforce "unsigned long flags;" when spinlocking Make it break or warn if you pass to spin_lock_irqsave() and friends something different from "unsigned long flags;". Suprisingly large amount of these was caught by recent commit c53421b18f205c5f97c604ae55c6a921f034b0f6 and others. Idea is largely from FRV typechecking. Suggestions from Andrew Morton. All stupid typos in first version fixed. Passes allmodconfig on i386, x86_64, alpha, arm as well as my usual config. Note #1: checking with sparse is still needed, because a driver can save and pass around flags or something. So far patch is very intrusive. Note #2: techically, we should break only if sizeof(flags) < sizeof(unsigned long), however, the more pain for getting suspicious code into kernel, the better. Signed-off-by: Alexey Dobriyan Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 412e025..4fe740b 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -11,6 +11,12 @@ #ifndef _LINUX_TRACE_IRQFLAGS_H #define _LINUX_TRACE_IRQFLAGS_H +#define BUILD_CHECK_IRQ_FLAGS(flags) \ + do { \ + BUILD_BUG_ON(sizeof(flags) != sizeof(unsigned long)); \ + typecheck(unsigned long, flags); \ + } while (0) + #ifdef CONFIG_TRACE_IRQFLAGS extern void trace_hardirqs_on(void); extern void trace_hardirqs_off(void); @@ -50,10 +56,15 @@ #define local_irq_disable() \ do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) #define local_irq_save(flags) \ - do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + raw_local_irq_save(flags); \ + trace_hardirqs_off(); \ + } while (0) #define local_irq_restore(flags) \ do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ if (raw_irqs_disabled_flags(flags)) { \ raw_local_irq_restore(flags); \ trace_hardirqs_off(); \ @@ -69,8 +80,16 @@ */ # define raw_local_irq_disable() local_irq_disable() # define raw_local_irq_enable() local_irq_enable() -# define raw_local_irq_save(flags) local_irq_save(flags) -# define raw_local_irq_restore(flags) local_irq_restore(flags) +# define raw_local_irq_save(flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + local_irq_save(flags); \ + } while (0) +# define raw_local_irq_restore(flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + local_irq_restore(flags); \ + } while (0) #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT @@ -80,7 +99,11 @@ raw_safe_halt(); \ } while (0) -#define local_save_flags(flags) raw_local_save_flags(flags) +#define local_save_flags(flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + raw_local_save_flags(flags); \ + } while (0) #define irqs_disabled() \ ({ \ @@ -90,7 +113,11 @@ raw_irqs_disabled_flags(flags); \ }) -#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) +#define irqs_disabled_flags(flags) \ +({ \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + raw_irqs_disabled_flags(flags); \ +}) #endif /* CONFIG_X86 */ #endif diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index b800d2d..54ad370 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -183,13 +184,37 @@ do { \ #define read_lock(lock) _read_lock(lock) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) -#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) -#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock) -#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock) +#define spin_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + flags = _spin_lock_irqsave(lock); \ + } while (0) +#define read_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + flags = _read_lock_irqsave(lock); \ + } while (0) +#define write_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + flags = _write_lock_irqsave(lock); \ + } while (0) #else -#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags) -#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags) -#define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags) +#define spin_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _spin_lock_irqsave(lock, flags); \ + } while (0) +#define read_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _read_lock_irqsave(lock, flags); \ + } while (0) +#define write_lock_irqsave(lock, flags) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _write_lock_irqsave(lock, flags); \ + } while (0) #endif #define spin_lock_irq(lock) _spin_lock_irq(lock) @@ -225,15 +250,24 @@ do { \ #endif #define spin_unlock_irqrestore(lock, flags) \ - _spin_unlock_irqrestore(lock, flags) + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _spin_unlock_irqrestore(lock, flags); \ + } while (0) #define spin_unlock_bh(lock) _spin_unlock_bh(lock) #define read_unlock_irqrestore(lock, flags) \ - _read_unlock_irqrestore(lock, flags) + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _read_unlock_irqrestore(lock, flags); \ + } while (0) #define read_unlock_bh(lock) _read_unlock_bh(lock) #define write_unlock_irqrestore(lock, flags) \ - _write_unlock_irqrestore(lock, flags) + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + _write_unlock_irqrestore(lock, flags); \ + } while (0) #define write_unlock_bh(lock) _write_unlock_bh(lock) #define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock)) @@ -247,6 +281,7 @@ do { \ #define spin_trylock_irqsave(lock, flags) \ ({ \ + BUILD_CHECK_IRQ_FLAGS(flags); \ local_irq_save(flags); \ spin_trylock(lock) ? \ 1 : ({ local_irq_restore(flags); 0; }); \ -- cgit v0.10.2 From cfd3ef2346f924d6c0e82236c20fdb3a8840136a Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 25 Nov 2006 11:09:37 -0800 Subject: [PATCH] lockdep: spin_lock_irqsave_nested() Introduce spin_lock_irqsave_nested(); implementation from: http://lkml.org/lkml/2006/6/1/122 Patch from: http://lkml.org/lkml/2006/9/13/258 [akpm@osdl.org: two compile fixes] Signed-off-by: Arjan van de Ven Signed-off-by: Jiri Kosina Signed-off-by: Peter Zijlstra Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 54ad370..57f670d 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -199,6 +199,21 @@ do { \ BUILD_CHECK_IRQ_FLAGS(flags); \ flags = _write_lock_irqsave(lock); \ } while (0) + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +#define spin_lock_irqsave_nested(lock, flags, subclass) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + flags = _spin_lock_irqsave_nested(lock, subclass); \ + } while (0) +#else +#define spin_lock_irqsave_nested(lock, flags, subclass) \ + do { \ + BUILD_CHECK_IRQ_FLAGS(flags); \ + flags = _spin_lock_irqsave(lock); \ + } while (0) +#endif + #else #define spin_lock_irqsave(lock, flags) \ do { \ @@ -215,6 +230,9 @@ do { \ BUILD_CHECK_IRQ_FLAGS(flags); \ _write_lock_irqsave(lock, flags); \ } while (0) +#define spin_lock_irqsave_nested(lock, flags, subclass) \ + spin_lock_irqsave(lock, flags) + #endif #define spin_lock_irq(lock) _spin_lock_irq(lock) diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index 8828b81..8a2307ce 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -32,6 +32,8 @@ void __lockfunc _read_lock_irq(rwlock_t *lock) __acquires(lock); void __lockfunc _write_lock_irq(rwlock_t *lock) __acquires(lock); unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) __acquires(lock); +unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass) + __acquires(lock); unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) __acquires(lock); unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) diff --git a/kernel/spinlock.c b/kernel/spinlock.c index 476c374..2c6c2bf 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -293,6 +293,27 @@ void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass) } EXPORT_SYMBOL(_spin_lock_nested); +unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass) +{ + unsigned long flags; + + local_irq_save(flags); + preempt_disable(); + spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); + /* + * On lockdep we dont want the hand-coded irq-enable of + * _raw_spin_lock_flags() code, because lockdep assumes + * that interrupts are not re-enabled during lock-acquire: + */ +#ifdef CONFIG_PROVE_SPIN_LOCKING + _raw_spin_lock(lock); +#else + _raw_spin_lock_flags(lock, &flags); +#endif + return flags; +} + +EXPORT_SYMBOL(_spin_lock_irqsave_nested); #endif -- cgit v0.10.2 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 diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index f659f30..787b847 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 v0.10.2 From 5d48545e5e88ab7a27ba6a5cb1e8fff617754b61 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 25 Nov 2006 11:09:39 -0800 Subject: [PATCH] uml: make execvp safe for our usage Reimplement execvp for our purposes - after we call fork() it is fundamentally unsafe to use the kernel allocator - current is not valid there. So we simply pass to our modified execvp() a preallocated buffer. This fixes a real bug and works very well in testing (I've seen indirectly warning messages from the forked thread - they went on the pipe connected to its stdout and where read as a number by UML, when calling read_output(). I verified the obtained number corresponded to "BUG:"). The added use of __cant_sleep() is not a new bug since __cant_sleep() is already used in the same function - passing an atomicity parameter would be better but it would require huge change, stating that this function must not be called in atomic context and can sleep is a better idea (will make sure of this gradually). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Acked-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6516f6d..13a86bd 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -233,6 +233,8 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n, void (*op)(void *to, const void *from, int n), int *faulted_out); +/* execvp.c */ +extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); /* helper.c */ extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, unsigned long *stack_out); diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index b418392..2f8c794 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,8 +3,8 @@ # Licensed under the GPL # -obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ - signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ +obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ + sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ user_syms.o util.o drivers/ sys-$(SUBARCH)/ obj-$(CONFIG_MODE_SKAS) += skas/ @@ -15,9 +15,9 @@ user-objs-$(CONFIG_MODE_TT) += tt.o obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ - process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \ - uaccess.o umid.o util.o +USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ + main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ + tls.o uaccess.o umid.o util.o CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c new file mode 100644 index 0000000..66e583a --- /dev/null +++ b/arch/um/os-Linux/execvp.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c. + Original copyright notice follows: + + Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; 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 + +#ifndef TEST +#include "um_malloc.h" +#else +#include +#define um_kmalloc malloc +#endif +#include "os.h" + +/* Execute FILE, searching in the `PATH' environment variable if it contains + no slashes, with arguments ARGV and environment from `environ'. */ +int execvp_noalloc(char *buf, const char *file, char *const argv[]) +{ + if (*file == '\0') { + return -ENOENT; + } + + if (strchr (file, '/') != NULL) { + /* Don't search when it contains a slash. */ + execv(file, argv); + } else { + int got_eacces; + size_t len, pathlen; + char *name, *p; + char *path = getenv("PATH"); + if (path == NULL) + path = ":/bin:/usr/bin"; + + len = strlen(file) + 1; + pathlen = strlen(path); + /* Copy the file name at the top. */ + name = memcpy(buf + pathlen + 1, file, len); + /* And add the slash. */ + *--name = '/'; + + got_eacces = 0; + p = path; + do { + char *startp; + + path = p; + //Let's avoid this GNU extension. + //p = strchrnul (path, ':'); + p = strchr(path, ':'); + if (!p) + p = strchr(path, '\0'); + + if (p == path) + /* Two adjacent colons, or a colon at the beginning or the end + of `PATH' means to search the current directory. */ + startp = name + 1; + else + startp = memcpy(name - (p - path), path, p - path); + + /* Try to execute this name. If it works, execv will not return. */ + execv(startp, argv); + + /* + if (errno == ENOEXEC) { + } + */ + + switch (errno) { + case EACCES: + /* Record the we got a `Permission denied' error. If we end + up finding no executable we can use, we want to diagnose + that we did find one but were denied access. */ + got_eacces = 1; + case ENOENT: + case ESTALE: + case ENOTDIR: + /* Those errors indicate the file is missing or not executable + by us, in which case we want to just try the next path + directory. */ + case ENODEV: + case ETIMEDOUT: + /* Some strange filesystems like AFS return even + stranger error numbers. They cannot reasonably mean + anything else so ignore those, too. */ + case ENOEXEC: + /* We won't go searching for the shell + * if it is not executable - the Linux + * kernel already handles this enough, + * for us. */ + break; + + default: + /* Some other error means we found an executable file, but + something went wrong executing it; return the error to our + caller. */ + return -errno; + } + } while (*p++ != '\0'); + + /* We tried every element and none of them worked. */ + if (got_eacces) + /* At least one failure was due to permissions, so report that + error. */ + return -EACCES; + } + + /* Return the error from the last attempt (probably ENOENT). */ + return -errno; +} +#ifdef TEST +int main(int argc, char**argv) +{ + char buf[PATH_MAX]; + int ret; + argc--; + if (!argc) { + fprintf(stderr, "Not enough arguments\n"); + return 1; + } + argv++; + if (ret = execvp_noalloc(buf, argv[0], argv)) { + errno = -ret; + perror("execvp_noalloc"); + } + return 0; +} +#endif diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index d13299c..c7ad630 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -8,18 +8,21 @@ #include #include #include +#include #include #include #include "user.h" #include "kern_util.h" #include "user_util.h" #include "os.h" +#include "um_malloc.h" struct helper_data { void (*pre_exec)(void*); void *pre_data; char **argv; int fd; + char *buf; }; /* Debugging aid, changed only from gdb */ @@ -41,9 +44,8 @@ static int helper_child(void *arg) } if (data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); - execvp(argv[0], argv); - errval = -errno; - printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); + errval = execvp_noalloc(data->buf, argv[0], argv); + printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval); os_write_file(data->fd, &errval, sizeof(errval)); kill(os_getpid(), SIGKILL); return 0; @@ -84,11 +86,13 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, data.pre_data = pre_data; data.argv = argv; data.fd = fds[1]; + data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) : + um_kmalloc(PATH_MAX); pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if (pid < 0) { ret = -errno; printk("run_helper : clone failed, errno = %d\n", errno); - goto out_close; + goto out_free2; } close(fds[1]); @@ -109,6 +113,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, CATCH_EINTR(waitpid(pid, NULL, 0)); } +out_free2: + kfree(data.buf); out_close: if (fds[1] != -1) close(fds[1]); -- cgit v0.10.2 From 38f7efd52c4f3f0b22c460eadbfe7c42f9ebff82 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 21 Nov 2006 21:46:02 -0800 Subject: [NETFILTER]: H.323 conntrack: fix crash with CONFIG_IP_NF_CT_ACCT H.323 connection tracking code calls ip_ct_refresh_acct() when processing RCFs and URQs but passes NULL as the skb. When CONFIG_IP_NF_CT_ACCT is enabled, the connection tracking core tries to derefence the skb, which results in an obvious panic. A similar fix was applied on the SIP connection tracking code some time ago. Signed-off-by: Faidon Liambotis Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 7b74412..6cb9070 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -1417,7 +1417,7 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, DEBUGP ("ip_ct_ras: set RAS connection timeout to %u seconds\n", info->timeout); - ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ); + ip_ct_refresh(ct, *pskb, info->timeout * HZ); /* Set expect timeout */ read_lock_bh(&ip_conntrack_lock); @@ -1465,7 +1465,7 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, info->sig_port[!dir] = 0; /* Give it 30 seconds for UCF or URJ */ - ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ); + ip_ct_refresh(ct, *pskb, 30 * HZ); return 0; } -- cgit v0.10.2 From 753eab76a3337863a0d86ce045fa4eb6c3cbeef9 Mon Sep 17 00:00:00 2001 From: Olaf Kirch Date: Wed, 22 Nov 2006 20:11:42 -0800 Subject: [UDP]: Make udp_encap_rcv use pskb_may_pull Make udp_encap_rcv use pskb_may_pull IPsec with NAT-T breaks on some notebooks using the latest e1000 chipset, when header split is enabled. When receiving sufficiently large packets, the driver puts everything up to and including the UDP header into the header portion of the skb, and the rest goes into the paged part. udp_encap_rcv forgets to use pskb_may_pull, and fails to decapsulate it. Instead, it passes it up it to the IKE daemon. Signed-off-by: Olaf Kirch Signed-off-by: Jean Delvare Signed-off-by: David S. Miller diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 865d752..9e1bd37 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -928,23 +928,32 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) return 1; #else struct udp_sock *up = udp_sk(sk); - struct udphdr *uh = skb->h.uh; + struct udphdr *uh; struct iphdr *iph; int iphlen, len; - __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr); - __be32 *udpdata32 = (__be32 *)udpdata; + __u8 *udpdata; + __be32 *udpdata32; __u16 encap_type = up->encap_type; /* if we're overly short, let UDP handle it */ - if (udpdata > skb->tail) + len = skb->len - sizeof(struct udphdr); + if (len <= 0) return 1; /* if this is not encapsulated socket, then just return now */ if (!encap_type) return 1; - len = skb->tail - udpdata; + /* If this is a paged skb, make sure we pull up + * whatever data we need to look at. */ + if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) + return 1; + + /* Now we can get the pointers */ + uh = skb->h.uh; + udpdata = (__u8 *)uh + sizeof(struct udphdr); + udpdata32 = (__be32 *)udpdata; switch (encap_type) { default: -- cgit v0.10.2 From ac16ca6412d9feb5b2f8fc76a4ed938b5d107f94 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 22 Nov 2006 20:26:11 -0800 Subject: [NET]: Fix kfifo_alloc() error check. The return value of kfifo_alloc() should be checked by IS_ERR(). Signed-off-by: Akinobu Mita Signed-off-by: David S. Miller diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 146496f..fded149 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -160,6 +160,8 @@ static __init int dccpprobe_init(void) init_waitqueue_head(&dccpw.wait); spin_lock_init(&dccpw.lock); dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock); + if (IS_ERR(dccpw.fifo)) + return PTR_ERR(dccpw.fifo); if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops)) goto err0; diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 4be336f..f230eee 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -156,6 +156,8 @@ static __init int tcpprobe_init(void) init_waitqueue_head(&tcpw.wait); spin_lock_init(&tcpw.lock); tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); + if (IS_ERR(tcpw.fifo)) + return PTR_ERR(tcpw.fifo); if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) goto err0; -- cgit v0.10.2 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 diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 86b3bb9..92420f0 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 v0.10.2 From dc9b334622bff6d22456917a034c2e2d194b9328 Mon Sep 17 00:00:00 2001 From: Paul Bonser Date: Thu, 23 Nov 2006 17:56:13 -0800 Subject: [NET]: Re-fix of doc-comment in sock.h Restoring old, correct comment for sk_filter_release, moving it to where it should actually be, and changing new comment into proper comment for sk_filter_rcu_free, where it actually makes sense. The original fix submitted for this on Oct 23 mistakenly documented the wrong function. Signed-off-by: Paul Bonser Signed-off-by: David S. Miller diff --git a/include/net/sock.h b/include/net/sock.h index ac286a3..9cdbae2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -883,18 +883,23 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) } /** - * sk_filter_release: Release a socket filter - * @rcu: rcu_head that contains the sk_filter info to remove - * - * Remove a filter from a socket and release its resources. + * sk_filter_rcu_free: Free a socket filter + * @rcu: rcu_head that contains the sk_filter to free */ - static inline void sk_filter_rcu_free(struct rcu_head *rcu) { struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); kfree(fp); } +/** + * sk_filter_release: Release a socket filter + * @sk: socket + * @fp: filter to remove + * + * Remove a filter from a socket and release its resources. + */ + static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) { unsigned int size = sk_filter_len(fp); -- cgit v0.10.2 From 9abbffee861c6c56fce27e4eda96a10cf0de0f84 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Fri, 24 Nov 2006 20:34:51 -0800 Subject: [XFRM] STATE: Fix to respond error to get operation if no matching entry exists. When application uses XFRM_MSG_GETSA to get state entry through netlink socket and kernel has no matching one, the application expects reply message with error status by kernel. Kernel doesn't send the message back in the case of Mobile IPv6 route optimization protocols (i.e. routing header or destination options header). This is caused by incorrect return code "0" from net/xfrm/xfrm_user.c(xfrm_user_state_lookup) and it makes kernel skip to acknowledge at net/netlink/af_netlink.c(netlink_rcv_skb). This patch fix to reply ESRCH to application. Signed-off-by: Masahide NAKAMURA Signed-off-by: TAKAMIYA Noriaki Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c4cde57..2ee14f8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -495,6 +495,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, goto out; } + err = -ESRCH; x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, p->family); } -- cgit v0.10.2 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 diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e58f039..e28617b 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 v0.10.2 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 diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e28617b..56f1c80 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 v0.10.2 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 diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 53304e6..a2ab2ee 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 v0.10.2 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 diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index a81285c..7b9859c 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 v0.10.2 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 diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index f786ab1..86e353b 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 a4702d3..42fb60d 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 v0.10.2 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 diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c5719f7..f28398d 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 v0.10.2 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 diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 7456b0b..4c27a2d9 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 v0.10.2 From d00ec458cb9235025d20cf2783d3ddcd879a6c48 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 25 Nov 2006 16:19:23 +0000 Subject: [ARM] Add PM_LEGACY defaults Eliminate two warnings: kernel/power/pm.c:205: warning: 'pm_register' is deprecated (declared at kernel/power/pm.c:64) kernel/power/pm.c:206: warning: 'pm_send_all' is deprecated (declared at kernel/power/pm.c:180) by updating defconfig files to contain a sensible PM_LEGACY default. Signed-off-by: Russell King diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig index 089c9d5..b1cd331 100644 --- a/arch/arm/configs/assabet_defconfig +++ b/arch/arm/configs/assabet_defconfig @@ -184,6 +184,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_APM is not set # diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig index f81a600..09b7acd 100644 --- a/arch/arm/configs/cerfcube_defconfig +++ b/arch/arm/configs/cerfcube_defconfig @@ -194,6 +194,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_APM is not set # diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig index 3c3461e..c41c04f 100644 --- a/arch/arm/configs/corgi_defconfig +++ b/arch/arm/configs/corgi_defconfig @@ -208,6 +208,7 @@ CONFIG_BINFMT_MISC=m # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set CONFIG_APM=y # diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig index 7a0da0b..8f986e9 100644 --- a/arch/arm/configs/h3600_defconfig +++ b/arch/arm/configs/h3600_defconfig @@ -194,6 +194,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_APM is not set # diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index d1ba7fd..692ab57 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -190,6 +190,7 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_APM is not set # diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig index ad1048d..80a6fd9 100644 --- a/arch/arm/configs/jornada720_defconfig +++ b/arch/arm/configs/jornada720_defconfig @@ -182,6 +182,7 @@ CONFIG_BINFMT_AOUT=m # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set # CONFIG_APM is not set # diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig index c3a9328..a1cc34f 100644 --- a/arch/arm/configs/lart_defconfig +++ b/arch/arm/configs/lart_defconfig @@ -180,6 +180,7 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set CONFIG_APM=m # diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig index 3d35255..df8168e 100644 --- a/arch/arm/configs/neponset_defconfig +++ b/arch/arm/configs/neponset_defconfig @@ -190,6 +190,7 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set CONFIG_APM=y # diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig index 2e5a616..140056a 100644 --- a/arch/arm/configs/simpad_defconfig +++ b/arch/arm/configs/simpad_defconfig @@ -180,6 +180,7 @@ CONFIG_BINFMT_MISC=m # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set CONFIG_APM=y # diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig index d1ace3a..bd03238 100644 --- a/arch/arm/configs/spitz_defconfig +++ b/arch/arm/configs/spitz_defconfig @@ -207,6 +207,7 @@ CONFIG_BINFMT_MISC=m # Power management options # CONFIG_PM=y +# CONFIG_PM_LEGACY is not set CONFIG_APM=y # -- cgit v0.10.2 From e730bf96c89b27b2a90ae3e8054dae6133b4f90b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 25 Nov 2006 20:15:12 +0000 Subject: [ARM] Export smp_call_function() smp_call_function() will be used with the MP/core oprofile support patch. Export it as _GPL. Signed-off-by: Russell King diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index a07d202..070bcb7 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -451,6 +451,7 @@ int smp_call_function(void (*func)(void *info), void *info, int retry, return smp_call_function_on_cpu(func, info, retry, wait, cpu_online_map); } +EXPORT_SYMBOL_GPL(smp_call_function); void show_ipi_list(struct seq_file *p) { -- cgit v0.10.2 From b8e6ec865fd1d8838b6ce9516977b65e9f08f876 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 26 Nov 2006 16:27:17 -0800 Subject: Revert "[PATCH] Enforce "unsigned long flags;" when spinlocking" This reverts commit ee3ce191e8eaa4cc15c51a28b34143b36404c4f5, since it broke on at least ARM, MIPS and PA-RISC due to complicated header file dependencies. Conflicts in include/linux/spinlock.h (due to the "nested" variety fixes) fixed up by hand. Cc: Alexey Dobriyan Cc: Ralf Baechle Cc: Kyle McMartin Cc: Russell King Signed-off-by: Linus Torvalds diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 4fe740b..412e025 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -11,12 +11,6 @@ #ifndef _LINUX_TRACE_IRQFLAGS_H #define _LINUX_TRACE_IRQFLAGS_H -#define BUILD_CHECK_IRQ_FLAGS(flags) \ - do { \ - BUILD_BUG_ON(sizeof(flags) != sizeof(unsigned long)); \ - typecheck(unsigned long, flags); \ - } while (0) - #ifdef CONFIG_TRACE_IRQFLAGS extern void trace_hardirqs_on(void); extern void trace_hardirqs_off(void); @@ -56,15 +50,10 @@ #define local_irq_disable() \ do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) #define local_irq_save(flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - raw_local_irq_save(flags); \ - trace_hardirqs_off(); \ - } while (0) + do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) #define local_irq_restore(flags) \ do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ if (raw_irqs_disabled_flags(flags)) { \ raw_local_irq_restore(flags); \ trace_hardirqs_off(); \ @@ -80,16 +69,8 @@ */ # define raw_local_irq_disable() local_irq_disable() # define raw_local_irq_enable() local_irq_enable() -# define raw_local_irq_save(flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - local_irq_save(flags); \ - } while (0) -# define raw_local_irq_restore(flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - local_irq_restore(flags); \ - } while (0) +# define raw_local_irq_save(flags) local_irq_save(flags) +# define raw_local_irq_restore(flags) local_irq_restore(flags) #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT @@ -99,11 +80,7 @@ raw_safe_halt(); \ } while (0) -#define local_save_flags(flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - raw_local_save_flags(flags); \ - } while (0) +#define local_save_flags(flags) raw_local_save_flags(flags) #define irqs_disabled() \ ({ \ @@ -113,11 +90,7 @@ raw_irqs_disabled_flags(flags); \ }) -#define irqs_disabled_flags(flags) \ -({ \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - raw_irqs_disabled_flags(flags); \ -}) +#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) #endif /* CONFIG_X86 */ #endif diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 57f670d..8451052 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -52,7 +52,6 @@ #include #include #include -#include #include @@ -184,52 +183,24 @@ do { \ #define read_lock(lock) _read_lock(lock) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) -#define spin_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - flags = _spin_lock_irqsave(lock); \ - } while (0) -#define read_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - flags = _read_lock_irqsave(lock); \ - } while (0) -#define write_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - flags = _write_lock_irqsave(lock); \ - } while (0) + +#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) +#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock) +#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock) #ifdef CONFIG_DEBUG_LOCK_ALLOC -#define spin_lock_irqsave_nested(lock, flags, subclass) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - flags = _spin_lock_irqsave_nested(lock, subclass); \ - } while (0) +#define spin_lock_irqsave_nested(lock, flags, subclass) \ + flags = _spin_lock_irqsave_nested(lock, subclass) #else -#define spin_lock_irqsave_nested(lock, flags, subclass) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - flags = _spin_lock_irqsave(lock); \ - } while (0) +#define spin_lock_irqsave_nested(lock, flags, subclass) \ + flags = _spin_lock_irqsave(lock) #endif #else -#define spin_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _spin_lock_irqsave(lock, flags); \ - } while (0) -#define read_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _read_lock_irqsave(lock, flags); \ - } while (0) -#define write_lock_irqsave(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _write_lock_irqsave(lock, flags); \ - } while (0) + +#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags) +#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags) +#define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags) #define spin_lock_irqsave_nested(lock, flags, subclass) \ spin_lock_irqsave(lock, flags) @@ -268,24 +239,15 @@ do { \ #endif #define spin_unlock_irqrestore(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _spin_unlock_irqrestore(lock, flags); \ - } while (0) + _spin_unlock_irqrestore(lock, flags) #define spin_unlock_bh(lock) _spin_unlock_bh(lock) #define read_unlock_irqrestore(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _read_unlock_irqrestore(lock, flags); \ - } while (0) + _read_unlock_irqrestore(lock, flags) #define read_unlock_bh(lock) _read_unlock_bh(lock) #define write_unlock_irqrestore(lock, flags) \ - do { \ - BUILD_CHECK_IRQ_FLAGS(flags); \ - _write_unlock_irqrestore(lock, flags); \ - } while (0) + _write_unlock_irqrestore(lock, flags) #define write_unlock_bh(lock) _write_unlock_bh(lock) #define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock)) @@ -299,7 +261,6 @@ do { \ #define spin_trylock_irqsave(lock, flags) \ ({ \ - BUILD_CHECK_IRQ_FLAGS(flags); \ local_irq_save(flags); \ spin_trylock(lock) ? \ 1 : ({ local_irq_restore(flags); 0; }); \ -- cgit v0.10.2 From c9c3b86f2ab79f7f6e87eb735f9cc4508b73fc48 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 26 Nov 2006 18:56:56 -0500 Subject: [PATCH] Fix incorrent type of flags in I still think using BUILD_BUG_ON() is unacceptable, especially given how vague the error message was. Signed-off-by: Kyle McMartin [ And I already removed gthe BUILD_BUG_ON() in the previous commit ] Signed-off-by: Linus Torvalds diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h index c9ee41c..d45827a 100644 --- a/include/asm-parisc/semaphore.h +++ b/include/asm-parisc/semaphore.h @@ -115,7 +115,8 @@ extern __inline__ int down_interruptible(struct semaphore * sem) */ extern __inline__ int down_trylock(struct semaphore * sem) { - int flags, count; + unsigned long flags; + int count; spin_lock_irqsave(&sem->sentry, flags); count = sem->count - 1; @@ -131,7 +132,8 @@ extern __inline__ int down_trylock(struct semaphore * sem) */ extern __inline__ void up(struct semaphore * sem) { - int flags; + unsigned long flags; + spin_lock_irqsave(&sem->sentry, flags); if (sem->count < 0) { __up(sem); -- cgit v0.10.2 From 2ea5814472c3c910aed5c5b60f1f3b1000e353f1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 26 Nov 2006 19:05:22 -0800 Subject: Fix 'ALIGN()' macro, take 2 You wouldn't think that doing an ALIGN() macro that aligns something up to a power-of-two boundary would be likely to have bugs, would you? But hey, in the wonderful world of mixing integer types, you have to be careful. This just makes sure that the alignment is interpreted in the same type as the thing to be aligned. Thanks to Roland Dreier, who noticed that the amso1100 driver got broken by the previous fix (that just extended the mask to "unsigned long", but was still broken in "unsigned long long" - it just happened to be the same on 64-bit architectures). See commit 4c8bd7eeee4c8f157fb61fb64b57500990b42e0e for the history of bugs here... Acked-by: Roland Dreier Cc: Andrew Morton Cc: David Miller Cc: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 24b6111..b9b5e4b 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -30,8 +30,10 @@ extern const char linux_banner[]; #define STACK_MAGIC 0xdeadbeef +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) -- cgit v0.10.2 From fc5d81e69d15c65ca20d9e5b4e242690e3e9c27d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 27 Nov 2006 15:16:48 +0900 Subject: selinux: fix dentry_open() error check The return value of dentry_open() shoud be checked by IS_ERR(). Cc: Stephen Smalley Cc: James Morris Signed-off-by: Akinobu Mita Signed-off-by: James Morris diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8ab5679..28ee187 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1754,7 +1754,8 @@ static inline void flush_unauthorized_files(struct files_struct * files) get_file(devnull); } else { devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); - if (!devnull) { + if (IS_ERR(devnull)) { + devnull = NULL; put_unused_fd(fd); fput(file); continue; -- cgit v0.10.2 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 diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5c1fc46..22643c0 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 v0.10.2 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 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 234197e..f510e11 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 v0.10.2 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 diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 22643c0..47ea111 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 v0.10.2 From ac5d1a7d253f3c02d1e5c93edfa26e81466ec71e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 27 Oct 2006 10:45:00 +0200 Subject: [ALSA] rtctimer: handle RTC interrupts with a tasklet The calls to rtc_control() from inside the interrupt handler can upset the RTC code, so move our interrupt handling code to a tasklet. Signed-off-by: Clemens Ladisch Signed-off-by: Jaroslav Kysela diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 412dd62..9f7b32e 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -22,13 +22,10 @@ #include #include -#include -#include #include #include #include #include -#include #if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE) @@ -50,7 +47,9 @@ static int rtctimer_stop(struct snd_timer *t); * The hardware dependent description for this timer. */ static struct snd_timer_hardware rtc_hw = { - .flags = SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO, + .flags = SNDRV_TIMER_HW_AUTO | + SNDRV_TIMER_HW_FIRST | + SNDRV_TIMER_HW_TASKLET, .ticks = 100000000L, /* FIXME: XXX */ .open = rtctimer_open, .close = rtctimer_close, @@ -60,6 +59,7 @@ static struct snd_timer_hardware rtc_hw = { static int rtctimer_freq = RTC_FREQ; /* frequency */ static struct snd_timer *rtctimer; +static struct tasklet_struct rtc_tasklet; static rtc_task_t rtc_task; @@ -81,6 +81,7 @@ rtctimer_close(struct snd_timer *t) rtc_task_t *rtc = t->private_data; if (rtc) { rtc_unregister(rtc); + tasklet_kill(&rtc_tasklet); t->private_data = NULL; } return 0; @@ -105,12 +106,17 @@ rtctimer_stop(struct snd_timer *timer) return 0; } +static void rtctimer_tasklet(unsigned long data) +{ + snd_timer_interrupt((struct snd_timer *)data, 1); +} + /* * interrupt */ static void rtctimer_interrupt(void *private_data) { - snd_timer_interrupt(private_data, 1); + tasklet_hi_schedule(private_data); } @@ -139,9 +145,11 @@ static int __init rtctimer_init(void) timer->hw = rtc_hw; timer->hw.resolution = NANO_SEC / rtctimer_freq; + tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer); + /* set up RTC callback */ rtc_task.func = rtctimer_interrupt; - rtc_task.private_data = timer; + rtc_task.private_data = &rtc_tasklet; err = snd_timer_global_register(timer); if (err < 0) { -- cgit v0.10.2 From 80b8d5d6bc0000c6e499260883cfc95e645f49d1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 31 Oct 2006 15:24:45 +0100 Subject: [ALSA] Enable stereo line input for TAS codec Despite what the data sheet says in one place, to get stereo input from input A (line in), we have to clear the 'input B monaural' bit in the ACR. Signed-off-by: Paul Mackerras Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c index 2ef55a1..9de8485 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -514,9 +514,15 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, mutex_lock(&tas->mtx); oldacr = tas->acr; - tas->acr &= ~TAS_ACR_INPUT_B; + /* + * Despite what the data sheet says in one place, the + * TAS_ACR_B_MONAUREAL bit forces mono output even when + * input A (line in) is selected. + */ + tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL); if (ucontrol->value.enumerated.item[0]) - tas->acr |= TAS_ACR_INPUT_B; + tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | + TAS_ACR_B_MON_SEL_RIGHT; if (oldacr == tas->acr) { mutex_unlock(&tas->mtx); return 0; @@ -686,8 +692,7 @@ static int tas_reset_init(struct tas *tas) if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) goto outerr; - tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | - TAS_ACR_B_MON_SEL_RIGHT; + tas->acr |= TAS_ACR_ANALOG_PDOWN; if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) goto outerr; -- cgit v0.10.2 From e7377071cd1dbe99bab9f35b11293b33f53b438d Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 6 Nov 2006 11:20:38 +0100 Subject: [ALSA] hda: fix sigmatel dell system detection Fixes Dell system detection on 9200 codecs. The support to detect certain Dell machines was merged in the 9205 table where it will be unused on the various Dell 9200-based codec systems. This moves the subsystem IDs to the correct 9200 table. Signed-off-by: Matt Porter Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 731b7b9..fe51ef3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -336,6 +336,13 @@ static struct hda_board_config stac9200_cfg_tbl[] = { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x2668, /* DFI LanParty */ .config = STAC_REF }, + /* Dell laptops have BIOS problem */ + { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, + .config = STAC_REF }, /* Dell Inspiron 630m */ + { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, + .config = STAC_REF }, /* Dell Latitude D620 */ + { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, + .config = STAC_REF }, /* Dell Latitude 120L */ {} /* terminator */ }; @@ -591,13 +598,6 @@ static struct hda_board_config stac9205_cfg_tbl[] = { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x2668, /* DFI LanParty */ .config = STAC_REF }, /* SigmaTel reference board */ - /* Dell laptops have BIOS problem */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, - .config = STAC_REF }, /* Dell Inspiron 630m */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, - .config = STAC_REF }, /* Dell Latitude D620 */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, - .config = STAC_REF }, /* Dell Latitude 120L */ {} /* terminator */ }; -- cgit v0.10.2 From 282e0c87f223afbe8b182197eb06c127a66353ce Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 6 Nov 2006 12:01:53 +0100 Subject: [ALSA] hda: fix typo for xw4400 PCI sub-ID The PCI sub-device ID for the HP xw4400 is actually 0x280c. Signed-off-by: John W. Linville Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0d728c6..fb96144 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5870,7 +5870,7 @@ static struct hda_board_config alc262_cfg_tbl[] = { { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, .config = ALC262_FUJITSU }, { .modelname = "hp-bpc", .config = ALC262_HP_BPC }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, + { .pci_subvendor = 0x103c, .pci_subdevice = 0x280c, .config = ALC262_HP_BPC }, /* xw4400 */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC262_HP_BPC }, /* xw6400 */ -- cgit v0.10.2 From de1b8b93a0ba016b07d13086a15ad692536e6995 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 Nov 2006 15:41:29 +0100 Subject: [ALSA] Fix hang-up at disconnection of usb-audio Fix hang-up at disconnection of usb-audio devices while accessing PCM. Don't handle PCM operations any more after shutdown flag is set. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 505b23e..e0821eb 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2359,7 +2359,8 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; snd_assert(substream != NULL, return -ENXIO); pcm = substream->pcm; - snd_pcm_oss_sync(pcm_oss_file); + if (!pcm->card->shutdown) + snd_pcm_oss_sync(pcm_oss_file); mutex_lock(&pcm->open_mutex); snd_pcm_oss_release_file(pcm_oss_file); mutex_unlock(&pcm->open_mutex); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 37b4b10..66e24b5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1310,7 +1310,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int f_flags) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->status->state == SNDRV_PCM_STATE_OPEN || + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (snd_pcm_running(substream)) return -EBUSY; @@ -1568,7 +1569,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) runtime = substream->runtime; card = substream->pcm->card; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->status->state == SNDRV_PCM_STATE_OPEN || + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; snd_power_lock(card); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c82b01c..67202b9 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1469,7 +1469,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - release_substream_urbs(subs, 0); + if (!subs->stream->chip->shutdown) + release_substream_urbs(subs, 0); return snd_pcm_free_vmalloc_buffer(substream); } -- cgit v0.10.2 From 3271b7b2da1db2e5f882d8b2a5f668157a76992f Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sat, 25 Nov 2006 22:02:47 +0000 Subject: [ALSA] snd-emu10k1: Fix capture for one variant. Fixes ALSA bug#324 Signed-off-by: James Courtier-Dutton Signed-off-by: Jaroslav Kysela diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 8058059..8bc4ffa 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -956,6 +956,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0151_chip = 1, .spk71 = 1, .spdif_bug = 1, + .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, .driver = "Audigy2", .name = "Audigy 2 [Unknown]", -- cgit v0.10.2 From c4423cccc0846a812013f39c8f8cae1d2d9dff9d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 28 Nov 2006 15:07:33 +0100 Subject: [ALSA] version 1.0.13 Signed-off-by: Jaroslav Kysela diff --git a/include/sound/version.h b/include/sound/version.h index 52fd687..17137f3 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by alsa/ksync script. */ #define CONFIG_SND_VERSION "1.0.13" -#define CONFIG_SND_DATE " (Sun Oct 22 08:56:16 2006 UTC)" +#define CONFIG_SND_DATE " (Tue Nov 28 14:07:24 2006 UTC)" -- cgit v0.10.2 From 5a64d4438ed1e759ccd30d9e90842bf360f19298 Mon Sep 17 00:00:00 2001 From: Chad Sellers Date: Mon, 6 Nov 2006 12:38:15 -0500 Subject: SELinux: remove current object class and permission validation mechanism Removes the current SELinux object class and permission validation code, as the current code makes it impossible to change or remove object classes and permissions on a running system. Additionally, the current code does not actually validate that the classes and permissions are correct, but instead merely validates that they do not change between policy reloads. Signed-off-by: Chad Sellers Acked-by: Stephen Smalley Signed-off-by: James Morris diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index bfe1227..33ae102 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1018,89 +1018,6 @@ int security_change_sid(u32 ssid, return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); } -/* - * Verify that each permission that is defined under the - * existing policy is still defined with the same value - * in the new policy. - */ -static int validate_perm(void *key, void *datum, void *p) -{ - struct hashtab *h; - struct perm_datum *perdatum, *perdatum2; - int rc = 0; - - - h = p; - perdatum = datum; - - perdatum2 = hashtab_search(h, key); - if (!perdatum2) { - printk(KERN_ERR "security: permission %s disappeared", - (char *)key); - rc = -ENOENT; - goto out; - } - if (perdatum->value != perdatum2->value) { - printk(KERN_ERR "security: the value of permission %s changed", - (char *)key); - rc = -EINVAL; - } -out: - return rc; -} - -/* - * Verify that each class that is defined under the - * existing policy is still defined with the same - * attributes in the new policy. - */ -static int validate_class(void *key, void *datum, void *p) -{ - struct policydb *newp; - struct class_datum *cladatum, *cladatum2; - int rc; - - newp = p; - cladatum = datum; - - cladatum2 = hashtab_search(newp->p_classes.table, key); - if (!cladatum2) { - printk(KERN_ERR "security: class %s disappeared\n", - (char *)key); - rc = -ENOENT; - goto out; - } - if (cladatum->value != cladatum2->value) { - printk(KERN_ERR "security: the value of class %s changed\n", - (char *)key); - rc = -EINVAL; - goto out; - } - if ((cladatum->comdatum && !cladatum2->comdatum) || - (!cladatum->comdatum && cladatum2->comdatum)) { - printk(KERN_ERR "security: the inherits clause for the access " - "vector definition for class %s changed\n", (char *)key); - rc = -EINVAL; - goto out; - } - if (cladatum->comdatum) { - rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm, - cladatum2->comdatum->permissions.table); - if (rc) { - printk(" in the access vector definition for class " - "%s\n", (char *)key); - goto out; - } - } - rc = hashtab_map(cladatum->permissions.table, validate_perm, - cladatum2->permissions.table); - if (rc) - printk(" in access vector definition for class %s\n", - (char *)key); -out: - return rc; -} - /* Clone the SID into the new SID table. */ static int clone_sid(u32 sid, struct context *context, @@ -1265,14 +1182,6 @@ int security_load_policy(void *data, size_t len) sidtab_init(&newsidtab); - /* Verify that the existing classes did not change. */ - if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) { - printk(KERN_ERR "security: the definition of an existing " - "class changed\n"); - rc = -EINVAL; - goto err; - } - /* Clone the SID table. */ sidtab_shutdown(&sidtab); if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { -- cgit v0.10.2 From 5c45899879e8caadb78f04c9c639f4c2025b9f00 Mon Sep 17 00:00:00 2001 From: Chad Sellers Date: Mon, 6 Nov 2006 12:38:16 -0500 Subject: SELinux: export object class and permission definitions Moves the definition of the 3 structs containing object class and permission definitions from avc.c to avc_ss.h so that the security server can access them for validation on policy load. This also adds a new struct type, defined_classes_perms_t, suitable for allowing the security server to access these data structures from the avc. Signed-off-by: Chad Sellers Acked-by: Stephen Smalley Signed-off-by: James Morris diff --git a/security/selinux/avc.c b/security/selinux/avc.c index a300702..74c0319 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -32,12 +32,7 @@ #include "avc.h" #include "avc_ss.h" -static const struct av_perm_to_string -{ - u16 tclass; - u32 value; - const char *name; -} av_perm_to_string[] = { +static const struct av_perm_to_string av_perm_to_string[] = { #define S_(c, v, s) { c, v, s }, #include "av_perm_to_string.h" #undef S_ @@ -57,17 +52,21 @@ static const char *class_to_string[] = { #undef TE_ #undef S_ -static const struct av_inherit -{ - u16 tclass; - const char **common_pts; - u32 common_base; -} av_inherit[] = { +static const struct av_inherit av_inherit[] = { #define S_(c, i, b) { c, common_##i##_perm_to_string, b }, #include "av_inherit.h" #undef S_ }; +const struct selinux_class_perm selinux_class_perm = { + av_perm_to_string, + ARRAY_SIZE(av_perm_to_string), + class_to_string, + ARRAY_SIZE(class_to_string), + av_inherit, + ARRAY_SIZE(av_inherit) +}; + #define AVC_CACHE_SLOTS 512 #define AVC_DEF_CACHE_THRESHOLD 512 #define AVC_CACHE_RECLAIM 16 diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 450a283..ff869e8 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h @@ -10,5 +10,29 @@ int avc_ss_reset(u32 seqno); +struct av_perm_to_string +{ + u16 tclass; + u32 value; + const char *name; +}; + +struct av_inherit +{ + u16 tclass; + const char **common_pts; + u32 common_base; +}; + +struct selinux_class_perm +{ + const struct av_perm_to_string *av_perm_to_string; + u32 av_pts_len; + const char **class_to_string; + u32 cts_len; + const struct av_inherit *av_inherit; + u32 av_inherit_len; +}; + #endif /* _SELINUX_AVC_SS_H_ */ -- cgit v0.10.2 From bb242497474da317a7169cc939c741ccf2e79e8c Mon Sep 17 00:00:00 2001 From: Chad Sellers Date: Mon, 6 Nov 2006 12:38:17 -0500 Subject: SELinux: ensure keys constant in hashtab_search Makes the key argument passed into hashtab_search and all the functions it calls constant. These functions include hash table function pointers hash_value and keycmp. The only implementations of these currently are symhash and symcmp, which do not modify the key. The key parameter should never be changed by any of these, so it should be const. This is necessary to allow calling these functions with keys found in kernel object class and permission definitions. Signed-off-by: Chad Sellers Acked-by: Stephen Smalley Signed-off-by: James Morris diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 24e5ec9..77b530c 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -8,8 +8,8 @@ #include #include "hashtab.h" -struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), - int (*keycmp)(struct hashtab *h, void *key1, void *key2), +struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key), + int (*keycmp)(struct hashtab *h, const void *key1, const void *key2), u32 size) { struct hashtab *p; @@ -71,7 +71,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum) return 0; } -void *hashtab_search(struct hashtab *h, void *key) +void *hashtab_search(struct hashtab *h, const void *key) { u32 hvalue; struct hashtab_node *cur; diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 4cc8581..7e2ff3e 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h @@ -22,9 +22,9 @@ struct hashtab { struct hashtab_node **htable; /* hash table */ u32 size; /* number of slots in hash table */ u32 nel; /* number of elements in hash table */ - u32 (*hash_value)(struct hashtab *h, void *key); + u32 (*hash_value)(struct hashtab *h, const void *key); /* hash function */ - int (*keycmp)(struct hashtab *h, void *key1, void *key2); + int (*keycmp)(struct hashtab *h, const void *key1, const void *key2); /* key comparison function */ }; @@ -39,8 +39,8 @@ struct hashtab_info { * Returns NULL if insufficent space is available or * the new hash table otherwise. */ -struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), - int (*keycmp)(struct hashtab *h, void *key1, void *key2), +struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key), + int (*keycmp)(struct hashtab *h, const void *key1, const void *key2), u32 size); /* @@ -59,7 +59,7 @@ int hashtab_insert(struct hashtab *h, void *k, void *d); * Returns NULL if no entry has the specified key or * the datum of the entry otherwise. */ -void *hashtab_search(struct hashtab *h, void *k); +void *hashtab_search(struct hashtab *h, const void *k); /* * Destroys the specified hash table. diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 24a10d3..837658a 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -9,9 +9,9 @@ #include #include "symtab.h" -static unsigned int symhash(struct hashtab *h, void *key) +static unsigned int symhash(struct hashtab *h, const void *key) { - char *p, *keyp; + const char *p, *keyp; unsigned int size; unsigned int val; @@ -23,9 +23,9 @@ static unsigned int symhash(struct hashtab *h, void *key) return val & (h->size - 1); } -static int symcmp(struct hashtab *h, void *key1, void *key2) +static int symcmp(struct hashtab *h, const void *key1, const void *key2) { - char *keyp1, *keyp2; + const char *keyp1, *keyp2; keyp1 = key1; keyp2 = key2; -- cgit v0.10.2 From b94c7e677b9d28bd3f9ba4a70df6bfa7942867ca Mon Sep 17 00:00:00 2001 From: Chad Sellers Date: Mon, 6 Nov 2006 12:38:18 -0500 Subject: SELinux: validate kernel object classes and permissions This is a new object class and permission validation scheme that validates against the defined kernel headers. This scheme allows extra classes and permissions that do not conflict with the kernel definitions to be added to the policy. This validation is now done for all policy loads, not just subsequent loads after the first policy load. The implementation walks the three structrures containing the defined object class and permission values and ensures their values are the same in the policy being loaded. This includes verifying the object classes themselves, the permissions they contain, and the permissions they inherit from commons. Classes or permissions that are present in the kernel but missing from the policy cause a warning (printed to KERN_INFO) to be printed, but do not stop the policy from loading, emulating current behavior. Any other inconsistencies cause the load to fail. Signed-off-by: Chad Sellers Acked-by: Stephen Smalley Signed-off-by: James Morris diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 33ae102..4088204 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -17,9 +17,13 @@ * * Added support for NetLabel * + * Updated: Chad Sellers + * + * Added validation of kernel classes and permissions + * * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. - * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC * Copyright (C) 2003 Red Hat, Inc., James Morris * 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 @@ -53,6 +57,11 @@ extern void selnl_notify_policyload(u32 seqno); unsigned int policydb_loaded_version; +/* + * This is declared in avc.c + */ +extern const struct selinux_class_perm selinux_class_perm; + static DEFINE_RWLOCK(policy_rwlock); #define POLICY_RDLOCK read_lock(&policy_rwlock) #define POLICY_WRLOCK write_lock_irq(&policy_rwlock) @@ -1018,6 +1027,115 @@ int security_change_sid(u32 ssid, return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); } +/* + * Verify that each kernel class that is defined in the + * policy is correct + */ +static int validate_classes(struct policydb *p) +{ + int i, j; + struct class_datum *cladatum; + struct perm_datum *perdatum; + u32 nprim, tmp, common_pts_len, perm_val, pol_val; + u16 class_val; + const struct selinux_class_perm *kdefs = &selinux_class_perm; + const char *def_class, *def_perm, *pol_class; + struct symtab *perms; + + for (i = 1; i < kdefs->cts_len; i++) { + def_class = kdefs->class_to_string[i]; + if (i > p->p_classes.nprim) { + printk(KERN_INFO + "security: class %s not defined in policy\n", + def_class); + continue; + } + pol_class = p->p_class_val_to_name[i-1]; + if (strcmp(pol_class, def_class)) { + printk(KERN_ERR + "security: class %d is incorrect, found %s but should be %s\n", + i, pol_class, def_class); + return -EINVAL; + } + } + for (i = 0; i < kdefs->av_pts_len; i++) { + class_val = kdefs->av_perm_to_string[i].tclass; + perm_val = kdefs->av_perm_to_string[i].value; + def_perm = kdefs->av_perm_to_string[i].name; + if (class_val > p->p_classes.nprim) + continue; + pol_class = p->p_class_val_to_name[class_val-1]; + cladatum = hashtab_search(p->p_classes.table, pol_class); + BUG_ON(!cladatum); + perms = &cladatum->permissions; + nprim = 1 << (perms->nprim - 1); + if (perm_val > nprim) { + printk(KERN_INFO + "security: permission %s in class %s not defined in policy\n", + def_perm, pol_class); + continue; + } + perdatum = hashtab_search(perms->table, def_perm); + if (perdatum == NULL) { + printk(KERN_ERR + "security: permission %s in class %s not found in policy\n", + def_perm, pol_class); + return -EINVAL; + } + pol_val = 1 << (perdatum->value - 1); + if (pol_val != perm_val) { + printk(KERN_ERR + "security: permission %s in class %s has incorrect value\n", + def_perm, pol_class); + return -EINVAL; + } + } + for (i = 0; i < kdefs->av_inherit_len; i++) { + class_val = kdefs->av_inherit[i].tclass; + if (class_val > p->p_classes.nprim) + continue; + pol_class = p->p_class_val_to_name[class_val-1]; + cladatum = hashtab_search(p->p_classes.table, pol_class); + BUG_ON(!cladatum); + if (!cladatum->comdatum) { + printk(KERN_ERR + "security: class %s should have an inherits clause but does not\n", + pol_class); + return -EINVAL; + } + tmp = kdefs->av_inherit[i].common_base; + common_pts_len = 0; + while (!(tmp & 0x01)) { + common_pts_len++; + tmp >>= 1; + } + perms = &cladatum->comdatum->permissions; + for (j = 0; j < common_pts_len; j++) { + def_perm = kdefs->av_inherit[i].common_pts[j]; + if (j >= perms->nprim) { + printk(KERN_INFO + "security: permission %s in class %s not defined in policy\n", + def_perm, pol_class); + continue; + } + perdatum = hashtab_search(perms->table, def_perm); + if (perdatum == NULL) { + printk(KERN_ERR + "security: permission %s in class %s not found in policy\n", + def_perm, pol_class); + return -EINVAL; + } + if (perdatum->value != j + 1) { + printk(KERN_ERR + "security: permission %s in class %s has incorrect value\n", + def_perm, pol_class); + return -EINVAL; + } + } + } + return 0; +} + /* Clone the SID into the new SID table. */ static int clone_sid(u32 sid, struct context *context, @@ -1160,6 +1278,16 @@ int security_load_policy(void *data, size_t len) avtab_cache_destroy(); return -EINVAL; } + /* Verify that the kernel defined classes are correct. */ + if (validate_classes(&policydb)) { + printk(KERN_ERR + "security: the definition of a class is incorrect\n"); + LOAD_UNLOCK; + sidtab_destroy(&sidtab); + policydb_destroy(&policydb); + avtab_cache_destroy(); + return -EINVAL; + } policydb_loaded_version = policydb.policyvers; ss_initialized = 1; seqno = ++latest_granting; @@ -1182,6 +1310,14 @@ int security_load_policy(void *data, size_t len) sidtab_init(&newsidtab); + /* Verify that the kernel defined classes are correct. */ + if (validate_classes(&newpolicydb)) { + printk(KERN_ERR + "security: the definition of a class is incorrect\n"); + rc = -EINVAL; + goto err; + } + /* Clone the SID table. */ sidtab_shutdown(&sidtab); if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { -- cgit v0.10.2 From 24d7bb3396c51ceb2285e0e7b0c1bd1865652c43 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 28 Nov 2006 09:14:05 +0100 Subject: [PATCH] x86_64: fix 'earlyprintk=...,keep' regression Commit 2c8c0e6b8d7700a990da8d24eff767f9ca223b96 ("[PATCH] Convert x86-64 to early param") broke the earlyprintk=...,keep feature. This restores that functionality. Tested on x86_64. Must-have for v2.6.19, no risk. Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index e22ecd5..47b6d90 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c @@ -224,7 +224,7 @@ static int __init setup_early_printk(char *buf) return 0; early_console_initialized = 1; - if (!strcmp(buf,"keep")) + if (strstr(buf, "keep")) keep_early = 1; if (!strncmp(buf, "serial", 6)) { -- cgit v0.10.2 From a3df3b6f2e37474cdb8b56d55d31be41c22f9b18 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 27 Nov 2006 14:37:21 -0600 Subject: [PATCH] softmac: remove netif_tx_disable when scanning In the scan section of ieee80211softmac, network transmits are disabled. When SoftMAC re-enables transmits, it may override the wishes of a driver that may have very good reasons for disabling transmits. At least one failure in bcm43xx can be traced to this problem. In addition, several unexplained problems may arise from the unexpected enabling of transmits. Note that making this change introduces a new bug that would allow transmits for the current session to be transmitted on the wrong channel; however, the new bug is much less severe than the one being fixed, as the new one only leads to a few retransmits, whereas the old one can bring the interface down. A fix that will not introduce new bugs is being investigated; however, the current, more serious one should be fixed now. Signed-off-by: Michael Buesch Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index d31cf77..ad67368 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,7 +47,6 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); - netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -248,7 +247,6 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } - netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 3faaeb2..a15b095 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 v0.10.2 From ff0a538d8b08700df2b46f9aafc9fb2765071f0a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 28 Nov 2006 20:12:59 +0100 Subject: [PATCH] x86-64: work around gcc4 issue with -Os in Dwarf2 stack unwind This fixes a problem with gcc4 mis-compiling the stack unwind code under -Os, which resulted in 'stuck' messages whenever an assembly routine was encountered. (The second hunk is trivial cleanup.) Signed-off-by: Jan Beulich diff --git a/kernel/unwind.c b/kernel/unwind.c index f7e50d1..ed0a21d 100644 --- a/kernel/unwind.c +++ b/kernel/unwind.c @@ -938,8 +938,11 @@ int unwind(struct unwind_frame_info *frame) else { retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); /* skip augmentation */ - if (((const char *)(cie + 2))[1] == 'z') - ptr += get_uleb128(&ptr, end); + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + + ptr += augSize; + } if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info) || REG_INVALID(retAddrReg) @@ -963,9 +966,7 @@ int unwind(struct unwind_frame_info *frame) if (cie == NULL || fde == NULL) { #ifdef CONFIG_FRAME_POINTER unsigned long top, bottom; -#endif -#ifdef CONFIG_FRAME_POINTER top = STACK_TOP(frame->task); bottom = STACK_BOTTOM(frame->task); # if FRAME_RETADDR_OFFSET < 0 -- cgit v0.10.2 From f7a23328a738b45124400d85eaf78a76939da726 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 28 Nov 2006 20:12:59 +0100 Subject: [PATCH] x86-64: Fix warning in io_apic.c diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 14654e6..c80081a 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -754,10 +754,8 @@ void __setup_vector_irq(int cpu) { /* Initialize vector_irq on a new cpu */ /* This function must be called with vector_lock held */ - unsigned long flags; int irq, vector; - /* Mark the inuse vectors */ for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) { if (!cpu_isset(cpu, irq_domain[irq])) -- cgit v0.10.2 From 38b5b036b91248be8033d42dd0778b1c75c5af58 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 28 Nov 2006 20:12:59 +0100 Subject: [PATCH] i386: Fix compilation with UP genericarch Fix arch/i386/mach-generic/built-in.o: In function `apicid_to_node': summit.c:(.text+0x2f): undefined reference to `apicid_2_node' with CONFIG_GENERICH_ARCH and !CONFIG_SMP Signed-off-by: Andi Kleen diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h index ef0671e..43e5bd8 100644 --- a/include/asm-i386/mach-summit/mach_apic.h +++ b/include/asm-i386/mach-summit/mach_apic.h @@ -88,7 +88,11 @@ static inline void clustered_apic_check(void) static inline int apicid_to_node(int logical_apicid) { +#ifdef CONFIG_SMP return apicid_2_node[hard_smp_processor_id()]; +#else + return 0; +#endif } /* Mapping from cpu number to logical apicid */ -- cgit v0.10.2 From c547c77ee4d0408907847f64c403df1bf2f9c7a0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 28 Nov 2006 20:12:59 +0100 Subject: [PATCH] x86-64: Use stricter in process stack check for unwinder Previously it would check for alignment only, which could break if the stack pointer was unaligned. Now explicitely check if the stack pointer is in the stack page of the current process. Ported from i386. Signed-off-by: Andi Kleen diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index a153d0a..0d65b22 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -242,12 +242,19 @@ static int dump_trace_unwind(struct unwind_frame_info *info, void *context) * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack */ +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +{ + void *t = (void *)tinfo; + return p > t && p < t + THREAD_SIZE - 3; +} + void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack, struct stacktrace_ops *ops, void *data) { const unsigned cpu = smp_processor_id(); unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; unsigned used = 0; + struct thread_info *tinfo; if (!tsk) tsk = current; @@ -370,7 +377,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s /* * This handles the process stack: */ - HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0); + tinfo = current_thread_info(); + HANDLE_STACK (valid_stack_ptr(tinfo, stack)); #undef HANDLE_STACK } EXPORT_SYMBOL(dump_trace); -- cgit v0.10.2 From 177b2927e2eea73c598a218680b4dc9043c51dcb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 24 Nov 2006 12:17:51 +0000 Subject: [MIPS] Fix Bonito bootup message. Even when enabling Bonito IOBC coherence the kernel would actually claim it was disabling it. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index ab460f8..282f3e5 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c @@ -159,7 +159,7 @@ void __init plat_mem_setup(void) BONITO_PCIMEMBASECFG |= (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); - printk("Disabled Bonito IOBC coherency\n"); + printk("Enabled Bonito IOBC coherency\n"); } } else -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h index f63245b..3632989 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 a7d29bd..e5fedf9 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 b8ea3de..e4dd40a 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 e81a2d3..317d37c 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 v0.10.2 From ba8379b220509e9448c00a77cf6c15ac2a559cc7 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 20 Nov 2006 15:02:49 -0800 Subject: [PATCH] bridge: fix possible overflow in get_fdb_entries Make sure to properly clamp maxnum to avoid overflow Signed-off-by: Chris Wright Acked-by: Eugene Teo Acked-by: Marcel Holtmann Signed-off-by: Linus Torvalds diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 4e4119a..4c61a7e 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -58,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, { int num; void *buf; - size_t size = maxnum * sizeof(struct __fdb_entry); + size_t size; - if (size > PAGE_SIZE) { - size = PAGE_SIZE; + /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */ + if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry)) maxnum = PAGE_SIZE/sizeof(struct __fdb_entry); - } + + size = maxnum * sizeof(struct __fdb_entry); buf = kmalloc(size, GFP_USER); if (!buf) -- cgit v0.10.2 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 diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 7ea49a0..296159e 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 v0.10.2 From 3cce4856ff3dfa663b1a168dab48120d70820da6 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 28 Nov 2006 12:29:43 -0800 Subject: [PATCH] fix create_write_pipe() error check The return value of create_write_pipe()/create_read_pipe() should be checked by IS_ERR(). Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/kmod.c b/kernel/kmod.c index bb4e29d..2b76dee 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -307,14 +307,14 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, return 0; f = create_write_pipe(); - if (!f) - return -ENOMEM; + if (IS_ERR(f)) + return PTR_ERR(f); *filp = f; f = create_read_pipe(f); - if (!f) { + if (IS_ERR(f)) { free_write_pipe(*filp); - return -ENOMEM; + return PTR_ERR(f); } sub_info.stdin = f; -- cgit v0.10.2 From de88777e6942de76410ad2eb2858f5fbb6eb9c35 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 28 Nov 2006 12:29:49 -0800 Subject: [PATCH] ecryptfs: fix crypto_alloc_blkcipher() error check The return value of crypto_alloc_blkcipher() should be checked by IS_ERR(). Cc: Mike Halcrow Cc: Phillip Hellewell Signed-off-by: Akinobu Mita Cc: Herbert Xu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 136175a..f63a775 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -820,7 +820,8 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); kfree(full_alg_name); - if (!crypt_stat->tfm) { + if (IS_ERR(crypt_stat->tfm)) { + rc = PTR_ERR(crypt_stat->tfm); ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " "Error initializing cipher [%s]\n", crypt_stat->cipher); -- cgit v0.10.2 From 4195bdbea42151c04485b0d131eed6dd97309cee Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 27 Nov 2006 23:58:11 -0500 Subject: [PATCH] add missing libsas include to fix s390 compilation. include/scsi/libsas.h:479: error: field 'smp_req' has incomplete type include/scsi/libsas.h:480: error: field 'smp_resp' has incomplete type Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9582e84..1d77b63 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -35,6 +35,7 @@ #include #include #include +#include struct block_device; -- cgit v0.10.2 From dafc741cf23351a6f43895579a72ab8818ba00ae Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:25:32 -0800 Subject: [NETFILTER]: nfctnetlink: assign helper to newly created conntrack This fixes the bug which doesn't assign helper to newly created conntrack via nf_conntrack_netlink. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index bd0156a..77a46ee 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -949,6 +949,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], { struct nf_conn *ct; int err = -EINVAL; + struct nf_conn_help *help; ct = nf_conntrack_alloc(otuple, rtuple); if (ct == NULL || IS_ERR(ct)) @@ -976,9 +977,16 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif + help = nfct_help(ct); + if (help) + help->helper = nf_ct_helper_find_get(rtuple); + add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); + if (help && help->helper) + nf_ct_helper_put(help->helper); + return 0; err: -- cgit v0.10.2 From 22e7410b760b9c1777839fdd10382c60df8cbda2 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:25:59 -0800 Subject: [NETFILTER]: nf_conntrack: fix the race on assign helper to new conntrack The found helper cannot be assigned to conntrack after unlocking nf_conntrack_lock. This tries to find helper to assign again. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 836541e5..0f58307 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -893,12 +893,6 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, memset(conntrack, 0, nf_ct_cache[features].size); conntrack->features = features; - if (helper) { - struct nf_conn_help *help = nfct_help(conntrack); - NF_CT_ASSERT(help); - help->helper = helper; - } - atomic_set(&conntrack->ct_general.use, 1); conntrack->ct_general.destroy = destroy_conntrack; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; @@ -982,8 +976,13 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, #endif nf_conntrack_get(&conntrack->master->ct_general); NF_CT_STAT_INC(expect_new); - } else + } else { + struct nf_conn_help *help = nfct_help(conntrack); + + if (help) + help->helper = __nf_ct_helper_find(&repl_tuple); NF_CT_STAT_INC(new); + } /* Overload tuple linked list to put us in unconfirmed list. */ list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); -- cgit v0.10.2 From c537b75a3ba9f5d2569f313742cd379dff6ceb70 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 27 Nov 2006 10:26:25 -0800 Subject: [NETFILTER]: ctnetlink: fix reference count leak When NFA_NEST exceeds the skb size the protocol reference is leaked. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 262d0d4..55f0ae6 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -153,6 +153,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct) return ret; nfattr_failure: + ip_conntrack_proto_put(proto); return -1; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 77a46ee..ab67c2b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -161,6 +161,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) return ret; nfattr_failure: + nf_ct_proto_put(proto); return -1; } -- cgit v0.10.2 From 2e47c264a2e6ea24c27b4987607222202818c1f4 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 27 Nov 2006 10:26:46 -0800 Subject: [NETFILTER]: conntrack: fix refcount leak when finding expectation All users of __{ip,nf}_conntrack_expect_find() don't expect that it increments the reference count of expectation. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 143c466..8b848aa 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -225,10 +225,8 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) struct ip_conntrack_expect *i; list_for_each_entry(i, &ip_conntrack_expect_list, list) { - if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { - atomic_inc(&i->use); + if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; - } } return NULL; } @@ -241,6 +239,8 @@ ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) read_lock_bh(&ip_conntrack_lock); i = __ip_conntrack_expect_find(tuple); + if (i) + atomic_inc(&i->use); read_unlock_bh(&ip_conntrack_lock); return i; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0f58307..de0567b 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -469,10 +469,8 @@ __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) struct nf_conntrack_expect *i; list_for_each_entry(i, &nf_conntrack_expect_list, list) { - if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { - atomic_inc(&i->use); + if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) return i; - } } return NULL; } @@ -485,6 +483,8 @@ nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) read_lock_bh(&nf_conntrack_lock); i = __nf_conntrack_expect_find(tuple); + if (i) + atomic_inc(&i->use); read_unlock_bh(&nf_conntrack_lock); return i; -- cgit v0.10.2 From af443b6d90de17f7630621269cf0610d9d772670 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 28 Nov 2006 20:10:21 -0800 Subject: [NETFILTER]: ipt_REJECT: fix memory corruption On devices with hard_header_len > LL_MAX_HEADER ip_route_me_harder() reallocates the skb, leading to memory corruption when using the stale tcph pointer to update the checksum. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index ad0312d..264763a 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -114,6 +114,14 @@ static void send_reset(struct sk_buff *oldskb, int hook) tcph->window = 0; tcph->urg_ptr = 0; + /* Adjust TCP checksum */ + tcph->check = 0; + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), + nskb->nh.iph->saddr, + nskb->nh.iph->daddr, + csum_partial((char *)tcph, + sizeof(struct tcphdr), 0)); + /* Set DF, id = 0 */ nskb->nh.iph->frag_off = htons(IP_DF); nskb->nh.iph->id = 0; @@ -129,14 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook) if (ip_route_me_harder(&nskb, addr_type)) goto free_nskb; - /* Adjust TCP checksum */ nskb->ip_summed = CHECKSUM_NONE; - tcph->check = 0; - tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), - nskb->nh.iph->saddr, - nskb->nh.iph->daddr, - csum_partial((char *)tcph, - sizeof(struct tcphdr), 0)); + /* Adjust IP TTL */ nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); -- cgit v0.10.2 From e81c73596704793e73e6dbb478f41686f15a4b34 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 28 Nov 2006 20:53:39 -0800 Subject: [NET]: Fix MAX_HEADER setting. MAX_HEADER is either set to LL_MAX_HEADER or LL_MAX_HEADER + 48, and this is controlled by a set of CONFIG_* ifdef tests. It is trying to use LL_MAX_HEADER + 48 when any of the tunnels are enabled which set hard_header_len like this: dev->hard_header_len = LL_MAX_HEADER + sizeof(struct xxx); The correct set of tunnel drivers which do this are: ipip ip_gre ip6_tunnel sit so make the ifdef test match. Noticed by Patrick McHardy and with help from Herbert Xu. Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9264139..83b8c4f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -93,8 +93,10 @@ struct netpoll_info; #endif #endif -#if !defined(CONFIG_NET_IPIP) && \ - !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) +#if !defined(CONFIG_NET_IPIP) && !defined(CONFIG_NET_IPIP_MODULE) && \ + !defined(CONFIG_NET_IPGRE) && !defined(CONFIG_NET_IPGRE_MODULE) && \ + !defined(CONFIG_IPV6_SIT) && !defined(CONFIG_IPV6_SIT_MODULE) && \ + !defined(CONFIG_IPV6_TUNNEL) && !defined(CONFIG_IPV6_TUNNEL_MODULE) #define MAX_HEADER LL_MAX_HEADER #else #define MAX_HEADER (LL_MAX_HEADER + 48) -- cgit v0.10.2 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 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f510e11..bddb14e 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 v0.10.2 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 diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 377425e..4a80ff9 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 1d695df..64eed99 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 5c47a9e..8be46a6 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 96a0980..2cd3076 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 1ce28d2..4e1d3b5 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 b9bbd1d..29a60df 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 2cd3c0f..33d2b88f 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 a07cc81..981f492 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 f8def3f..8dafa4a 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 247b436..5a0b811 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 ef18c60..755f792 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 6d3e4c0..c0e150a9 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 fce3fcd..1eeb16f 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 58cfb2b..47d7664 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 3334d72..d216cc5 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 640b8b0..40ca2b8 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 18ff3e5..7f68f14 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 52a2bdf..0210b10 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 10231ef..b39078b 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 9dfe3e9..e00d406 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 f5672de..1963a4d 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 2a3dbee..7ec800f 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 fc947df..8837256 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 a7320ba..c6319cf 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 c6906b4..2f4770c 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 e93ea27..999922d 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 d894d99..beb6d10 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 5ba9eb2..6baf51b 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 2c3cc0c..314938d 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 1af83d7..048c2bb 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 4533b63..e4e5ea4 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 067d9d2..0c75dae 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 5bbf76e..be7f60e 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 4a2b72b..11942fd 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 b9ffafb..91e85f9 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 08a6dc8..dc1cfc6 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 9640f80..bfda1f7 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 1e7be9e..c5f1616 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 v0.10.2 From f5d6c63a67a8f124ddae88511427249d1dd87880 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 29 Nov 2006 15:04:08 +0000 Subject: [MIPS] Do topology_init even on uniprocessor kernels. Otherwise CPU 0 doesn't show up in sysfs which breaks some software. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index cd9cec9..6bfbbed 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ - time.o traps.o unaligned.o + time.o topology.o traps.o unaligned.o binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ irix5sys.o sysirix.o diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index db80957..49db516 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -463,28 +463,5 @@ void flush_tlb_one(unsigned long vaddr) smp_on_each_tlb(flush_tlb_one_ipi, (void *) vaddr); } -static DEFINE_PER_CPU(struct cpu, cpu_devices); - -static int __init topology_init(void) -{ - int i, ret; - -#ifdef CONFIG_NUMA - for_each_online_node(i) - register_one_node(i); -#endif /* CONFIG_NUMA */ - - for_each_present_cpu(i) { - ret = register_cpu(&per_cpu(cpu_devices, i), i); - if (ret) - printk(KERN_WARNING "topology_init: register_cpu %d " - "failed (%d)\n", i, ret); - } - - return 0; -} - -subsys_initcall(topology_init); - EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(flush_tlb_one); diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c new file mode 100644 index 0000000..660e44e --- /dev/null +++ b/arch/mips/kernel/topology.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(struct cpu, cpu_devices); + +static int __init topology_init(void) +{ + int i, ret; + +#ifdef CONFIG_NUMA + for_each_online_node(i) + register_one_node(i); +#endif /* CONFIG_NUMA */ + + for_each_present_cpu(i) { + ret = register_cpu(&per_cpu(cpu_devices, i), i); + if (ret) + printk(KERN_WARNING "topology_init: register_cpu %d " + "failed (%d)\n", i, ret); + } + + return 0; +} + +subsys_initcall(topology_init); -- cgit v0.10.2 From aed6fad8beca30a71a6950b6f650822254efa8c6 Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Wed, 29 Nov 2006 12:09:52 +0100 Subject: [ARM] 3943/1: share declaration of struct pxa2xx_udc_mach_info between multiple platforms Move declaration of struct pxa2xx_udc_mach_info from include/asm-arm/arch-pxa/udc.h to new file include/asm-arm/mach/udc_pxa2xx.h. This allow us to use this structure with multiple platforms - pxa and ixp4xx. USB device controller used in pxa25x is the same as controller used in ixp4xx. Signed-off-by: Milan Svoboda Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h index 121cd24..646480d 100644 --- a/include/asm-arm/arch-pxa/udc.h +++ b/include/asm-arm/arch-pxa/udc.h @@ -4,23 +4,8 @@ * This supports machine-specific differences in how the PXA2xx * USB Device Controller (UDC) is wired. * - * It is set in linux/arch/arm/mach-pxa/.c and used in - * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c */ -struct pxa2xx_udc_mach_info { - int (*udc_is_connected)(void); /* do we see host? */ - void (*udc_command)(int cmd); -#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */ -#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */ - - /* Boards following the design guidelines in the developer's manual, - * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane - * VBUS IRQ and omit the methods above. Store the GPIO number - * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits. - */ - u16 gpio_vbus; /* high == vbus present */ - u16 gpio_pullup; /* high == pullup activated */ -}; +#include extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info); diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h new file mode 100644 index 0000000..ff0a957 --- /dev/null +++ b/include/asm-arm/mach/udc_pxa2xx.h @@ -0,0 +1,26 @@ +/* + * linux/include/asm-arm/mach/udc_pxa2xx.h + * + * This supports machine-specific differences in how the PXA2xx + * USB Device Controller (UDC) is wired. + * + * It is set in linux/arch/arm/mach-pxa/.c or in + * linux/arch/mach-ixp4xx/.c and used in + * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c + */ + +struct pxa2xx_udc_mach_info { + int (*udc_is_connected)(void); /* do we see host? */ + void (*udc_command)(int cmd); +#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */ +#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */ + + /* Boards following the design guidelines in the developer's manual, + * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane + * VBUS IRQ and omit the methods above. Store the GPIO number + * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits. + */ + u16 gpio_vbus; /* high == vbus present */ + u16 gpio_pullup; /* high == pullup activated */ +}; + -- cgit v0.10.2 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 diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 27f90b2..b977ed8 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 v0.10.2 From 0215ffb08ce99e2bb59eca114a99499a4d06e704 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 29 Nov 2006 13:57:37 -0800 Subject: Linux 2.6.19 It's all good. diff --git a/Makefile b/Makefile index 958fad6..aef9625 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc6 +EXTRAVERSION = NAME=Avast! A bilge rat! # *DOCUMENTATION* -- cgit v0.10.2 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 diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 845090b..4975d81 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 4975d81..9aba4ea 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 v0.10.2 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 diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index e11187e..a68d7c7 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9aba4ea..b449e26 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 25b1018..82bc83b 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 c3fb304..2bbcfa5 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 ad4f4d5..b4894ba 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 fc67f78..21422a3 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 82bc83b..78d9c0c 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 b449e26..cf48f26 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 v0.10.2 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 diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4b09147..613be2e 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 6959945..57cdc1b 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 149b369..283d50b 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 e284e06..8ec9fa1 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 45e106f..acfa41d 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 47ea021..0491ec7 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 47ca8a9..a8ad072 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 a486dec..f71ffa8 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 59df516..c1e9507 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 6a7822e..33e3ba7 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 f5d7677..58fcf5a 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 623dc95..1687c51 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index a545610..acdee33 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 v0.10.2 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 diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a72bcea..3f9c162 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 1b17dcd..04a9db5 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 9c53916..234e5b0 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 v0.10.2 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 diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 2bbcfa5..22d498c 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 v0.10.2 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 diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 22d498c..0cfd784 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 v0.10.2 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 diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 0cfd784..b02e541 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 v0.10.2 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 diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index b02e541..54faa03 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 v0.10.2 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 diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 54faa03..cf797d7 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 01f5aa9..3d1c1c5 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 cf3e50e..8682aa5 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 e028ff1..bf7a400 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 2f13509..dc3bda2 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 58fcf5a..34d2c47 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 v0.10.2 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 diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c index 5bcf697..179d005 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 v0.10.2 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 diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index a68d7c7..15ba518 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 v0.10.2 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 diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 15ba518..7767a11 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 v0.10.2 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 diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 613be2e..64ab5fc 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 v0.10.2 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 diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 0b8a79d..f2b6185 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 85522da..5ba3154 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 3faa182..d282d65 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 v0.10.2 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 diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 78d9c0c..e5dc453 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 b4894ba..1f4f2d2 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 c9b4738..5c07017 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 066c20b..37650af 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 v0.10.2 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 diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 1f4f2d2..f15220a 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 v0.10.2 From 99e3b942c62f42c8d5added63305e12372b06daf Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:19:59 +0200 Subject: [MIPS] page.h: remove __pa() usages. __pa() was used by virt_to_page() and virt_addr_valid(). These latter are used when kernel is initialised so __pa() is not appropriate, we use virt_to_phys() instead. Futhermore __pa() is going to take care of CKSEG0/XKPHYS address mix for 64 bit kernels. This makes __pa() more complex than virt_to_phys() and this extra work is not needed by virt_to_page() and virt_addr_valid(). Eventually it consolidates virt_to_phys() prototype by making its argument 'const'. this avoids some warnings that was due to some virt_to_page() usages which pass const pointer. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2de4d3c..3049912 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -90,9 +90,9 @@ unsigned long setup_zero_pages(void) if (!empty_zero_page) panic("Oh boy, that early out of memory?"); - page = virt_to_page(empty_zero_page); + page = virt_to_page((void *)empty_zero_page); split_page(page, order); - while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { + while (page < virt_to_page((void *)(empty_zero_page + (PAGE_SIZE << order)))) { SetPageReserved(page); page++; } @@ -448,8 +448,8 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) unsigned long addr; for (addr = begin; addr < end; addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - init_page_count(virt_to_page(addr)); + ClearPageReserved(virt_to_page((void *)addr)); + init_page_count(virt_to_page((void *)addr)); memset((void *)addr, 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h index bc5f3c5..d77b657 100644 --- a/include/asm-mips/io.h +++ b/include/asm-mips/io.h @@ -113,7 +113,7 @@ static inline void set_io_port_base(unsigned long base) * almost all conceivable cases a device driver should not be using * this function */ -static inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile const void *address) { return (unsigned long)address - PAGE_OFFSET; } diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index 85b258e..edb33a1 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -34,7 +34,9 @@ #ifndef __ASSEMBLY__ +#include #include +#include extern void clear_page(void * page); extern void copy_page(void * to, void * from); @@ -160,8 +162,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #endif -#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr))) +#define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr))) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 1ca4d1e..f2e1325 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -67,7 +67,7 @@ extern unsigned long empty_zero_page; extern unsigned long zero_page_mask; #define ZERO_PAGE(vaddr) \ - (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))) + (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))) #define __HAVE_ARCH_MOVE_PTE #define move_pte(pte, prot, old_addr, new_addr) \ -- cgit v0.10.2 From 620a4802be8ee7989b1b6684b7198ebae02af854 Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:00 +0200 Subject: [MIPS] Make __pa() aware of XKPHYS/CKSEG0 address mix for 64 bit kernels During early boot mem init, some configs couldn't use __pa() to convert virtual into physical addresses. Specially for 64 bit kernel cases when CONFIG_BUILD_ELF64=n. This patch make __pa() work for _all_ configs and thus make CPHYSADDR() useless. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index edb33a1..c3b13de 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -136,8 +136,13 @@ typedef struct { unsigned long pgprot; } pgprot_t; /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) -#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) +#define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0) +#else +#define __pa_page_offset(x) PAGE_OFFSET +#endif +#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x)) +#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) -- cgit v0.10.2 From d4df6d4e7a66b7a9bd57f5dc7d80d6b55dc12dbb Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:01 +0200 Subject: [MIPS] setup.c: get ride of CPHYSADDR() and use new __pa() implementation instead introduced by the previous patch. Indeed this macro can be used now even by the 64 bit kernels with CONFIG_BUILD_ELF64=n config. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 8f6e896..715451a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -204,12 +204,12 @@ static void __init finalize_initrd(void) printk(KERN_INFO "Initrd not found or empty"); goto disable; } - if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { + if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { printk("Initrd extends beyond end of memory"); goto disable; } - reserve_bootmem(CPHYSADDR(initrd_start), size); + reserve_bootmem(__pa(initrd_start), size); initrd_below_start_ok = 1; printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", @@ -260,7 +260,7 @@ static void __init bootmem_init(void) * of usable memory. */ reserved_end = init_initrd(); - reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end))); + reserved_end = PFN_UP(__pa(max(reserved_end, (unsigned long)&_end))); /* * Find the highest page frame number we have available. -- cgit v0.10.2 From 8431fd094d625b94d364fe393076ccef88e6ce18 Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:02 +0200 Subject: [MIPS] Introduce __pa_symbol() This patch introduces __pa_symbol() macro which should be used to calculate the physical address of kernel symbols. It also relies on RELOC_HIDE() to avoid any compiler's oddities when doing arithmetics on symbols. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index c3b13de..0dc1a45 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -142,6 +142,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define __pa_page_offset(x) PAGE_OFFSET #endif #define __pa(x) ((unsigned long)(x) - __pa_page_offset(x)) +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0)) #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) -- cgit v0.10.2 From f5bffe3a9bcd6e5319b5fd3a8109625f8638425a Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:03 +0200 Subject: [MIPS] setup.c: use __pa_symbol() where needed It should fix the broken code in resource_init() too. Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 715451a..b52cc97 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -260,7 +260,7 @@ static void __init bootmem_init(void) * of usable memory. */ reserved_end = init_initrd(); - reserved_end = PFN_UP(__pa(max(reserved_end, (unsigned long)&_end))); + reserved_end = PFN_UP(max(__pa(reserved_end), __pa_symbol(&_end))); /* * Find the highest page frame number we have available. @@ -432,10 +432,10 @@ static void __init resource_init(void) if (UNCAC_BASE != IO_BASE) return; - code_resource.start = virt_to_phys(&_text); - code_resource.end = virt_to_phys(&_etext) - 1; - data_resource.start = virt_to_phys(&_etext); - data_resource.end = virt_to_phys(&_edata) - 1; + code_resource.start = __pa_symbol(&_text); + code_resource.end = __pa_symbol(&_etext) - 1; + data_resource.start = __pa_symbol(&_etext); + data_resource.end = __pa_symbol(&_edata) - 1; /* * Request address space for all standard RAM. -- cgit v0.10.2 From a7837b76b6de932c31d0b7c71176ca8d1213a3ce Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:04 +0200 Subject: [MIPS] setup.c: clean up initrd related code Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index b52cc97..89440a0 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -145,13 +145,12 @@ static int __init rd_start_early(char *p) unsigned long start = memparse(p, &p); #ifdef CONFIG_64BIT - /* HACK: Guess if the sign extension was forgotten */ - if (start > 0x0000000080000000 && start < 0x00000000ffffffff) - start |= 0xffffffff00000000UL; + /* Guess if the sign extension was forgotten by bootloader */ + if (start < XKPHYS) + start = (int)start; #endif initrd_start = start; initrd_end += start; - return 0; } early_param("rd_start", rd_start_early); @@ -159,41 +158,64 @@ early_param("rd_start", rd_start_early); static int __init rd_size_early(char *p) { initrd_end += memparse(p, &p); - return 0; } early_param("rd_size", rd_size_early); +/* it returns the next free pfn after initrd */ static unsigned long __init init_initrd(void) { - unsigned long tmp, end, size; + unsigned long end; u32 *initrd_header; - ROOT_DEV = Root_RAM0; - /* * Board specific code or command line parser should have * already set up initrd_start and initrd_end. In these cases * perfom sanity checks and use them if all looks good. */ - size = initrd_end - initrd_start; - if (initrd_end == 0 || size == 0) { - initrd_start = 0; - initrd_end = 0; - } else - return initrd_end; - - end = (unsigned long)&_end; - tmp = PAGE_ALIGN(end) - sizeof(u32) * 2; - if (tmp < end) - tmp += PAGE_SIZE; - - initrd_header = (u32 *)tmp; - if (initrd_header[0] == 0x494E5244) { - initrd_start = (unsigned long)&initrd_header[2]; - initrd_end = initrd_start + initrd_header[1]; + if (initrd_start && initrd_end > initrd_start) + goto sanitize; + + /* + * See if initrd has been added to the kernel image by + * arch/mips/boot/addinitrd.c. In that case a header is + * prepended to initrd and is made up by 8 bytes. The fisrt + * word is a magic number and the second one is the size of + * initrd. Initrd start must be page aligned in any cases. + */ + initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; + if (initrd_header[0] != 0x494E5244) + goto disable; + initrd_start = (unsigned long)(initrd_header + 2); + initrd_end = initrd_start + initrd_header[1]; + +sanitize: + if (initrd_start & ~PAGE_MASK) { + printk(KERN_ERR "initrd start must be page aligned\n"); + goto disable; } - return initrd_end; + if (initrd_start < PAGE_OFFSET) { + printk(KERN_ERR "initrd start < PAGE_OFFSET\n"); + goto disable; + } + + /* + * Sanitize initrd addresses. For example firmware + * can't guess if they need to pass them through + * 64-bits values if the kernel has been built in pure + * 32-bit. We need also to switch from KSEG0 to XKPHYS + * addresses now, so the code can now safely use __pa(). + */ + end = __pa(initrd_end); + initrd_end = (unsigned long)__va(end); + initrd_start = (unsigned long)__va(__pa(initrd_start)); + + ROOT_DEV = Root_RAM0; + return PFN_UP(end); +disable: + initrd_start = 0; + initrd_end = 0; + return 0; } static void __init finalize_initrd(void) @@ -259,8 +281,7 @@ static void __init bootmem_init(void) * not selected. Once that done we can determine the low bound * of usable memory. */ - reserved_end = init_initrd(); - reserved_end = PFN_UP(max(__pa(reserved_end), __pa_symbol(&_end))); + reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end))); /* * Find the highest page frame number we have available. diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 3049912..4076963 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -460,11 +460,6 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { -#ifdef CONFIG_64BIT - /* Switch from KSEG0 to XKPHYS addresses */ - start = (unsigned long)phys_to_virt(CPHYSADDR(start)); - end = (unsigned long)phys_to_virt(CPHYSADDR(end)); -#endif free_init_pages("initrd memory", start, end); } #endif -- cgit v0.10.2 From acd86b8622099c3206e0a1665545ae2318089b9c Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Thu, 19 Oct 2006 13:20:05 +0200 Subject: [MIPS] Make free_init_pages() arguments to be physical addresses It allows caller of this function to not care about CKSEG0/XKPHYS address mixes. It's now automatically done by free_init_pages(). We can now safely remove hack needed by 64 bit kernels with CONFIG_BUILD_ELF64=n in free_initmem(). Signed-off-by: Franck Bui-Huu Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 4076963..9e29ba9 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -443,15 +443,18 @@ void __init mem_init(void) } #endif /* !CONFIG_NEED_MULTIPLE_NODES */ -void free_init_pages(char *what, unsigned long begin, unsigned long end) +static void free_init_pages(char *what, unsigned long begin, unsigned long end) { - unsigned long addr; + unsigned long pfn; - for (addr = begin; addr < end; addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page((void *)addr)); - init_page_count(virt_to_page((void *)addr)); - memset((void *)addr, 0xcc, PAGE_SIZE); - free_page(addr); + for (pfn = PFN_UP(begin); pfn < PFN_DOWN(end); pfn++) { + struct page *page = pfn_to_page(pfn); + void *addr = phys_to_virt(PFN_PHYS(pfn)); + + ClearPageReserved(page); + init_page_count(page); + memset(addr, POISON_FREE_INITMEM, PAGE_SIZE); + __free_page(page); totalram_pages++; } printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); @@ -460,7 +463,9 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - free_init_pages("initrd memory", start, end); + free_init_pages("initrd memory", + virt_to_phys((void *)start), + virt_to_phys((void *)end)); } #endif @@ -468,17 +473,13 @@ extern unsigned long prom_free_prom_memory(void); void free_initmem(void) { - unsigned long start, end, freed; + unsigned long freed; freed = prom_free_prom_memory(); if (freed) printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed); - start = (unsigned long)(&__init_begin); - end = (unsigned long)(&__init_end); -#ifdef CONFIG_64BIT - start = PAGE_OFFSET | CPHYSADDR(start); - end = PAGE_OFFSET | CPHYSADDR(end); -#endif - free_init_pages("unused kernel memory", start, end); + free_init_pages("unused kernel memory", + __pa_symbol(&__init_begin), + __pa_symbol(&__init_end)); } -- cgit v0.10.2 From 4e3884fc83f40b5daabceeee3a428a8ebebbbe4a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 21 Oct 2006 01:28:26 +0900 Subject: [MIPS] Use "long" for 64-bit values on 64-bit kernel. This would get rid of some warnings about "long" vs. "long long". Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h index 45c706e..c627508 100644 --- a/include/asm-mips/addrspace.h +++ b/include/asm-mips/addrspace.h @@ -19,12 +19,16 @@ #define _ATYPE_ #define _ATYPE32_ #define _ATYPE64_ -#define _LLCONST_(x) x +#define _CONST64_(x) x #else #define _ATYPE_ __PTRDIFF_TYPE__ #define _ATYPE32_ int -#define _ATYPE64_ long long -#define _LLCONST_(x) x ## LL +#define _ATYPE64_ __s64 +#ifdef CONFIG_64BIT +#define _CONST64_(x) x ## L +#else +#define _CONST64_(x) x ## LL +#endif #endif /* @@ -48,7 +52,7 @@ */ #define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) #define XPHYSADDR(a) ((_ACAST64_(a)) & \ - _LLCONST_(0x000000ffffffffff)) + _CONST64_(0x000000ffffffffff)) #ifdef CONFIG_64BIT @@ -57,14 +61,14 @@ * The compatibility segments use the full 64-bit sign extended value. Note * the R8000 doesn't have them so don't reference these in generic MIPS code. */ -#define XKUSEG _LLCONST_(0x0000000000000000) -#define XKSSEG _LLCONST_(0x4000000000000000) -#define XKPHYS _LLCONST_(0x8000000000000000) -#define XKSEG _LLCONST_(0xc000000000000000) -#define CKSEG0 _LLCONST_(0xffffffff80000000) -#define CKSEG1 _LLCONST_(0xffffffffa0000000) -#define CKSSEG _LLCONST_(0xffffffffc0000000) -#define CKSEG3 _LLCONST_(0xffffffffe0000000) +#define XKUSEG _CONST64_(0x0000000000000000) +#define XKSSEG _CONST64_(0x4000000000000000) +#define XKPHYS _CONST64_(0x8000000000000000) +#define XKSEG _CONST64_(0xc000000000000000) +#define CKSEG0 _CONST64_(0xffffffff80000000) +#define CKSEG1 _CONST64_(0xffffffffa0000000) +#define CKSSEG _CONST64_(0xffffffffc0000000) +#define CKSEG3 _CONST64_(0xffffffffe0000000) #define CKSEG0ADDR(a) (CPHYSADDR(a) | CKSEG0) #define CKSEG1ADDR(a) (CPHYSADDR(a) | CKSEG1) @@ -122,7 +126,7 @@ #define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED,(p)) #define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE,(p)) #define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK) -#define PHYS_TO_XKPHYS(cm,a) (_LLCONST_(0x8000000000000000) | \ +#define PHYS_TO_XKPHYS(cm,a) (_CONST64_(0x8000000000000000) | \ ((cm)<<59) | (a)) #if defined (CONFIG_CPU_R4300) \ @@ -132,20 +136,20 @@ || defined (CONFIG_CPU_NEVADA) \ || defined (CONFIG_CPU_TX49XX) \ || defined (CONFIG_CPU_MIPS64) -#define TO_PHYS_MASK _LLCONST_(0x0000000fffffffff) /* 2^^36 - 1 */ +#define TO_PHYS_MASK _CONST64_(0x0000000fffffffff) /* 2^^36 - 1 */ #endif #if defined (CONFIG_CPU_R8000) /* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */ -#define TO_PHYS_MASK _LLCONST_(0x000000ffffffffff) /* 2^^40 - 1 */ +#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */ #endif #if defined (CONFIG_CPU_R10000) -#define TO_PHYS_MASK _LLCONST_(0x000000ffffffffff) /* 2^^40 - 1 */ +#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */ #endif #if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A) -#define TO_PHYS_MASK _LLCONST_(0x00000fffffffffff) /* 2^^44 - 1 */ +#define TO_PHYS_MASK _CONST64_(0x00000fffffffffff) /* 2^^44 - 1 */ #endif #ifndef CONFIG_CPU_R8000 @@ -155,7 +159,7 @@ * in order to catch bugs in the source code. */ -#define COMPAT_K1BASE32 _LLCONST_(0xffffffffa0000000) +#define COMPAT_K1BASE32 _CONST64_(0xffffffffa0000000) #define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */ #endif -- cgit v0.10.2 From 56ae58333031bb0564c141f955d1e42276cade55 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Sat, 14 Oct 2006 00:25:04 +0900 Subject: [MIPS] Rewrite GALILEO_INL/GALILEO_OUTL to GT_READ/GT_WRITE This patch has rewritten GALILEO_INL/GALILEO_OUTL using GT_READ/GT_WRITE. This patch tested on Cobalt Qube2. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c index 82e569d..4c46f0e 100644 --- a/arch/mips/cobalt/irq.c +++ b/arch/mips/cobalt/irq.c @@ -45,25 +45,22 @@ static inline void galileo_irq(void) { unsigned int mask, pending, devfn; - mask = GALILEO_INL(GT_INTRMASK_OFS); - pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask; + mask = GT_READ(GT_INTRMASK_OFS); + pending = GT_READ(GT_INTRCAUSE_OFS) & mask; - if (pending & GALILEO_INTR_T0EXP) { - - GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS); + if (pending & GT_INTR_T0EXP_MSK) { + GT_WRITE(GT_INTRCAUSE_OFS, ~GT_INTR_T0EXP_MSK); do_IRQ(COBALT_GALILEO_IRQ); - - } else if (pending & GALILEO_INTR_RETRY_CTR) { - - devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8; - GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS); - printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n", - PCI_SLOT(devfn), PCI_FUNC(devfn)); - + } else if (pending & GT_INTR_RETRYCTR0_MSK) { + devfn = GT_READ(GT_PCI0_CFGADDR_OFS) >> 8; + GT_WRITE(GT_INTRCAUSE_OFS, ~GT_INTR_RETRYCTR0_MSK); + printk(KERN_WARNING + "Galileo: PCI retry count exceeded (%02x.%u)\n", + PCI_SLOT(devfn), PCI_FUNC(devfn)); } else { - - GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS); - printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); + GT_WRITE(GT_INTRMASK_OFS, mask & ~pending); + printk(KERN_WARNING + "Galileo: masking unexpected interrupt %08x\n", pending); } } @@ -104,7 +101,7 @@ void __init arch_init_irq(void) * Mask all Galileo interrupts. The Galileo * handler is set in cobalt_timer_setup() */ - GALILEO_OUTL(0, GT_INTRMASK_OFS); + GT_WRITE(GT_INTRMASK_OFS, 0); init_i8259_irqs(); /* 0 ... 15 */ mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index bf9dc72..e8f0f20 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -51,23 +51,23 @@ const char *get_system_type(void) void __init plat_timer_setup(struct irqaction *irq) { /* Load timer value for HZ (TCLK is 50MHz) */ - GALILEO_OUTL(50*1000*1000 / HZ, GT_TC0_OFS); + GT_WRITE(GT_TC0_OFS, 50*1000*1000 / HZ); /* Enable timer */ - GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS); + GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); /* Register interrupt */ setup_irq(COBALT_GALILEO_IRQ, irq); /* Enable interrupt */ - GALILEO_OUTL(GALILEO_INTR_T0EXP | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS); + GT_WRITE(GT_INTRMASK_OFS, GT_INTR_T0EXP_MSK | GT_READ(GT_INTRMASK_OFS)); } extern struct pci_ops gt64111_pci_ops; static struct resource cobalt_mem_resource = { - .start = GT64111_MEM_BASE, - .end = GT64111_MEM_END, + .start = GT_DEF_PCI0_MEM0_BASE, + .end = GT_DEF_PCI0_MEM0_BASE + GT_DEF_PCI0_MEM0_SIZE - 1, .name = "PCI memory", .flags = IORESOURCE_MEM }; @@ -115,7 +115,7 @@ static struct pci_controller cobalt_pci_controller = { .mem_resource = &cobalt_mem_resource, .mem_offset = 0, .io_resource = &cobalt_io_resource, - .io_offset = 0 - GT64111_IO_BASE + .io_offset = 0 - GT_DEF_PCI0_IO_BASE, }; void __init plat_mem_setup(void) @@ -128,7 +128,7 @@ void __init plat_mem_setup(void) _machine_halt = cobalt_machine_halt; pm_power_off = cobalt_machine_power_off; - set_io_port_base(CKSEG1ADDR(GT64111_IO_BASE)); + set_io_port_base(CKSEG1ADDR(GT_DEF_PCI0_IO_BASE)); /* I/O port resource must include UART and LCD/buttons */ ioport_resource.end = 0x0fffffff; @@ -139,7 +139,7 @@ void __init plat_mem_setup(void) /* Read the cobalt id register out of the PCI config space */ PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3)); - cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + cobalt_board_id = GT_READ(GT_PCI0_CFGDATA_OFS); cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8); cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index 75a01e7..7d5f6bb 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -94,22 +94,21 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev) #if 0 if (galileo_id >= 0x10) { /* New Galileo, assumes PCI stop line to VIA is connected. */ - GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS); + GT_WRITE(GT_PCI0_TOR_OFS, 0x4020); } else if (galileo_id == 0x1 || galileo_id == 0x2) #endif { signed int timeo; /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ - timeo = GALILEO_INL(GT_PCI0_TOR_OFS); + timeo = GT_READ(GT_PCI0_TOR_OFS); /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ - GALILEO_OUTL( + GT_WRITE(GT_PCI0_TOR_OFS, (0xff << 16) | /* retry count */ (0xff << 8) | /* timeout 1 */ - 0xff, /* timeout 0 */ - GT_PCI0_TOR_OFS); + 0xff); /* timeout 0 */ /* enable PCI retry exceeded interrupt */ - GALILEO_OUTL(GALILEO_INTR_RETRY_CTR | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS); + GT_WRITE(GT_INTRMASK_OFS, GT_INTR_RETRYCTR0_MSK | GT_READ(GT_INTRMASK_OFS)); } } diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c index 13de459..ecd3991 100644 --- a/arch/mips/pci/ops-gt64111.c +++ b/arch/mips/pci/ops-gt64111.c @@ -38,18 +38,18 @@ static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn, switch (size) { case 4: PCI_CFG_SET(devfn, where); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + *val = GT_READ(GT_PCI0_CFGDATA_OFS); return PCIBIOS_SUCCESSFUL; case 2: PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + *val = GT_READ(GT_PCI0_CFGDATA_OFS) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; case 1: PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + *val = GT_READ(GT_PCI0_CFGDATA_OFS) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } @@ -68,25 +68,25 @@ static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn, switch (size) { case 4: PCI_CFG_SET(devfn, where); - GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS); + GT_WRITE(GT_PCI0_CFGDATA_OFS, val); return PCIBIOS_SUCCESSFUL; case 2: PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp = GT_READ(GT_PCI0_CFGDATA_OFS); tmp &= ~(0xffff << ((where & 0x3) * 8)); tmp |= (val << ((where & 0x3) * 8)); - GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp); return PCIBIOS_SUCCESSFUL; case 1: PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp = GT_READ(GT_PCI0_CFGDATA_OFS); tmp &= ~(0xff << ((where & 0x3) * 8)); tmp |= (val << ((where & 0x3) * 8)); - GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp); return PCIBIOS_SUCCESSFUL; } diff --git a/include/asm-mips/gt64120.h b/include/asm-mips/gt64120.h index 2edd171..4bf8e28 100644 --- a/include/asm-mips/gt64120.h +++ b/include/asm-mips/gt64120.h @@ -451,6 +451,13 @@ #define GT_SDRAM_OPMODE_OP_MODE 3 #define GT_SDRAM_OPMODE_OP_CBR 4 +#define GT_TC_CONTROL_ENTC0_SHF 0 +#define GT_TC_CONTROL_ENTC0_MSK (MSK(1) << GT_TC_CONTROL_ENTC0_SHF) +#define GT_TC_CONTROL_ENTC0_BIT GT_TC_CONTROL_ENTC0_MSK +#define GT_TC_CONTROL_SELTC0_SHF 1 +#define GT_TC_CONTROL_SELTC0_MSK (MSK(1) << GT_TC_CONTROL_SELTC0_SHF) +#define GT_TC_CONTROL_SELTC0_BIT GT_TC_CONTROL_SELTC0_MSK + #define GT_PCI0_BARE_SWSCS3BOOTDIS_SHF 0 #define GT_PCI0_BARE_SWSCS3BOOTDIS_MSK (MSK(1) << GT_PCI0_BARE_SWSCS3BOOTDIS_SHF) @@ -523,6 +530,13 @@ #define GT_PCI0_CMD_SWORDSWAP_MSK (MSK(1) << GT_PCI0_CMD_SWORDSWAP_SHF) #define GT_PCI0_CMD_SWORDSWAP_BIT GT_PCI0_CMD_SWORDSWAP_MSK +#define GT_INTR_T0EXP_SHF 8 +#define GT_INTR_T0EXP_MSK (MSK(1) << GT_INTR_T0EXP_SHF) +#define GT_INTR_T0EXP_BIT GT_INTR_T0EXP_MSK +#define GT_INTR_RETRYCTR0_SHF 20 +#define GT_INTR_RETRYCTR0_MSK (MSK(1) << GT_INTR_RETRYCTR0_SHF) +#define GT_INTR_RETRYCTR0_BIT GT_INTR_RETRYCTR0_MSK + /* * Misc */ diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h index b3c5ecb..00b0fc6 100644 --- a/include/asm-mips/mach-cobalt/cobalt.h +++ b/include/asm-mips/mach-cobalt/cobalt.h @@ -67,34 +67,9 @@ #define COBALT_BRD_ID_QUBE2 0x5 #define COBALT_BRD_ID_RAQ2 0x6 -/* - * Galileo chipset access macros for the Cobalt. The base address for - * the GT64111 chip is 0x14000000 - * - * Most of this really should go into a separate GT64111 header file. - */ -#define GT64111_IO_BASE 0x10000000UL -#define GT64111_IO_END 0x11ffffffUL -#define GT64111_MEM_BASE 0x12000000UL -#define GT64111_MEM_END 0x13ffffffUL -#define GT64111_BASE 0x14000000UL -#define GALILEO_REG(ofs) CKSEG1ADDR(GT64111_BASE + (unsigned long)(ofs)) - -#define GALILEO_INL(port) (*(volatile unsigned int *) GALILEO_REG(port)) -#define GALILEO_OUTL(val, port) \ -do { \ - *(volatile unsigned int *) GALILEO_REG(port) = (val); \ -} while (0) - -#define GALILEO_INTR_T0EXP (1 << 8) -#define GALILEO_INTR_RETRY_CTR (1 << 20) - -#define GALILEO_ENTC0 0x01 -#define GALILEO_SELTC0 0x02 - #define PCI_CFG_SET(devfn,where) \ - GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) | \ - (PCI_FUNC (devfn) << 8) | (where)), GT_PCI0_CFGADDR_OFS) + GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \ + (PCI_FUNC (devfn) << 8) | (where))) #define COBALT_LED_PORT (*(volatile unsigned char *) CKSEG1ADDR(0x1c000000)) # define COBALT_LED_BAR_LEFT (1 << 0) /* Qube */ diff --git a/include/asm-mips/mach-cobalt/mach-gt64120.h b/include/asm-mips/mach-cobalt/mach-gt64120.h index 587fc43..ae9c552 100644 --- a/include/asm-mips/mach-cobalt/mach-gt64120.h +++ b/include/asm-mips/mach-cobalt/mach-gt64120.h @@ -1 +1,27 @@ -/* there's something here ... in the dark */ +/* + * Copyright (C) 2006 Yoichi Yuasa + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _COBALT_MACH_GT64120_H +#define _COBALT_MACH_GT64120_H + +/* + * Cobalt uses GT64111. GT64111 is almost the same as GT64120. + */ + +#define GT64120_BASE CKSEG1ADDR(GT_DEF_BASE) + +#endif /* _COBALT_MACH_GT64120_H */ -- cgit v0.10.2 From 656be92f9ae194ed62bc81310a4589a7cd765f13 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 26 Oct 2006 00:08:31 +0900 Subject: [MIPS] Load modules to CKSEG0 if CONFIG_BUILD_ELF64=n This is a patch to load 64-bit modules to CKSEG0 so that can be compiled with -msym32 option. This makes each module ~10% smaller. * introduce MODULE_START and MODULE_END * custom module_alloc() * PGD for modules * change XTLB refill handler synthesizer * enable -msym32 for modules again (revert ca78b1a5c6a6e70e052d3ea253828e49b5d07c8a) New XTLB refill handler looks like this: 80000080 dmfc0 k0,C0_BADVADDR 80000084 bltz k0,800000e4 # goto l_module_alloc 80000088 lui k1,0x8046 # %high(pgd_current) 8000008c ld k1,24600(k1) # %low(pgd_current) 80000090 dsrl k0,k0,0x1b # l_vmalloc_done: 80000094 andi k0,k0,0x1ff8 80000098 daddu k1,k1,k0 8000009c dmfc0 k0,C0_BADVADDR 800000a0 ld k1,0(k1) 800000a4 dsrl k0,k0,0x12 800000a8 andi k0,k0,0xff8 800000ac daddu k1,k1,k0 800000b0 dmfc0 k0,C0_XCONTEXT 800000b4 ld k1,0(k1) 800000b8 andi k0,k0,0xff0 800000bc daddu k1,k1,k0 800000c0 ld k0,0(k1) 800000c4 ld k1,8(k1) 800000c8 dsrl k0,k0,0x6 800000cc mtc0 k0,C0_ENTRYLO0 800000d0 dsrl k1,k1,0x6 800000d4 mtc0 k1,C0_ENTRYL01 800000d8 nop 800000dc tlbwr 800000e0 eret 800000e4 dsll k1,k0,0x2 # l_module_alloc: 800000e8 bgez k1,80000008 # goto l_vmalloc 800000ec lui k1,0xc000 800000f0 dsubu k0,k0,k1 800000f4 lui k1,0x8046 # %high(module_pg_dir) 800000f8 beq zero,zero,80000000 800000fc nop 80000000 beq zero,zero,80000090 # goto l_vmalloc_done 80000004 daddiu k1,k1,0x4000 80000008 dsll32 k1,k1,0x0 # l_vmalloc: 8000000c dsubu k0,k0,k1 80000010 beq zero,zero,80000090 # goto l_vmalloc_done 80000014 lui k1,0x8046 # %high(swapper_pg_dir) Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d580d46..641aa30 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -63,9 +63,7 @@ cflags-y += -mabi=64 ifdef CONFIG_BUILD_ELF64 cflags-y += $(call cc-option,-mno-explicit-relocs) else -# -msym32 can not be used for modules since they are loaded into XKSEG -CFLAGS_MODULE += $(call cc-option,-mno-explicit-relocs) -CFLAGS_KERNEL += $(call cc-option,-msym32) +cflags-y += $(call cc-option,-msym32) endif endif diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index ddc1b71..a2e095a 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -250,6 +250,9 @@ NESTED(smp_bootstrap, 16, sp) */ page swapper_pg_dir, _PGD_ORDER #ifdef CONFIG_64BIT +#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64) + page module_pg_dir, _PGD_ORDER +#endif page invalid_pmd_table, _PMD_ORDER #endif page invalid_pte_table, _PTE_ORDER diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index d7bf021..cb08014 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -29,6 +29,7 @@ #include #include #include +#include /* MODULE_START */ struct mips_hi16 { struct mips_hi16 *next; @@ -43,9 +44,23 @@ static DEFINE_SPINLOCK(dbe_lock); void *module_alloc(unsigned long size) { +#ifdef MODULE_START + struct vm_struct *area; + + size = PAGE_ALIGN(size); + if (!size) + return NULL; + + area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END); + if (!area) + return NULL; + + return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); +#else if (size == 0) return NULL; return vmalloc(size); +#endif } /* Free memory returned from module_alloc */ diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 8423d85..6f90e7e 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -60,6 +60,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, */ if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END)) goto vmalloc_fault; +#ifdef MODULE_START + if (unlikely(address >= MODULE_START && address < MODULE_END)) + goto vmalloc_fault; +#endif /* * If we're in an interrupt or have no user diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 8d600d3..c46eb65 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -58,6 +58,9 @@ void __init pagetable_init(void) /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); +#ifdef MODULE_START + pgd_init((unsigned long)module_pg_dir); +#endif pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); pgd_base = swapper_pg_dir; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index fec318a..492c518 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -423,6 +423,9 @@ enum label_id { label_invalid, label_second_part, label_leave, +#ifdef MODULE_START + label_module_alloc, +#endif label_vmalloc, label_vmalloc_done, label_tlbw_hazard, @@ -455,6 +458,9 @@ static __init void build_label(struct label **lab, u32 *addr, L_LA(_second_part) L_LA(_leave) +#ifdef MODULE_START +L_LA(_module_alloc) +#endif L_LA(_vmalloc) L_LA(_vmalloc_done) L_LA(_tlbw_hazard) @@ -686,6 +692,13 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg, i_bgezl(p, reg, 0); } +static void __init __attribute__((unused)) +il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) +{ + r_mips_pc16(r, *p, l); + i_bgez(p, reg, 0); +} + /* The only general purpose registers allowed in TLB handlers. */ #define K0 26 #define K1 27 @@ -970,7 +983,11 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, * The vmalloc handling is not in the hotpath. */ i_dmfc0(p, tmp, C0_BADVADDR); +#ifdef MODULE_START + il_bltz(p, r, tmp, label_module_alloc); +#else il_bltz(p, r, tmp, label_vmalloc); +#endif /* No i_nop needed here, since the next insn doesn't touch TMP. */ #ifdef CONFIG_SMP @@ -1023,8 +1040,46 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, { long swpd = (long)swapper_pg_dir; +#ifdef MODULE_START + long modd = (long)module_pg_dir; + + l_module_alloc(l, *p); + /* + * Assumption: + * VMALLOC_START >= 0xc000000000000000UL + * MODULE_START >= 0xe000000000000000UL + */ + i_SLL(p, ptr, bvaddr, 2); + il_bgez(p, r, ptr, label_vmalloc); + + if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START)) { + i_lui(p, ptr, rel_hi(MODULE_START)); /* delay slot */ + } else { + /* unlikely configuration */ + i_nop(p); /* delay slot */ + i_LA(p, ptr, MODULE_START); + } + i_dsubu(p, bvaddr, bvaddr, ptr); + + if (in_compat_space_p(modd) && !rel_lo(modd)) { + il_b(p, r, label_vmalloc_done); + i_lui(p, ptr, rel_hi(modd)); + } else { + i_LA_mostly(p, ptr, modd); + il_b(p, r, label_vmalloc_done); + i_daddiu(p, ptr, ptr, rel_lo(modd)); + } + + l_vmalloc(l, *p); + if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START) && + MODULE_START << 32 == VMALLOC_START) + i_dsll32(p, ptr, ptr, 0); /* typical case */ + else + i_LA(p, ptr, VMALLOC_START); +#else l_vmalloc(l, *p); i_LA(p, ptr, VMALLOC_START); +#endif i_dsubu(p, bvaddr, bvaddr, ptr); if (in_compat_space_p(swpd) && !rel_lo(swpd)) { diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h index 7e73203..b9b1e86 100644 --- a/include/asm-mips/pgtable-64.h +++ b/include/asm-mips/pgtable-64.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -103,6 +104,13 @@ #define VMALLOC_START MAP_BASE #define VMALLOC_END \ (VMALLOC_START + PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE) +#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64) && \ + VMALLOC_START != CKSSEG +/* Load modules into 32bit-compatible segment. */ +#define MODULE_START CKSSEG +#define MODULE_END (FIXADDR_START-2*PAGE_SIZE) +extern pgd_t module_pg_dir[PTRS_PER_PGD]; +#endif #define pte_ERROR(e) \ printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) @@ -174,7 +182,12 @@ static inline void pud_clear(pud_t *pudp) #define __pmd_offset(address) pmd_index(address) /* to find an entry in a kernel page-table-directory */ +#ifdef MODULE_START +#define pgd_offset_k(address) \ + ((address) >= MODULE_START ? module_pg_dir : pgd_offset(&init_mm, 0UL)) +#else #define pgd_offset_k(address) pgd_offset(&init_mm, 0UL) +#endif #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -- cgit v0.10.2 From 5b10496b6e6577f65b032a5c4c97d0d3a841273c Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 11 Sep 2006 17:50:29 +0900 Subject: [MIPS] Fast path for rdhwr emulation for TLS Add special short path for emulationg RDHWR which is used to support TLS. Add an extra prologue for cpu_has_vtag_icache case. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 5baca16..aacd4a0 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -19,6 +19,7 @@ #include #include #include +#include #define PANIC_PIC(msg) \ .set push; \ @@ -378,6 +379,68 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER dsp dsp sti silent /* #26 */ BUILD_HANDLER reserved reserved sti verbose /* others */ + .align 5 + LEAF(handle_ri_rdhwr_vivt) +#ifdef CONFIG_MIPS_MT_SMTC + PANIC_PIC("handle_ri_rdhwr_vivt called") +#else + .set push + .set noat + .set noreorder + /* check if TLB contains a entry for EPC */ + MFC0 k1, CP0_ENTRYHI + andi k1, 0xff /* ASID_MASK */ + MFC0 k0, CP0_EPC + PTR_SRL k0, PAGE_SHIFT + 1 + PTR_SLL k0, PAGE_SHIFT + 1 + or k1, k0 + MTC0 k1, CP0_ENTRYHI + mtc0_tlbw_hazard + tlbp + tlb_probe_hazard + mfc0 k1, CP0_INDEX + .set pop + bltz k1, handle_ri /* slow path */ + /* fall thru */ +#endif + END(handle_ri_rdhwr_vivt) + + LEAF(handle_ri_rdhwr) + .set push + .set noat + .set noreorder + /* 0x7c03e83b: rdhwr v1,$29 */ + MFC0 k1, CP0_EPC + lui k0, 0x7c03 + lw k1, (k1) + ori k0, 0xe83b + .set reorder + bne k0, k1, handle_ri /* if not ours */ + /* The insn is rdhwr. No need to check CAUSE.BD here. */ + get_saved_sp /* k1 := current_thread_info */ + .set noreorder + MFC0 k0, CP0_EPC +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + ori k1, _THREAD_MASK + xori k1, _THREAD_MASK + LONG_L v1, TI_TP_VALUE(k1) + LONG_ADDIU k0, 4 + jr k0 + rfe +#else + LONG_ADDIU k0, 4 /* stall on $k0 */ + MTC0 k0, CP0_EPC + /* I hope three instructions between MTC0 and ERET are enough... */ + ori k1, _THREAD_MASK + xori k1, _THREAD_MASK + LONG_L v1, TI_TP_VALUE(k1) + .set mips3 + eret + .set mips0 +#endif + .set pop + END(handle_ri_rdhwr) + #ifdef CONFIG_64BIT /* A temporary overflow handler used by check_daddi(). */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 9fda1b8..6eccfb4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -54,6 +54,8 @@ extern asmlinkage void handle_dbe(void); extern asmlinkage void handle_sys(void); extern asmlinkage void handle_bp(void); extern asmlinkage void handle_ri(void); +extern asmlinkage void handle_ri_rdhwr_vivt(void); +extern asmlinkage void handle_ri_rdhwr(void); extern asmlinkage void handle_cpu(void); extern asmlinkage void handle_ov(void); extern asmlinkage void handle_tr(void); @@ -1423,6 +1425,15 @@ void __init set_uncached_handler (unsigned long offset, void *addr, unsigned lon memcpy((void *)(uncached_ebase + offset), addr, size); } +static int __initdata rdhwr_noopt; +static int __init set_rdhwr_noopt(char *str) +{ + rdhwr_noopt = 1; + return 1; +} + +__setup("rdhwr_noopt", set_rdhwr_noopt); + void __init trap_init(void) { extern char except_vec3_generic, except_vec3_r4000; @@ -1502,7 +1513,9 @@ void __init trap_init(void) set_except_vector(8, handle_sys); set_except_vector(9, handle_bp); - set_except_vector(10, handle_ri); + set_except_vector(10, rdhwr_noopt ? handle_ri : + (cpu_has_vtag_icache ? + handle_ri_rdhwr_vivt : handle_ri_rdhwr)); set_except_vector(11, handle_cpu); set_except_vector(12, handle_ov); set_except_vector(13, handle_tr); -- cgit v0.10.2 From c237923009da464881d89f4bc27c3b5b1a93d61b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:44 +0000 Subject: [MIPS] Don't print presence of WAIT instruction on bootup. Not useful and quite a big of noise on bootup of large systems. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8485af3..442839e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -110,9 +110,8 @@ static inline void check_wait(void) { struct cpuinfo_mips *c = ¤t_cpu_data; - printk("Checking for 'wait' instruction... "); if (nowait) { - printk (" disabled.\n"); + printk("Wait instruction disabled.\n"); return; } @@ -120,11 +119,9 @@ static inline void check_wait(void) case CPU_R3081: case CPU_R3081E: cpu_wait = r3081_wait; - printk(" available.\n"); break; case CPU_TX3927: cpu_wait = r39xx_wait; - printk(" available.\n"); break; case CPU_R4200: /* case CPU_R4300: */ @@ -146,33 +143,23 @@ static inline void check_wait(void) case CPU_74K: case CPU_PR4450: cpu_wait = r4k_wait; - printk(" available.\n"); break; case CPU_TX49XX: cpu_wait = r4k_wait_irqoff; - printk(" available.\n"); break; case CPU_AU1000: case CPU_AU1100: case CPU_AU1500: case CPU_AU1550: case CPU_AU1200: - if (allow_au1k_wait) { + if (allow_au1k_wait) cpu_wait = au1k_wait; - printk(" available.\n"); - } else - printk(" unavailable.\n"); break; case CPU_RM9000: - if ((c->processor_id & 0x00ff) >= 0x40) { + if ((c->processor_id & 0x00ff) >= 0x40) cpu_wait = r4k_wait; - printk(" available.\n"); - } else { - printk(" unavailable.\n"); - } break; default: - printk(" unavailable.\n"); break; } } -- cgit v0.10.2 From 583bb86fbb9e85287f020fe4eb5352a0ec3c66a3 Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Wed, 18 Oct 2006 15:14:55 +0200 Subject: [MIPS] Add support for kexec A tiny userland application loading the kernel and invoking kexec_load for mips is available here: http://chac.le-poulpe.net/~nico/kexec/kexec-2006-10-18.tar.gz Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1443024..c0da0ff 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -766,6 +766,23 @@ config TOSHIBA_RBTX4938 endchoice +config KEXEC + bool "Kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + source "arch/mips/ddb5xxx/Kconfig" source "arch/mips/gt64120/ev64120/Kconfig" source "arch/mips/jazz/Kconfig" diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 6bfbbed..f35b739 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -67,6 +67,8 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o obj-$(CONFIG_I8253) += i8253.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o + CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c new file mode 100644 index 0000000..e0ad754 --- /dev/null +++ b/arch/mips/kernel/machine_kexec.c @@ -0,0 +1,85 @@ +/* + * machine_kexec.c for kexec + * Created by on Thu Oct 12 15:15:06 2006 + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include + +#include +#include + +const extern unsigned char relocate_new_kernel[]; +const extern unsigned int relocate_new_kernel_size; + +extern unsigned long kexec_start_address; +extern unsigned long kexec_indirection_page; + +int +machine_kexec_prepare(struct kimage *kimage) +{ + return 0; +} + +void +machine_kexec_cleanup(struct kimage *kimage) +{ +} + +void +machine_shutdown(void) +{ +} + +void +machine_crash_shutdown(struct pt_regs *regs) +{ +} + +void +machine_kexec(struct kimage *image) +{ + unsigned long reboot_code_buffer; + unsigned long entry; + unsigned long *ptr; + + reboot_code_buffer = + (unsigned long)page_address(image->control_code_page); + + kexec_start_address = image->start; + kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK); + + memcpy((void*)reboot_code_buffer, relocate_new_kernel, + relocate_new_kernel_size); + + /* + * The generic kexec code builds a page list with physical + * addresses. they are directly accessible through KSEG0 (or + * CKSEG0 or XPHYS if on 64bit system), hence the + * pys_to_virt() call. + */ + for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); + ptr = (entry & IND_INDIRECTION) ? + phys_to_virt(entry & PAGE_MASK) : ptr + 1) { + if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || + *ptr & IND_DESTINATION) + *ptr = phys_to_virt(*ptr); + } + + /* + * we do not want to be bothered. + */ + local_irq_disable(); + + flush_icache_range(reboot_code_buffer, + reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE); + + printk("Will call new kernel at %08x\n", image->start); + printk("Bye ...\n"); + flush_cache_all(); + ((void (*)(void))reboot_code_buffer)(); +} diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S new file mode 100644 index 0000000..a3f0d00c --- /dev/null +++ b/arch/mips/kernel/relocate_kernel.S @@ -0,0 +1,80 @@ +/* + * relocate_kernel.S for kexec + * Created by on Thu Oct 12 17:49:57 2006 + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + + .globl relocate_new_kernel +relocate_new_kernel: + + PTR_L s0, kexec_indirection_page + PTR_L s1, kexec_start_address + +process_entry: + PTR_L s2, (s0) + PTR_ADD s0, s0, SZREG + + /* destination page */ + and s3, s2, 0x1 + beq s3, zero, 1f + and s4, s2, ~0x1 /* store destination addr in s4 */ + move a0, s4 + b process_entry + +1: + /* indirection page, update s0 */ + and s3, s2, 0x2 + beq s3, zero, 1f + and s0, s2, ~0x2 + b process_entry + +1: + /* done page */ + and s3, s2, 0x4 + beq s3, zero, 1f + b done +1: + /* source page */ + and s3, s2, 0x8 + beq s3, zero, process_entry + and s2, s2, ~0x8 + li s6, (1 << PAGE_SHIFT) / SZREG + +copy_word: + /* copy page word by word */ + REG_L s5, (s2) + REG_S s5, (s4) + INT_ADD s4, s4, SZREG + INT_ADD s2, s2, SZREG + INT_SUB s6, s6, 1 + beq s6, zero, process_entry + b copy_word + b process_entry + +done: + /* jump to kexec_start_address */ + j s1 + + .globl kexec_start_address +kexec_start_address: + .long 0x0 + + .globl kexec_indirection_page +kexec_indirection_page: + .long 0x0 + +relocate_new_kernel_end: + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long relocate_new_kernel_end - relocate_new_kernel diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index a95f37d..7c0b393 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -653,7 +653,7 @@ einval: li v0, -EINVAL sys sys_move_pages 6 sys sys_set_robust_list 2 sys sys_get_robust_list 3 /* 4310 */ - sys sys_ni_syscall 0 + sys sys_kexec_load 4 sys sys_getcpu 3 sys sys_epoll_pwait 6 .endm diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 8fb0f60..e569b84 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -468,6 +468,6 @@ sys_call_table: PTR sys_move_pages PTR sys_set_robust_list PTR sys_get_robust_list - PTR sys_ni_syscall /* 5270 */ + PTR sys_kexec_load /* 5270 */ PTR sys_getcpu PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 0da5ca2..5b18f26 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -394,6 +394,6 @@ EXPORT(sysn32_call_table) PTR sys_move_pages PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list - PTR sys_ni_syscall + PTR compat_sys_kexec_load PTR sys_getcpu PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index b9d00ca..e91379c 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -516,7 +516,7 @@ sys_call_table: PTR compat_sys_move_pages PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list /* 4310 */ - PTR sys_ni_syscall + PTR compat_sys_kexec_load PTR sys_getcpu PTR sys_epoll_pwait .size sys_call_table,.-sys_call_table diff --git a/include/asm-mips/kexec.h b/include/asm-mips/kexec.h new file mode 100644 index 0000000..b25267e --- /dev/null +++ b/include/asm-mips/kexec.h @@ -0,0 +1,32 @@ +/* + * kexec.h for kexec + * Created by on Thu Oct 12 14:59:34 2006 + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#ifndef _MIPS_KEXEC +# define _MIPS_KEXEC + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000) + /* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000) + +#define KEXEC_CONTROL_CODE_SIZE 4096 + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_MIPS + +#define MAX_NOTE_BYTES 1024 + +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + /* Dummy implementation for now */ +} + +#endif /* !_MIPS_KEXEC */ diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 6427949..a4ede62 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -122,6 +122,8 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ARCH_IA_64 (50 << 16) #define KEXEC_ARCH_S390 (22 << 16) #define KEXEC_ARCH_SH (42 << 16) +#define KEXEC_ARCH_MIPS_LE (10 << 16) +#define KEXEC_ARCH_MIPS ( 8 << 16) #define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */ -- cgit v0.10.2 From 2472d0b519c9634d89420064315c0926149947aa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:45 +0000 Subject: [MIPS] Remove unused R10000 performance counter definitions. Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index 1f318d7..9985cb7 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -545,62 +545,6 @@ #define MIPS_FPIR_L (_ULCAST_(1) << 21) #define MIPS_FPIR_F64 (_ULCAST_(1) << 22) -/* - * R10000 performance counter definitions. - * - * FIXME: The R10000 performance counter opens a nice way to implement CPU - * time accounting with a precission of one cycle. I don't have - * R10000 silicon but just a manual, so ... - */ - -/* - * Events counted by counter #0 - */ -#define CE0_CYCLES 0 -#define CE0_INSN_ISSUED 1 -#define CE0_LPSC_ISSUED 2 -#define CE0_S_ISSUED 3 -#define CE0_SC_ISSUED 4 -#define CE0_SC_FAILED 5 -#define CE0_BRANCH_DECODED 6 -#define CE0_QW_WB_SECONDARY 7 -#define CE0_CORRECTED_ECC_ERRORS 8 -#define CE0_ICACHE_MISSES 9 -#define CE0_SCACHE_I_MISSES 10 -#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 -#define CE0_EXT_INTERVENTIONS_REQ 12 -#define CE0_EXT_INVALIDATE_REQ 13 -#define CE0_VIRTUAL_COHERENCY_COND 14 -#define CE0_INSN_GRADUATED 15 - -/* - * Events counted by counter #1 - */ -#define CE1_CYCLES 0 -#define CE1_INSN_GRADUATED 1 -#define CE1_LPSC_GRADUATED 2 -#define CE1_S_GRADUATED 3 -#define CE1_SC_GRADUATED 4 -#define CE1_FP_INSN_GRADUATED 5 -#define CE1_QW_WB_PRIMARY 6 -#define CE1_TLB_REFILL 7 -#define CE1_BRANCH_MISSPREDICTED 8 -#define CE1_DCACHE_MISS 9 -#define CE1_SCACHE_D_MISSES 10 -#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 -#define CE1_EXT_INTERVENTION_HITS 12 -#define CE1_EXT_INVALIDATE_REQ 13 -#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 -#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 - -/* - * These flags define in which privilege mode the counters count events - */ -#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ -#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ -#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ -#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ - #ifndef __ASSEMBLY__ /* -- cgit v0.10.2 From 714cfe7865e5182a3b25be6a95c0b17aa8e64aa9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 23 Oct 2006 00:44:02 +0100 Subject: [MIPS] Oprofile: kernel support for the R10000. Signed-off-by: Ralf Baechle diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile index 0a50aad..bf3be6f 100644 --- a/arch/mips/oprofile/Makefile +++ b/arch/mips/oprofile/Makefile @@ -12,5 +12,6 @@ oprofile-y := $(DRIVER_OBJS) common.o oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o +oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_RM9000) += op_model_rm9000.o diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index 65eb554..4e0a90b 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -83,6 +83,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_74K: case CPU_SB1: case CPU_SB1A: + case CPU_R10000: + case CPU_R12000: + case CPU_R14000: lmodel = &op_model_mipsxx_ops; break; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 1fb240c..455d76a 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -18,7 +18,7 @@ #define M_PERFCTL_SUPERVISOR (1UL << 2) #define M_PERFCTL_USER (1UL << 3) #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) -#define M_PERFCTL_EVENT(event) ((event) << 5) +#define M_PERFCTL_EVENT(event) (((event) & 0x3f) << 5) #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) #define M_PERFCTL_MT_EN(filter) ((filter) << 20) #define M_TC_EN_ALL M_PERFCTL_MT_EN(0) @@ -218,13 +218,23 @@ static inline int __n_counters(void) static inline int n_counters(void) { - int counters = __n_counters(); + int counters; + + switch (current_cpu_data.cputype) { + case CPU_R10000: + counters = 2; + + case CPU_R12000: + case CPU_R14000: + counters = 4; + + default: + counters = __n_counters(); + } #ifdef CONFIG_MIPS_MT_SMP - if (current_cpu_data.cputype == CPU_34K) - return counters >> 1; + counters >> 1; #endif - return counters; } @@ -284,6 +294,18 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/5K"; break; + case CPU_R10000: + if ((current_cpu_data.processor_id & 0xff) == 0x20) + op_model_mipsxx_ops.cpu_type = "mips/r10000-v2.x"; + else + op_model_mipsxx_ops.cpu_type = "mips/r10000"; + break; + + case CPU_R12000: + case CPU_R14000: + op_model_mipsxx_ops.cpu_type = "mips/r12000"; + break; + case CPU_SB1: case CPU_SB1A: op_model_mipsxx_ops.cpu_type = "mips/sb1"; -- cgit v0.10.2 From 6f2c3fa022312d5381f44359984395761e375f1b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:45 +0000 Subject: [MIPS] Fix alignment hole in struct cache_desc; shrink struct. Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index a2f0c8e..610d0cd 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h @@ -22,12 +22,12 @@ * Descriptor for a cache */ struct cache_desc { - unsigned short linesz; /* Size of line in bytes */ - unsigned short ways; /* Number of ways */ - unsigned short sets; /* Number of lines per set */ unsigned int waysize; /* Bytes per way */ - unsigned int waybit; /* Bits to select in a cache set */ - unsigned int flags; /* Flags describing cache properties */ + unsigned short sets; /* Number of lines per set */ + unsigned char ways; /* Number of ways */ + unsigned char linesz; /* Size of line in bytes */ + unsigned char waybit; /* Bits to select in a cache set */ + unsigned char flags; /* Flags describing cache properties */ }; /* -- cgit v0.10.2 From 0d02f0734f8d2310497fae4f960c978f679f66d9 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Nov 2006 18:40:15 +0900 Subject: [MIPS] PB1200: Remove duplicate definitions Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c index 8b953b9..043302b 100644 --- a/arch/mips/au1000/pb1200/board_setup.c +++ b/arch/mips/au1000/pb1200/board_setup.c @@ -55,7 +55,7 @@ #endif extern void _board_init_irq(void); -extern void (*board_init_irq)(void); +extern void (*board_init_irq)(void); void board_reset (void) { @@ -151,11 +151,7 @@ void __init board_setup(void) #endif /* Setup Pb1200 External Interrupt Controller */ - { - extern void (*board_init_irq)(void); - extern void _board_init_irq(void); - board_init_irq = _board_init_irq; - } + board_init_irq = _board_init_irq; } int -- cgit v0.10.2 From c87b6ebaea034c0e0ce86127870cf1511a307b64 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 28 Oct 2006 01:14:37 +0900 Subject: [MIPS] mips hpt cleanup: get rid of mips_hpt_init Currently nobody outside time.c require mips_hpt_init(). Remove it and call c0_hpt_timer_init() directly if R4k counter was used for timer interrupt. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index e535f86..111d1ba 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -88,12 +88,6 @@ static unsigned int null_hpt_read(void) return 0; } -static void __init null_hpt_init(void) -{ - /* nothing */ -} - - /* * Timer ack for an R4k-compatible timer of a known frequency. */ @@ -133,7 +127,6 @@ static void __init c0_hpt_timer_init(void) int (*mips_timer_state)(void); void (*mips_timer_ack)(void); unsigned int (*mips_hpt_read)(void); -void (*mips_hpt_init)(void) __initdata = null_hpt_init; unsigned int mips_hpt_mask = 0xffffffff; /* last time when xtime and rtc are sync'ed up */ @@ -383,16 +376,20 @@ void __init time_init(void) if (!mips_timer_state) { /* No external timer interrupt -- use R4k. */ - mips_hpt_init = c0_hpt_timer_init; mips_timer_ack = c0_timer_ack; + /* Calculate cache parameters. */ + cycles_per_jiffy = + (mips_hpt_frequency + HZ / 2) / HZ; + /* + * This sets up the high precision + * timer for the first interrupt. + */ + c0_hpt_timer_init(); } } if (!mips_hpt_frequency) mips_hpt_frequency = calibrate_hpt(); - /* Calculate cache parameters. */ - cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; - /* Report the high precision timer rate for a reference. */ printk("Using %u.%03u MHz high precision timer.\n", ((mips_hpt_frequency + 500) / 1000) / 1000, @@ -403,9 +400,6 @@ void __init time_init(void) /* No timer interrupt ack (e.g. i8254). */ mips_timer_ack = null_timer_ack; - /* This sets up the high precision timer for the first interrupt. */ - mips_hpt_init(); - /* * Call board specific timer interrupt setup. * diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 3cc0436..305491e 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -99,8 +99,6 @@ void prom_cpus_done(void) */ void prom_init_secondary(void) { - mips_hpt_init(); - set_c0_status(ST0_CO | ST0_IE | ST0_IM); } diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 625acd3..b58665e 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -48,7 +48,6 @@ extern void (*mips_timer_ack)(void); * If mips_hpt_read is NULL, an R4k-compatible timer setup is attempted. */ extern unsigned int (*mips_hpt_read)(void); -extern void (*mips_hpt_init)(void); extern unsigned int mips_hpt_mask; /* -- cgit v0.10.2 From 1603b5aca4f15b34848fb5594d0c7b6333b99144 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 2 Nov 2006 02:08:36 +0900 Subject: [MIPS] IRQ cleanups This is a big irq cleanup patch. * Use set_irq_chip() to register irq_chip. * Initialize .mask, .unmask, .mask_ack field. Functions for these method are already exist in most case. * Do not initialize .startup, .shutdown, .enable, .disable fields if default routines provided by irq_chip_set_defaults() were suitable. * Remove redundant irq_desc initializations. * Remove unnecessary local_irq_save/local_irq_restore, spin_lock. With this cleanup, it would be easy to switch to slightly lightwait irq flow handlers (handle_level_irq(), etc.) instead of __do_IRQ(). Though whole this patch is quite large, changes in each irq_chip are not quite simple. Please review and test on your platform. Thanks. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 2abe132..9cf7b671 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -70,7 +70,6 @@ extern irq_cpustat_t irq_stat [NR_CPUS]; extern void mips_timer_interrupt(void); static void setup_local_irq(unsigned int irq, int type, int int_req); -static unsigned int startup_irq(unsigned int irq); static void end_irq(unsigned int irq_nr); static inline void mask_and_ack_level_irq(unsigned int irq_nr); static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); @@ -84,20 +83,6 @@ void (*board_init_irq)(void); static DEFINE_SPINLOCK(irq_lock); -static unsigned int startup_irq(unsigned int irq_nr) -{ - local_enable_irq(irq_nr); - return 0; -} - - -static void shutdown_irq(unsigned int irq_nr) -{ - local_disable_irq(irq_nr); - return; -} - - inline void local_enable_irq(unsigned int irq_nr) { if (irq_nr > AU1000_LAST_INTC0_INT) { @@ -249,41 +234,37 @@ void restore_local_and_enable(int controller, unsigned long mask) static struct irq_chip rise_edge_irq_type = { .typename = "Au1000 Rise Edge", - .startup = startup_irq, - .shutdown = shutdown_irq, - .enable = local_enable_irq, - .disable = local_disable_irq, .ack = mask_and_ack_rise_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_rise_edge_irq, + .unmask = local_enable_irq, .end = end_irq, }; static struct irq_chip fall_edge_irq_type = { .typename = "Au1000 Fall Edge", - .startup = startup_irq, - .shutdown = shutdown_irq, - .enable = local_enable_irq, - .disable = local_disable_irq, .ack = mask_and_ack_fall_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_fall_edge_irq, + .unmask = local_enable_irq, .end = end_irq, }; static struct irq_chip either_edge_irq_type = { .typename = "Au1000 Rise or Fall Edge", - .startup = startup_irq, - .shutdown = shutdown_irq, - .enable = local_enable_irq, - .disable = local_disable_irq, .ack = mask_and_ack_either_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_either_edge_irq, + .unmask = local_enable_irq, .end = end_irq, }; static struct irq_chip level_irq_type = { .typename = "Au1000 Level", - .startup = startup_irq, - .shutdown = shutdown_irq, - .enable = local_enable_irq, - .disable = local_disable_irq, .ack = mask_and_ack_level_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_level_irq, + .unmask = local_enable_irq, .end = end_irq, }; @@ -328,31 +309,31 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req) au_writel(1<<(irq_nr-32), IC1_CFG2CLR); au_writel(1<<(irq_nr-32), IC1_CFG1CLR); au_writel(1<<(irq_nr-32), IC1_CFG0SET); - irq_desc[irq_nr].chip = &rise_edge_irq_type; + set_irq_chip(irq_nr, &rise_edge_irq_type); break; case INTC_INT_FALL_EDGE: /* 0:1:0 */ au_writel(1<<(irq_nr-32), IC1_CFG2CLR); au_writel(1<<(irq_nr-32), IC1_CFG1SET); au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - irq_desc[irq_nr].chip = &fall_edge_irq_type; + set_irq_chip(irq_nr, &fall_edge_irq_type); break; case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ au_writel(1<<(irq_nr-32), IC1_CFG2CLR); au_writel(1<<(irq_nr-32), IC1_CFG1SET); au_writel(1<<(irq_nr-32), IC1_CFG0SET); - irq_desc[irq_nr].chip = &either_edge_irq_type; + set_irq_chip(irq_nr, &either_edge_irq_type); break; case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ au_writel(1<<(irq_nr-32), IC1_CFG2SET); au_writel(1<<(irq_nr-32), IC1_CFG1CLR); au_writel(1<<(irq_nr-32), IC1_CFG0SET); - irq_desc[irq_nr].chip = &level_irq_type; + set_irq_chip(irq_nr, &level_irq_type); break; case INTC_INT_LOW_LEVEL: /* 1:1:0 */ au_writel(1<<(irq_nr-32), IC1_CFG2SET); au_writel(1<<(irq_nr-32), IC1_CFG1SET); au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - irq_desc[irq_nr].chip = &level_irq_type; + set_irq_chip(irq_nr, &level_irq_type); break; case INTC_INT_DISABLED: /* 0:0:0 */ au_writel(1<<(irq_nr-32), IC1_CFG0CLR); @@ -380,31 +361,31 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req) au_writel(1< #include #include -#include #include #include @@ -231,13 +230,10 @@ irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id) static inline void dec_kn02_be_init(void) { volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR); - unsigned long flags; kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR); kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN); - spin_lock_irqsave(&kn02_lock, flags); - /* Preset write-only bits of the Control Register cache. */ cached_kn02_csr = *csr | KN02_CSR_LEDS; @@ -247,8 +243,6 @@ static inline void dec_kn02_be_init(void) cached_kn02_csr |= KN02_CSR_CORRECT; *csr = cached_kn02_csr; iob(); - - spin_unlock_irqrestore(&kn02_lock, flags); } static inline void dec_kn03_be_init(void) diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c index 41cd2a9..d0af08b 100644 --- a/arch/mips/dec/ioasic-irq.c +++ b/arch/mips/dec/ioasic-irq.c @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -21,8 +20,6 @@ #include -static DEFINE_SPINLOCK(ioasic_lock); - static int ioasic_irq_base; @@ -52,65 +49,31 @@ static inline void clear_ioasic_irq(unsigned int irq) ioasic_write(IO_REG_SIR, sir); } -static inline void enable_ioasic_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&ioasic_lock, flags); - unmask_ioasic_irq(irq); - spin_unlock_irqrestore(&ioasic_lock, flags); -} - -static inline void disable_ioasic_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&ioasic_lock, flags); - mask_ioasic_irq(irq); - spin_unlock_irqrestore(&ioasic_lock, flags); -} - - -static inline unsigned int startup_ioasic_irq(unsigned int irq) -{ - enable_ioasic_irq(irq); - return 0; -} - -#define shutdown_ioasic_irq disable_ioasic_irq - static inline void ack_ioasic_irq(unsigned int irq) { - spin_lock(&ioasic_lock); mask_ioasic_irq(irq); - spin_unlock(&ioasic_lock); fast_iob(); } static inline void end_ioasic_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_ioasic_irq(irq); + unmask_ioasic_irq(irq); } static struct irq_chip ioasic_irq_type = { .typename = "IO-ASIC", - .startup = startup_ioasic_irq, - .shutdown = shutdown_ioasic_irq, - .enable = enable_ioasic_irq, - .disable = disable_ioasic_irq, .ack = ack_ioasic_irq, + .mask = mask_ioasic_irq, + .mask_ack = ack_ioasic_irq, + .unmask = unmask_ioasic_irq, .end = end_ioasic_irq, }; -#define startup_ioasic_dma_irq startup_ioasic_irq - -#define shutdown_ioasic_dma_irq shutdown_ioasic_irq - -#define enable_ioasic_dma_irq enable_ioasic_irq +#define unmask_ioasic_dma_irq unmask_ioasic_irq -#define disable_ioasic_dma_irq disable_ioasic_irq +#define mask_ioasic_dma_irq mask_ioasic_irq #define ack_ioasic_dma_irq ack_ioasic_irq @@ -123,11 +86,10 @@ static inline void end_ioasic_dma_irq(unsigned int irq) static struct irq_chip ioasic_dma_irq_type = { .typename = "IO-ASIC-DMA", - .startup = startup_ioasic_dma_irq, - .shutdown = shutdown_ioasic_dma_irq, - .enable = enable_ioasic_dma_irq, - .disable = disable_ioasic_dma_irq, .ack = ack_ioasic_dma_irq, + .mask = mask_ioasic_dma_irq, + .mask_ack = ack_ioasic_dma_irq, + .unmask = unmask_ioasic_dma_irq, .end = end_ioasic_dma_irq, }; @@ -140,18 +102,10 @@ void __init init_ioasic_irqs(int base) ioasic_write(IO_REG_SIMR, 0); fast_iob(); - for (i = base; i < base + IO_INR_DMA; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &ioasic_irq_type; - } - for (; i < base + IO_IRQ_LINES; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &ioasic_dma_irq_type; - } + for (i = base; i < base + IO_INR_DMA; i++) + set_irq_chip(i, &ioasic_irq_type); + for (; i < base + IO_IRQ_LINES; i++) + set_irq_chip(i, &ioasic_dma_irq_type); ioasic_irq_base = base; } diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c index 04a367a..c761d97 100644 --- a/arch/mips/dec/kn02-irq.c +++ b/arch/mips/dec/kn02-irq.c @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -29,7 +28,6 @@ * There is no default value -- it has to be initialized. */ u32 cached_kn02_csr; -DEFINE_SPINLOCK(kn02_lock); static int kn02_irq_base; @@ -53,54 +51,24 @@ static inline void mask_kn02_irq(unsigned int irq) *csr = cached_kn02_csr; } -static inline void enable_kn02_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&kn02_lock, flags); - unmask_kn02_irq(irq); - spin_unlock_irqrestore(&kn02_lock, flags); -} - -static inline void disable_kn02_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&kn02_lock, flags); - mask_kn02_irq(irq); - spin_unlock_irqrestore(&kn02_lock, flags); -} - - -static unsigned int startup_kn02_irq(unsigned int irq) -{ - enable_kn02_irq(irq); - return 0; -} - -#define shutdown_kn02_irq disable_kn02_irq - static void ack_kn02_irq(unsigned int irq) { - spin_lock(&kn02_lock); mask_kn02_irq(irq); - spin_unlock(&kn02_lock); iob(); } static void end_kn02_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_kn02_irq(irq); + unmask_kn02_irq(irq); } static struct irq_chip kn02_irq_type = { .typename = "KN02-CSR", - .startup = startup_kn02_irq, - .shutdown = shutdown_kn02_irq, - .enable = enable_kn02_irq, - .disable = disable_kn02_irq, .ack = ack_kn02_irq, + .mask = mask_kn02_irq, + .mask_ack = ack_kn02_irq, + .unmask = unmask_kn02_irq, .end = end_kn02_irq, }; @@ -109,22 +77,15 @@ void __init init_kn02_irqs(int base) { volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR); - unsigned long flags; int i; /* Mask interrupts. */ - spin_lock_irqsave(&kn02_lock, flags); cached_kn02_csr &= ~KN02_CSR_IOINTEN; *csr = cached_kn02_csr; iob(); - spin_unlock_irqrestore(&kn02_lock, flags); - - for (i = base; i < base + KN02_IRQ_LINES; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &kn02_irq_type; - } + + for (i = base; i < base + KN02_IRQ_LINES; i++) + set_irq_chip(i, &kn02_irq_type); kn02_irq_base = base; } diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index 197ed4c..bf1b83b 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -56,22 +56,6 @@ static void emma2rh_irq_disable(unsigned int irq) ll_emma2rh_irq_disable(irq - emma2rh_irq_base); } -static unsigned int emma2rh_irq_startup(unsigned int irq) -{ - emma2rh_irq_enable(irq); - return 0; -} - -#define emma2rh_irq_shutdown emma2rh_irq_disable - -static void emma2rh_irq_ack(unsigned int irq) -{ - /* disable interrupt - some handler will re-enable the irq - * and if the interrupt is leveled, we will have infinite loop - */ - ll_emma2rh_irq_disable(irq - emma2rh_irq_base); -} - static void emma2rh_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -80,25 +64,19 @@ static void emma2rh_irq_end(unsigned int irq) struct irq_chip emma2rh_irq_controller = { .typename = "emma2rh_irq", - .startup = emma2rh_irq_startup, - .shutdown = emma2rh_irq_shutdown, - .enable = emma2rh_irq_enable, - .disable = emma2rh_irq_disable, - .ack = emma2rh_irq_ack, + .ack = emma2rh_irq_disable, + .mask = emma2rh_irq_disable, + .mask_ack = emma2rh_irq_disable, + .unmask = emma2rh_irq_enable, .end = emma2rh_irq_end, - .set_affinity = NULL /* no affinity stuff for UP */ }; void emma2rh_irq_init(u32 irq_base) { u32 i; - for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &emma2rh_irq_controller; - } + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) + set_irq_chip(i, &emma2rh_irq_controller); emma2rh_irq_base = irq_base; } diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index 0b36eb0..8e5f08a 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -48,19 +48,6 @@ static void emma2rh_sw_irq_disable(unsigned int irq) ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); } -static unsigned int emma2rh_sw_irq_startup(unsigned int irq) -{ - emma2rh_sw_irq_enable(irq); - return 0; -} - -#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable - -static void emma2rh_sw_irq_ack(unsigned int irq) -{ - ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); -} - static void emma2rh_sw_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -69,25 +56,19 @@ static void emma2rh_sw_irq_end(unsigned int irq) struct irq_chip emma2rh_sw_irq_controller = { .typename = "emma2rh_sw_irq", - .startup = emma2rh_sw_irq_startup, - .shutdown = emma2rh_sw_irq_shutdown, - .enable = emma2rh_sw_irq_enable, - .disable = emma2rh_sw_irq_disable, - .ack = emma2rh_sw_irq_ack, + .ack = emma2rh_sw_irq_disable, + .mask = emma2rh_sw_irq_disable, + .mask_ack = emma2rh_sw_irq_disable, + .unmask = emma2rh_sw_irq_enable, .end = emma2rh_sw_irq_end, - .set_affinity = NULL, }; void emma2rh_sw_irq_init(u32 irq_base) { u32 i; - for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 2; - irq_desc[i].chip = &emma2rh_sw_irq_controller; - } + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) + set_irq_chip(i, &emma2rh_sw_irq_controller); emma2rh_sw_irq_base = irq_base; } @@ -126,14 +107,6 @@ static void emma2rh_gpio_irq_disable(unsigned int irq) ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base); } -static unsigned int emma2rh_gpio_irq_startup(unsigned int irq) -{ - emma2rh_gpio_irq_enable(irq); - return 0; -} - -#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable - static void emma2rh_gpio_irq_ack(unsigned int irq) { irq -= emma2rh_gpio_irq_base; @@ -149,25 +122,19 @@ static void emma2rh_gpio_irq_end(unsigned int irq) struct irq_chip emma2rh_gpio_irq_controller = { .typename = "emma2rh_gpio_irq", - .startup = emma2rh_gpio_irq_startup, - .shutdown = emma2rh_gpio_irq_shutdown, - .enable = emma2rh_gpio_irq_enable, - .disable = emma2rh_gpio_irq_disable, .ack = emma2rh_gpio_irq_ack, + .mask = emma2rh_gpio_irq_disable, + .mask_ack = emma2rh_gpio_irq_ack, + .unmask = emma2rh_gpio_irq_enable, .end = emma2rh_gpio_irq_end, - .set_affinity = NULL, }; void emma2rh_gpio_irq_init(u32 irq_base) { u32 i; - for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 2; - irq_desc[i].chip = &emma2rh_gpio_irq_controller; - } + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) + set_irq_chip(i, &emma2rh_gpio_irq_controller); emma2rh_gpio_irq_base = irq_base; } diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c index ed4d82b..b3e5796 100644 --- a/arch/mips/gt64120/ev64120/irq.c +++ b/arch/mips/gt64120/ev64120/irq.c @@ -66,38 +66,21 @@ asmlinkage void plat_irq_dispatch(void) static void disable_ev64120_irq(unsigned int irq_nr) { - unsigned long flags; - - local_irq_save(flags); if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2 clear_c0_status(9 << 10); } else { clear_c0_status(1 << (irq_nr + 8)); } - local_irq_restore(flags); } static void enable_ev64120_irq(unsigned int irq_nr) { - unsigned long flags; - - local_irq_save(flags); if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2 set_c0_status(9 << 10); else set_c0_status(1 << (irq_nr + 8)); - local_irq_restore(flags); -} - -static unsigned int startup_ev64120_irq(unsigned int irq) -{ - enable_ev64120_irq(irq); - return 0; /* Never anything pending */ } -#define shutdown_ev64120_irq disable_ev64120_irq -#define mask_and_ack_ev64120_irq disable_ev64120_irq - static void end_ev64120_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -106,13 +89,11 @@ static void end_ev64120_irq(unsigned int irq) static struct irq_chip ev64120_irq_type = { .typename = "EV64120", - .startup = startup_ev64120_irq, - .shutdown = shutdown_ev64120_irq, - .enable = enable_ev64120_irq, - .disable = disable_ev64120_irq, - .ack = mask_and_ack_ev64120_irq, + .ack = disable_ev64120_irq, + .mask = disable_ev64120_irq, + .mask_ack = disable_ev64120_irq, + .unmask = enable_ev64120_irq, .end = end_ev64120_irq, - .set_affinity = NULL }; void gt64120_irq_setup(void) @@ -122,8 +103,6 @@ void gt64120_irq_setup(void) */ clear_c0_status(ST0_IM); - local_irq_disable(); - /* * Enable timer. Other interrupts will be enabled as they are * registered. @@ -133,16 +112,5 @@ void gt64120_irq_setup(void) void __init arch_init_irq(void) { - int i; - - /* Let's initialize our IRQ descriptors */ - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = 0; - irq_desc[i].chip = &no_irq_chip; - irq_desc[i].action = NULL; - irq_desc[i].depth = 0; - spin_lock_init(&irq_desc[i].lock); - } - gt64120_irq_setup(); } diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index d5bd6b3..4bbb6cb 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -28,14 +28,6 @@ static void enable_r4030_irq(unsigned int irq) spin_unlock_irqrestore(&r4030_lock, flags); } -static unsigned int startup_r4030_irq(unsigned int irq) -{ - enable_r4030_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_r4030_irq disable_r4030_irq - void disable_r4030_irq(unsigned int irq) { unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); @@ -47,8 +39,6 @@ void disable_r4030_irq(unsigned int irq) spin_unlock_irqrestore(&r4030_lock, flags); } -#define mask_and_ack_r4030_irq disable_r4030_irq - static void end_r4030_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -57,11 +47,10 @@ static void end_r4030_irq(unsigned int irq) static struct irq_chip r4030_irq_type = { .typename = "R4030", - .startup = startup_r4030_irq, - .shutdown = shutdown_r4030_irq, - .enable = enable_r4030_irq, - .disable = disable_r4030_irq, - .ack = mask_and_ack_r4030_irq, + .ack = disable_r4030_irq, + .mask = disable_r4030_irq, + .mask_ack = disable_r4030_irq, + .unmask = enable_r4030_irq, .end = end_r4030_irq, }; @@ -69,12 +58,8 @@ void __init init_r4030_ints(void) { int i; - for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &r4030_irq_type; - } + for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) + set_irq_chip(i, &r4030_irq_type); r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index de4a238..3da49c5 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -90,17 +90,6 @@ static unsigned char irc_level[TX3927_NUM_IR] = { static void jmr3927_irq_disable(unsigned int irq_nr); static void jmr3927_irq_enable(unsigned int irq_nr); -static DEFINE_SPINLOCK(jmr3927_irq_lock); - -static unsigned int jmr3927_irq_startup(unsigned int irq) -{ - jmr3927_irq_enable(irq); - - return 0; -} - -#define jmr3927_irq_shutdown jmr3927_irq_disable - static void jmr3927_irq_ack(unsigned int irq) { if (irq == JMR3927_IRQ_IRC_TMR0) @@ -118,9 +107,7 @@ static void jmr3927_irq_end(unsigned int irq) static void jmr3927_irq_disable(unsigned int irq_nr) { struct tb_irq_space* sp; - unsigned long flags; - spin_lock_irqsave(&jmr3927_irq_lock, flags); for (sp = tb_irq_spaces; sp; sp = sp->next) { if (sp->start_irqno <= irq_nr && irq_nr < sp->start_irqno + sp->nr_irqs) { @@ -130,15 +117,12 @@ static void jmr3927_irq_disable(unsigned int irq_nr) break; } } - spin_unlock_irqrestore(&jmr3927_irq_lock, flags); } static void jmr3927_irq_enable(unsigned int irq_nr) { struct tb_irq_space* sp; - unsigned long flags; - spin_lock_irqsave(&jmr3927_irq_lock, flags); for (sp = tb_irq_spaces; sp; sp = sp->next) { if (sp->start_irqno <= irq_nr && irq_nr < sp->start_irqno + sp->nr_irqs) { @@ -148,7 +132,6 @@ static void jmr3927_irq_enable(unsigned int irq_nr) break; } } - spin_unlock_irqrestore(&jmr3927_irq_lock, flags); } /* @@ -457,11 +440,10 @@ void __init arch_init_irq(void) static struct irq_chip jmr3927_irq_controller = { .typename = "jmr3927_irq", - .startup = jmr3927_irq_startup, - .shutdown = jmr3927_irq_shutdown, - .enable = jmr3927_irq_enable, - .disable = jmr3927_irq_disable, .ack = jmr3927_irq_ack, + .mask = jmr3927_irq_disable, + .mask_ack = jmr3927_irq_ack, + .unmask = jmr3927_irq_enable, .end = jmr3927_irq_end, }; @@ -469,12 +451,8 @@ void jmr3927_irq_init(u32 irq_base) { u32 i; - for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &jmr3927_irq_controller; - } + for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) + set_irq_chip(i, &jmr3927_irq_controller); jmr3927_irq_base = irq_base; } diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 48e3418..2526c0c 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -40,21 +40,10 @@ static void end_8259A_irq (unsigned int irq) enable_8259A_irq(irq); } -#define shutdown_8259A_irq disable_8259A_irq - void mask_and_ack_8259A(unsigned int); -static unsigned int startup_8259A_irq(unsigned int irq) -{ - enable_8259A_irq(irq); - - return 0; /* never anything pending */ -} - static struct irq_chip i8259A_irq_type = { .typename = "XT-PIC", - .startup = startup_8259A_irq, - .shutdown = shutdown_8259A_irq, .enable = enable_8259A_irq, .disable = disable_8259A_irq, .ack = mask_and_ack_8259A, @@ -120,7 +109,7 @@ int i8259A_irq_pending(unsigned int irq) void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); - irq_desc[irq].chip = &i8259A_irq_type; + set_irq_chip(irq, &i8259A_irq_type); enable_irq(irq); } @@ -323,12 +312,8 @@ void __init init_i8259_irqs (void) init_8259A(0); - for (i = 0; i < 16; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &i8259A_irq_type; - } + for (i = 0; i < 16; i++) + set_irq_chip(i, &i8259A_irq_type); setup_irq(2, &irq2); } diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c index 650a80c..e1880b2 100644 --- a/arch/mips/kernel/irq-msc01.c +++ b/arch/mips/kernel/irq-msc01.c @@ -45,31 +45,6 @@ static inline void unmask_msc_irq(unsigned int irq) } /* - * Enables the IRQ on SOC-it - */ -static void enable_msc_irq(unsigned int irq) -{ - unmask_msc_irq(irq); -} - -/* - * Initialize the IRQ on SOC-it - */ -static unsigned int startup_msc_irq(unsigned int irq) -{ - unmask_msc_irq(irq); - return 0; -} - -/* - * Disables the IRQ on SOC-it - */ -static void disable_msc_irq(unsigned int irq) -{ - mask_msc_irq(irq); -} - -/* * Masks and ACKs an IRQ */ static void level_mask_and_ack_msc_irq(unsigned int irq) @@ -136,25 +111,21 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set) (irq<im_type) { case MSC01_IRQ_EDGE: - irq_desc[base+n].chip = &msc_edgeirq_type; + set_irq_chip(base+n, &msc_edgeirq_type); if (cpu_has_veic) MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT); else MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl); break; case MSC01_IRQ_LEVEL: - irq_desc[base+n].chip = &msc_levelirq_type; + set_irq_chip(base+n, &msc_levelirq_type); if (cpu_has_veic) MSCIC_WRITE(MSC01_IC_SUP+n*8, 0); else diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index 37d1062..5012b9d 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c @@ -67,39 +67,6 @@ static inline void unmask_mv64340_irq(unsigned int irq) } /* - * Enables the IRQ on Marvell Chip - */ -static void enable_mv64340_irq(unsigned int irq) -{ - unmask_mv64340_irq(irq); -} - -/* - * Initialize the IRQ on Marvell Chip - */ -static unsigned int startup_mv64340_irq(unsigned int irq) -{ - unmask_mv64340_irq(irq); - return 0; -} - -/* - * Disables the IRQ on Marvell Chip - */ -static void disable_mv64340_irq(unsigned int irq) -{ - mask_mv64340_irq(irq); -} - -/* - * Masks and ACKs an IRQ - */ -static void mask_and_ack_mv64340_irq(unsigned int irq) -{ - mask_mv64340_irq(irq); -} - -/* * End IRQ processing */ static void end_mv64340_irq(unsigned int irq) @@ -133,15 +100,12 @@ void ll_mv64340_irq(void) do_IRQ(ls1bit32(irq_src_high) + irq_base + 32); } -#define shutdown_mv64340_irq disable_mv64340_irq - struct irq_chip mv64340_irq_type = { .typename = "MV-64340", - .startup = startup_mv64340_irq, - .shutdown = shutdown_mv64340_irq, - .enable = enable_mv64340_irq, - .disable = disable_mv64340_irq, - .ack = mask_and_ack_mv64340_irq, + .ack = mask_mv64340_irq, + .mask = mask_mv64340_irq, + .mask_ack = mask_mv64340_irq, + .unmask = unmask_mv64340_irq, .end = end_mv64340_irq, }; @@ -149,13 +113,8 @@ void __init mv64340_irq_init(unsigned int base) { int i; - /* Reset irq handlers pointers to NULL */ - for (i = base; i < base + 64; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 2; - irq_desc[i].chip = &mv64340_irq_type; - } + for (i = base; i < base + 64; i++) + set_irq_chip(i, &mv64340_irq_type); irq_base = base; } diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index 6b54c71..6a297e3 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -29,42 +29,6 @@ static inline void mask_rm7k_irq(unsigned int irq) clear_c0_intcontrol(0x100 << (irq - irq_base)); } -static inline void rm7k_cpu_irq_enable(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - unmask_rm7k_irq(irq); - local_irq_restore(flags); -} - -static void rm7k_cpu_irq_disable(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - mask_rm7k_irq(irq); - local_irq_restore(flags); -} - -static unsigned int rm7k_cpu_irq_startup(unsigned int irq) -{ - rm7k_cpu_irq_enable(irq); - - return 0; -} - -#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable - -/* - * While we ack the interrupt interrupts are disabled and thus we don't need - * to deal with concurrency issues. Same for rm7k_cpu_irq_end. - */ -static void rm7k_cpu_irq_ack(unsigned int irq) -{ - mask_rm7k_irq(irq); -} - static void rm7k_cpu_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -73,11 +37,10 @@ static void rm7k_cpu_irq_end(unsigned int irq) static struct irq_chip rm7k_irq_controller = { .typename = "RM7000", - .startup = rm7k_cpu_irq_startup, - .shutdown = rm7k_cpu_irq_shutdown, - .enable = rm7k_cpu_irq_enable, - .disable = rm7k_cpu_irq_disable, - .ack = rm7k_cpu_irq_ack, + .ack = mask_rm7k_irq, + .mask = mask_rm7k_irq, + .mask_ack = mask_rm7k_irq, + .unmask = unmask_rm7k_irq, .end = rm7k_cpu_irq_end, }; @@ -87,12 +50,8 @@ void __init rm7k_cpu_irq_init(int base) clear_c0_intcontrol(0x00000f00); /* Mask all */ - for (i = base; i < base + 4; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &rm7k_irq_controller; - } + for (i = base; i < base + 4; i++) + set_irq_chip(i, &rm7k_irq_controller); irq_base = base; } diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index 62f011b..9775384 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -48,15 +48,6 @@ static void rm9k_cpu_irq_disable(unsigned int irq) local_irq_restore(flags); } -static unsigned int rm9k_cpu_irq_startup(unsigned int irq) -{ - rm9k_cpu_irq_enable(irq); - - return 0; -} - -#define rm9k_cpu_irq_shutdown rm9k_cpu_irq_disable - /* * Performance counter interrupts are global on all processors. */ @@ -89,16 +80,6 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq) on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1); } - -/* - * While we ack the interrupt interrupts are disabled and thus we don't need - * to deal with concurrency issues. Same for rm9k_cpu_irq_end. - */ -static void rm9k_cpu_irq_ack(unsigned int irq) -{ - mask_rm9k_irq(irq); -} - static void rm9k_cpu_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -107,11 +88,10 @@ static void rm9k_cpu_irq_end(unsigned int irq) static struct irq_chip rm9k_irq_controller = { .typename = "RM9000", - .startup = rm9k_cpu_irq_startup, - .shutdown = rm9k_cpu_irq_shutdown, - .enable = rm9k_cpu_irq_enable, - .disable = rm9k_cpu_irq_disable, - .ack = rm9k_cpu_irq_ack, + .ack = mask_rm9k_irq, + .mask = mask_rm9k_irq, + .mask_ack = mask_rm9k_irq, + .unmask = unmask_rm9k_irq, .end = rm9k_cpu_irq_end, }; @@ -119,9 +99,10 @@ static struct irq_chip rm9k_perfcounter_irq = { .typename = "RM9000", .startup = rm9k_perfcounter_irq_startup, .shutdown = rm9k_perfcounter_irq_shutdown, - .enable = rm9k_cpu_irq_enable, - .disable = rm9k_cpu_irq_disable, - .ack = rm9k_cpu_irq_ack, + .ack = mask_rm9k_irq, + .mask = mask_rm9k_irq, + .mask_ack = mask_rm9k_irq, + .unmask = unmask_rm9k_irq, .end = rm9k_cpu_irq_end, }; @@ -135,15 +116,11 @@ void __init rm9k_cpu_irq_init(int base) clear_c0_intcontrol(0x0000f000); /* Mask all */ - for (i = base; i < base + 4; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &rm9k_irq_controller; - } + for (i = base; i < base + 4; i++) + set_irq_chip(i, &rm9k_irq_controller); rm9000_perfcount_irq = base + 1; - irq_desc[rm9000_perfcount_irq].chip = &rm9k_perfcounter_irq; + set_irq_chip(rm9000_perfcount_irq, &rm9k_perfcounter_irq); irq_base = base; } diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 9b0e49d..e997c94 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -172,19 +172,6 @@ __setup("nokgdb", nokgdb); void __init init_IRQ(void) { - int i; - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &no_irq_chip; - spin_lock_init(&irq_desc[i].lock); -#ifdef CONFIG_MIPS_MT_SMTC - irq_hwmask[i] = 0; -#endif /* CONFIG_MIPS_MT_SMTC */ - } - arch_init_irq(); #ifdef CONFIG_KGDB diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 9bb21c7..3b7cfa4 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -50,44 +50,6 @@ static inline void mask_mips_irq(unsigned int irq) irq_disable_hazard(); } -static inline void mips_cpu_irq_enable(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - unmask_mips_irq(irq); - back_to_back_c0_hazard(); - local_irq_restore(flags); -} - -static void mips_cpu_irq_disable(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - mask_mips_irq(irq); - back_to_back_c0_hazard(); - local_irq_restore(flags); -} - -static unsigned int mips_cpu_irq_startup(unsigned int irq) -{ - mips_cpu_irq_enable(irq); - - return 0; -} - -#define mips_cpu_irq_shutdown mips_cpu_irq_disable - -/* - * While we ack the interrupt interrupts are disabled and thus we don't need - * to deal with concurrency issues. Same for mips_cpu_irq_end. - */ -static void mips_cpu_irq_ack(unsigned int irq) -{ - mask_mips_irq(irq); -} - static void mips_cpu_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -96,11 +58,10 @@ static void mips_cpu_irq_end(unsigned int irq) static struct irq_chip mips_cpu_irq_controller = { .typename = "MIPS", - .startup = mips_cpu_irq_startup, - .shutdown = mips_cpu_irq_shutdown, - .enable = mips_cpu_irq_enable, - .disable = mips_cpu_irq_disable, - .ack = mips_cpu_irq_ack, + .ack = mask_mips_irq, + .mask = mask_mips_irq, + .mask_ack = mask_mips_irq, + .unmask = unmask_mips_irq, .end = mips_cpu_irq_end, }; @@ -110,8 +71,6 @@ static struct irq_chip mips_cpu_irq_controller = { #define unmask_mips_mt_irq unmask_mips_irq #define mask_mips_mt_irq mask_mips_irq -#define mips_mt_cpu_irq_enable mips_cpu_irq_enable -#define mips_mt_cpu_irq_disable mips_cpu_irq_disable static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) { @@ -119,13 +78,11 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); evpe(vpflags); - mips_mt_cpu_irq_enable(irq); + unmask_mips_mt_irq(irq); return 0; } -#define mips_mt_cpu_irq_shutdown mips_mt_cpu_irq_disable - /* * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for mips_cpu_irq_end. @@ -143,10 +100,10 @@ static void mips_mt_cpu_irq_ack(unsigned int irq) static struct irq_chip mips_mt_cpu_irq_controller = { .typename = "MIPS", .startup = mips_mt_cpu_irq_startup, - .shutdown = mips_mt_cpu_irq_shutdown, - .enable = mips_mt_cpu_irq_enable, - .disable = mips_mt_cpu_irq_disable, .ack = mips_mt_cpu_irq_ack, + .mask = mask_mips_mt_irq, + .mask_ack = mips_mt_cpu_irq_ack, + .unmask = unmask_mips_mt_irq, .end = mips_mt_cpu_irq_end, }; @@ -163,19 +120,11 @@ void __init mips_cpu_irq_init(int irq_base) * leave them uninitialized for other processors. */ if (cpu_has_mipsmt) - for (i = irq_base; i < irq_base + 2; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &mips_mt_cpu_irq_controller; - } - - for (i = irq_base + 2; i < irq_base + 8; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &mips_cpu_irq_controller; - } + for (i = irq_base; i < irq_base + 2; i++) + set_irq_chip(i, &mips_mt_cpu_irq_controller); + + for (i = irq_base + 2; i < irq_base + 8; i++) + set_irq_chip(i, &mips_cpu_irq_controller); mips_cpu_irq_base = irq_base; } diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index a144a00..cac82af 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -36,33 +36,14 @@ static volatile int lasat_int_mask_shift; void disable_lasat_irq(unsigned int irq_nr) { - unsigned long flags; - - local_irq_save(flags); *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; - local_irq_restore(flags); } void enable_lasat_irq(unsigned int irq_nr) { - unsigned long flags; - - local_irq_save(flags); *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; - local_irq_restore(flags); } -static unsigned int startup_lasat_irq(unsigned int irq) -{ - enable_lasat_irq(irq); - - return 0; /* never anything pending */ -} - -#define shutdown_lasat_irq disable_lasat_irq - -#define mask_and_ack_lasat_irq disable_lasat_irq - static void end_lasat_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -71,11 +52,10 @@ static void end_lasat_irq(unsigned int irq) static struct irq_chip lasat_irq_type = { .typename = "Lasat", - .startup = startup_lasat_irq, - .shutdown = shutdown_lasat_irq, - .enable = enable_lasat_irq, - .disable = disable_lasat_irq, - .ack = mask_and_ack_lasat_irq, + .ack = disable_lasat_irq, + .mask = disable_lasat_irq, + .mask_ack = disable_lasat_irq, + .unmask = enable_lasat_irq, .end = end_lasat_irq, }; @@ -152,10 +132,6 @@ void __init arch_init_irq(void) panic("arch_init_irq: mips_machtype incorrect"); } - for (i = 0; i <= LASATINT_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &lasat_irq_type; - } + for (i = 0; i <= LASATINT_END; i++) + set_irq_chip(i, &lasat_irq_type); } diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c index be624b8..7c71004 100644 --- a/arch/mips/mips-boards/atlas/atlas_int.c +++ b/arch/mips/mips-boards/atlas/atlas_int.c @@ -62,16 +62,6 @@ void enable_atlas_irq(unsigned int irq_nr) iob(); } -static unsigned int startup_atlas_irq(unsigned int irq) -{ - enable_atlas_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_atlas_irq disable_atlas_irq - -#define mask_and_ack_atlas_irq disable_atlas_irq - static void end_atlas_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -80,11 +70,10 @@ static void end_atlas_irq(unsigned int irq) static struct irq_chip atlas_irq_type = { .typename = "Atlas", - .startup = startup_atlas_irq, - .shutdown = shutdown_atlas_irq, - .enable = enable_atlas_irq, - .disable = disable_atlas_irq, - .ack = mask_and_ack_atlas_irq, + .ack = disable_atlas_irq, + .mask = disable_atlas_irq, + .mask_ack = disable_atlas_irq, + .unmask = enable_atlas_irq, .end = end_atlas_irq, }; @@ -217,13 +206,8 @@ static inline void init_atlas_irqs (int base) */ atlas_hw0_icregs->intrsten = 0xffffffff; - for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &atlas_irq_type; - spin_lock_init(&irq_desc[i].lock); - } + for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) + set_irq_chip(i, &atlas_irq_type); } static struct irqaction atlasirq = { diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c index 47e3fa3..7723f09 100644 --- a/arch/mips/momentum/ocelot_c/cpci-irq.c +++ b/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -66,39 +66,6 @@ static inline void unmask_cpci_irq(unsigned int irq) } /* - * Enables the IRQ in the FPGA - */ -static void enable_cpci_irq(unsigned int irq) -{ - unmask_cpci_irq(irq); -} - -/* - * Initialize the IRQ in the FPGA - */ -static unsigned int startup_cpci_irq(unsigned int irq) -{ - unmask_cpci_irq(irq); - return 0; -} - -/* - * Disables the IRQ in the FPGA - */ -static void disable_cpci_irq(unsigned int irq) -{ - mask_cpci_irq(irq); -} - -/* - * Masks and ACKs an IRQ - */ -static void mask_and_ack_cpci_irq(unsigned int irq) -{ - mask_cpci_irq(irq); -} - -/* * End IRQ processing */ static void end_cpci_irq(unsigned int irq) @@ -125,15 +92,12 @@ void ll_cpci_irq(void) do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE); } -#define shutdown_cpci_irq disable_cpci_irq - struct irq_chip cpci_irq_type = { .typename = "CPCI/FPGA", - .startup = startup_cpci_irq, - .shutdown = shutdown_cpci_irq, - .enable = enable_cpci_irq, - .disable = disable_cpci_irq, - .ack = mask_and_ack_cpci_irq, + .ack = mask_cpci_irq, + .mask = mask_cpci_irq, + .mask_ack = mask_cpci_irq, + .unmask = unmask_cpci_irq, .end = end_cpci_irq, }; @@ -141,11 +105,6 @@ void cpci_irq_init(void) { int i; - /* Reset irq handlers pointers to NULL */ - for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 2; - irq_desc[i].chip = &cpci_irq_type; - } + for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) + set_irq_chip(i, &cpci_irq_type); } diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c index 510257d..72faf81 100644 --- a/arch/mips/momentum/ocelot_c/uart-irq.c +++ b/arch/mips/momentum/ocelot_c/uart-irq.c @@ -60,39 +60,6 @@ static inline void unmask_uart_irq(unsigned int irq) } /* - * Enables the IRQ in the FPGA - */ -static void enable_uart_irq(unsigned int irq) -{ - unmask_uart_irq(irq); -} - -/* - * Initialize the IRQ in the FPGA - */ -static unsigned int startup_uart_irq(unsigned int irq) -{ - unmask_uart_irq(irq); - return 0; -} - -/* - * Disables the IRQ in the FPGA - */ -static void disable_uart_irq(unsigned int irq) -{ - mask_uart_irq(irq); -} - -/* - * Masks and ACKs an IRQ - */ -static void mask_and_ack_uart_irq(unsigned int irq) -{ - mask_uart_irq(irq); -} - -/* * End IRQ processing */ static void end_uart_irq(unsigned int irq) @@ -118,28 +85,17 @@ void ll_uart_irq(void) do_IRQ(ls1bit8(irq_src) + 74); } -#define shutdown_uart_irq disable_uart_irq - struct irq_chip uart_irq_type = { .typename = "UART/FPGA", - .startup = startup_uart_irq, - .shutdown = shutdown_uart_irq, - .enable = enable_uart_irq, - .disable = disable_uart_irq, - .ack = mask_and_ack_uart_irq, + .ack = mask_uart_irq, + .mask = mask_uart_irq, + .mask_ack = mask_uart_irq, + .unmask = unmask_uart_irq, .end = end_uart_irq, }; void uart_irq_init(void) { - /* Reset irq handlers pointers to NULL */ - irq_desc[80].status = IRQ_DISABLED; - irq_desc[80].action = 0; - irq_desc[80].depth = 2; - irq_desc[80].chip = &uart_irq_type; - - irq_desc[81].status = IRQ_DISABLED; - irq_desc[81].action = 0; - irq_desc[81].depth = 2; - irq_desc[81].chip = &uart_irq_type; + set_irq_chip(80, &uart_irq_type); + set_irq_chip(81, &uart_irq_type); } diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c index 7106116..e4bf494 100644 --- a/arch/mips/philips/pnx8550/common/int.c +++ b/arch/mips/philips/pnx8550/common/int.c @@ -38,8 +38,6 @@ #include #include -static DEFINE_SPINLOCK(irq_lock); - /* default prio for interrupts */ /* first one is a no-no so therefore always prio 0 (disabled) */ static char gic_prio[PNX8550_INT_GIC_TOTINT] = { @@ -149,38 +147,6 @@ static inline void unmask_irq(unsigned int irq_nr) } } -#define pnx8550_disable pnx8550_ack -static void pnx8550_ack(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - mask_irq(irq); - spin_unlock_irqrestore(&irq_lock, flags); -} - -#define pnx8550_enable pnx8550_unmask -static void pnx8550_unmask(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - unmask_irq(irq); - spin_unlock_irqrestore(&irq_lock, flags); -} - -static unsigned int startup_irq(unsigned int irq_nr) -{ - pnx8550_unmask(irq_nr); - return 0; -} - -static void shutdown_irq(unsigned int irq_nr) -{ - pnx8550_ack(irq_nr); - return; -} - int pnx8550_set_gic_priority(int irq, int priority) { int gic_irq = irq-PNX8550_INT_GIC_MIN; @@ -192,26 +158,19 @@ int pnx8550_set_gic_priority(int irq, int priority) return prev_priority; } -static inline void mask_and_ack_level_irq(unsigned int irq) -{ - pnx8550_disable(irq); - return; -} - static void end_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { - pnx8550_enable(irq); + unmask_irq(irq); } } static struct irq_chip level_irq_type = { .typename = "PNX Level IRQ", - .startup = startup_irq, - .shutdown = shutdown_irq, - .enable = pnx8550_enable, - .disable = pnx8550_disable, - .ack = mask_and_ack_level_irq, + .ack = mask_irq, + .mask = mask_irq, + .mask_ack = mask_irq, + .unmask = unmask_irq, .end = end_irq, }; @@ -233,8 +192,8 @@ void __init arch_init_irq(void) int configPR; for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { - irq_desc[i].chip = &level_irq_type; - pnx8550_ack(i); /* mask the irq just in case */ + set_irq_chip(i, &level_irq_type); + mask_irq(i); /* mask the irq just in case */ } /* init of GIC/IPC interrupts */ @@ -270,7 +229,7 @@ void __init arch_init_irq(void) /* mask/priority is still 0 so we will not get any * interrupts until it is unmasked */ - irq_desc[i].chip = &level_irq_type; + set_irq_chip(i, &level_irq_type); } /* Priority level 0 */ @@ -279,20 +238,19 @@ void __init arch_init_irq(void) /* Set int vector table address */ PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; - irq_desc[MIPS_CPU_GIC_IRQ].chip = &level_irq_type; + set_irq_chip(MIPS_CPU_GIC_IRQ, &level_irq_type); setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); /* init of Timer interrupts */ - for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) { - irq_desc[i].chip = &level_irq_type; - } + for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) + set_irq_chip(i, &level_irq_type); /* Stop Timer 1-3 */ configPR = read_c0_config7(); configPR |= 0x00000038; write_c0_config7(configPR); - irq_desc[MIPS_CPU_TIMER_IRQ].chip = &level_irq_type; + set_irq_chip(MIPS_CPU_TIMER_IRQ, &level_irq_type); setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); } diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index 0d18ed4..a1a9af6 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c @@ -95,16 +95,11 @@ static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) static void enable_eisa1_irq(unsigned int irq) { - unsigned long flags; u8 mask; - local_irq_save(flags); - mask = inb(EISA_INT1_MASK); mask &= ~((u8) (1 << irq)); outb(mask, EISA_INT1_MASK); - - local_irq_restore(flags); } static unsigned int startup_eisa1_irq(unsigned int irq) @@ -130,8 +125,6 @@ static void disable_eisa1_irq(unsigned int irq) outb(mask, EISA_INT1_MASK); } -#define shutdown_eisa1_irq disable_eisa1_irq - static void mask_and_ack_eisa1_irq(unsigned int irq) { disable_eisa1_irq(irq); @@ -148,25 +141,20 @@ static void end_eisa1_irq(unsigned int irq) static struct irq_chip ip22_eisa1_irq_type = { .typename = "IP22 EISA", .startup = startup_eisa1_irq, - .shutdown = shutdown_eisa1_irq, - .enable = enable_eisa1_irq, - .disable = disable_eisa1_irq, .ack = mask_and_ack_eisa1_irq, + .mask = disable_eisa1_irq, + .mask_ack = mask_and_ack_eisa1_irq, + .unmask = enable_eisa1_irq, .end = end_eisa1_irq, }; static void enable_eisa2_irq(unsigned int irq) { - unsigned long flags; u8 mask; - local_irq_save(flags); - mask = inb(EISA_INT2_MASK); mask &= ~((u8) (1 << (irq - 8))); outb(mask, EISA_INT2_MASK); - - local_irq_restore(flags); } static unsigned int startup_eisa2_irq(unsigned int irq) @@ -192,8 +180,6 @@ static void disable_eisa2_irq(unsigned int irq) outb(mask, EISA_INT2_MASK); } -#define shutdown_eisa2_irq disable_eisa2_irq - static void mask_and_ack_eisa2_irq(unsigned int irq) { disable_eisa2_irq(irq); @@ -210,10 +196,10 @@ static void end_eisa2_irq(unsigned int irq) static struct irq_chip ip22_eisa2_irq_type = { .typename = "IP22 EISA", .startup = startup_eisa2_irq, - .shutdown = shutdown_eisa2_irq, - .enable = enable_eisa2_irq, - .disable = disable_eisa2_irq, .ack = mask_and_ack_eisa2_irq, + .mask = disable_eisa2_irq, + .mask_ack = mask_and_ack_eisa2_irq, + .unmask = enable_eisa2_irq, .end = end_eisa2_irq, }; @@ -275,13 +261,10 @@ int __init ip22_eisa_init(void) outb(0, EISA_DMA2_WRITE_SINGLE); for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; if (i < (SGINT_EISA + 8)) - irq_desc[i].chip = &ip22_eisa1_irq_type; + set_irq_chip(i, &ip22_eisa1_irq_type); else - irq_desc[i].chip = &ip22_eisa2_irq_type; + set_irq_chip(i, &ip22_eisa2_irq_type); } /* Cannot use request_irq because of kmalloc not being ready at such diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index af51889..8e2074b 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -40,34 +40,17 @@ extern int ip22_eisa_init(void); static void enable_local0_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ if (irq != SGI_MAP_0_IRQ) sgint->imask0 |= (1 << (irq - SGINT_LOCAL0)); - local_irq_restore(flags); -} - -static unsigned int startup_local0_irq(unsigned int irq) -{ - enable_local0_irq(irq); - return 0; /* Never anything pending */ } static void disable_local0_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); - local_irq_restore(flags); } -#define shutdown_local0_irq disable_local0_irq -#define mask_and_ack_local0_irq disable_local0_irq - static void end_local0_irq (unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -76,44 +59,26 @@ static void end_local0_irq (unsigned int irq) static struct irq_chip ip22_local0_irq_type = { .typename = "IP22 local 0", - .startup = startup_local0_irq, - .shutdown = shutdown_local0_irq, - .enable = enable_local0_irq, - .disable = disable_local0_irq, - .ack = mask_and_ack_local0_irq, + .ack = disable_local0_irq, + .mask = disable_local0_irq, + .mask_ack = disable_local0_irq, + .unmask = enable_local0_irq, .end = end_local0_irq, }; static void enable_local1_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ if (irq != SGI_MAP_1_IRQ) sgint->imask1 |= (1 << (irq - SGINT_LOCAL1)); - local_irq_restore(flags); -} - -static unsigned int startup_local1_irq(unsigned int irq) -{ - enable_local1_irq(irq); - return 0; /* Never anything pending */ } void disable_local1_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); - local_irq_restore(flags); } -#define shutdown_local1_irq disable_local1_irq -#define mask_and_ack_local1_irq disable_local1_irq - static void end_local1_irq (unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -122,44 +87,26 @@ static void end_local1_irq (unsigned int irq) static struct irq_chip ip22_local1_irq_type = { .typename = "IP22 local 1", - .startup = startup_local1_irq, - .shutdown = shutdown_local1_irq, - .enable = enable_local1_irq, - .disable = disable_local1_irq, - .ack = mask_and_ack_local1_irq, + .ack = disable_local1_irq, + .mask = disable_local1_irq, + .mask_ack = disable_local1_irq, + .unmask = enable_local1_irq, .end = end_local1_irq, }; static void enable_local2_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); - local_irq_restore(flags); -} - -static unsigned int startup_local2_irq(unsigned int irq) -{ - enable_local2_irq(irq); - return 0; /* Never anything pending */ } void disable_local2_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); if (!sgint->cmeimask0) sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); - local_irq_restore(flags); } -#define shutdown_local2_irq disable_local2_irq -#define mask_and_ack_local2_irq disable_local2_irq - static void end_local2_irq (unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -168,44 +115,26 @@ static void end_local2_irq (unsigned int irq) static struct irq_chip ip22_local2_irq_type = { .typename = "IP22 local 2", - .startup = startup_local2_irq, - .shutdown = shutdown_local2_irq, - .enable = enable_local2_irq, - .disable = disable_local2_irq, - .ack = mask_and_ack_local2_irq, + .ack = disable_local2_irq, + .mask = disable_local2_irq, + .mask_ack = disable_local2_irq, + .unmask = enable_local2_irq, .end = end_local2_irq, }; static void enable_local3_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3)); - local_irq_restore(flags); -} - -static unsigned int startup_local3_irq(unsigned int irq) -{ - enable_local3_irq(irq); - return 0; /* Never anything pending */ } void disable_local3_irq(unsigned int irq) { - unsigned long flags; - - local_irq_save(flags); sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3)); if (!sgint->cmeimask1) sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); - local_irq_restore(flags); } -#define shutdown_local3_irq disable_local3_irq -#define mask_and_ack_local3_irq disable_local3_irq - static void end_local3_irq (unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -214,11 +143,10 @@ static void end_local3_irq (unsigned int irq) static struct irq_chip ip22_local3_irq_type = { .typename = "IP22 local 3", - .startup = startup_local3_irq, - .shutdown = shutdown_local3_irq, - .enable = enable_local3_irq, - .disable = disable_local3_irq, - .ack = mask_and_ack_local3_irq, + .ack = disable_local3_irq, + .mask = disable_local3_irq, + .mask_ack = disable_local3_irq, + .unmask = enable_local3_irq, .end = end_local3_irq, }; @@ -430,10 +358,7 @@ void __init arch_init_irq(void) else handler = &ip22_local3_irq_type; - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = handler; + set_irq_chip(i, handler); } /* vector handler. this register the IRQ as non-sharable */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 270ecd3..8243202 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -332,11 +332,6 @@ static inline void disable_bridge_irq(unsigned int irq) intr_disconnect_level(cpu, swlevel); } -static void mask_and_ack_bridge_irq(unsigned int irq) -{ - disable_bridge_irq(irq); -} - static void end_bridge_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && @@ -348,18 +343,16 @@ static struct irq_chip bridge_irq_type = { .typename = "bridge", .startup = startup_bridge_irq, .shutdown = shutdown_bridge_irq, - .enable = enable_bridge_irq, - .disable = disable_bridge_irq, - .ack = mask_and_ack_bridge_irq, + .ack = disable_bridge_irq, + .mask = disable_bridge_irq, + .mask_ack = disable_bridge_irq, + .unmask = enable_bridge_irq, .end = end_bridge_irq, }; void __devinit register_bridge_irq(unsigned int irq) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &bridge_irq_type; + set_irq_chip(irq, &bridge_irq_type); } int __devinit request_bridge_irq(struct bridge_controller *bc) diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 5e82a26..86ba7fc 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -172,15 +172,6 @@ static __init unsigned long get_m48t35_time(void) return mktime(year, month, date, hour, min, sec); } -static unsigned int startup_rt_irq(unsigned int irq) -{ - return 0; -} - -static void shutdown_rt_irq(unsigned int irq) -{ -} - static void enable_rt_irq(unsigned int irq) { } @@ -189,21 +180,16 @@ static void disable_rt_irq(unsigned int irq) { } -static void mask_and_ack_rt(unsigned int irq) -{ -} - static void end_rt_irq(unsigned int irq) { } static struct irq_chip rt_irq_type = { .typename = "SN HUB RT timer", - .startup = startup_rt_irq, - .shutdown = shutdown_rt_irq, - .enable = enable_rt_irq, - .disable = disable_rt_irq, - .ack = mask_and_ack_rt, + .ack = disable_rt_irq, + .mask = disable_rt_irq, + .mask_ack = disable_rt_irq, + .unmask = enable_rt_irq, .end = end_rt_irq, }; @@ -221,10 +207,7 @@ void __init plat_timer_setup(struct irqaction *irq) if (irqno < 0) panic("Can't allocate interrupt number for timer interrupt"); - irq_desc[irqno].status = IRQ_DISABLED; - irq_desc[irqno].action = NULL; - irq_desc[irqno].depth = 1; - irq_desc[irqno].chip = &rt_irq_type; + set_irq_chip(irqno, &rt_irq_type); /* over-write the handler, we use our own way */ irq->handler = no_action; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index c9acadd..ae06386 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -113,12 +113,6 @@ static void inline flush_mace_bus(void) * is quite different anyway. */ -/* - * IRQ spinlock - Ralf says not to disable CPU interrupts, - * and I think he knows better. - */ -static DEFINE_SPINLOCK(ip32_irq_lock); - /* Some initial interrupts to set up */ extern irqreturn_t crime_memerr_intr(int irq, void *dev_id); extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id); @@ -138,12 +132,6 @@ static void enable_cpu_irq(unsigned int irq) set_c0_status(STATUSF_IP7); } -static unsigned int startup_cpu_irq(unsigned int irq) -{ - enable_cpu_irq(irq); - return 0; -} - static void disable_cpu_irq(unsigned int irq) { clear_c0_status(STATUSF_IP7); @@ -155,16 +143,12 @@ static void end_cpu_irq(unsigned int irq) enable_cpu_irq (irq); } -#define shutdown_cpu_irq disable_cpu_irq -#define mask_and_ack_cpu_irq disable_cpu_irq - static struct irq_chip ip32_cpu_interrupt = { .typename = "IP32 CPU", - .startup = startup_cpu_irq, - .shutdown = shutdown_cpu_irq, - .enable = enable_cpu_irq, - .disable = disable_cpu_irq, - .ack = mask_and_ack_cpu_irq, + .ack = disable_cpu_irq, + .mask = disable_cpu_irq, + .mask_ack = disable_cpu_irq, + .unmask = enable_cpu_irq, .end = end_cpu_irq, }; @@ -177,45 +161,27 @@ static uint64_t crime_mask; static void enable_crime_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); -} - -static unsigned int startup_crime_irq(unsigned int irq) -{ - enable_crime_irq(irq); - return 0; /* This is probably not right; we could have pending irqs */ } static void disable_crime_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); crime->imask = crime_mask; flush_crime_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void mask_and_ack_crime_irq(unsigned int irq) { - unsigned long flags; - /* Edge triggered interrupts must be cleared. */ if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { uint64_t crime_int; - spin_lock_irqsave(&ip32_irq_lock, flags); crime_int = crime->hard_int; crime_int &= ~(1 << (irq - 1)); crime->hard_int = crime_int; - spin_unlock_irqrestore(&ip32_irq_lock, flags); } disable_crime_irq(irq); } @@ -226,15 +192,12 @@ static void end_crime_irq(unsigned int irq) enable_crime_irq(irq); } -#define shutdown_crime_irq disable_crime_irq - static struct irq_chip ip32_crime_interrupt = { .typename = "IP32 CRIME", - .startup = startup_crime_irq, - .shutdown = shutdown_crime_irq, - .enable = enable_crime_irq, - .disable = disable_crime_irq, .ack = mask_and_ack_crime_irq, + .mask = disable_crime_irq, + .mask_ack = mask_and_ack_crime_irq, + .unmask = enable_crime_irq, .end = end_crime_irq, }; @@ -248,34 +211,20 @@ static unsigned long macepci_mask; static void enable_macepci_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); mace->pci.control = macepci_mask; crime_mask |= 1 << (irq - 1); crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); -} - -static unsigned int startup_macepci_irq(unsigned int irq) -{ - enable_macepci_irq (irq); - return 0; } static void disable_macepci_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); crime->imask = crime_mask; flush_crime_bus(); macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); mace->pci.control = macepci_mask; flush_mace_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void end_macepci_irq(unsigned int irq) @@ -284,16 +233,12 @@ static void end_macepci_irq(unsigned int irq) enable_macepci_irq(irq); } -#define shutdown_macepci_irq disable_macepci_irq -#define mask_and_ack_macepci_irq disable_macepci_irq - static struct irq_chip ip32_macepci_interrupt = { .typename = "IP32 MACE PCI", - .startup = startup_macepci_irq, - .shutdown = shutdown_macepci_irq, - .enable = enable_macepci_irq, - .disable = disable_macepci_irq, - .ack = mask_and_ack_macepci_irq, + .ack = disable_macepci_irq, + .mask = disable_macepci_irq, + .mask_ack = disable_macepci_irq, + .unmask = enable_macepci_irq, .end = end_macepci_irq, }; @@ -339,7 +284,6 @@ static unsigned long maceisa_mask; static void enable_maceisa_irq (unsigned int irq) { unsigned int crime_int = 0; - unsigned long flags; DBG ("maceisa enable: %u\n", irq); @@ -355,26 +299,16 @@ static void enable_maceisa_irq (unsigned int irq) break; } DBG ("crime_int %08x enabled\n", crime_int); - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= crime_int; crime->imask = crime_mask; maceisa_mask |= 1 << (irq - 33); mace->perif.ctrl.imask = maceisa_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); -} - -static unsigned int startup_maceisa_irq(unsigned int irq) -{ - enable_maceisa_irq(irq); - return 0; } static void disable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - unsigned long flags; - spin_lock_irqsave(&ip32_irq_lock, flags); maceisa_mask &= ~(1 << (irq - 33)); if(!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; @@ -387,23 +321,20 @@ static void disable_maceisa_irq(unsigned int irq) flush_crime_bus(); mace->perif.ctrl.imask = maceisa_mask; flush_mace_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void mask_and_ack_maceisa_irq(unsigned int irq) { - unsigned long mace_int, flags; + unsigned long mace_int; switch (irq) { case MACEISA_PARALLEL_IRQ: case MACEISA_SERIAL1_TDMAPR_IRQ: case MACEISA_SERIAL2_TDMAPR_IRQ: /* edge triggered */ - spin_lock_irqsave(&ip32_irq_lock, flags); mace_int = mace->perif.ctrl.istat; mace_int &= ~(1 << (irq - 33)); mace->perif.ctrl.istat = mace_int; - spin_unlock_irqrestore(&ip32_irq_lock, flags); break; } disable_maceisa_irq(irq); @@ -415,15 +346,12 @@ static void end_maceisa_irq(unsigned irq) enable_maceisa_irq(irq); } -#define shutdown_maceisa_irq disable_maceisa_irq - static struct irq_chip ip32_maceisa_interrupt = { .typename = "IP32 MACE ISA", - .startup = startup_maceisa_irq, - .shutdown = shutdown_maceisa_irq, - .enable = enable_maceisa_irq, - .disable = disable_maceisa_irq, .ack = mask_and_ack_maceisa_irq, + .mask = disable_maceisa_irq, + .mask_ack = mask_and_ack_maceisa_irq, + .unmask = enable_maceisa_irq, .end = end_maceisa_irq, }; @@ -433,29 +361,15 @@ static struct irq_chip ip32_maceisa_interrupt = { static void enable_mace_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); crime->imask = crime_mask; - spin_unlock_irqrestore(&ip32_irq_lock, flags); -} - -static unsigned int startup_mace_irq(unsigned int irq) -{ - enable_mace_irq(irq); - return 0; } static void disable_mace_irq(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); crime->imask = crime_mask; flush_crime_bus(); - spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void end_mace_irq(unsigned int irq) @@ -464,16 +378,12 @@ static void end_mace_irq(unsigned int irq) enable_mace_irq(irq); } -#define shutdown_mace_irq disable_mace_irq -#define mask_and_ack_mace_irq disable_mace_irq - static struct irq_chip ip32_mace_interrupt = { .typename = "IP32 MACE", - .startup = startup_mace_irq, - .shutdown = shutdown_mace_irq, - .enable = enable_mace_irq, - .disable = disable_mace_irq, - .ack = mask_and_ack_mace_irq, + .ack = disable_mace_irq, + .mask = disable_mace_irq, + .mask_ack = disable_mace_irq, + .unmask = enable_mace_irq, .end = end_mace_irq, }; @@ -586,10 +496,7 @@ void __init arch_init_irq(void) else controller = &ip32_maceisa_interrupt; - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 0; - irq_desc[irq].chip = controller; + set_irq_chip(irq, controller); } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 8b1f414..2e8f6b2 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -45,11 +45,9 @@ */ -#define shutdown_bcm1480_irq disable_bcm1480_irq static void end_bcm1480_irq(unsigned int irq); static void enable_bcm1480_irq(unsigned int irq); static void disable_bcm1480_irq(unsigned int irq); -static unsigned int startup_bcm1480_irq(unsigned int irq); static void ack_bcm1480_irq(unsigned int irq); #ifdef CONFIG_SMP static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask); @@ -85,11 +83,10 @@ extern char sb1250_duart_present[]; static struct irq_chip bcm1480_irq_type = { .typename = "BCM1480-IMR", - .startup = startup_bcm1480_irq, - .shutdown = shutdown_bcm1480_irq, - .enable = enable_bcm1480_irq, - .disable = disable_bcm1480_irq, .ack = ack_bcm1480_irq, + .mask = disable_bcm1480_irq, + .mask_ack = ack_bcm1480_irq, + .unmask = enable_bcm1480_irq, .end = end_bcm1480_irq, #ifdef CONFIG_SMP .set_affinity = bcm1480_set_affinity @@ -188,14 +185,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask) /*****************************************************************************/ -static unsigned int startup_bcm1480_irq(unsigned int irq) -{ - bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq); - - return 0; /* never anything pending */ -} - - static void disable_bcm1480_irq(unsigned int irq) { bcm1480_mask_irq(bcm1480_irq_owner[irq], irq); @@ -270,16 +259,9 @@ void __init init_bcm1480_irqs(void) { int i; - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - if (i < BCM1480_NR_IRQS) { - irq_desc[i].chip = &bcm1480_irq_type; - bcm1480_irq_owner[i] = 0; - } else { - irq_desc[i].chip = &no_irq_chip; - } + for (i = 0; i < BCM1480_NR_IRQS; i++) { + set_irq_chip(i, &bcm1480_irq_type); + bcm1480_irq_owner[i] = 0; } } diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index d5d2677..82ce753 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -44,11 +44,9 @@ */ -#define shutdown_sb1250_irq disable_sb1250_irq static void end_sb1250_irq(unsigned int irq); static void enable_sb1250_irq(unsigned int irq); static void disable_sb1250_irq(unsigned int irq); -static unsigned int startup_sb1250_irq(unsigned int irq); static void ack_sb1250_irq(unsigned int irq); #ifdef CONFIG_SMP static void sb1250_set_affinity(unsigned int irq, cpumask_t mask); @@ -70,11 +68,10 @@ extern char sb1250_duart_present[]; static struct irq_chip sb1250_irq_type = { .typename = "SB1250-IMR", - .startup = startup_sb1250_irq, - .shutdown = shutdown_sb1250_irq, - .enable = enable_sb1250_irq, - .disable = disable_sb1250_irq, .ack = ack_sb1250_irq, + .mask = disable_sb1250_irq, + .mask_ack = ack_sb1250_irq, + .unmask = enable_sb1250_irq, .end = end_sb1250_irq, #ifdef CONFIG_SMP .set_affinity = sb1250_set_affinity @@ -163,14 +160,6 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t mask) /*****************************************************************************/ -static unsigned int startup_sb1250_irq(unsigned int irq) -{ - sb1250_unmask_irq(sb1250_irq_owner[irq], irq); - - return 0; /* never anything pending */ -} - - static void disable_sb1250_irq(unsigned int irq) { sb1250_mask_irq(sb1250_irq_owner[irq], irq); @@ -239,16 +228,9 @@ void __init init_sb1250_irqs(void) { int i; - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - if (i < SB1250_NR_IRQS) { - irq_desc[i].chip = &sb1250_irq_type; - sb1250_irq_owner[i] = 0; - } else { - irq_desc[i].chip = &no_irq_chip; - } + for (i = 0; i < SB1250_NR_IRQS; i++) { + set_irq_chip(i, &sb1250_irq_type); + sb1250_irq_owner[i] = 0; } } diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c index 48fb74a..8511bcc 100644 --- a/arch/mips/sni/irq.c +++ b/arch/mips/sni/irq.c @@ -11,44 +11,25 @@ #include #include #include -#include #include #include #include -DEFINE_SPINLOCK(pciasic_lock); - static void enable_pciasic_irq(unsigned int irq) { unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); - unsigned long flags; - spin_lock_irqsave(&pciasic_lock, flags); *(volatile u8 *) PCIMT_IRQSEL |= mask; - spin_unlock_irqrestore(&pciasic_lock, flags); -} - -static unsigned int startup_pciasic_irq(unsigned int irq) -{ - enable_pciasic_irq(irq); - return 0; /* never anything pending */ } -#define shutdown_pciasic_irq disable_pciasic_irq - void disable_pciasic_irq(unsigned int irq) { unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2)); - unsigned long flags; - spin_lock_irqsave(&pciasic_lock, flags); *(volatile u8 *) PCIMT_IRQSEL &= mask; - spin_unlock_irqrestore(&pciasic_lock, flags); } -#define mask_and_ack_pciasic_irq disable_pciasic_irq - static void end_pciasic_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) @@ -57,11 +38,10 @@ static void end_pciasic_irq(unsigned int irq) static struct irq_chip pciasic_irq_type = { .typename = "ASIC-PCI", - .startup = startup_pciasic_irq, - .shutdown = shutdown_pciasic_irq, - .enable = enable_pciasic_irq, - .disable = disable_pciasic_irq, - .ack = mask_and_ack_pciasic_irq, + .ack = disable_pciasic_irq, + .mask = disable_pciasic_irq, + .mask_ack = disable_pciasic_irq, + .unmask = enable_pciasic_irq, .end = end_pciasic_irq, }; @@ -178,12 +158,8 @@ asmlinkage void plat_irq_dispatch(void) void __init init_pciasic(void) { - unsigned long flags; - - spin_lock_irqsave(&pciasic_lock, flags); * (volatile u8 *) PCIMT_IRQSEL = IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD; - spin_unlock_irqrestore(&pciasic_lock, flags); } /* @@ -199,12 +175,8 @@ void __init arch_init_irq(void) init_pciasic(); /* Actually we've got more interrupts to handle ... */ - for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &pciasic_irq_type; - } + for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) + set_irq_chip(i, &pciasic_irq_type); change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4); } diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c index 8266a88..2c57ced 100644 --- a/arch/mips/tx4927/common/tx4927_irq.c +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -64,19 +64,13 @@ #define TX4927_IRQ_NEST4 ( 1 << 9 ) #define TX4927_IRQ_CP0_INIT ( 1 << 10 ) -#define TX4927_IRQ_CP0_STARTUP ( 1 << 11 ) -#define TX4927_IRQ_CP0_SHUTDOWN ( 1 << 12 ) #define TX4927_IRQ_CP0_ENABLE ( 1 << 13 ) #define TX4927_IRQ_CP0_DISABLE ( 1 << 14 ) -#define TX4927_IRQ_CP0_MASK ( 1 << 15 ) #define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 ) #define TX4927_IRQ_PIC_INIT ( 1 << 20 ) -#define TX4927_IRQ_PIC_STARTUP ( 1 << 21 ) -#define TX4927_IRQ_PIC_SHUTDOWN ( 1 << 22 ) #define TX4927_IRQ_PIC_ENABLE ( 1 << 23 ) #define TX4927_IRQ_PIC_DISABLE ( 1 << 24 ) -#define TX4927_IRQ_PIC_MASK ( 1 << 25 ) #define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 ) #define TX4927_IRQ_ALL 0xffffffff @@ -87,18 +81,12 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE | TX4927_IRQ_INFO | TX4927_IRQ_WARN | TX4927_IRQ_EROR // | TX4927_IRQ_CP0_INIT -// | TX4927_IRQ_CP0_STARTUP -// | TX4927_IRQ_CP0_SHUTDOWN // | TX4927_IRQ_CP0_ENABLE // | TX4927_IRQ_CP0_DISABLE -// | TX4927_IRQ_CP0_MASK // | TX4927_IRQ_CP0_ENDIRQ // | TX4927_IRQ_PIC_INIT -// | TX4927_IRQ_PIC_STARTUP -// | TX4927_IRQ_PIC_SHUTDOWN // | TX4927_IRQ_PIC_ENABLE // | TX4927_IRQ_PIC_DISABLE -// | TX4927_IRQ_PIC_MASK // | TX4927_IRQ_PIC_ENDIRQ // | TX4927_IRQ_INIT // | TX4927_IRQ_NEST1 @@ -124,49 +112,36 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE * Forwad definitions for all pic's */ -static unsigned int tx4927_irq_cp0_startup(unsigned int irq); -static void tx4927_irq_cp0_shutdown(unsigned int irq); static void tx4927_irq_cp0_enable(unsigned int irq); static void tx4927_irq_cp0_disable(unsigned int irq); -static void tx4927_irq_cp0_mask_and_ack(unsigned int irq); static void tx4927_irq_cp0_end(unsigned int irq); -static unsigned int tx4927_irq_pic_startup(unsigned int irq); -static void tx4927_irq_pic_shutdown(unsigned int irq); static void tx4927_irq_pic_enable(unsigned int irq); static void tx4927_irq_pic_disable(unsigned int irq); -static void tx4927_irq_pic_mask_and_ack(unsigned int irq); static void tx4927_irq_pic_end(unsigned int irq); /* * Kernel structs for all pic's */ -static DEFINE_SPINLOCK(tx4927_cp0_lock); -static DEFINE_SPINLOCK(tx4927_pic_lock); - #define TX4927_CP0_NAME "TX4927-CP0" static struct irq_chip tx4927_irq_cp0_type = { .typename = TX4927_CP0_NAME, - .startup = tx4927_irq_cp0_startup, - .shutdown = tx4927_irq_cp0_shutdown, - .enable = tx4927_irq_cp0_enable, - .disable = tx4927_irq_cp0_disable, - .ack = tx4927_irq_cp0_mask_and_ack, + .ack = tx4927_irq_cp0_disable, + .mask = tx4927_irq_cp0_disable, + .mask_ack = tx4927_irq_cp0_disable, + .unmask = tx4927_irq_cp0_enable, .end = tx4927_irq_cp0_end, - .set_affinity = NULL }; #define TX4927_PIC_NAME "TX4927-PIC" static struct irq_chip tx4927_irq_pic_type = { .typename = TX4927_PIC_NAME, - .startup = tx4927_irq_pic_startup, - .shutdown = tx4927_irq_pic_shutdown, - .enable = tx4927_irq_pic_enable, - .disable = tx4927_irq_pic_disable, - .ack = tx4927_irq_pic_mask_and_ack, + .ack = tx4927_irq_pic_disable, + .mask = tx4927_irq_pic_disable, + .mask_ack = tx4927_irq_pic_disable, + .unmask = tx4927_irq_pic_enable, .end = tx4927_irq_pic_end, - .set_affinity = NULL }; #define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL } @@ -211,8 +186,6 @@ tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits) break; } } - - return; } static void __init tx4927_irq_cp0_init(void) @@ -222,71 +195,22 @@ static void __init tx4927_irq_cp0_init(void) TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_INIT, "beg=%d end=%d\n", TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END); - for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &tx4927_irq_cp0_type; - } - - return; -} - -static unsigned int tx4927_irq_cp0_startup(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq); - - tx4927_irq_cp0_enable(irq); - - return (0); -} - -static void tx4927_irq_cp0_shutdown(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq); - - tx4927_irq_cp0_disable(irq); - - return; + for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) + set_irq_chip(i, &tx4927_irq_cp0_type); } static void tx4927_irq_cp0_enable(unsigned int irq) { - unsigned long flags; - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq); - spin_lock_irqsave(&tx4927_cp0_lock, flags); - tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq)); - - spin_unlock_irqrestore(&tx4927_cp0_lock, flags); - - return; } static void tx4927_irq_cp0_disable(unsigned int irq) { - unsigned long flags; - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq); - spin_lock_irqsave(&tx4927_cp0_lock, flags); - tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); - - spin_unlock_irqrestore(&tx4927_cp0_lock, flags); - - return; -} - -static void tx4927_irq_cp0_mask_and_ack(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq); - - tx4927_irq_cp0_disable(irq); - - return; } static void tx4927_irq_cp0_end(unsigned int irq) @@ -296,8 +220,6 @@ static void tx4927_irq_cp0_end(unsigned int irq) if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { tx4927_irq_cp0_enable(irq); } - - return; } /* @@ -418,94 +340,38 @@ static void tx4927_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, val &= (~clr_bits); val |= (set_bits); TX4927_WR(pic_reg, val); - - return; } static void __init tx4927_irq_pic_init(void) { - unsigned long flags; int i; TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_INIT, "beg=%d end=%d\n", TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END); - for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 2; - irq_desc[i].chip = &tx4927_irq_pic_type; - } + for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) + set_irq_chip(i, &tx4927_irq_pic_type); setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action); - spin_lock_irqsave(&tx4927_pic_lock, flags); - TX4927_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */ TX4927_WR(0xff1ff600, TX4927_RD(0xff1ff600) | 0x1); /* irq enable */ - - spin_unlock_irqrestore(&tx4927_pic_lock, flags); - - return; -} - -static unsigned int tx4927_irq_pic_startup(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq); - - tx4927_irq_pic_enable(irq); - - return (0); -} - -static void tx4927_irq_pic_shutdown(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq); - - tx4927_irq_pic_disable(irq); - - return; } static void tx4927_irq_pic_enable(unsigned int irq) { - unsigned long flags; - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq); - spin_lock_irqsave(&tx4927_pic_lock, flags); - tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0, tx4927_irq_pic_mask(irq)); - - spin_unlock_irqrestore(&tx4927_pic_lock, flags); - - return; } static void tx4927_irq_pic_disable(unsigned int irq) { - unsigned long flags; - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq); - spin_lock_irqsave(&tx4927_pic_lock, flags); - tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), tx4927_irq_pic_mask(irq), 0); - - spin_unlock_irqrestore(&tx4927_pic_lock, flags); - - return; -} - -static void tx4927_irq_pic_mask_and_ack(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq); - - tx4927_irq_pic_disable(irq); - - return; } static void tx4927_irq_pic_end(unsigned int irq) @@ -515,8 +381,6 @@ static void tx4927_irq_pic_end(unsigned int irq) if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { tx4927_irq_pic_enable(irq); } - - return; } /* @@ -533,8 +397,6 @@ void __init tx4927_irq_init(void) tx4927_irq_pic_init(); TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n"); - - return; } static int tx4927_irq_nested(void) diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index 0c3c3f6..1fdace8 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -151,16 +151,11 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB #define TOSHIBA_RBTX4927_IRQ_EROR ( 1 << 2 ) #define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 ) -#define TOSHIBA_RBTX4927_IRQ_IOC_STARTUP ( 1 << 11 ) -#define TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN ( 1 << 12 ) #define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 ) #define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 ) -#define TOSHIBA_RBTX4927_IRQ_IOC_MASK ( 1 << 15 ) #define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 ) #define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 ) -#define TOSHIBA_RBTX4927_IRQ_ISA_STARTUP ( 1 << 21 ) -#define TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN ( 1 << 22 ) #define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 ) #define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE ( 1 << 24 ) #define TOSHIBA_RBTX4927_IRQ_ISA_MASK ( 1 << 25 ) @@ -175,15 +170,10 @@ static const u32 toshiba_rbtx4927_irq_debug_flag = (TOSHIBA_RBTX4927_IRQ_NONE | TOSHIBA_RBTX4927_IRQ_INFO | TOSHIBA_RBTX4927_IRQ_WARN | TOSHIBA_RBTX4927_IRQ_EROR // | TOSHIBA_RBTX4927_IRQ_IOC_INIT -// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP -// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN // | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE // | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE -// | TOSHIBA_RBTX4927_IRQ_IOC_MASK // | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ // | TOSHIBA_RBTX4927_IRQ_ISA_INIT -// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP -// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN // | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE // | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE // | TOSHIBA_RBTX4927_IRQ_ISA_MASK @@ -231,35 +221,25 @@ extern void disable_8259A_irq(unsigned int irq); extern void mask_and_ack_8259A(unsigned int irq); #endif -static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq); -static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq); #ifdef CONFIG_TOSHIBA_FPCIB0 -static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq); -static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq); static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq); static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq); static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq); static void toshiba_rbtx4927_irq_isa_end(unsigned int irq); #endif -static DEFINE_SPINLOCK(toshiba_rbtx4927_ioc_lock); - - #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { .typename = TOSHIBA_RBTX4927_IOC_NAME, - .startup = toshiba_rbtx4927_irq_ioc_startup, - .shutdown = toshiba_rbtx4927_irq_ioc_shutdown, - .enable = toshiba_rbtx4927_irq_ioc_enable, - .disable = toshiba_rbtx4927_irq_ioc_disable, - .ack = toshiba_rbtx4927_irq_ioc_mask_and_ack, + .ack = toshiba_rbtx4927_irq_ioc_disable, + .mask = toshiba_rbtx4927_irq_ioc_disable, + .mask_ack = toshiba_rbtx4927_irq_ioc_disable, + .unmask = toshiba_rbtx4927_irq_ioc_enable, .end = toshiba_rbtx4927_irq_ioc_end, - .set_affinity = NULL }; #define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000 #define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006 @@ -269,13 +249,11 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { #define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA" static struct irq_chip toshiba_rbtx4927_irq_isa_type = { .typename = TOSHIBA_RBTX4927_ISA_NAME, - .startup = toshiba_rbtx4927_irq_isa_startup, - .shutdown = toshiba_rbtx4927_irq_isa_shutdown, - .enable = toshiba_rbtx4927_irq_isa_enable, - .disable = toshiba_rbtx4927_irq_isa_disable, .ack = toshiba_rbtx4927_irq_isa_mask_and_ack, + .mask = toshiba_rbtx4927_irq_isa_disable, + .mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack, + .unmask = toshiba_rbtx4927_irq_isa_enable, .end = toshiba_rbtx4927_irq_isa_end, - .set_affinity = NULL }; #endif @@ -363,58 +341,15 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void) TOSHIBA_RBTX4927_IRQ_IOC_END); for (i = TOSHIBA_RBTX4927_IRQ_IOC_BEG; - i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 3; - irq_desc[i].chip = &toshiba_rbtx4927_irq_ioc_type; - } + i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) + set_irq_chip(i, &toshiba_rbtx4927_irq_ioc_type); setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC, &toshiba_rbtx4927_irq_ioc_action); - - return; } -static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_STARTUP, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG - || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - toshiba_rbtx4927_irq_ioc_enable(irq); - - return (0); -} - - -static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG - || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - toshiba_rbtx4927_irq_ioc_disable(irq); - - return; -} - - static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq) { - unsigned long flags; volatile unsigned char v; TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENABLE, @@ -427,21 +362,14 @@ static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq) panic("\n"); } - spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags); - v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB); v |= (1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG)); TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); - - spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags); - - return; } static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) { - unsigned long flags; volatile unsigned char v; TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_DISABLE, @@ -454,36 +382,11 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) panic("\n"); } - spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags); - v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB); v &= ~(1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG)); TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); - - spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags); - - return; } - -static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_MASK, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG - || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - toshiba_rbtx4927_irq_ioc_disable(irq); - - return; -} - - static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq) { TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ, @@ -499,8 +402,6 @@ static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq) if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { toshiba_rbtx4927_irq_ioc_enable(irq); } - - return; } @@ -520,13 +421,8 @@ static void __init toshiba_rbtx4927_irq_isa_init(void) TOSHIBA_RBTX4927_IRQ_ISA_END); for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG; - i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = - ((i < TOSHIBA_RBTX4927_IRQ_ISA_MID) ? (4) : (5)); - irq_desc[i].chip = &toshiba_rbtx4927_irq_isa_type; - } + i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++) + set_irq_chip(i, &toshiba_rbtx4927_irq_isa_type); setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC, &toshiba_rbtx4927_irq_isa_master); @@ -536,48 +432,6 @@ static void __init toshiba_rbtx4927_irq_isa_init(void) /* make sure we are looking at IRR (not ISR) */ outb(0x0A, 0x20); outb(0x0A, 0xA0); - - return; -} -#endif - - -#ifdef CONFIG_TOSHIBA_FPCIB0 -static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_STARTUP, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG - || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - toshiba_rbtx4927_irq_isa_enable(irq); - - return (0); -} -#endif - - -#ifdef CONFIG_TOSHIBA_FPCIB0 -static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG - || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - toshiba_rbtx4927_irq_isa_disable(irq); - - return; } #endif @@ -596,8 +450,6 @@ static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq) } enable_8259A_irq(irq); - - return; } #endif @@ -616,8 +468,6 @@ static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq) } disable_8259A_irq(irq); - - return; } #endif @@ -636,8 +486,6 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq) } mask_and_ack_8259A(irq); - - return; } #endif @@ -658,8 +506,6 @@ static void toshiba_rbtx4927_irq_isa_end(unsigned int irq) if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { toshiba_rbtx4927_irq_isa_enable(irq); } - - return; } #endif @@ -668,8 +514,6 @@ void __init arch_init_irq(void) { extern void tx4927_irq_init(void); - local_irq_disable(); - tx4927_irq_init(); toshiba_rbtx4927_irq_ioc_init(); #ifdef CONFIG_TOSHIBA_FPCIB0 @@ -681,8 +525,6 @@ void __init arch_init_irq(void) #endif wbflush(); - - return; } void toshiba_rbtx4927_irq_dump(char *key) @@ -715,7 +557,6 @@ void toshiba_rbtx4927_irq_dump(char *key) } } #endif - return; } void toshiba_rbtx4927_irq_dump_pics(char *s) @@ -780,6 +621,4 @@ void toshiba_rbtx4927_irq_dump_pics(char *s) level5_s); TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, "[%s]\n", s); - - return; } diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c index 77fe245..19c9ee9 100644 --- a/arch/mips/tx4938/common/irq.c +++ b/arch/mips/tx4938/common/irq.c @@ -37,48 +37,36 @@ /* Forwad definitions for all pic's */ /**********************************************************************************/ -static unsigned int tx4938_irq_cp0_startup(unsigned int irq); -static void tx4938_irq_cp0_shutdown(unsigned int irq); static void tx4938_irq_cp0_enable(unsigned int irq); static void tx4938_irq_cp0_disable(unsigned int irq); -static void tx4938_irq_cp0_mask_and_ack(unsigned int irq); static void tx4938_irq_cp0_end(unsigned int irq); -static unsigned int tx4938_irq_pic_startup(unsigned int irq); -static void tx4938_irq_pic_shutdown(unsigned int irq); static void tx4938_irq_pic_enable(unsigned int irq); static void tx4938_irq_pic_disable(unsigned int irq); -static void tx4938_irq_pic_mask_and_ack(unsigned int irq); static void tx4938_irq_pic_end(unsigned int irq); /**********************************************************************************/ /* Kernel structs for all pic's */ /**********************************************************************************/ -DEFINE_SPINLOCK(tx4938_cp0_lock); -DEFINE_SPINLOCK(tx4938_pic_lock); #define TX4938_CP0_NAME "TX4938-CP0" static struct irq_chip tx4938_irq_cp0_type = { .typename = TX4938_CP0_NAME, - .startup = tx4938_irq_cp0_startup, - .shutdown = tx4938_irq_cp0_shutdown, - .enable = tx4938_irq_cp0_enable, - .disable = tx4938_irq_cp0_disable, - .ack = tx4938_irq_cp0_mask_and_ack, + .ack = tx4938_irq_cp0_disable, + .mask = tx4938_irq_cp0_disable, + .mask_ack = tx4938_irq_cp0_disable, + .unmask = tx4938_irq_cp0_enable, .end = tx4938_irq_cp0_end, - .set_affinity = NULL }; #define TX4938_PIC_NAME "TX4938-PIC" static struct irq_chip tx4938_irq_pic_type = { .typename = TX4938_PIC_NAME, - .startup = tx4938_irq_pic_startup, - .shutdown = tx4938_irq_pic_shutdown, - .enable = tx4938_irq_pic_enable, - .disable = tx4938_irq_pic_disable, - .ack = tx4938_irq_pic_mask_and_ack, + .ack = tx4938_irq_pic_disable, + .mask = tx4938_irq_pic_disable, + .mask_ack = tx4938_irq_pic_disable, + .unmask = tx4938_irq_pic_enable, .end = tx4938_irq_pic_end, - .set_affinity = NULL }; static struct irqaction tx4938_irq_pic_action = { @@ -99,56 +87,20 @@ tx4938_irq_cp0_init(void) { int i; - for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].chip = &tx4938_irq_cp0_type; - } -} - -static unsigned int -tx4938_irq_cp0_startup(unsigned int irq) -{ - tx4938_irq_cp0_enable(irq); - - return 0; -} - -static void -tx4938_irq_cp0_shutdown(unsigned int irq) -{ - tx4938_irq_cp0_disable(irq); + for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) + set_irq_chip(i, &tx4938_irq_cp0_type); } static void tx4938_irq_cp0_enable(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&tx4938_cp0_lock, flags); - set_c0_status(tx4938_irq_cp0_mask(irq)); - - spin_unlock_irqrestore(&tx4938_cp0_lock, flags); } static void tx4938_irq_cp0_disable(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&tx4938_cp0_lock, flags); - clear_c0_status(tx4938_irq_cp0_mask(irq)); - - spin_unlock_irqrestore(&tx4938_cp0_lock, flags); -} - -static void -tx4938_irq_cp0_mask_and_ack(unsigned int irq) -{ - tx4938_irq_cp0_disable(irq); } static void @@ -290,70 +242,29 @@ tx4938_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, unsigned set_bits) static void __init tx4938_irq_pic_init(void) { - unsigned long flags; int i; - for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 2; - irq_desc[i].chip = &tx4938_irq_pic_type; - } + for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) + set_irq_chip(i, &tx4938_irq_pic_type); setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action); - spin_lock_irqsave(&tx4938_pic_lock, flags); - TX4938_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */ TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1); /* irq enable */ - - spin_unlock_irqrestore(&tx4938_pic_lock, flags); -} - -static unsigned int -tx4938_irq_pic_startup(unsigned int irq) -{ - tx4938_irq_pic_enable(irq); - - return 0; -} - -static void -tx4938_irq_pic_shutdown(unsigned int irq) -{ - tx4938_irq_pic_disable(irq); } static void tx4938_irq_pic_enable(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&tx4938_pic_lock, flags); - tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), 0, tx4938_irq_pic_mask(irq)); - - spin_unlock_irqrestore(&tx4938_pic_lock, flags); } static void tx4938_irq_pic_disable(unsigned int irq) { - unsigned long flags; - - spin_lock_irqsave(&tx4938_pic_lock, flags); - tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), tx4938_irq_pic_mask(irq), 0); - - spin_unlock_irqrestore(&tx4938_pic_lock, flags); -} - -static void -tx4938_irq_pic_mask_and_ack(unsigned int irq) -{ - tx4938_irq_pic_disable(irq); } static void diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 102e473..2735ffe 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -87,25 +87,18 @@ IRQ Device #include #include -static unsigned int toshiba_rbtx4938_irq_ioc_startup(unsigned int irq); -static void toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq); static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq); static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq); -DEFINE_SPINLOCK(toshiba_rbtx4938_ioc_lock); - #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { .typename = TOSHIBA_RBTX4938_IOC_NAME, - .startup = toshiba_rbtx4938_irq_ioc_startup, - .shutdown = toshiba_rbtx4938_irq_ioc_shutdown, - .enable = toshiba_rbtx4938_irq_ioc_enable, - .disable = toshiba_rbtx4938_irq_ioc_disable, - .ack = toshiba_rbtx4938_irq_ioc_mask_and_ack, + .ack = toshiba_rbtx4938_irq_ioc_disable, + .mask = toshiba_rbtx4938_irq_ioc_disable, + .mask_ack = toshiba_rbtx4938_irq_ioc_disable, + .unmask = toshiba_rbtx4938_irq_ioc_enable, .end = toshiba_rbtx4938_irq_ioc_end, - .set_affinity = NULL }; #define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000 @@ -142,69 +135,35 @@ toshiba_rbtx4938_irq_ioc_init(void) int i; for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG; - i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 3; - irq_desc[i].chip = &toshiba_rbtx4938_irq_ioc_type; - } + i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) + set_irq_chip(i, &toshiba_rbtx4938_irq_ioc_type); setup_irq(RBTX4938_IRQ_IOCINT, &toshiba_rbtx4938_irq_ioc_action); } -static unsigned int -toshiba_rbtx4938_irq_ioc_startup(unsigned int irq) -{ - toshiba_rbtx4938_irq_ioc_enable(irq); - - return 0; -} - -static void -toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq) -{ - toshiba_rbtx4938_irq_ioc_disable(irq); -} - static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq) { - unsigned long flags; volatile unsigned char v; - spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags); - v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG)); TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v); mmiowb(); TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); - - spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags); } static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) { - unsigned long flags; volatile unsigned char v; - spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags); - v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG)); TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v); mmiowb(); TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); - - spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags); -} - -static void -toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq) -{ - toshiba_rbtx4938_irq_ioc_disable(irq); } static void diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index c215c0d..33d70a6 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -417,14 +417,7 @@ void vr41xx_disable_bcuint(void) EXPORT_SYMBOL(vr41xx_disable_bcuint); -static unsigned int startup_sysint1_irq(unsigned int irq) -{ - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); - - return 0; /* never anything pending */ -} - -static void shutdown_sysint1_irq(unsigned int irq) +static void disable_sysint1_irq(unsigned int irq) { icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } @@ -434,9 +427,6 @@ static void enable_sysint1_irq(unsigned int irq) icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } -#define disable_sysint1_irq shutdown_sysint1_irq -#define ack_sysint1_irq shutdown_sysint1_irq - static void end_sysint1_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -445,22 +435,14 @@ static void end_sysint1_irq(unsigned int irq) static struct irq_chip sysint1_irq_type = { .typename = "SYSINT1", - .startup = startup_sysint1_irq, - .shutdown = shutdown_sysint1_irq, - .enable = enable_sysint1_irq, - .disable = disable_sysint1_irq, - .ack = ack_sysint1_irq, + .ack = disable_sysint1_irq, + .mask = disable_sysint1_irq, + .mask_ack = disable_sysint1_irq, + .unmask = enable_sysint1_irq, .end = end_sysint1_irq, }; -static unsigned int startup_sysint2_irq(unsigned int irq) -{ - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); - - return 0; /* never anything pending */ -} - -static void shutdown_sysint2_irq(unsigned int irq) +static void disable_sysint2_irq(unsigned int irq) { icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } @@ -470,9 +452,6 @@ static void enable_sysint2_irq(unsigned int irq) icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } -#define disable_sysint2_irq shutdown_sysint2_irq -#define ack_sysint2_irq shutdown_sysint2_irq - static void end_sysint2_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) @@ -481,11 +460,10 @@ static void end_sysint2_irq(unsigned int irq) static struct irq_chip sysint2_irq_type = { .typename = "SYSINT2", - .startup = startup_sysint2_irq, - .shutdown = shutdown_sysint2_irq, - .enable = enable_sysint2_irq, - .disable = disable_sysint2_irq, - .ack = ack_sysint2_irq, + .ack = disable_sysint2_irq, + .mask = disable_sysint2_irq, + .mask_ack = disable_sysint2_irq, + .unmask = enable_sysint2_irq, .end = end_sysint2_irq, }; @@ -723,10 +701,10 @@ static int __init vr41xx_icu_init(void) icu2_write(MGIUINTHREG, 0xffff); for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) - irq_desc[i].chip = &sysint1_irq_type; + set_irq_chip(i, &sysint1_irq_type); for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) - irq_desc[i].chip = &sysint2_irq_type; + set_irq_chip(i, &sysint2_irq_type); cascade_irq(INT0_IRQ, icu_get_irq); cascade_irq(INT1_IRQ, icu_get_irq); diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c index 2483487..a039bb7 100644 --- a/arch/mips/vr41xx/nec-cmbvr4133/irq.c +++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c @@ -30,17 +30,6 @@ extern void init_8259A(int hoge); extern int vr4133_rockhopper; -static unsigned int startup_i8259_irq(unsigned int irq) -{ - enable_8259A_irq(irq - I8259_IRQ_BASE); - return 0; -} - -static void shutdown_i8259_irq(unsigned int irq) -{ - disable_8259A_irq(irq - I8259_IRQ_BASE); -} - static void enable_i8259_irq(unsigned int irq) { enable_8259A_irq(irq - I8259_IRQ_BASE); @@ -64,11 +53,10 @@ static void end_i8259_irq(unsigned int irq) static struct irq_chip i8259_irq_type = { .typename = "XT-PIC", - .startup = startup_i8259_irq, - .shutdown = shutdown_i8259_irq, - .enable = enable_i8259_irq, - .disable = disable_i8259_irq, .ack = ack_i8259_irq, + .mask = disable_i8259_irq, + .mask_ack = ack_i8259_irq, + .unmask = enable_i8259_irq, .end = end_i8259_irq, }; @@ -104,7 +92,7 @@ void __init rockhopper_init_irq(void) } for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++) - irq_desc[i].chip = &i8259_irq_type; + set_irq_chip(i, &i8259_irq_type); setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade); diff --git a/include/asm-mips/dec/kn02.h b/include/asm-mips/dec/kn02.h index 8319ad7..93430b5 100644 --- a/include/asm-mips/dec/kn02.h +++ b/include/asm-mips/dec/kn02.h @@ -82,11 +82,9 @@ #ifndef __ASSEMBLY__ -#include #include extern u32 cached_kn02_csr; -extern spinlock_t kn02_lock; extern void init_kn02_irqs(int base); #endif -- cgit v0.10.2 From 1417836e81c0ab8f5a0bfeafa90d3eaa41b2a067 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 14 Nov 2006 01:13:18 +0900 Subject: [MIPS] use generic_handle_irq, handle_level_irq, handle_percpu_irq Further incorporation of generic irq framework. Replacing __do_IRQ() by proper flow handler would make the irq handling path a bit simpler and faster. * use generic_handle_irq() instead of __do_IRQ(). * use handle_level_irq for obvious level-type irq chips. * use handle_percpu_irq for irqs marked as IRQ_PER_CPU. * setup .eoi routine for irq chips possibly used with handle_percpu_irq. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c index d0af08b..269b22b 100644 --- a/arch/mips/dec/ioasic-irq.c +++ b/arch/mips/dec/ioasic-irq.c @@ -103,9 +103,11 @@ void __init init_ioasic_irqs(int base) fast_iob(); for (i = base; i < base + IO_INR_DMA; i++) - set_irq_chip(i, &ioasic_irq_type); + set_irq_chip_and_handler(i, &ioasic_irq_type, + handle_level_irq); for (; i < base + IO_IRQ_LINES; i++) - set_irq_chip(i, &ioasic_dma_irq_type); + set_irq_chip_and_handler(i, &ioasic_dma_irq_type, + handle_level_irq); ioasic_irq_base = base; } diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c index c761d97..5a9be4c 100644 --- a/arch/mips/dec/kn02-irq.c +++ b/arch/mips/dec/kn02-irq.c @@ -85,7 +85,7 @@ void __init init_kn02_irqs(int base) iob(); for (i = base; i < base + KN02_IRQ_LINES; i++) - set_irq_chip(i, &kn02_irq_type); + set_irq_chip_and_handler(i, &kn02_irq_type, handle_level_irq); kn02_irq_base = base; } diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index bf1b83b..59b9829 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -76,7 +76,8 @@ void emma2rh_irq_init(u32 irq_base) u32 i; for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) - set_irq_chip(i, &emma2rh_irq_controller); + set_irq_chip_and_handler(i, &emma2rh_irq_controller, + handle_level_irq); emma2rh_irq_base = irq_base; } diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index 8e5f08a..3ac4e40 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -68,7 +68,8 @@ void emma2rh_sw_irq_init(u32 irq_base) u32 i; for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) - set_irq_chip(i, &emma2rh_sw_irq_controller); + set_irq_chip_and_handler(i, &emma2rh_sw_irq_controller, + handle_level_irq); emma2rh_sw_irq_base = irq_base; } diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index 4bbb6cb..5c4f50c 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -59,7 +59,7 @@ void __init init_r4030_ints(void) int i; for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) - set_irq_chip(i, &r4030_irq_type); + set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq); r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c index e1880b2..bcaad66 100644 --- a/arch/mips/kernel/irq-msc01.c +++ b/arch/mips/kernel/irq-msc01.c @@ -117,6 +117,7 @@ struct irq_chip msc_levelirq_type = { .mask = mask_msc_irq, .mask_ack = level_mask_and_ack_msc_irq, .unmask = unmask_msc_irq, + .eoi = unmask_msc_irq, .end = end_msc_irq, }; @@ -126,6 +127,7 @@ struct irq_chip msc_edgeirq_type = { .mask = mask_msc_irq, .mask_ack = edge_mask_and_ack_msc_irq, .unmask = unmask_msc_irq, + .eoi = unmask_msc_irq, .end = end_msc_irq, }; diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index 5012b9d..6cfb31c 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c @@ -114,7 +114,8 @@ void __init mv64340_irq_init(unsigned int base) int i; for (i = base; i < base + 64; i++) - set_irq_chip(i, &mv64340_irq_type); + set_irq_chip_and_handler(i, &mv64340_irq_type, + handle_level_irq); irq_base = base; } diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index 6a297e3..ddcc2a5 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -51,7 +51,8 @@ void __init rm7k_cpu_irq_init(int base) clear_c0_intcontrol(0x00000f00); /* Mask all */ for (i = base; i < base + 4; i++) - set_irq_chip(i, &rm7k_irq_controller); + set_irq_chip_and_handler(i, &rm7k_irq_controller, + handle_level_irq); irq_base = base; } diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index 9775384..ba6440c 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -117,10 +117,12 @@ void __init rm9k_cpu_irq_init(int base) clear_c0_intcontrol(0x0000f000); /* Mask all */ for (i = base; i < base + 4; i++) - set_irq_chip(i, &rm9k_irq_controller); + set_irq_chip_and_handler(i, &rm9k_irq_controller, + handle_level_irq); rm9000_perfcount_irq = base + 1; - set_irq_chip(rm9000_perfcount_irq, &rm9k_perfcounter_irq); + set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq, + handle_level_irq); irq_base = base; } diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 3b7cfa4..be5ac23 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -62,6 +62,7 @@ static struct irq_chip mips_cpu_irq_controller = { .mask = mask_mips_irq, .mask_ack = mask_mips_irq, .unmask = unmask_mips_irq, + .eoi = unmask_mips_irq, .end = mips_cpu_irq_end, }; @@ -104,6 +105,7 @@ static struct irq_chip mips_mt_cpu_irq_controller = { .mask = mask_mips_mt_irq, .mask_ack = mips_mt_cpu_irq_ack, .unmask = unmask_mips_mt_irq, + .eoi = unmask_mips_mt_irq, .end = mips_mt_cpu_irq_end, }; @@ -124,7 +126,8 @@ void __init mips_cpu_irq_init(int irq_base) set_irq_chip(i, &mips_mt_cpu_irq_controller); for (i = irq_base + 2; i < irq_base + 8; i++) - set_irq_chip(i, &mips_cpu_irq_controller); + set_irq_chip_and_handler(i, &mips_cpu_irq_controller, + handle_level_irq); mips_cpu_irq_base = irq_base; } diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 2ac19a6c..1ee689c 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -278,7 +278,9 @@ void __init plat_prepare_cpus(unsigned int max_cpus) /* need to mark IPI's as IRQ_PER_CPU */ irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU; + set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU; + set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); } /* diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 3b78caf..802febe 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -1009,6 +1009,7 @@ void setup_cross_vpe_interrupts(void) setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ)); irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU; + set_irq_handler(cpu_ipi_irq, handle_percpu_irq); } /* diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index cac82af..4a84a7b 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -133,5 +133,5 @@ void __init arch_init_irq(void) } for (i = 0; i <= LASATINT_END; i++) - set_irq_chip(i, &lasat_irq_type); + set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq); } diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c index 7c71004..43dba6c 100644 --- a/arch/mips/mips-boards/atlas/atlas_int.c +++ b/arch/mips/mips-boards/atlas/atlas_int.c @@ -74,6 +74,7 @@ static struct irq_chip atlas_irq_type = { .mask = disable_atlas_irq, .mask_ack = disable_atlas_irq, .unmask = enable_atlas_irq, + .eoi = enable_atlas_irq, .end = end_atlas_irq, }; @@ -207,7 +208,7 @@ static inline void init_atlas_irqs (int base) atlas_hw0_icregs->intrsten = 0xffffffff; for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) - set_irq_chip(i, &atlas_irq_type); + set_irq_chip_and_handler(i, &atlas_irq_type, handle_level_irq); } static struct irqaction atlasirq = { diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index d817c60..e4604c7 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -288,6 +288,7 @@ void __init plat_timer_setup(struct irqaction *irq) The effect is that the int remains disabled on the second cpu. Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU; + set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); #endif /* to generate the first timer interrupt */ diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c index 24a4ed0..f2d998d 100644 --- a/arch/mips/mips-boards/sim/sim_time.c +++ b/arch/mips/mips-boards/sim/sim_time.c @@ -203,7 +203,8 @@ void __init plat_timer_setup(struct irqaction *irq) on seperate cpu's the first one tries to handle the second interrupt. The effect is that the int remains disabled on the second cpu. Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ - irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU; + irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU; + set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); #endif /* to generate the first timer interrupt */ diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c index 7723f09..e5a4a0a 100644 --- a/arch/mips/momentum/ocelot_c/cpci-irq.c +++ b/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -106,5 +106,5 @@ void cpci_irq_init(void) int i; for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) - set_irq_chip(i, &cpci_irq_type); + set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq); } diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c index 72faf81..0029f00 100644 --- a/arch/mips/momentum/ocelot_c/uart-irq.c +++ b/arch/mips/momentum/ocelot_c/uart-irq.c @@ -96,6 +96,6 @@ struct irq_chip uart_irq_type = { void uart_irq_init(void) { - set_irq_chip(80, &uart_irq_type); - set_irq_chip(81, &uart_irq_type); + set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq); + set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq); } diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c index e4bf494..0dc2393 100644 --- a/arch/mips/philips/pnx8550/common/int.c +++ b/arch/mips/philips/pnx8550/common/int.c @@ -192,7 +192,7 @@ void __init arch_init_irq(void) int configPR; for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { - set_irq_chip(i, &level_irq_type); + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); mask_irq(i); /* mask the irq just in case */ } @@ -229,7 +229,7 @@ void __init arch_init_irq(void) /* mask/priority is still 0 so we will not get any * interrupts until it is unmasked */ - set_irq_chip(i, &level_irq_type); + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); } /* Priority level 0 */ @@ -238,19 +238,21 @@ void __init arch_init_irq(void) /* Set int vector table address */ PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; - set_irq_chip(MIPS_CPU_GIC_IRQ, &level_irq_type); + set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type, + handle_level_irq); setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); /* init of Timer interrupts */ for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) - set_irq_chip(i, &level_irq_type); + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); /* Stop Timer 1-3 */ configPR = read_c0_config7(); configPR |= 0x00000038; write_c0_config7(configPR); - set_irq_chip(MIPS_CPU_TIMER_IRQ, &level_irq_type); + set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type, + handle_level_irq); setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); } diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index 8e2074b..c7b1380 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -358,7 +358,7 @@ void __init arch_init_irq(void) else handler = &ip22_local3_irq_type; - set_irq_chip(i, handler); + set_irq_chip_and_handler(i, handler, handle_level_irq); } /* vector handler. this register the IRQ as non-sharable */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 8243202..5f8835b 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -352,7 +352,7 @@ static struct irq_chip bridge_irq_type = { void __devinit register_bridge_irq(unsigned int irq) { - set_irq_chip(irq, &bridge_irq_type); + set_irq_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); } int __devinit request_bridge_irq(struct bridge_controller *bc) diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 86ba7fc..e5441c3 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -190,6 +190,7 @@ static struct irq_chip rt_irq_type = { .mask = disable_rt_irq, .mask_ack = disable_rt_irq, .unmask = enable_rt_irq, + .eoi = enable_rt_irq, .end = end_rt_irq, }; @@ -207,7 +208,7 @@ void __init plat_timer_setup(struct irqaction *irq) if (irqno < 0) panic("Can't allocate interrupt number for timer interrupt"); - set_irq_chip(irqno, &rt_irq_type); + set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq); /* over-write the handler, we use our own way */ irq->handler = no_action; diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c index 2c57ced..21873de 100644 --- a/arch/mips/tx4927/common/tx4927_irq.c +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -196,7 +196,8 @@ static void __init tx4927_irq_cp0_init(void) TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END); for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) - set_irq_chip(i, &tx4927_irq_cp0_type); + set_irq_chip_and_handler(i, &tx4927_irq_cp0_type, + handle_level_irq); } static void tx4927_irq_cp0_enable(unsigned int irq) @@ -350,7 +351,8 @@ static void __init tx4927_irq_pic_init(void) TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END); for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) - set_irq_chip(i, &tx4927_irq_pic_type); + set_irq_chip_and_handler(i, &tx4927_irq_pic_type, + handle_level_irq); setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action); diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index 1fdace8..34cdb2a 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -342,7 +342,8 @@ static void __init toshiba_rbtx4927_irq_ioc_init(void) for (i = TOSHIBA_RBTX4927_IRQ_IOC_BEG; i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) - set_irq_chip(i, &toshiba_rbtx4927_irq_ioc_type); + set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type, + handle_level_irq); setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC, &toshiba_rbtx4927_irq_ioc_action); diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c index 19c9ee9..42e1276 100644 --- a/arch/mips/tx4938/common/irq.c +++ b/arch/mips/tx4938/common/irq.c @@ -88,7 +88,8 @@ tx4938_irq_cp0_init(void) int i; for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) - set_irq_chip(i, &tx4938_irq_cp0_type); + set_irq_chip_and_handler(i, &tx4938_irq_cp0_type, + handle_level_irq); } static void @@ -245,7 +246,8 @@ tx4938_irq_pic_init(void) int i; for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) - set_irq_chip(i, &tx4938_irq_pic_type); + set_irq_chip_and_handler(i, &tx4938_irq_pic_type, + handle_level_irq); setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action); diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 2735ffe..8c87a35 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -136,7 +136,8 @@ toshiba_rbtx4938_irq_ioc_init(void) for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG; i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) - set_irq_chip(i, &toshiba_rbtx4938_irq_ioc_type); + set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, + handle_level_irq); setup_irq(RBTX4938_IRQ_IOCINT, &toshiba_rbtx4938_irq_ioc_action); diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 33d70a6..54b92a7 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -701,10 +701,12 @@ static int __init vr41xx_icu_init(void) icu2_write(MGIUINTHREG, 0xffff); for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) - set_irq_chip(i, &sysint1_irq_type); + set_irq_chip_and_handler(i, &sysint1_irq_type, + handle_level_irq); for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) - set_irq_chip(i, &sysint2_irq_type); + set_irq_chip_and_handler(i, &sysint2_irq_type, + handle_level_irq); cascade_irq(INT0_IRQ, icu_get_irq); cascade_irq(INT1_IRQ, icu_get_irq); diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h index 35a05ca..aed3707 100644 --- a/include/asm-mips/irq.h +++ b/include/asm-mips/irq.h @@ -57,7 +57,7 @@ do { \ do { \ irq_enter(); \ __DO_IRQ_SMTC_HOOK(); \ - __do_IRQ((irq)); \ + generic_handle_irq(irq); \ irq_exit(); \ } while (0) -- cgit v0.10.2 From dd6bfd627c4f4df771b9b73e4df75c6c0c177b09 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Tue, 7 Nov 2006 09:56:24 +0100 Subject: [MIPS] Fix double inclusions Signed-off-by: Nicolas Kaiser Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 477c533..a67c185 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -17,7 +17,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c index f2d998d..30711d0 100644 --- a/arch/mips/mips-boards/sim/sim_time.c +++ b/arch/mips/mips-boards/sim/sim_time.c @@ -3,31 +3,24 @@ #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 unsigned long cpu_khz; diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index e136bde..03d5822 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -94,8 +94,6 @@ void bcm1480_time_init(void) */ } -#include - void bcm1480_timer_interrupt(void) { int cpu = smp_processor_id(); diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c index f415a1f..dc87d92 100644 --- a/arch/mips/tx4938/common/setup.c +++ b/arch/mips/tx4938/common/setup.c @@ -31,7 +31,6 @@ #include #include #include -#include #include extern void toshiba_rbtx4938_setup(void); -- cgit v0.10.2 From e56798824456bd907cefe840ca127df0518942e3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:47 +0000 Subject: [MIPS] Work around bogus gcc warnings. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6eccfb4..0ae19e1 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -399,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs) force_sig(SIGBUS, current); } -static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) -{ - unsigned int __user *epc; - - epc = (unsigned int __user *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (!get_user(*opcode, epc)) - return 0; - - force_sig(SIGSEGV, current); - return 1; -} - /* * ll/sc emulation */ @@ -546,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs) { unsigned int opcode; - if (unlikely(get_insn_opcode(regs, &opcode))) - return -EFAULT; + if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; if ((opcode & OPCODE) == LL) { simulate_ll(regs, opcode); @@ -559,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs) } return -EFAULT; /* Strange things going on ... */ + +out_sigsegv: + force_sig(SIGSEGV, current); + return -EFAULT; } /* @@ -571,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs) struct thread_info *ti = task_thread_info(current); unsigned int opcode; - if (unlikely(get_insn_opcode(regs, &opcode))) - return -EFAULT; + if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; if (unlikely(compute_return_epc(regs))) return -EFAULT; @@ -591,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs) /* Not ours. */ return -EFAULT; + +out_sigsegv: + force_sig(SIGSEGV, current); + return -EFAULT; } asmlinkage void do_ov(struct pt_regs *regs) @@ -676,8 +671,8 @@ asmlinkage void do_bp(struct pt_regs *regs) die_if_kernel("Break instruction in kernel code", regs); - if (get_insn_opcode(regs, &opcode)) - return; + if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; /* * There is the ancient bug in the MIPS assemblers that the break @@ -710,6 +705,9 @@ asmlinkage void do_bp(struct pt_regs *regs) default: force_sig(SIGTRAP, current); } + +out_sigsegv: + force_sig(SIGSEGV, current); } asmlinkage void do_tr(struct pt_regs *regs) @@ -719,8 +717,8 @@ asmlinkage void do_tr(struct pt_regs *regs) die_if_kernel("Trap instruction in kernel code", regs); - if (get_insn_opcode(regs, &opcode)) - return; + if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; /* Immediate versions don't provide a code. */ if (!(opcode & OPCODE)) @@ -747,6 +745,9 @@ asmlinkage void do_tr(struct pt_regs *regs) default: force_sig(SIGTRAP, current); } + +out_sigsegv: + force_sig(SIGSEGV, current); } asmlinkage void do_ri(struct pt_regs *regs) -- cgit v0.10.2 From 0550d9d13e02b30efa117d47fcadea450bb23d23 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 22 Aug 2006 21:15:47 +0900 Subject: [MIPS] Remove redundant r4k_blast_icache() calls r4k_flush_cache_all() and r4k_flush_cache_mm() case: these are noop if the CPU did not have dc_aliases. It would mean we do not need to care about icache here. r4k_flush_cache_range case: if r4k_flush_cache_mm() did not need to care about icache, it would be same for this function. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index cc895da..0138cb2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -323,7 +323,6 @@ static void __init r4k_blast_scache_setup(void) static inline void local_r4k_flush_cache_all(void * args) { r4k_blast_dcache(); - r4k_blast_icache(); } static void r4k_flush_cache_all(void) @@ -359,21 +358,19 @@ static void r4k___flush_cache_all(void) static inline void local_r4k_flush_cache_range(void * args) { struct vm_area_struct *vma = args; - int exec; if (!(cpu_context(smp_processor_id(), vma->vm_mm))) return; - exec = vma->vm_flags & VM_EXEC; - if (cpu_has_dc_aliases || exec) - r4k_blast_dcache(); - if (exec) - r4k_blast_icache(); + r4k_blast_dcache(); } static void r4k_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { + if (!cpu_has_dc_aliases) + return; + r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); } @@ -385,7 +382,6 @@ static inline void local_r4k_flush_cache_mm(void * args) return; r4k_blast_dcache(); - r4k_blast_icache(); /* * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we -- cgit v0.10.2 From 617667ba724d46ffeccb88ee99e1379f29b0bfa7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:48 +0000 Subject: [MIPS] Avoid dupliate D-cache flush on R400C / R4400 SC and MC variants. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 0138cb2..df04a31 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -381,17 +381,21 @@ static inline void local_r4k_flush_cache_mm(void * args) if (!cpu_context(smp_processor_id(), mm)) return; - r4k_blast_dcache(); - /* * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we * only flush the primary caches but R10000 and R12000 behave sane ... + * R4000SC and R4400SC indexed S-cache ops also invalidate primary + * caches, so we can bail out early. */ if (current_cpu_data.cputype == CPU_R4000SC || current_cpu_data.cputype == CPU_R4000MC || current_cpu_data.cputype == CPU_R4400SC || - current_cpu_data.cputype == CPU_R4400MC) + current_cpu_data.cputype == CPU_R4400MC) { r4k_blast_scache(); + return; + } + + r4k_blast_dcache(); } static void r4k_flush_cache_mm(struct mm_struct *mm) -- cgit v0.10.2 From 187933f23679c413706030aefad9e85e79164c44 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 25 Oct 2006 23:57:04 +0900 Subject: [MIPS] do_IRQ cleanup Now we have both function and macro version of do_IRQ() and the former is used only by DEC and non-preemptive kernel. This patch makes everyone use the macro version and removes the function version. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S index 31dd47d..b251ef8 100644 --- a/arch/mips/dec/int-handler.S +++ b/arch/mips/dec/int-handler.S @@ -267,7 +267,7 @@ handle_it: LONG_L s0, TI_REGS($28) LONG_S sp, TI_REGS($28) PTR_LA ra, ret_from_irq - j do_IRQ + j dec_irq_dispatch nop #ifdef CONFIG_32BIT diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 6b7481e..d34032a 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -761,3 +761,9 @@ void __init arch_init_irq(void) if (dec_interrupt[DEC_IRQ_HALT] >= 0) setup_irq(dec_interrupt[DEC_IRQ_HALT], &haltirq); } + +asmlinkage unsigned int dec_irq_dispatch(unsigned int irq) +{ + do_IRQ(irq); + return 0; +} diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index e997c94..b339798 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -88,25 +88,6 @@ atomic_t irq_err_count; unsigned long irq_hwmask[NR_IRQS]; #endif /* CONFIG_MIPS_MT_SMTC */ -#undef do_IRQ - -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -asmlinkage unsigned int do_IRQ(unsigned int irq) -{ - irq_enter(); - - __DO_IRQ_SMTC_HOOK(); - __do_IRQ(irq); - - irq_exit(); - - return 1; -} - /* * Generic, controller-independent functions: */ diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h index aed3707..6765708 100644 --- a/include/asm-mips/irq.h +++ b/include/asm-mips/irq.h @@ -24,8 +24,6 @@ static inline int irq_canonicalize(int irq) #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ #endif -extern asmlinkage unsigned int do_IRQ(unsigned int irq); - #ifdef CONFIG_MIPS_MT_SMTC /* * Clear interrupt mask handling "backstop" if irq_hwmask @@ -43,8 +41,6 @@ do { \ #define __DO_IRQ_SMTC_HOOK() do { } while (0) #endif -#ifdef CONFIG_PREEMPT - /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific @@ -61,8 +57,6 @@ do { \ irq_exit(); \ } while (0) -#endif - extern void arch_init_irq(void); extern void spurious_interrupt(void); -- cgit v0.10.2 From 005985609ff72df3257fde6b29aa9d71342c2a6b Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 12 Nov 2006 00:10:28 +0900 Subject: [MIPS] mips HPT cleanup: make clocksource_mips public Make clocksource_mips public and get rid of mips_hpt_read, mips_hpt_mask. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 69e424e..8b7e0c1 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -151,7 +151,7 @@ static void dec_timer_ack(void) CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ } -static unsigned int dec_ioasic_hpt_read(void) +static cycle_t dec_ioasic_hpt_read(void) { /* * The free-running counter is 32-bit which is good for about @@ -171,7 +171,7 @@ void __init dec_time_init(void) if (!cpu_has_counter && IOASIC) /* For pre-R4k systems we use the I/O ASIC's counter. */ - mips_hpt_read = dec_ioasic_hpt_read; + clocksource_mips.read = dec_ioasic_hpt_read; /* Set up the rate of periodic DS1287 interrupts. */ CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 16e5dfe..138f25e 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -170,7 +170,7 @@ static void jmr3927_machine_power_off(void) while (1); } -static unsigned int jmr3927_hpt_read(void) +static cycle_t jmr3927_hpt_read(void) { /* We assume this function is called xtime_lock held. */ return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; @@ -182,7 +182,7 @@ extern void rtc_ds1742_init(unsigned long base); #endif static void __init jmr3927_time_init(void) { - mips_hpt_read = jmr3927_hpt_read; + clocksource_mips.read = jmr3927_hpt_read; mips_hpt_frequency = JMR3927_TIMER_CLK; #ifdef USE_RTC_DS1742 if (jmr3927_have_nvram()) { diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 111d1ba..11aab6d 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -11,7 +11,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include @@ -83,7 +82,7 @@ static void null_timer_ack(void) { /* nothing */ } /* * Null high precision timer functions for systems lacking one. */ -static unsigned int null_hpt_read(void) +static cycle_t null_hpt_read(void) { return 0; } @@ -112,7 +111,7 @@ static void c0_timer_ack(void) /* * High precision timer functions for a R4k-compatible timer. */ -static unsigned int c0_hpt_read(void) +static cycle_t c0_hpt_read(void) { return read_c0_count(); } @@ -126,8 +125,6 @@ static void __init c0_hpt_timer_init(void) int (*mips_timer_state)(void); void (*mips_timer_ack)(void); -unsigned int (*mips_hpt_read)(void); -unsigned int mips_hpt_mask = 0xffffffff; /* last time when xtime and rtc are sync'ed up */ static long last_rtc_update; @@ -269,8 +266,7 @@ static struct irqaction timer_irqaction = { static unsigned int __init calibrate_hpt(void) { - u64 frequency; - u32 hpt_start, hpt_end, hpt_count, hz; + cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; const int loops = HZ / 10; int log_2_loops = 0; @@ -296,28 +292,23 @@ static unsigned int __init calibrate_hpt(void) * during the calculated number of periods between timer * interrupts. */ - hpt_start = mips_hpt_read(); + hpt_start = clocksource_mips.read(); do { while (mips_timer_state()); while (!mips_timer_state()); } while (--i); - hpt_end = mips_hpt_read(); + hpt_end = clocksource_mips.read(); - hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; + hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask; hz = HZ; - frequency = (u64)hpt_count * (u64)hz; + frequency = hpt_count * hz; return frequency >> log_2_loops; } -static cycle_t read_mips_hpt(void) -{ - return (cycle_t)mips_hpt_read(); -} - -static struct clocksource clocksource_mips = { +struct clocksource clocksource_mips = { .name = "MIPS", - .read = read_mips_hpt, + .mask = 0xffffffff, .is_continuous = 1, }; @@ -326,7 +317,7 @@ static void __init init_mips_clocksource(void) u64 temp; u32 shift; - if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) + if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read) return; /* Calclate a somewhat reasonable rating value */ @@ -340,7 +331,6 @@ static void __init init_mips_clocksource(void) } clocksource_mips.shift = shift; clocksource_mips.mult = (u32)temp; - clocksource_mips.mask = mips_hpt_mask; clocksource_register(&clocksource_mips); } @@ -360,19 +350,19 @@ void __init time_init(void) -xtime.tv_sec, -xtime.tv_nsec); /* Choose appropriate high precision timer routines. */ - if (!cpu_has_counter && !mips_hpt_read) + if (!cpu_has_counter && !clocksource_mips.read) /* No high precision timer -- sorry. */ - mips_hpt_read = null_hpt_read; + clocksource_mips.read = null_hpt_read; else if (!mips_hpt_frequency && !mips_timer_state) { /* A high precision timer of unknown frequency. */ - if (!mips_hpt_read) + if (!clocksource_mips.read) /* No external high precision timer -- use R4k. */ - mips_hpt_read = c0_hpt_read; + clocksource_mips.read = c0_hpt_read; } else { /* We know counter frequency. Or we can get it. */ - if (!mips_hpt_read) { + if (!clocksource_mips.read) { /* No external high precision timer -- use R4k. */ - mips_hpt_read = c0_hpt_read; + clocksource_mips.read = c0_hpt_read; if (!mips_timer_state) { /* No external timer interrupt -- use R4k. */ diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index e5441c3..7d36172 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -223,14 +223,14 @@ void __init plat_timer_setup(struct irqaction *irq) setup_irq(irqno, &rt_irqaction); } -static unsigned int ip27_hpt_read(void) +static cycle_t ip27_hpt_read(void) { return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); } void __init ip27_time_init(void) { - mips_hpt_read = ip27_hpt_read; + clocksource_mips.read = ip27_hpt_read; mips_hpt_frequency = CYCLES_PER_SEC; xtime.tv_sec = get_m48t35_time(); xtime.tv_nsec = 0; diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index 03d5822..6f3f71b 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -117,7 +117,7 @@ void bcm1480_timer_interrupt(void) } } -static unsigned int bcm1480_hpt_read(void) +static cycle_t bcm1480_hpt_read(void) { /* We assume this function is called xtime_lock held. */ unsigned long count = @@ -127,6 +127,6 @@ static unsigned int bcm1480_hpt_read(void) void __init bcm1480_hpt_setup(void) { - mips_hpt_read = bcm1480_hpt_read; + clocksource_mips.read = bcm1480_hpt_read; mips_hpt_frequency = BCM1480_HPT_VALUE; } diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index bcb74f2..2efffe1 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -51,7 +51,7 @@ extern int sb1250_steal_irq(int irq); -static unsigned int sb1250_hpt_read(void); +static cycle_t sb1250_hpt_read(void); void __init sb1250_hpt_setup(void) { @@ -66,8 +66,8 @@ void __init sb1250_hpt_setup(void) IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); mips_hpt_frequency = V_SCD_TIMER_FREQ; - mips_hpt_read = sb1250_hpt_read; - mips_hpt_mask = M_SCD_TIMER_INIT; + clocksource_mips.read = sb1250_hpt_read; + clocksource_mips.mask = M_SCD_TIMER_INIT; } } @@ -143,7 +143,7 @@ void sb1250_timer_interrupt(void) * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over * again. */ -static unsigned int sb1250_hpt_read(void) +static cycle_t sb1250_hpt_read(void) { unsigned int count; diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index b58665e..a632cef 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -21,6 +21,7 @@ #include #include #include +#include extern spinlock_t rtc_lock; @@ -44,11 +45,10 @@ extern int (*mips_timer_state)(void); extern void (*mips_timer_ack)(void); /* - * High precision timer functions. - * If mips_hpt_read is NULL, an R4k-compatible timer setup is attempted. + * High precision timer clocksource. + * If .read is NULL, an R4k-compatible timer setup is attempted. */ -extern unsigned int (*mips_hpt_read)(void); -extern unsigned int mips_hpt_mask; +extern struct clocksource clocksource_mips; /* * to_tm() converts system time back to (year, mon, day, hour, min, sec). -- cgit v0.10.2 From 63dc68a8cf60cb110b147dab1704d990808b39e2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 16 Oct 2006 01:38:50 +0100 Subject: [MIPS] Use conditional traps for BUG_ON on MIPS II and better. This shaves of around 4kB and a few cycles for the average kernel that has CONFIG_BUG enabled. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0ae19e1..2a932cad 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -669,8 +669,6 @@ asmlinkage void do_bp(struct pt_regs *regs) unsigned int opcode, bcode; siginfo_t info; - die_if_kernel("Break instruction in kernel code", regs); - if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) goto out_sigsegv; @@ -693,6 +691,7 @@ asmlinkage void do_bp(struct pt_regs *regs) switch (bcode) { case BRK_OVERFLOW << 10: case BRK_DIVZERO << 10: + die_if_kernel("Break instruction in kernel code", regs); if (bcode == (BRK_DIVZERO << 10)) info.si_code = FPE_INTDIV; else @@ -702,7 +701,11 @@ asmlinkage void do_bp(struct pt_regs *regs) info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; + case BRK_BUG: + die("Kernel bug detected", regs); + break; default: + die_if_kernel("Break instruction in kernel code", regs); force_sig(SIGTRAP, current); } @@ -715,8 +718,6 @@ asmlinkage void do_tr(struct pt_regs *regs) unsigned int opcode, tcode = 0; siginfo_t info; - die_if_kernel("Trap instruction in kernel code", regs); - if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) goto out_sigsegv; @@ -733,6 +734,7 @@ asmlinkage void do_tr(struct pt_regs *regs) switch (tcode) { case BRK_OVERFLOW: case BRK_DIVZERO: + die_if_kernel("Trap instruction in kernel code", regs); if (tcode == BRK_DIVZERO) info.si_code = FPE_INTDIV; else @@ -742,7 +744,11 @@ asmlinkage void do_tr(struct pt_regs *regs) info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; + case BRK_BUG: + die("Kernel bug detected", regs); + break; default: + die_if_kernel("Trap instruction in kernel code", regs); force_sig(SIGTRAP, current); } diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h index 7b4739d..4d560a5 100644 --- a/include/asm-mips/bug.h +++ b/include/asm-mips/bug.h @@ -1,6 +1,7 @@ #ifndef __ASM_BUG_H #define __ASM_BUG_H +#include #ifdef CONFIG_BUG @@ -13,6 +14,17 @@ do { \ #define HAVE_ARCH_BUG +#if (_MIPS_ISA > _MIPS_ISA_MIPS1) + +#define BUG_ON(condition) \ +do { \ + __asm__ __volatile__("tne $0, %0" : : "r" (condition)); \ +} while (0) + +#define HAVE_ARCH_BUG_ON + +#endif /* _MIPS_ISA > _MIPS_ISA_MIPS1 */ + #endif #include diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h index 5f3a907..30bf555 100644 --- a/include/asm-mips/ptrace.h +++ b/include/asm-mips/ptrace.h @@ -80,8 +80,6 @@ struct pt_regs { #define instruction_pointer(regs) ((regs)->cp0_epc) #define profile_pc(regs) instruction_pointer(regs) -extern void show_regs(struct pt_regs *); - extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit); #endif -- cgit v0.10.2 From e303e088f25dc7d8bafc0d1942314214a3a57b44 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:50 +0000 Subject: [MIPS] Remove old junk left from old atomic_lock. Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index e64abc0..7978d8e 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h @@ -9,16 +9,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 97, 99, 2000, 03, 04 by Ralf Baechle + * Copyright (C) 1996, 97, 99, 2000, 03, 04, 06 by Ralf Baechle */ - -/* - * As workaround for the ATOMIC_DEC_AND_LOCK / atomic_dec_and_lock mess in - * we have to include outside the - * main big wrapper ... - */ -#include - #ifndef _ASM_ATOMIC_H #define _ASM_ATOMIC_H -- cgit v0.10.2 From 4ffd8b3838f22c34b21a25b7612795ca45d14db6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:50 +0000 Subject: [MIPS] Remove userspace proofing from . Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index 1bb89c5..8cd61c1 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h @@ -10,10 +10,13 @@ #define _ASM_BITOPS_H #include +#include #include #include #include /* sigh ... */ #include +#include +#include #if (_MIPS_SZLONG == 32) #define SZLONG_LOG 5 @@ -29,12 +32,6 @@ #define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x)) #endif -#ifdef __KERNEL__ - -#include -#include -#include - /* * clear_bit() doesn't provide any barrier for the compiler. */ @@ -42,20 +39,6 @@ #define smp_mb__after_clear_bit() smp_mb() /* - * Only disable interrupt for kernel mode stuff to keep usermode stuff - * that dares to use kernel include files alive. - */ - -#define __bi_flags unsigned long flags -#define __bi_local_irq_save(x) local_irq_save(x) -#define __bi_local_irq_restore(x) local_irq_restore(x) -#else -#define __bi_flags -#define __bi_local_irq_save(x) -#define __bi_local_irq_restore(x) -#endif /* __KERNEL__ */ - -/* * set_bit - Atomically set a bit in memory * @nr: the bit to set * @addr: the address to start counting from @@ -93,13 +76,13 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) } else { volatile unsigned long *a = addr; unsigned long mask; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); *a |= mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); } } @@ -141,13 +124,13 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) } else { volatile unsigned long *a = addr; unsigned long mask; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); *a &= ~mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); } } @@ -191,13 +174,13 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) } else { volatile unsigned long *a = addr; unsigned long mask; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); *a ^= mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); } } @@ -258,14 +241,14 @@ static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *a = addr; unsigned long mask; int retval; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); retval = (mask & *a) != 0; *a |= mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); return retval; } @@ -330,14 +313,14 @@ static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *a = addr; unsigned long mask; int retval; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); retval = (mask & *a) != 0; *a &= ~mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); return retval; } @@ -399,23 +382,19 @@ static inline int test_and_change_bit(unsigned long nr, } else { volatile unsigned long *a = addr; unsigned long mask, retval; - __bi_flags; + unsigned long flags; a += nr >> SZLONG_LOG; mask = 1UL << (nr & SZLONG_MASK); - __bi_local_irq_save(flags); + local_irq_save(flags); retval = (mask & *a) != 0; *a ^= mask; - __bi_local_irq_restore(flags); + local_irq_restore(flags); return retval; } } -#undef __bi_flags -#undef __bi_local_irq_save -#undef __bi_local_irq_restore - #include /* -- cgit v0.10.2 From 0b7883f49810ec91755caa222b3b28f047b8c93b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:51 +0000 Subject: [MIPS] Remove unused definition of cpu_to_lelongp() Signed-off-by: Ralf Baechle diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index 8cd61c1..b900741 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h @@ -23,13 +23,11 @@ #define SZLONG_MASK 31UL #define __LL "ll " #define __SC "sc " -#define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x)) #elif (_MIPS_SZLONG == 64) #define SZLONG_LOG 6 #define SZLONG_MASK 63UL #define __LL "lld " #define __SC "scd " -#define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x)) #endif /* -- cgit v0.10.2 From aa414dff4f7bef29457592414551becdca72dd6b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 30 Nov 2006 01:14:51 +0000 Subject: [MIPS] Remove duplicate ISA DMA code for 0 DMA channel case. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c0da0ff..9614367 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -266,8 +266,8 @@ config MIPS_MALTA select BOOT_ELF32 select HAVE_STD_PC_SERIAL_PORT select DMA_NONCOHERENT - select IRQ_CPU select GENERIC_ISA_DMA + select IRQ_CPU select HW_HAS_PCI select I8259 select MIPS_BOARDS_GEN @@ -534,7 +534,7 @@ config SGI_IP22 select HW_HAS_EISA select IP22_CPU_SCACHE select IRQ_CPU - select NO_ISA if ISA + select GENERIC_ISA_DMA_SUPPORT_BROKEN select SWAP_IO_SPACE select SYS_HAS_CPU_R4X00 select SYS_HAS_CPU_R5000 @@ -881,6 +881,9 @@ config MIPS_NILE4 config MIPS_DISABLE_OBSOLETE_IDE bool +config GENERIC_ISA_DMA_SUPPORT_BROKEN + bool + # # Endianess selection. Suffiently obscure so many users don't know what to # answer,so we try hard to limit the available choices. Also the use of a @@ -1852,13 +1855,11 @@ source "drivers/pci/Kconfig" config ISA bool -config NO_ISA - bool - config EISA bool "EISA support" depends on HW_HAS_EISA select ISA + select GENERIC_ISA_DMA ---help--- The Extended Industry Standard Architecture (EISA) bus was developed as an open alternative to the IBM MicroChannel bus. diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index f35b739..bbbb8d7 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o -obj-$(CONFIG_NO_ISA) += dma-no-isa.o obj-$(CONFIG_I8259) += i8259.o obj-$(CONFIG_IRQ_CPU) += irq_cpu.o obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o diff --git a/arch/mips/kernel/dma-no-isa.c b/arch/mips/kernel/dma-no-isa.c deleted file mode 100644 index 6df8b07..0000000 --- a/arch/mips/kernel/dma-no-isa.c +++ /dev/null @@ -1,28 +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) 2004 by Ralf Baechle - * - * Dummy ISA DMA functions for systems that don't have ISA but share drivers - * with ISA such as legacy free PCI. - */ -#include -#include -#include - -DEFINE_SPINLOCK(dma_spin_lock); - -int request_dma(unsigned int dmanr, const char * device_id) -{ - return -EINVAL; -} - -void free_dma(unsigned int dmanr) -{ -} - -EXPORT_SYMBOL(dma_spin_lock); -EXPORT_SYMBOL(request_dma); -EXPORT_SYMBOL(free_dma); diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h index e85849a..23f789c 100644 --- a/include/asm-mips/dma.h +++ b/include/asm-mips/dma.h @@ -74,7 +74,9 @@ * */ +#ifndef GENERIC_ISA_DMA_SUPPORT_BROKEN #define MAX_DMA_CHANNELS 8 +#endif /* * The maximum address in KSEG0 that we can perform a DMA transfer to on this -- cgit v0.10.2 From 139a7bdc2b9391a4d0362190d9e5625dcf580105 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 30 Nov 2006 04:40:22 +0100 Subject: mqueue.h: don't include linux/types.h This #include is not required. Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk diff --git a/include/linux/mqueue.h b/include/linux/mqueue.h index 8db9d75..8b5a796 100644 --- a/include/linux/mqueue.h +++ b/include/linux/mqueue.h @@ -18,8 +18,6 @@ #ifndef _LINUX_MQUEUE_H #define _LINUX_MQUEUE_H -#include - #define MQ_PRIO_MAX 32768 /* per-uid limit of kernel memory used by mqueue, in bytes */ #define MQ_BYTES_MAX 819200 -- cgit v0.10.2 From e20ec9911bfef897459b9f8aeaf6eadb0920299a Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Thu, 30 Nov 2006 04:46:13 +0100 Subject: fix spelling error in include/linux/kernel.h Signed-off-by: Adrian Bunk diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b9b5e4b..6738283 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -65,7 +65,7 @@ struct user; * context (spinlock, irq-handler, ...). * * This is a useful debugging help to be able to catch problems early and not - * be biten later when the calling function happens to sleep when it is not + * be bitten later when the calling function happens to sleep when it is not * supposed to. */ #ifdef CONFIG_PREEMPT_VOLUNTARY -- cgit v0.10.2 From ce00f85c45d7f8c13cf67d9ca24d0f100f8e9c59 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Thu, 30 Nov 2006 04:49:44 +0100 Subject: tabify MAINTAINERS Signed-off-by: Adrian Bunk diff --git a/MAINTAINERS b/MAINTAINERS index e182992..846e77a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -155,16 +155,16 @@ L: netdev@vger.kernel.org S: Maintained 9P FILE SYSTEM -P: Eric Van Hensbergen -M: ericvh@gmail.com -P: Ron Minnich -M: rminnich@lanl.gov -P: Latchesar Ionkov -M: lucho@ionkov.net -L: v9fs-developer@lists.sourceforge.net -W: http://v9fs.sf.net -T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git -S: Maintained +P: Eric Van Hensbergen +M: ericvh@gmail.com +P: Ron Minnich +M: rminnich@lanl.gov +P: Latchesar Ionkov +M: lucho@ionkov.net +L: v9fs-developer@lists.sourceforge.net +W: http://v9fs.sf.net +T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git +S: Maintained A2232 SERIAL BOARD DRIVER P: Enver Haase @@ -290,8 +290,8 @@ M: ink@jurassic.park.msu.ru S: Maintained for 2.4; PCI support for 2.6. AMD GEODE PROCESSOR/CHIPSET SUPPORT -P: Jordan Crouse -M: info-linux@geode.amd.com +P: Jordan Crouse +M: info-linux@geode.amd.com L: info-linux@geode.amd.com W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html S: Supported @@ -601,13 +601,13 @@ M: maxk@qualcomm.com S: Maintained BONDING DRIVER -P: Chad Tindel -M: ctindel@users.sourceforge.net -P: Jay Vosburgh -M: fubar@us.ibm.com -L: bonding-devel@lists.sourceforge.net -W: http://sourceforge.net/projects/bonding/ -S: Supported +P: Chad Tindel +M: ctindel@users.sourceforge.net +P: Jay Vosburgh +M: fubar@us.ibm.com +L: bonding-devel@lists.sourceforge.net +W: http://sourceforge.net/projects/bonding/ +S: Supported BROADBAND PROCESSOR ARCHITECTURE P: Arnd Bergmann @@ -744,8 +744,8 @@ W: http://www.bullopensource.org/cpuset/ S: Supported CRAMFS FILESYSTEM -W: http://sourceforge.net/projects/cramfs/ -S: Orphan +W: http://sourceforge.net/projects/cramfs/ +S: Orphan CRIS PORT P: Mikael Starvik @@ -1054,11 +1054,11 @@ W: http://sourceforge.net/projects/emu10k1/ S: Maintained EMULEX LPFC FC SCSI DRIVER -P: James Smart -M: james.smart@emulex.com -L: linux-scsi@vger.kernel.org -W: http://sourceforge.net/projects/lpfcxxxx -S: Supported +P: James Smart +M: james.smart@emulex.com +L: linux-scsi@vger.kernel.org +W: http://sourceforge.net/projects/lpfcxxxx +S: Supported EPSON 1355 FRAMEBUFFER DRIVER P: Christopher Hoover @@ -1495,16 +1495,16 @@ L: linux-kernel@vger.kernel.org S: Maintained INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) -P: Sylvain Meyer -M: sylvain.meyer@worldonline.fr -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained +P: Sylvain Meyer +M: sylvain.meyer@worldonline.fr +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained INTEL 810/815 FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT P: Ingo Molnar @@ -1830,11 +1830,11 @@ L: linuxppc-embedded@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX -P: Kumar Gala -M: galak@kernel.crashing.org -W: http://www.penguinppc.org/ -L: linuxppc-embedded@ozlabs.org -S: Maintained +P: Kumar Gala +M: galak@kernel.crashing.org +W: http://www.penguinppc.org/ +L: linuxppc-embedded@ozlabs.org +S: Maintained LINUX FOR POWERPC PA SEMI PWRFICIENT P: Olof Johansson @@ -1933,10 +1933,10 @@ W: http://www.syskonnect.com S: Supported MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 -P: Michael Kerrisk -M: mtk-manpages@gmx.net -W: ftp://ftp.kernel.org/pub/linux/docs/manpages -S: Maintained +P: Michael Kerrisk +M: mtk-manpages@gmx.net +W: ftp://ftp.kernel.org/pub/linux/docs/manpages +S: Maintained MARVELL MV643XX ETHERNET DRIVER P: Dale Farnsworth @@ -1953,11 +1953,11 @@ L: linux-fbdev-devel@lists.sourceforge.net S: Maintained MEGARAID SCSI DRIVERS -P: Neela Syam Kolli -M: Neela.Kolli@engenio.com -S: linux-scsi@vger.kernel.org -W: http://megaraid.lsilogic.com -S: Maintained +P: Neela Syam Kolli +M: Neela.Kolli@engenio.com +S: linux-scsi@vger.kernel.org +W: http://megaraid.lsilogic.com +S: Maintained MEMORY MANAGEMENT L: linux-mm@kvack.org @@ -2186,10 +2186,10 @@ T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git S: Maintained NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained OPENCORES I2C BUS DRIVER P: Peter Korsgaard @@ -2539,10 +2539,10 @@ RISCOM8 DRIVER S: Orphan S3 SAVAGE FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net -S: Maintained +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained S390 P: Martin Schwidefsky @@ -2623,10 +2623,10 @@ L: linux-scsi@vger.kernel.org S: Maintained SCTP PROTOCOL -P: Sridhar Samudrala -M: sri@us.ibm.com -L: lksctp-developers@lists.sourceforge.net -S: Supported +P: Sridhar Samudrala +M: sri@us.ibm.com +L: lksctp-developers@lists.sourceforge.net +S: Supported SCx200 CPU SUPPORT P: Jim Cromie @@ -2794,9 +2794,9 @@ L: tpmdd-devel@lists.sourceforge.net S: Maintained Telecom Clock Driver for MCPL0010 -P: Mark Gross -M: mark.gross@intel.com -S: Supported +P: Mark Gross +M: mark.gross@intel.com +S: Supported TENSILICA XTENSA PORT (xtensa): P: Chris Zankel @@ -2943,9 +2943,9 @@ L: linux-kernel@vger.kernel.org S: Maintained TI PARALLEL LINK CABLE DRIVER -P: Romain Lievin -M: roms@lpg.ticalc.org -S: Maintained +P: Romain Lievin +M: roms@lpg.ticalc.org +S: Maintained TIPC NETWORK LAYER P: Per Liden @@ -2995,12 +2995,12 @@ L: linux-kernel@vger.kernel.org S: Maintained TRIVIAL PATCHES -P: Adrian Bunk -M: trivial@kernel.org -L: linux-kernel@vger.kernel.org -W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/ -T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git -S: Maintained +P: Adrian Bunk +M: trivial@kernel.org +L: linux-kernel@vger.kernel.org +W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/ +T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git +S: Maintained TMS380 TOKEN-RING NETWORK DRIVER P: Adam Fritzler -- cgit v0.10.2 From 98c4f0c336afe4318c12397bc74910d86ee036a2 Mon Sep 17 00:00:00 2001 From: Chase Venters Date: Thu, 30 Nov 2006 04:53:49 +0100 Subject: Fix jiffies.h comment jiffies.h includes a comment informing that jiffies_64 must be read with the assistance of the xtime_lock seqlock. The comment text, however, calls jiffies_64 "not volatile", which should probably read "not atomic". Signed-off-by: Chase Venters Signed-off-by: Adrian Bunk diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index c8d5f20..0ec6e28 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -74,7 +74,7 @@ #define __jiffy_data __attribute__((section(".data"))) /* - * The 64-bit value is not volatile - you MUST NOT read it + * The 64-bit value is not atomic - you MUST NOT read it * without sampling the sequence number in xtime_lock. * get_jiffies_64() will do this for you as appropriate. */ -- cgit v0.10.2 From fa00e7e152690adc17fdc318e64909d4aff1763e Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 04:55:36 +0100 Subject: Fix typos in /Documentation : 'T'' This patch fixes typos in various Documentation txts. The patch addresses some +words starting with the letter 'T'. Signed-off-by: Matt LaPlante Acked-by: Randy Dunlap Signed-off-by: Adrian Bunk diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt index 705f6be..e767805 100644 --- a/Documentation/DMA-ISA-LPC.txt +++ b/Documentation/DMA-ISA-LPC.txt @@ -110,7 +110,7 @@ lock. Once the DMA transfer is finished (or timed out) you should disable the channel again. You should also check get_dma_residue() to make -sure that all data has been transfered. +sure that all data has been transferred. Example: diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt index 92ebf29..b55e041 100644 --- a/Documentation/accounting/taskstats.txt +++ b/Documentation/accounting/taskstats.txt @@ -96,9 +96,9 @@ a) TASKSTATS_TYPE_AGGR_PID/TGID : attribute containing no payload but indicates a pid/tgid will be followed by some stats. b) TASKSTATS_TYPE_PID/TGID: attribute whose payload is the pid/tgid whose stats -is being returned. +are being returned. -c) TASKSTATS_TYPE_STATS: attribute with a struct taskstsats as payload. The +c) TASKSTATS_TYPE_STATS: attribute with a struct taskstats as payload. The same structure is used for both per-pid and per-tgid stats. 3. New message sent by kernel whenever a task exits. The payload consists of a diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt index a584f05..3d74477 100644 --- a/Documentation/filesystems/fuse.txt +++ b/Documentation/filesystems/fuse.txt @@ -111,7 +111,7 @@ For each connection the following files exist within this directory: 'waiting' - The number of requests which are waiting to be transfered to + The number of requests which are waiting to be transferred to userspace or being processed by the filesystem daemon. If there is no filesystem activity and 'waiting' is non-zero, then the filesystem is hung or deadlocked. @@ -136,7 +136,7 @@ following will happen: 2) If the request is not yet sent to userspace AND the signal is not fatal, then an 'interrupted' flag is set for the request. When - the request has been successfully transfered to userspace and + the request has been successfully transferred to userspace and this flag is set, an INTERRUPT request is queued. 3) If the request is already sent to userspace, then an INTERRUPT diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 35f105b..21e7ba1 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -337,7 +337,7 @@ Finally, for a mirrored volume, i.e. raid level 1, the table would look like this (note all values are in 512-byte sectors): --- cut here --- -# Ofs Size Raid Log Number Region Should Number Source Start Taget Start +# Ofs Size Raid Log Number Region Should Number Source Start Target Start # in of the type type of log size sync? of Device in Device in # vol volume params mirrors Device Device 0 2056320 mirror core 2 16 nosync 2 /dev/hda1 0 /dev/hdb1 0 diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 3355e69..bbd2e58 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1538,10 +1538,10 @@ TCP settings tcp_ecn ------- -This file controls the use of the ECN bit in the IPv4 headers, this is a new +This file controls the use of the ECN bit in the IPv4 headers. This is a new feature about Explicit Congestion Notification, but some routers and firewalls -block trafic that has this bit set, so it could be necessary to echo 0 to -/proc/sys/net/ipv4/tcp_ecn, if you want to talk to this sites. For more info +block traffic that has this bit set, so it could be necessary to echo 0 to +/proc/sys/net/ipv4/tcp_ecn if you want to talk to these sites. For more info you could read RFC2481. tcp_retrans_collapse diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 7751704..58408dd 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -212,7 +212,7 @@ There are some minimal guarantees that may be expected of a CPU: STORE *X = c, d = LOAD *X - (Loads and stores overlap if they are targetted at overlapping pieces of + (Loads and stores overlap if they are targeted at overlapping pieces of memory). And there are a number of things that _must_ or _must_not_ be assumed: diff --git a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt index 93af3e8..c300f26 100644 --- a/Documentation/networking/NAPI_HOWTO.txt +++ b/Documentation/networking/NAPI_HOWTO.txt @@ -95,8 +95,8 @@ There are two types of event register ACK mechanisms. Move all to dev->poll() C) Ability to detect new work correctly. -NAPI works by shutting down event interrupts when theres work and -turning them on when theres none. +NAPI works by shutting down event interrupts when there's work and +turning them on when there's none. New packets might show up in the small window while interrupts were being re-enabled (refer to appendix 2). A packet might sneak in during the period we are enabling interrupts. We only get to know about such a packet when the @@ -114,7 +114,7 @@ Locking rules and environmental guarantees only one CPU can pick the initial interrupt and hence the initial netif_rx_schedule(dev); - The core layer invokes devices to send packets in a round robin format. -This implies receive is totaly lockless because of the guarantee only that +This implies receive is totally lockless because of the guarantee that only one CPU is executing it. - contention can only be the result of some other CPU accessing the rx ring. This happens only in close() and suspend() (when these methods @@ -510,7 +510,7 @@ static int my_poll (struct net_device *dev, int *budget) an interrupt will be generated */ goto done; } - /* done! at least thats what it looks like ;-> + /* done! at least that's what it looks like ;-> if new packets came in after our last check on status bits they'll be caught by the while check and we go back and clear them since we havent exceeded our quota */ @@ -678,10 +678,10 @@ routine: CSR5 bit of interest is only the rx status. If you look at the last if statement: you just finished grabbing all the packets from the rx ring .. you check if -status bit says theres more packets just in ... it says none; you then +status bit says there are more packets just in ... it says none; you then enable rx interrupts again; if a new packet just came in during this check, we are counting that CSR5 will be set in that small window of opportunity -and that by re-enabling interrupts, we would actually triger an interrupt +and that by re-enabling interrupts, we would actually trigger an interrupt to register the new packet for processing. [The above description nay be very verbose, if you have better wording diff --git a/Documentation/networking/cs89x0.txt b/Documentation/networking/cs89x0.txt index 6489647..e4d2287 100644 --- a/Documentation/networking/cs89x0.txt +++ b/Documentation/networking/cs89x0.txt @@ -248,7 +248,7 @@ c) The driver's hardware probe routine is designed to avoid with device probing. To avoid this behaviour, add one to the `io=' module parameter. This doesn't actually change the I/O address, but it is a flag to tell the driver - topartially initialise the hardware before trying to + to partially initialise the hardware before trying to identify the card. This could be dangerous if you are not sure that there is a cs89x0 card at the provided address. diff --git a/Documentation/networking/iphase.txt b/Documentation/networking/iphase.txt index 493203a..55eac4a 100644 --- a/Documentation/networking/iphase.txt +++ b/Documentation/networking/iphase.txt @@ -81,7 +81,7 @@ Installation 1M. The RAM size decides the number of buffers and buffer size. The default size and number of buffers are set as following: - Totol Rx RAM Tx RAM Rx Buf Tx Buf Rx buf Tx buf + Total Rx RAM Tx RAM Rx Buf Tx Buf Rx buf Tx buf RAM size size size size size cnt cnt -------- ------ ------ ------ ------ ------ ------ 128K 64K 64K 10K 10K 6 6 diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt index c8eee23..7b35855 100644 --- a/Documentation/networking/pktgen.txt +++ b/Documentation/networking/pktgen.txt @@ -116,7 +116,7 @@ Examples: there must be no spaces between the arguments. Leading zeros are required. Do not set the bottom of stack bit, - thats done automatically. If you do + that's done automatically. If you do set the bottom of stack bit, that indicates that you want to randomly generate that address and the flag diff --git a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt index 59cb915..5e21f7c 100644 --- a/Documentation/networking/proc_net_tcp.txt +++ b/Documentation/networking/proc_net_tcp.txt @@ -25,7 +25,7 @@ up into 3 parts because of the length of the line): 1000 0 54165785 4 cd1e6040 25 4 27 3 -1 | | | | | | | | | |--> slow start size threshold, - | | | | | | | | | or -1 if the treshold + | | | | | | | | | or -1 if the threshold | | | | | | | | | is >= 0xFFFF | | | | | | | | |----> sending congestion window | | | | | | | |-------> (ack.quick<<1)|ack.pingpong diff --git a/Documentation/s390/crypto/crypto-API.txt b/Documentation/s390/crypto/crypto-API.txt index 29dee79..41a8b07 100644 --- a/Documentation/s390/crypto/crypto-API.txt +++ b/Documentation/s390/crypto/crypto-API.txt @@ -75,8 +75,8 @@ name of the respective module is given in square brackets. - SHA1 Digest Algorithm [sha1 -> sha1_z990] - DES Encrypt/Decrypt Algorithm (64bit key) [des -> des_z990] -- Tripple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990] -- Tripple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990] +- Triple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990] +- Triple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990] In order to load, for example, the sha1_z990 module when the sha1 algorithm is requested (see 3.2.) add 'alias sha1 sha1_z990' to /etc/modprobe.conf. diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt index 904d49e..1231085 100644 --- a/Documentation/scsi/aic79xx.txt +++ b/Documentation/scsi/aic79xx.txt @@ -127,7 +127,7 @@ The following information is available in this file: - Correct a reference to free'ed memory during controller shutdown. - Reset the bus on an SE->LVD change. This is required - to reset our transcievers. + to reset our transceivers. 1.3.5 (March 24th, 2003) - Fix a few register window mode bugs. diff --git a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt index c92f447..11606ee 100644 --- a/Documentation/scsi/aic7xxx_old.txt +++ b/Documentation/scsi/aic7xxx_old.txt @@ -436,7 +436,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD the commas to periods, insmod won't interpret this as more than one string and write junk into our binary image. I consider it a bug in the insmod program that even if you wrap your string in quotes (quotes - that pass the shell mind you and that insmod sees) it still treates + that pass the shell mind you and that insmod sees) it still treats a comma inside of those quotes as starting a new variable, resulting in memory scribbles if you don't switch the commas to periods. diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index 35f6b8e..b168743 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -920,7 +920,7 @@ completed in such a way, that they are now completely conform to the demands in the technical description of IBM. Main candidates were the DEVICE_INQUIRY, REQUEST_SENSE and DEVICE_CAPACITY commands. They must - be tranferred by bypassing the internal command buffer of the adapter + be transferred by bypassing the internal command buffer of the adapter or else the response can be a random result. GET_POS_INFO would be more safe in usage, if one could use the SUPRESS_EXCEPTION_SHORT, but this is not allowed by the technical references of IBM. (Sorry, folks, the diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt index 9e2078b..aa54f54 100644 --- a/Documentation/scsi/libsas.txt +++ b/Documentation/scsi/libsas.txt @@ -393,7 +393,7 @@ struct sas_task { task_proto -- _one_ of enum sas_proto scatter -- pointer to scatter gather list array num_scatter -- number of elements in scatter - total_xfer_len -- total number of bytes expected to be transfered + total_xfer_len -- total number of bytes expected to be transferred data_dir -- PCI_DMA_... task_done -- callback when the task has finished execution }; diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt index 5ff65b1..3c12422 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.txt @@ -261,7 +261,7 @@ pairs are separated with a comma (no spaces allowed). A colon can be used instead of the equal mark. The definition is prepended by the string st=. Here is an example: - st=buffer_kbs:64,write_threhold_kbs:60 + st=buffer_kbs:64,write_threshold_kbs:60 The following syntax used by the old kernel versions is also supported: diff --git a/Documentation/sharedsubtree.txt b/Documentation/sharedsubtree.txt index 2d8f403..ccf1ceb 100644 --- a/Documentation/sharedsubtree.txt +++ b/Documentation/sharedsubtree.txt @@ -942,13 +942,13 @@ replicas continue to be exactly same. ->mnt_slave ->mnt_master - ->mnt_share links togather all the mount to/from which this vfsmount + ->mnt_share links together all the mount to/from which this vfsmount send/receives propagation events. ->mnt_slave_list links all the mounts to which this vfsmount propagates to. - ->mnt_slave links togather all the slaves that its master vfsmount + ->mnt_slave links together all the slaves that its master vfsmount propagates to. ->mnt_master points to the master vfsmount from which this vfsmount diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3472d9c..9fef210 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -955,7 +955,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. dmx6fire, dsp24, dsp24_value, dsp24_71, ez8, phase88, mediastation omni - Omni I/O support for MidiMan M-Audio Delta44/66 - cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever) + cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transceiver) in msec resolution, default value is 500 (0.5 sec) This module supports multiple cards and autoprobe. Note: The consumer part diff --git a/Documentation/usb/rio.txt b/Documentation/usb/rio.txt index ab21db4..aee715a 100644 --- a/Documentation/usb/rio.txt +++ b/Documentation/usb/rio.txt @@ -24,10 +24,10 @@ are in no way responsible for any damage that may occur, no matter how inconsequential. It seems that the Rio has a problem when sending .mp3 with low batteries. -I suggest when the batteries are low and want to transfer stuff that you +I suggest when the batteries are low and you want to transfer stuff that you replace it with a fresh one. In my case, what happened is I lost two 16kb blocks (they are no longer usable to store information to it). But I don't -know if thats normal or not. It could simply be a problem with the flash +know if that's normal or not; it could simply be a problem with the flash memory. In an extreme case, I left my Rio playing overnight and the batteries wore diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 50436e1..a043764 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -175,7 +175,7 @@ Keyspan USA-series Serial Adapters Current status: The USA-18X, USA-28X, USA-19, USA-19W and USA-49W are supported and - have been pretty throughly tested at various baud rates with 8-N-1 + have been pretty thoroughly tested at various baud rates with 8-N-1 character settings. Other character lengths and parity setups are presently untested. @@ -253,7 +253,7 @@ Cypress M8 CY4601 Family Serial Driver together without hacking the adapter to set the line high. The driver is smp safe. Performance with the driver is rather low when using - it for transfering files. This is being worked on, but I would be willing to + it for transferring files. This is being worked on, but I would be willing to accept patches. An urb queue or packet buffer would likely fit the bill here. If you have any questions, problems, patches, feature requests, etc. you can diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index 7e8ae83..8d16f6f 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt @@ -214,7 +214,7 @@ returned value is the temperature in degrees fahrenheit. Finally the SETOPTIONS ioctl can be used to control some aspects of the cards operation; right now the pcwd driver is the only one -supporting thiss ioctl. +supporting this ioctl. int options = 0; ioctl(fd, WDIOC_SETOPTIONS, options); -- cgit v0.10.2 From 4ae0edc21b152c126e4a8c94ad5391f8ea051b31 Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 04:58:40 +0100 Subject: Fix typos in /Documentation : 'U-Z' This patch fixes typos in various Documentation txts. The patch addresses some +words starting with the letters 'U-Z'. Looks like I made it through the alphabet...just in time to start over again +too! Maybe I can fit more profound fixes into the next round...? Time will +tell. :) Signed-off-by: Matt LaPlante Acked-by: Randy Dunlap Signed-off-by: Adrian Bunk diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 2ffb0d6..0543162 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -489,7 +489,7 @@ size is the size of the area (must be multiples of PAGE_SIZE). flags can be or'd together and are DMA_MEMORY_MAP - request that the memory returned from -dma_alloc_coherent() be directly writeable. +dma_alloc_coherent() be directly writable. DMA_MEMORY_IO - request that the memory returned from dma_alloc_coherent() be addressable using read/write/memcpy_toio etc. diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt index 5c34910..d389388 100644 --- a/Documentation/MSI-HOWTO.txt +++ b/Documentation/MSI-HOWTO.txt @@ -219,7 +219,7 @@ into the field vector of each element contained in a second argument. Note that the pre-assigned IOAPIC dev->irq is valid only if the device operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at using dev->irq by the device driver to request for interrupt service -may result unpredictabe behavior. +may result in unpredictable behavior. For each MSI-X vector granted, a device driver is responsible for calling other functions like request_irq(), enable_irq(), etc. to enable diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt index b55e041..ff06b73 100644 --- a/Documentation/accounting/taskstats.txt +++ b/Documentation/accounting/taskstats.txt @@ -122,12 +122,12 @@ of atomicity). However, maintaining per-process, in addition to per-task stats, within the kernel has space and time overheads. To address this, the taskstats code -accumalates each exiting task's statistics into a process-wide data structure. -When the last task of a process exits, the process level data accumalated also +accumulates each exiting task's statistics into a process-wide data structure. +When the last task of a process exits, the process level data accumulated also gets sent to userspace (along with the per-task data). When a user queries to get per-tgid data, the sum of all other live threads in -the group is added up and added to the accumalated total for previously exited +the group is added up and added to the accumulated total for previously exited threads of the same thread group. Extending taskstats diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 34bf8f6..980a6e6 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -391,7 +391,7 @@ forced such requests to be broken up into small chunks before being passed on to the generic block layer, only to be merged by the i/o scheduler when the underlying device was capable of handling the i/o in one shot. Also, using the buffer head as an i/o structure for i/os that didn't originate -from the buffer cache unecessarily added to the weight of the descriptors +from the buffer cache unnecessarily added to the weight of the descriptors which were generated for each such chunk. The following were some of the goals and expectations considered in the @@ -403,14 +403,14 @@ i. Should be appropriate as a descriptor for both raw and buffered i/o - for raw i/o. ii. Ability to represent high-memory buffers (which do not have a virtual address mapping in kernel address space). -iii.Ability to represent large i/os w/o unecessarily breaking them up (i.e +iii.Ability to represent large i/os w/o unnecessarily breaking them up (i.e greater than PAGE_SIZE chunks in one shot) iv. At the same time, ability to retain independent identity of i/os from different sources or i/o units requiring individual completion (e.g. for latency reasons) v. Ability to represent an i/o involving multiple physical memory segments (including non-page aligned page fragments, as specified via readv/writev) - without unecessarily breaking it up, if the underlying device is capable of + without unnecessarily breaking it up, if the underlying device is capable of handling it. vi. Preferably should be based on a memory descriptor structure that can be passed around different types of subsystems or layers, maybe even diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt index 531239b..2ecd834 100644 --- a/Documentation/dvb/ci.txt +++ b/Documentation/dvb/ci.txt @@ -71,7 +71,7 @@ eliminating the need for any additional ioctls. The disadvantage is that the driver/hardware has to manage the rest. For the application programmer it would be as simple as sending/receiving an array to/from the CI ioctls as defined in the Linux DVB API. No changes -have been made in the API to accomodate this feature. +have been made in the API to accommodate this feature. * Why the need for another CI interface ? @@ -102,7 +102,7 @@ This CI interface follows the CI high level interface, which is not implemented by most applications. Hence this area is revisited. This CI interface is quite different in the case that it tries to -accomodate all other CI based devices, that fall into the other categories +accommodate all other CI based devices, that fall into the other categories. This means that this CI interface handles the EN50221 style tags in the Application layer only and no session management is taken care of by the diff --git a/Documentation/eisa.txt b/Documentation/eisa.txt index 6a099ed..60e361b 100644 --- a/Documentation/eisa.txt +++ b/Documentation/eisa.txt @@ -62,7 +62,7 @@ res : root device I/O resource bus_base_addr : slot 0 address on this bus slots : max slot number to probe force_probe : Probe even when slot 0 is empty (no EISA mainboard) -dma_mask : Default DMA mask. Usualy the bridge device dma_mask. +dma_mask : Default DMA mask. Usually the bridge device dma_mask. bus_nr : unique bus id, set by eisa_root_register ** Driver : diff --git a/Documentation/filesystems/adfs.txt b/Documentation/filesystems/adfs.txt index 060abb0..9e8811f 100644 --- a/Documentation/filesystems/adfs.txt +++ b/Documentation/filesystems/adfs.txt @@ -3,7 +3,7 @@ Mount options for ADFS uid=nnn All files in the partition will be owned by user id nnn. Default 0 (root). - gid=nnn All files in the partition willbe in group + gid=nnn All files in the partition will be in group nnn. Default 0 (root). ownmask=nnn The permission mask for ADFS 'owner' permissions will be nnn. Default 0700. diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt index c3a7afb..b34cdb5 100644 --- a/Documentation/filesystems/configfs/configfs.txt +++ b/Documentation/filesystems/configfs/configfs.txt @@ -209,7 +209,7 @@ will happen for write(2). [struct config_group] -A config_item cannot live in a vaccum. The only way one can be created +A config_item cannot live in a vacuum. The only way one can be created is via mkdir(2) on a config_group. This will trigger creation of a child item. @@ -275,7 +275,7 @@ directory is not empty. [struct configfs_subsystem] -A subsystem must register itself, ususally at module_init time. This +A subsystem must register itself, usually at module_init time. This tells configfs to make the subsystem appear in the file tree. struct configfs_subsystem { diff --git a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt index 33dc360..38aba03 100644 --- a/Documentation/filesystems/hpfs.txt +++ b/Documentation/filesystems/hpfs.txt @@ -274,7 +274,7 @@ History Fixed race-condition in buffer code - it is in all filesystems in Linux; when reading device (cat /dev/hda) while creating files on it, files could be damaged -2.02 Woraround for bug in breada in Linux. breada could cause accesses beyond +2.02 Workaround for bug in breada in Linux. breada could cause accesses beyond end of partition 2.03 Char, block devices and pipes are correctly created Fixed non-crashing race in unlink (Alexander Viro) diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index 4389c68..af6defd 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt @@ -30,7 +30,7 @@ Caveats Features which OCFS2 does not support yet: - sparse files - extended attributes - - shared writeable mmap + - shared writable mmap - loopback is supported, but data written will not be cluster coherent. - quotas diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index bbd2e58..72af5de 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1220,9 +1220,9 @@ applications are using mlock(), or if you are running with no swap then you probably should increase the lower_zone_protection setting. The units of this tunable are fairly vague. It is approximately equal -to "megabytes". So setting lower_zone_protection=100 will protect around 100 +to "megabytes," so setting lower_zone_protection=100 will protect around 100 megabytes of the lowmem zone from user allocations. It will also make -those 100 megabytes unavaliable for use by applications and by +those 100 megabytes unavailable for use by applications and by pagecache, so there is a cost. The effects of this tunable may be observed by monitoring diff --git a/Documentation/filesystems/spufs.txt b/Documentation/filesystems/spufs.txt index 982645a..1343d11 100644 --- a/Documentation/filesystems/spufs.txt +++ b/Documentation/filesystems/spufs.txt @@ -210,7 +210,7 @@ FILES /signal2 The two signal notification channels of an SPU. These are read-write files that operate on a 32 bit word. Writing to one of these files - triggers an interrupt on the SPU. The value writting to the signal + triggers an interrupt on the SPU. The value written to the signal files can be read from the SPU through a channel read or from host user space through the file. After the value has been read by the SPU, it is reset to zero. The possible operations on an open signal1 or sig- diff --git a/Documentation/ide.txt b/Documentation/ide.txt index 0bf38ba..786c3a7 100644 --- a/Documentation/ide.txt +++ b/Documentation/ide.txt @@ -390,5 +390,5 @@ mlord@pobox.com Wed Apr 17 22:52:44 CEST 2002 edited by Marcin Dalecki, the current maintainer. -Wed Aug 20 22:31:29 CEST 2003 updated ide boot uptions to current ide.c +Wed Aug 20 22:31:29 CEST 2003 updated ide boot options to current ide.c comments at 2.6.0-test4 time. Maciej Soltysiak diff --git a/Documentation/input/atarikbd.txt b/Documentation/input/atarikbd.txt index 1e7e585..1b00ad7 100644 --- a/Documentation/input/atarikbd.txt +++ b/Documentation/input/atarikbd.txt @@ -103,7 +103,7 @@ LEFT=0x74 & RIGHT=0x75). 5.1 Joystick Event Reporting -In this mode, the ikbd generates a record whever the joystick position is +In this mode, the ikbd generates a record whenever the joystick position is changed (i.e. for each opening or closing of a joystick switch or trigger). The joystick event record is two bytes of the form: diff --git a/Documentation/ioctl/cdrom.txt b/Documentation/ioctl/cdrom.txt index 8ec32cc..62d4af4 100644 --- a/Documentation/ioctl/cdrom.txt +++ b/Documentation/ioctl/cdrom.txt @@ -735,7 +735,7 @@ CDROM_DISC_STATUS Get disc type, etc. Ok, this is where problems start. The current interface for the CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. - Unfortunatly, while this is often the case, it is also + Unfortunately, while this is often the case, it is also very common for CDs to have some tracks with data, and some tracks with audio. Just because I feel like it, I declare the following to be the best way to cope. If the CD has diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt index c487186..9ead3af 100644 --- a/Documentation/laptop-mode.txt +++ b/Documentation/laptop-mode.txt @@ -699,7 +699,7 @@ ACPI integration Dax Kelson submitted this so that the ACPI acpid daemon will kick off the laptop_mode script and run hdparm. The part that automatically disables laptop mode when the battery is low was -writen by Jan Topinski. +written by Jan Topinski. -----------------/etc/acpi/events/ac_adapter BEGIN------------------------------ event=ac_adapter diff --git a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt index c300f26..fb6e49c 100644 --- a/Documentation/networking/NAPI_HOWTO.txt +++ b/Documentation/networking/NAPI_HOWTO.txt @@ -601,7 +601,7 @@ a) 5) dev->close() and dev->suspend() issues ========================================== -The driver writter neednt worry about this. The top net layer takes +The driver writer needn't worry about this; the top net layer takes care of it. 6) Adding new Stats to /proc @@ -622,9 +622,9 @@ FC should be programmed to apply in the case when the system cant pull out packets fast enough i.e send a pause only when you run out of rx buffers. Note FC in itself is a good solution but we have found it to not be much of a commodity feature (both in NICs and switches) and hence falls -under the same category as using NIC based mitigation. Also experiments -indicate that its much harder to resolve the resource allocation -issue (aka lazy receiving that NAPI offers) and hence quantify its usefullness +under the same category as using NIC based mitigation. Also, experiments +indicate that it's much harder to resolve the resource allocation +issue (aka lazy receiving that NAPI offers) and hence quantify its usefulness proved harder. In any case, FC works even better with NAPI but is not necessary. diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt index 4e1cc74..8590a95 100644 --- a/Documentation/networking/sk98lin.txt +++ b/Documentation/networking/sk98lin.txt @@ -346,7 +346,7 @@ Possible modes: depending on the load of the system. If the driver detects that the system load is too high, the driver tries to shield the system against too much network load by enabling interrupt moderation. If - at a later - time - the CPU utilizaton decreases again (or if the network load is + time - the CPU utilization decreases again (or if the network load is negligible) the interrupt moderation will automatically be disabled. Interrupt moderation should be used when the driver has to handle one or more diff --git a/Documentation/networking/slicecom.txt b/Documentation/networking/slicecom.txt index 2f04c92..32d3b91 100644 --- a/Documentation/networking/slicecom.txt +++ b/Documentation/networking/slicecom.txt @@ -126,7 +126,7 @@ comx0/boardnum - board number of the SliceCom in the PC (using the 'natural' Though the options below are to be set on a single interface, they apply to the whole board. The restriction, to use them on 'UP' interfaces, is because the -command sequence below could lead to unpredicable results. +command sequence below could lead to unpredictable results. # echo 0 >boardnum # echo internal >clock_source diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt index 0cf6541..66b9026 100644 --- a/Documentation/networking/wan-router.txt +++ b/Documentation/networking/wan-router.txt @@ -412,7 +412,7 @@ beta-2.1.4 Jul 2000 o Dynamic interface configuration: beta3-2.1.4 Jul 2000 o X25 M_BIT Problem fix. o Added the Multi-Port PPP - Updated utilites for the Multi-Port PPP. + Updated utilities for the Multi-Port PPP. 2.1.4 Aut 2000 o In X25API: @@ -450,7 +450,7 @@ beta1-2.1.5 Nov 15 2000 o Keyboard Led Monitor/Debugger - - A new utilty /usr/sbin/wpkbdmon uses keyboard leds + - A new utility /usr/sbin/wpkbdmon uses keyboard leds to convey operational statistic information of the Sangoma WANPIPE cards. NUM_LOCK = Line State (On=connected, Off=disconnected) diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt index 9ff966b..28037aa 100644 --- a/Documentation/pnp.txt +++ b/Documentation/pnp.txt @@ -184,7 +184,7 @@ static const struct pnp_id pnp_dev_table[] = { Please note that the character 'X' can be used as a wild card in the function portion (last four characters). ex: - /* Unkown PnP modems */ + /* Unknown PnP modems */ { "PNPCXXX", UNKNOWN_DEV }, Supported PnP card IDs can optionally be defined. diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt index 8529a17..535f69f 100644 --- a/Documentation/robust-futex-ABI.txt +++ b/Documentation/robust-futex-ABI.txt @@ -170,7 +170,7 @@ any point: 1) the 'head' pointer or an subsequent linked list pointer is not a valid address of a user space word 2) the calculated location of the 'lock word' (address plus - 'offset') is not the valud address of a 32 bit user space + 'offset') is not the valid address of a 32 bit user space word 3) if the list contains more than 1 million (subject to future kernel configuration changes) elements. diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index b168743..745f3cc 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -461,7 +461,7 @@ This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which allows data to be written from the system to the device. It is a necessary step to be allowed to set blocksize of SCSI-tape-drives and - the tape-speed, whithout confusing the SCSI-Subsystem. + the tape-speed, without confusing the SCSI-Subsystem. 2) The recognition of a tape is included in the check_devices routine. This is done by checking for TYPE_TAPE, that is already defined in the kernel-scsi-environment. The markup of a tape is done in the diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt index 58ad8db..caf10b1 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.txt @@ -115,7 +115,7 @@ SCSI standard documentations are available at SYMBIOS ftp server: ftp://ftp.symbios.com/ -Usefull SCSI tools written by Eric Youngdale are available at tsx-11: +Useful SCSI tools written by Eric Youngdale are available at tsx-11: ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz diff --git a/Documentation/sound/alsa/Audigy-mixer.txt b/Documentation/sound/alsa/Audigy-mixer.txt index 5132fd9..7f10dc6 100644 --- a/Documentation/sound/alsa/Audigy-mixer.txt +++ b/Documentation/sound/alsa/Audigy-mixer.txt @@ -6,7 +6,7 @@ This is based on SB-Live-mixer.txt. The EMU10K2 chips have a DSP part which can be programmed to support various ways of sample processing, which is described here. -(This acticle does not deal with the overall functionality of the +(This article does not deal with the overall functionality of the EMU10K2 chips. See the manuals section for further details.) The ALSA driver programs this portion of chip by default code diff --git a/Documentation/sound/alsa/SB-Live-mixer.txt b/Documentation/sound/alsa/SB-Live-mixer.txt index 651adaf..f5639d4 100644 --- a/Documentation/sound/alsa/SB-Live-mixer.txt +++ b/Documentation/sound/alsa/SB-Live-mixer.txt @@ -5,7 +5,7 @@ The EMU10K1 chips have a DSP part which can be programmed to support various ways of sample processing, which is described here. -(This acticle does not deal with the overall functionality of the +(This article does not deal with the overall functionality of the EMU10K1 chips. See the manuals section for further details.) The ALSA driver programs this portion of chip by default code diff --git a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt index b60590e..628013f 100644 --- a/Documentation/uml/UserModeLinux-HOWTO.txt +++ b/Documentation/uml/UserModeLinux-HOWTO.txt @@ -1477,7 +1477,7 @@ - Making it world-writeable looks bad, but it seems not to be + Making it world-writable looks bad, but it seems not to be exploitable as a security hole. However, it does allow anyone to cre- ate useless tap devices (useless because they can't configure them), which is a DOS attack. A somewhat more secure alternative would to be -- cgit v0.10.2 From 5d3f083d8f897ce2560bbd4dace483d5aa60d623 Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 05:21:10 +0100 Subject: Fix typos in /Documentation : Misc This patch fixes typos in various Documentation txts. The patch addresses some misc words. Signed-off-by: Matt LaPlante Acked-by: Randy Dunlap Signed-off-by: Adrian Bunk diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 980a6e6..c6c9a9c 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -183,7 +183,7 @@ it, the pci dma mapping routines and associated data structures have now been modified to accomplish a direct page -> bus translation, without requiring a virtual address mapping (unlike the earlier scheme of virtual address -> bus translation). So this works uniformly for high-memory pages (which -do not have a correponding kernel virtual address space mapping) and +do not have a corresponding kernel virtual address space mapping) and low-memory pages. Note: Please refer to DMA-mapping.txt for a discussion on PCI high mem DMA @@ -1013,7 +1013,7 @@ Characteristics: i. Binary tree AS and deadline i/o schedulers use red black binary trees for disk position sorting and searching, and a fifo linked list for time-based searching. This -gives good scalability and good availablility of information. Requests are +gives good scalability and good availability of information. Requests are almost always dispatched in disk sort order, so a cache is kept of the next request in sort order to prevent binary tree lookups. diff --git a/Documentation/cpu-freq/cpufreq-nforce2.txt b/Documentation/cpu-freq/cpufreq-nforce2.txt index 9188337..babce13 100644 --- a/Documentation/cpu-freq/cpufreq-nforce2.txt +++ b/Documentation/cpu-freq/cpufreq-nforce2.txt @@ -1,7 +1,7 @@ -The cpufreq-nforce2 driver changes the FSB on nVidia nForce2 plattforms. +The cpufreq-nforce2 driver changes the FSB on nVidia nForce2 platforms. -This works better than on other plattforms, because the FSB of the CPU +This works better than on other platforms, because the FSB of the CPU can be controlled independently from the PCI/AGP clock. The module has two options: diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index 4868c34..cc60d29 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -54,8 +54,8 @@ additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets ia64 and x86_64 use the number of disabled local apics in ACPI tables MADT to determine the number of potentially hot-pluggable cpus. The implementation -should only rely on this to count the #of cpus, but *MUST* not rely on the -apicid values in those tables for disabled apics. In the event BIOS doesnt +should only rely on this to count the # of cpus, but *MUST* not rely on the +apicid values in those tables for disabled apics. In the event BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could use this parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map. diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 28c4f79..70690f1 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -92,7 +92,7 @@ Your cooperation is appreciated. 7 = /dev/full Returns ENOSPC on write 8 = /dev/random Nondeterministic random number gen. 9 = /dev/urandom Faster, less secure random number gen. - 10 = /dev/aio Asyncronous I/O notification interface + 10 = /dev/aio Asynchronous I/O notification interface 11 = /dev/kmsg Writes to this come out as printk's 1 block RAM disk 0 = /dev/ram0 First RAM disk @@ -1093,7 +1093,7 @@ Your cooperation is appreciated. 55 char DSP56001 digital signal processor 0 = /dev/dsp56k First DSP56001 - 55 block Mylex DAC960 PCI RAID controller; eigth controller + 55 block Mylex DAC960 PCI RAID controller; eighth controller 0 = /dev/rd/c7d0 First disk, whole disk 8 = /dev/rd/c7d1 Second disk, whole disk ... @@ -1456,7 +1456,7 @@ Your cooperation is appreciated. 1 = /dev/cum1 Callout device for ttyM1 ... - 79 block Compaq Intelligent Drive Array, eigth controller + 79 block Compaq Intelligent Drive Array, eighth controller 0 = /dev/ida/c7d0 First logical drive whole disk 16 = /dev/ida/c7d1 Second logical drive whole disk ... @@ -1900,7 +1900,7 @@ Your cooperation is appreciated. 1 = /dev/av1 Second A/V card ... -111 block Compaq Next Generation Drive Array, eigth controller +111 block Compaq Next Generation Drive Array, eighth controller 0 = /dev/cciss/c7d0 First logical drive, whole disk 16 = /dev/cciss/c7d1 Second logical drive, whole disk ... diff --git a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt index 98b233c..92d86f7 100644 --- a/Documentation/driver-model/porting.txt +++ b/Documentation/driver-model/porting.txt @@ -92,7 +92,7 @@ struct device represents a single device. It mainly contains metadata describing the relationship the device has to other entities. -- Embedd a struct device in the bus-specific device type. +- Embed a struct device in the bus-specific device type. struct pci_dev { diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 21e7ba1..13ba649 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -599,7 +599,7 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. - Major bug fixes for reading files and volumes in corner cases which were being hit by Windows 2k/XP users. 2.1.2: - - Major bug fixes aleviating the hangs in statfs experienced by some + - Major bug fixes alleviating the hangs in statfs experienced by some users. 2.1.1: - Update handling of compressed files so people no longer get the diff --git a/Documentation/fujitsu/frv/gdbstub.txt b/Documentation/fujitsu/frv/gdbstub.txt index 6ce5aa9..9304fb3 100644 --- a/Documentation/fujitsu/frv/gdbstub.txt +++ b/Documentation/fujitsu/frv/gdbstub.txt @@ -59,7 +59,7 @@ the following things on the "Kernel Hacking" tab: Then build as usual, download to the board and execute. Note that if "Immediate activation" was selected, then the kernel will wait for GDB to attach. If not, then the kernel will boot immediately and GDB will have to -interupt it or wait for an exception to occur if before doing anything with +interrupt it or wait for an exception to occur before doing anything with the kernel. diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt index 8b0a5fc..aaa1cec 100644 --- a/Documentation/fujitsu/frv/kernel-ABI.txt +++ b/Documentation/fujitsu/frv/kernel-ABI.txt @@ -156,7 +156,7 @@ with the main kernel in this regard. Hence the debug mode code (gdbstub) is almost completely self-contained. The only external code used is the sprintf family of functions. -Futhermore, break.S is so complicated because single-step mode does not +Furthermore, break.S is so complicated because single-step mode does not switch off on entry to an exception. That means unless manually disabled, single-stepping will blithely go on stepping into things like interrupts. See gdbstub.txt for more information. diff --git a/Documentation/input/amijoy.txt b/Documentation/input/amijoy.txt index 4f0e89d..7dc4f17 100644 --- a/Documentation/input/amijoy.txt +++ b/Documentation/input/amijoy.txt @@ -91,8 +91,8 @@ JOY1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0 | 1 | M0HQ | JOY0DAT Horizontal Clock (quadrature) | | 2 | M0V | JOY0DAT Vertical Clock | | 3 | M0VQ | JOY0DAT Vertical Clock (quadrature) | - | 4 | M1V | JOY1DAT Horizontall Clock | - | 5 | M1VQ | JOY1DAT Horizontall Clock (quadrature) | + | 4 | M1V | JOY1DAT Horizontal Clock | + | 5 | M1VQ | JOY1DAT Horizontal Clock (quadrature) | | 6 | M1V | JOY1DAT Vertical Clock | | 7 | M1VQ | JOY1DAT Vertical Clock (quadrature) | +--------+----------+-----------------------------------------+ diff --git a/Documentation/input/atarikbd.txt b/Documentation/input/atarikbd.txt index 1b00ad7..668f4d0 100644 --- a/Documentation/input/atarikbd.txt +++ b/Documentation/input/atarikbd.txt @@ -277,8 +277,8 @@ default to 1 at RESET (or power-up). 9.7 SET MOUSE SCALE 0x0C - X ; horizontal mouse ticks per internel X - Y ; vertical mouse ticks per internel Y + X ; horizontal mouse ticks per internal X + Y ; vertical mouse ticks per internal Y This command sets the scale factor for the ABSOLUTE MOUSE POSITIONING mode. In this mode, the specified number of mouse phase changes ('clicks') must @@ -323,7 +323,7 @@ mouse position. 0x0F This command makes the origin of the Y axis to be at the bottom of the -logical coordinate system internel to the ikbd for all relative or absolute +logical coordinate system internal to the ikbd for all relative or absolute mouse motion. This causes mouse motion toward the user to be negative in sign and away from the user to be positive. @@ -597,8 +597,8 @@ mode or FIRE BUTTON MONITORING mode. 10. SCAN CODES -The key scan codes return by the ikbd are chosen to simplify the -implementaion of GSX. +The key scan codes returned by the ikbd are chosen to simplify the +implementation of GSX. GSX Standard Keyboard Mapping. diff --git a/Documentation/input/yealink.txt b/Documentation/input/yealink.txt index 0a8c97e..5360e43 100644 --- a/Documentation/input/yealink.txt +++ b/Documentation/input/yealink.txt @@ -134,7 +134,7 @@ Reading /sys/../lineX will return the format string with its current value: 888888888888 Linux Rocks! -Writing to /sys/../lineX will set the coresponding LCD line. +Writing to /sys/../lineX will set the corresponding LCD line. - Excess characters are ignored. - If less characters are written than allowed, the remaining digits are unchanged. diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 50f4edd..4b3d671 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -227,9 +227,9 @@ more details, with real examples. be included in a library, lib.a. All objects listed with lib-y are combined in a single library for that directory. - Objects that are listed in obj-y and additionaly listed in - lib-y will not be included in the library, since they will anyway - be accessible. + Objects that are listed in obj-y and additionally listed in + lib-y will not be included in the library, since they will + be accessible anyway. For consistency, objects listed in lib-m will be included in lib.a. Note that the same kbuild makefile may list files to be built-in @@ -535,7 +535,7 @@ Both possibilities are described in the following. Host programs can be made up based on composite objects. The syntax used to define composite objects for host programs is similar to the syntax used for kernel objects. - $(-objs) lists all objects used to link the final + $(-objs) lists all objects used to link the final executable. Example: @@ -1022,7 +1022,7 @@ When kbuild executes, the following steps are followed (roughly): In this example, there are two possible targets, requiring different options to the linker. The linker options are specified using the LDFLAGS_$@ syntax - one for each potential target. - $(targets) are assinged all potential targets, by which kbuild knows + $(targets) are assigned all potential targets, by which kbuild knows the targets and will: 1) check for commandline changes 2) delete target during make clean diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 3da586b..60c665d 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -304,7 +304,7 @@ about the status of the key service: R Revoked D Dead Q Contributes to user's quota - U Under contruction by callback to userspace + U Under construction by callback to userspace N Negative key This file must be enabled at kernel configuration time as it allows anyone diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt index 9ead3af..6f639e3 100644 --- a/Documentation/laptop-mode.txt +++ b/Documentation/laptop-mode.txt @@ -121,7 +121,7 @@ contains the following options: MAX_AGE: Maximum time, in seconds, of hard drive spindown time that you are -confortable with. Worst case, it's possible that you could lose this +comfortable with. Worst case, it's possible that you could lose this amount of work if your battery fails while you're in laptop mode. MINIMUM_BATTERY_MINUTES: @@ -235,7 +235,7 @@ It should be installed as /etc/default/laptop-mode on Debian, and as --------------------CONFIG FILE BEGIN------------------------------------------- # Maximum time, in seconds, of hard drive spindown time that you are -# confortable with. Worst case, it's possible that you could lose this +# comfortable with. Worst case, it's possible that you could lose this # amount of work if your battery fails you while in laptop mode. #MAX_AGE=600 @@ -350,7 +350,7 @@ fi # set defaults instead: # Maximum time, in seconds, of hard drive spindown time that you are -# confortable with. Worst case, it's possible that you could lose this +# comfortable with. Worst case, it's possible that you could lose this # amount of work if your battery fails you while in laptop mode. MAX_AGE=${MAX_AGE:-'600'} diff --git a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt index fb6e49c..fb8dc64 100644 --- a/Documentation/networking/NAPI_HOWTO.txt +++ b/Documentation/networking/NAPI_HOWTO.txt @@ -535,11 +535,11 @@ done: * 1. it can race with disabling irqs in irq handler (which are done to * schedule polls) * 2. it can race with dis/enabling irqs in other poll threads - * 3. if an irq raised after the begining of the outer beginning - * loop(marked in the code above), it will be immediately + * 3. if an irq raised after the beginning of the outer beginning + * loop (marked in the code above), it will be immediately * triggered here. * - * Summarizing: the logic may results in some redundant irqs both + * Summarizing: the logic may result in some redundant irqs both * due to races in masking and due to too late acking of already * processed irqs. The good news: no events are ever lost. */ diff --git a/Documentation/networking/cs89x0.txt b/Documentation/networking/cs89x0.txt index e4d2287..6387d3d 100644 --- a/Documentation/networking/cs89x0.txt +++ b/Documentation/networking/cs89x0.txt @@ -620,8 +620,8 @@ I/O Address Device IRQ Device 12 Mouse (PS/2) Memory Address Device 13 Math Coprocessor -------------- --------------------- 14 Hard Disk controller -A000-BFFF EGA Graphics Adpater -A000-C7FF VGA Graphics Adpater +A000-BFFF EGA Graphics Adapter +A000-C7FF VGA Graphics Adapter B000-BFFF Mono Graphics Adapter B800-BFFF Color Graphics Adapter E000-FFFF AT BIOS diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 12a008a..5a232d9 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -284,7 +284,7 @@ the necessary memory, so normally limits can be reached. ------------------- If you check the source code you will see that what I draw here as a frame -is not only the link level frame. At the begining of each frame there is a +is not only the link level frame. At the beginning of each frame there is a header called struct tpacket_hdr used in PACKET_MMAP to hold link level's frame meta information like timestamp. So what we draw here a frame it's really the following (from include/linux/if_packet.h): diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt index 7b35855..c6cf4a3 100644 --- a/Documentation/networking/pktgen.txt +++ b/Documentation/networking/pktgen.txt @@ -63,8 +63,8 @@ Current: Result: OK: 13101142(c12220741+d880401) usec, 10000000 (60byte,0frags) 763292pps 390Mb/sec (390805504bps) errors: 39664 -Confguring threads and devices -============================== +Configuring threads and devices +================================ This is done via the /proc interface easiest done via pgset in the scripts Examples: diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt index 66b9026..653978d 100644 --- a/Documentation/networking/wan-router.txt +++ b/Documentation/networking/wan-router.txt @@ -444,7 +444,7 @@ beta1-2.1.5 Nov 15 2000 o Cpipemon - Added set FT1 commands to the cpipemon. Thus CSU/DSU - configuraiton can be performed using cpipemon. + configuration can be performed using cpipemon. All systems that cannot run cfgft1 GUI utility should use cpipemon to configure the on board CSU/DSU. @@ -464,7 +464,7 @@ beta1-2.1.5 Nov 15 2000 - Appropriate number of devices are dynamically loaded based on the number of Sangoma cards found. - Note: The kernel configuraiton option + Note: The kernel configuration option CONFIG_WANPIPE_CARDS has been taken out. o Fixed the Frame Relay and Chdlc network interfaces so they are diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index 24edf25..c750f9f 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -153,7 +153,7 @@ Description: events, which is implicit if it doesn't even support it in the first place). - Note that the PMC Register in the device's PM Capabilties has a bitmask + Note that the PMC Register in the device's PM Capabilities has a bitmask of the states it supports generating PME# from. D3hot is bit 3 and D3cold is bit 4. So, while a value of 4 as the state may not seem semantically correct, it is. @@ -268,7 +268,7 @@ to wake the system up. (However, it is possible that a device may support some non-standard way of generating a wake event on sleep.) Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's -PM Capabilties describe what power states the device supports generating a +PM Capabilities describe what power states the device supports generating a wake event from: +------------------+ diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 9ea2208..e635e6f 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -153,7 +153,7 @@ add: If the thread is needed for writing the image to storage, you should instead set the PF_NOFREEZE process flag when creating the thread (and -be very carefull). +be very careful). Q: What is the difference between "platform", "shutdown" and diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 27b457c..4ac2d64 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -33,13 +33,13 @@ - Change version 16 format to always align property data to 4 bytes. Since tokens are already aligned, that means no specific - required alignement between property size + required alignment between property size and property data. The old style variable alignment would make it impossible to do "simple" insertion of properties using memove (thanks Milton for noticing). Updated kernel patch as well - - Correct a few more alignement constraints + - Correct a few more alignment constraints - Add a chapter about the device-tree compiler and the textural representation of the tree that can be "compiled" by dtc. @@ -854,7 +854,7 @@ address which can extend beyond that limit. console device if any. Typically, if you have serial devices on your board, you may want to put the full path to the one set as the default console in the firmware here, for the kernel to pick - it up as it's own default console. If you look at the funciton + it up as its own default console. If you look at the function set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see that the kernel tries to find out the default console and has knowledge of various types like 8250 serial ports. You may want @@ -1124,7 +1124,7 @@ should have the following properties: - interrupt-parent : contains the phandle of the interrupt controller which handles interrupts for this device - interrupts : a list of tuples representing the interrupt - number and the interrupt sense and level for each interupt + number and the interrupt sense and level for each interrupt for this device. This information is used by the kernel to build the interrupt table diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt index 76e8064..0a9446a 100644 --- a/Documentation/robust-futexes.txt +++ b/Documentation/robust-futexes.txt @@ -181,7 +181,7 @@ for new threads, without the need of another syscall.] So there is virtually zero overhead for tasks not using robust futexes, and even for robust futex users, there is only one extra syscall per thread lifetime, and the cleanup operation, if it happens, is fast and -straightforward. The kernel doesnt have any internal distinction between +straightforward. The kernel doesn't have any internal distinction between robust and normal futexes. If a futex is found to be held at exit time, the kernel sets the diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt index 1231085..6aa9a89 100644 --- a/Documentation/scsi/aic79xx.txt +++ b/Documentation/scsi/aic79xx.txt @@ -169,7 +169,7 @@ The following information is available in this file: 1.3.0 (January 21st, 2003) - Full regression testing for all U320 products completed. - Added abort and target/lun reset error recovery handler and - interrupt coalessing. + interrupt coalescing. 1.2.0 (November 14th, 2002) - Added support for Domain Validation diff --git a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt index 11606ee..05667e7 100644 --- a/Documentation/scsi/aic7xxx_old.txt +++ b/Documentation/scsi/aic7xxx_old.txt @@ -256,7 +256,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD En/Disable High Byte LVD Termination The upper 2 bits that deal with LVD termination only apply to Ultra2 - controllers. Futhermore, due to the current Ultra2 controller + controllers. Furthermore, due to the current Ultra2 controller designs, these bits are tied together such that setting either bit enables both low and high byte LVD termination. It is not possible to only set high or low byte LVD termination in this manner. This is diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index 745f3cc..9707941 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -710,8 +710,8 @@ of troubles with some controllers and after I wanted to apply some extensions, it jumped out in the same situation, on my w/cache, as like on D. Weinehalls' Model 56, having integrated SCSI. This gave me the - descissive hint to move the code-part out and declare it global. Now, - it seems to work by far much better an more stable. Let us see, what + decisive hint to move the code-part out and declare it global. Now + it seems to work far better and more stable. Let us see what the world thinks of it... 3) By the way, only Sony DAT-drives seem to show density code 0x13. A test with a HP drive gave right results, so the problem is vendor- @@ -822,10 +822,10 @@ A long period of collecting bugreports from all corners of the world now lead to the following corrections to the code: 1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this - was, that it is possible to disbale Fast-SCSI for the external bus. - The feature-control command, where this crash appeared regularly tried + was that it is possible to disable Fast-SCSI for the external bus. + The feature-control command, where this crash appeared regularly, tried to set the maximum speed of 10MHz synchronous transfer speed and that - reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now, + reports a COMMAND ERROR if external bus Fast-SCSI is disabled. Now, the feature-command probes down from maximum speed until the adapter stops to complain, which is at the same time the maximum possible speed selected in the reference program. So, F/W external can run at diff --git a/Documentation/scsi/in2000.txt b/Documentation/scsi/in2000.txt index 80f1040..c3e2a90 100644 --- a/Documentation/scsi/in2000.txt +++ b/Documentation/scsi/in2000.txt @@ -24,7 +24,7 @@ UPDATE NEWS: version 1.32 - 28 Mar 98 UPDATE NEWS: version 1.31 - 6 Jul 97 Fixed a bug that caused incorrect SCSI status bytes to be - returned from commands sent to LUN's greater than 0. This + returned from commands sent to LUNs greater than 0. This means that CDROM changers work now! Fixed a bug in the handling of command-line arguments when loaded as a module. Also put all the header data in in2000.h where it belongs. diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.txt index d74bbd2..032399b 100644 --- a/Documentation/scsi/scsi-changer.txt +++ b/Documentation/scsi/scsi-changer.txt @@ -88,7 +88,7 @@ If the module finds the changer, it prints some messages about the device [ try "dmesg" if you don't see anything ] and should show up in /proc/devices. If not.... some changers use ID ? / LUN 0 for the device and ID ? / LUN 1 for the robot mechanism. But Linux does *not* -look for LUN's other than 0 as default, becauce there are to many +look for LUNs other than 0 as default, because there are too many broken devices. So you can try: 1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi @@ -107,7 +107,7 @@ because the kernel will translate the error codes into human-readable strings then. You can display these messages with the dmesg command (or check the -logfiles). If you email me some question becauce of a problem with the +logfiles). If you email me some question because of a problem with the driver, please include these messages. diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index b964eef..7acbebb 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt @@ -75,7 +75,7 @@ with the command. - otherwise scsi_eh_scmd_add(scmd, 0) is invoked for the command. See - [1-3] for details of this funciton. + [1-3] for details of this function. [1-2-2] Completing a scmd w/ timeout diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt index 26c8a08..2c1745a 100644 --- a/Documentation/scsi/sym53c8xx_2.txt +++ b/Documentation/scsi/sym53c8xx_2.txt @@ -609,7 +609,7 @@ appropriate mailing lists or news-groups. Send me a copy in order to be sure I will receive it. Obviously, a bug in the driver code is possible. - My cyrrent email address: Gerard Roudier + My current email address: Gerard Roudier Allowing disconnections is important if you use several devices on your SCSI bus but often causes problems with buggy devices. diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 02a4812..c815c52 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -50,7 +50,7 @@ Review cycle: Contact the kernel security team for more details on this procedure. -Review committe: +Review committee: - This is made up of a number of kernel developers who have volunteered for this task, and a few that haven't. diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 5c3a519..aa986a3 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -146,7 +146,7 @@ or otherwise protected/tainted binaries. The modes are readable by root only. This allows the end user to remove such a dump but not access it directly. For security reasons core dumps in this mode will not overwrite one another or - other files. This mode is appropriate when adminstrators are + other files. This mode is appropriate when administrators are attempting to debug problems in a normal environment. ============================================================== diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 20d0d79..e96a341 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -129,7 +129,7 @@ the high water marks for each per cpu page list. zone_reclaim_mode: -Zone_reclaim_mode allows to set more or less agressive approaches to +Zone_reclaim_mode allows someone to set more or less aggressive approaches to reclaim memory when a zone runs out of memory. If it is set to zero then no zone reclaim occurs. Allocations will be satisfied from other zones / nodes in the system. diff --git a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt index 6a79075..6e8c9f1 100644 --- a/Documentation/usb/hiddev.txt +++ b/Documentation/usb/hiddev.txt @@ -8,7 +8,7 @@ interfaces, but have similar sorts of communication needs. The two big examples for this are power devices (especially uninterruptable power supplies) and monitor control on higher end monitors. -To support these disparite requirements, the Linux USB system provides +To support these disparate requirements, the Linux USB system provides HID events to two separate interfaces: * the input subsystem, which converts HID events into normal input device interfaces (such as keyboard, mouse and joystick) and a diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index a043764..d61f6e7 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -297,7 +297,7 @@ Belkin USB Serial Adapter F5U103 Parity N,E,O,M,S Handshake None, Software (XON/XOFF), Hardware (CTSRTS,CTSDTR)* Break Set and clear - Line contrl Input/Output query and control ** + Line control Input/Output query and control ** * Hardware input flow control is only enabled for firmware levels above 2.06. Read source code comments describing Belkin @@ -309,7 +309,7 @@ Belkin USB Serial Adapter F5U103 automatic hardware flow control. TO DO List: - -- Add true modem contol line query capability. Currently tracks the + -- Add true modem control line query capability. Currently tracks the states reported by the interrupt and the states requested. -- Add error reporting back to application for UART error conditions. -- Add support for flush ioctls. -- cgit v0.10.2 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 diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 57f23b4..e316bd9 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 147b019..6f4c6a1 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 63965c7..9aa26b9 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 c0bfb82..b09a19f 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 44eb1b9..c7ea9ef 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 734d5f3..e7e724bc 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 a33097f..f64624f 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 6d920d4..c1bc22c 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 1443024..22bb540 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 0673dbe..116d7d3 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 7edb6b4..edcd5b8 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 077711e..ef018e2 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 6a461d4..bffc7e1 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 2f96610..92a7c8a 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 2af12fc..ad8b537 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 bf26755..b8fde5c 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 24747bd..d132ed5 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 6e863aa..b6c70c5 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 b79ec0d..ecb61f8 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 5f1b9f5..d0ba112 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 23334c8..d895a1a 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 cf10cbc..cc60759 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 7b1511d..8bec76b 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 e0d791a..95949b6 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 v0.10.2 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 diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index 6e1f191..284ebfd 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 6114596..092c724 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 34528da..07628a1 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 db8e1fc..14691cd 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 1326f45..4310fc8 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 9ed1c60..bb7ef57 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 4df6ab2..167ebc8 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 99f3df0..0794844 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 1066d97..bb498d2 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 8ccee9c..e3a2676 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 11e6f93..7b4ec3f 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 e8f9c07..9d5d2a5 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 fc1267b..9a15539 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 19ab344..3a8df47 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 65077f3..796c4f7d 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 778d9e6..3fa6717 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 07c1b4c..37ce03f 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 1f74281..72120d5 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 68cb3a0..fe3f5f5 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 c2949b4..12bab64 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 c3ac98a..f55ac38 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 969be46..1ee9a6f 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 b79f45f..a11f4e6 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 de7c04d..e5a0ec3 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 6cc2bc2..adb8eb4 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 cb8b770..b39357d 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 32c635e..a00d159 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 551ba89..5b5a3e6 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 bdb5810..5e3ac28 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 85ce232..ac93174 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 13df9d4..319899c 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 da2cf37..31ad0f0 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 7b8ad11..7b3be9a 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 5542dd0..007a8806 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 fd1756d..88b4589 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 73e0bec..62a7169 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 6f39faa..c205973 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 9479659..316211d 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 6e3c41f..b1c5d82 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 v0.10.2 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 diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 46c1148..e8db6e5 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 762fa28..d593ef3 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 v0.10.2 From 93e06b4140cc018826bce4d97b0bf7c9ba05ae6e Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 30 Nov 2006 05:29:23 +0100 Subject: BUG_ON conversion for fs/aio.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 diff --git a/fs/aio.c b/fs/aio.c index 9476659..277a5f2 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -367,8 +367,7 @@ void fastcall __put_ioctx(struct kioctx *ctx) { unsigned nr_events = ctx->max_reqs; - if (unlikely(ctx->reqs_active)) - BUG(); + BUG_ON(ctx->reqs_active); cancel_delayed_work(&ctx->wq); flush_workqueue(aio_wq); @@ -505,8 +504,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) assert_spin_locked(&ctx->ctx_lock); req->ki_users --; - if (unlikely(req->ki_users < 0)) - BUG(); + BUG_ON(req->ki_users < 0); if (likely(req->ki_users)) return 0; list_del(&req->ki_list); /* remove from active_reqs */ -- cgit v0.10.2 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 diff --git a/Documentation/Changes b/Documentation/Changes index abee7f5..73a8617 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 3e5e5d3..0931a33 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 2f880cb..0cad354 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 e5c7271..051b7c5 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 92b5d88..65e5ee5 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 d0ba112..3cfb0a3 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 8bec76b..b3b5aa0 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 9901928..eb550b3 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 7dac8f0..004808a 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 2cb4a43..98bcadc 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 v0.10.2 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 diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 6d04317..cd3b5ad 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 v0.10.2 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 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6e863aa..30ae712 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 v0.10.2 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 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 17a4611..488d8ed 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 v0.10.2 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 diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 418138d..9dd2823 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 b3b4611..cb85cbb 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 v0.10.2 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 diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 9dd2823..cef7e66 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 cb85cbb..3e196df 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 v0.10.2 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 diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 4ffc9b4..dec70c2 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 v0.10.2 From b729c09a452a659cdf4d29d83943aa798c5c4ffc Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 7 Nov 2006 21:00:22 +0000 Subject: [ARM] Improve reliability of APM-emulation suspend The APM emulation can sometimes cause suspend to fail to work due to apparantly waiting for some process to acknowledge an event when it actually has already done so. We re-jig the event handling to work around this behaviour. Signed-off-by: Russell King diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index ecf4f94..bbe98e3 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c @@ -12,7 +12,6 @@ */ #include #include -#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include /* apm_power_info */ #include @@ -71,7 +71,8 @@ struct apm_user { #define SUSPEND_PENDING 1 /* suspend pending read */ #define SUSPEND_READ 2 /* suspend read, pending ack */ #define SUSPEND_ACKED 3 /* suspend acked */ -#define SUSPEND_DONE 4 /* suspend completed */ +#define SUSPEND_WAIT 4 /* waiting for suspend */ +#define SUSPEND_DONE 5 /* suspend completed */ struct apm_queue queue; }; @@ -101,6 +102,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); static DEFINE_SPINLOCK(kapmd_queue_lock); static struct apm_queue kapmd_queue; +static DECLARE_MUTEX(state_lock); static const char driver_version[] = "1.13"; /* no spaces */ @@ -148,38 +150,60 @@ static void queue_add_event(struct apm_queue *q, apm_event_t event) q->events[q->event_head] = event; } -static void queue_event_one_user(struct apm_user *as, apm_event_t event) +static void queue_event(apm_event_t event) { - if (as->suser && as->writer) { - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - /* - * If this user already has a suspend pending, - * don't queue another one. - */ - if (as->suspend_state != SUSPEND_NONE) - return; + struct apm_user *as; - as->suspend_state = SUSPEND_PENDING; - suspends_pending++; - break; - } + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as->reader) + queue_add_event(&as->queue, event); } - queue_add_event(&as->queue, event); + up_read(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); } -static void queue_event(apm_event_t event, struct apm_user *sender) +/* + * queue_suspend_event - queue an APM suspend event. + * + * Check that we're in a state where we can suspend. If not, + * return -EBUSY. Otherwise, queue an event to all "writer" + * users. If there are no "writer" users, return '1' to + * indicate that we can immediately suspend. + */ +static int queue_suspend_event(apm_event_t event, struct apm_user *sender) { struct apm_user *as; + int ret = 1; + down(&state_lock); down_read(&user_list_lock); + + /* + * If a thread is still processing, we can't suspend, so reject + * the request. + */ + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser && + as->suspend_state != SUSPEND_NONE) { + ret = -EBUSY; + goto out; + } + } + list_for_each_entry(as, &apm_user_list, list) { - if (as != sender && as->reader) - queue_event_one_user(as, event); + if (as != sender && as->reader && as->writer && as->suser) { + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + queue_add_event(&as->queue, event); + ret = 0; + } } + out: up_read(&user_list_lock); + up(&state_lock); wake_up_interruptible(&apm_waitqueue); + return ret; } static void apm_suspend(void) @@ -191,17 +215,22 @@ static void apm_suspend(void) * Anyone on the APM queues will think we're still suspended. * Send a message so everyone knows we're now awake again. */ - queue_event(APM_NORMAL_RESUME, NULL); + queue_event(APM_NORMAL_RESUME); /* * Finally, wake up anyone who is sleeping on the suspend. */ + down(&state_lock); down_read(&user_list_lock); list_for_each_entry(as, &apm_user_list, list) { - as->suspend_result = err; - as->suspend_state = SUSPEND_DONE; + if (as->suspend_state == SUSPEND_WAIT || + as->suspend_state == SUSPEND_ACKED) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } } up_read(&user_list_lock); + up(&state_lock); wake_up(&apm_suspend_waitqueue); } @@ -227,8 +256,11 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t if (copy_to_user(buf, &event, sizeof(event))) break; - if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) + down(&state_lock); + if (as->suspend_state == SUSPEND_PENDING && + (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) as->suspend_state = SUSPEND_READ; + up(&state_lock); buf += sizeof(event); i -= sizeof(event); @@ -270,9 +302,13 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) switch (cmd) { case APM_IOC_SUSPEND: + down(&state_lock); + as->suspend_result = -EINTR; if (as->suspend_state == SUSPEND_READ) { + int pending; + /* * If we read a suspend command from /dev/apm_bios, * then the corresponding APM_IOC_SUSPEND ioctl is @@ -280,47 +316,66 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) */ as->suspend_state = SUSPEND_ACKED; suspends_pending--; + pending = suspends_pending == 0; + up(&state_lock); + + /* + * If there are no further acknowledges required, + * suspend the system. + */ + if (pending) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); } else { + up(&state_lock); + /* * Otherwise it is a request to suspend the system. * Queue an event for all readers, and expect an * acknowledge from all writers who haven't already * acknowledged. */ - queue_event(APM_USER_SUSPEND, as); - } + err = queue_suspend_event(APM_USER_SUSPEND, as); + if (err < 0) + break; - /* - * If there are no further acknowledges required, suspend - * the system. - */ - if (suspends_pending == 0) - apm_suspend(); + if (err > 0) + apm_suspend(); - /* - * Wait for the suspend/resume to complete. If there are - * pending acknowledges, we wait here for them. - * - * Note that we need to ensure that the PM subsystem does - * not kick us out of the wait when it suspends the threads. - */ - flags = current->flags; - current->flags |= PF_NOFREEZE; + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; - /* - * Note: do not allow a thread which is acking the suspend - * to escape until the resume is complete. - */ - if (as->suspend_state == SUSPEND_ACKED) - wait_event(apm_suspend_waitqueue, - as->suspend_state == SUSPEND_DONE); - else wait_event_interruptible(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); + } current->flags = flags; + + down(&state_lock); err = as->suspend_result; as->suspend_state = SUSPEND_NONE; + up(&state_lock); break; } @@ -330,6 +385,8 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) static int apm_release(struct inode * inode, struct file * filp) { struct apm_user *as = filp->private_data; + int pending = 0; + filp->private_data = NULL; down_write(&user_list_lock); @@ -342,11 +399,14 @@ static int apm_release(struct inode * inode, struct file * filp) * need to balance suspends_pending, which means the * possibility of sleeping. */ + down(&state_lock); if (as->suspend_state != SUSPEND_NONE) { suspends_pending -= 1; - if (suspends_pending == 0) - apm_suspend(); + pending = suspends_pending == 0; } + up(&state_lock); + if (pending) + apm_suspend(); kfree(as); return 0; @@ -470,6 +530,7 @@ static int kapmd(void *arg) { do { apm_event_t event; + int ret; wait_event_interruptible(kapmd_wait, !queue_empty(&kapmd_queue) || kthread_should_stop()); @@ -489,13 +550,20 @@ static int kapmd(void *arg) case APM_LOW_BATTERY: case APM_POWER_STATUS_CHANGE: - queue_event(event, NULL); + queue_event(event); break; case APM_USER_SUSPEND: case APM_SYS_SUSPEND: - queue_event(event, NULL); - if (suspends_pending == 0) + ret = queue_suspend_event(event, NULL); + if (ret < 0) { + /* + * We were busy. Try again in 50ms. + */ + queue_add_event(&kapmd_queue, event); + msleep(50); + } + if (ret > 0) apm_suspend(); break; -- cgit v0.10.2 From df58d0359581bbd4ee741406d81e69456c684f9d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 7 Nov 2006 21:01:30 +0000 Subject: [ARM] Fix "apm -s" command hang Fix an apparant hang with the "apm -s" command. We omitted to wake up this process once resume had completed. Signed-off-by: Russell King diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index bbe98e3..845af0b 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c @@ -340,6 +340,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) wait_event(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); } else { + as->suspend_state = SUSPEND_WAIT; up(&state_lock); /* @@ -349,8 +350,14 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) * acknowledged. */ err = queue_suspend_event(APM_USER_SUSPEND, as); - if (err < 0) + if (err < 0) { + /* + * Avoid taking the lock here - this + * should be fine. + */ + as->suspend_state = SUSPEND_NONE; break; + } if (err > 0) apm_suspend(); -- cgit v0.10.2 From beea494d5e09f9e2172894ec84324b94244826a9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 7 Nov 2006 21:03:20 +0000 Subject: [ARM] Remove EEPROM slave emulation from i2c-pxa driver. The i2c-pxa driver should not contain EEPROM slave-mode emulation; this is something the platform should provide where required. Remove it. Signed-off-by: Russell King diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index c95a6c1..c3b1567 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -358,133 +358,6 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) #ifdef CONFIG_I2C_PXA_SLAVE /* - * I2C EEPROM emulation. - */ -static struct i2c_eeprom_emu eeprom = { - .size = I2C_EEPROM_EMU_SIZE, - .watch = LIST_HEAD_INIT(eeprom.watch), -}; - -struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void) -{ - return &eeprom; -} - -int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data, - unsigned int addr, unsigned int size, - struct i2c_eeprom_emu_watcher *watcher) -{ - struct i2c_eeprom_emu_watch *watch; - unsigned long flags; - - if (addr + size > emu->size) - return -EINVAL; - - watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL); - if (watch) { - watch->start = addr; - watch->end = addr + size - 1; - watch->ops = watcher; - watch->data = data; - - local_irq_save(flags); - list_add(&watch->node, &emu->watch); - local_irq_restore(flags); - } - - return watch ? 0 : -ENOMEM; -} - -void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data, - struct i2c_eeprom_emu_watcher *watcher) -{ - struct i2c_eeprom_emu_watch *watch, *n; - unsigned long flags; - - list_for_each_entry_safe(watch, n, &emu->watch, node) { - if (watch->ops == watcher && watch->data == data) { - local_irq_save(flags); - list_del(&watch->node); - local_irq_restore(flags); - kfree(watch); - } - } -} - -static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event) -{ - struct i2c_eeprom_emu *emu = ptr; - - eedbg(3, "i2c_eeprom_emu_event: %d\n", event); - - switch (event) { - case I2C_SLAVE_EVENT_START_WRITE: - emu->seen_start = 1; - eedbg(2, "i2c_eeprom: write initiated\n"); - break; - - case I2C_SLAVE_EVENT_START_READ: - emu->seen_start = 0; - eedbg(2, "i2c_eeprom: read initiated\n"); - break; - - case I2C_SLAVE_EVENT_STOP: - emu->seen_start = 0; - eedbg(2, "i2c_eeprom: received stop\n"); - break; - - default: - eedbg(0, "i2c_eeprom: unhandled event\n"); - break; - } -} - -static int i2c_eeprom_emu_read(void *ptr) -{ - struct i2c_eeprom_emu *emu = ptr; - int ret; - - ret = emu->bytes[emu->ptr]; - emu->ptr = (emu->ptr + 1) % emu->size; - - return ret; -} - -static void i2c_eeprom_emu_write(void *ptr, unsigned int val) -{ - struct i2c_eeprom_emu *emu = ptr; - struct i2c_eeprom_emu_watch *watch; - - if (emu->seen_start != 0) { - eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val); - emu->ptr = val; - emu->seen_start = 0; - return; - } - - emu->bytes[emu->ptr] = val; - - eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n", - emu->ptr, val); - - list_for_each_entry(watch, &emu->watch, node) { - if (!watch->ops || !watch->ops->write) - continue; - if (watch->start <= emu->ptr && watch->end >= emu->ptr) - watch->ops->write(watch->data, emu->ptr, val); - } - - emu->ptr = (emu->ptr + 1) % emu->size; -} - -struct i2c_slave_client eeprom_client = { - .data = &eeprom, - .event = i2c_eeprom_emu_event, - .read = i2c_eeprom_emu_read, - .write = i2c_eeprom_emu_write -}; - -/* * PXA I2C Slave mode */ @@ -963,11 +836,9 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->slave_addr = I2C_PXA_SLAVE_ADDR; #ifdef CONFIG_I2C_PXA_SLAVE - i2c->slave = &eeprom_client; if (plat) { i2c->slave_addr = plat->slave_addr; - if (plat->slave) - i2c->slave = plat->slave; + i2c->slave = plat->slave; } #endif diff --git a/include/linux/i2c-pxa.h b/include/linux/i2c-pxa.h index 5f3eaf8..41dcdfe 100644 --- a/include/linux/i2c-pxa.h +++ b/include/linux/i2c-pxa.h @@ -1,29 +1,6 @@ #ifndef _LINUX_I2C_ALGO_PXA_H #define _LINUX_I2C_ALGO_PXA_H -struct i2c_eeprom_emu_watcher { - void (*write)(void *, unsigned int addr, unsigned char newval); -}; - -struct i2c_eeprom_emu_watch { - struct list_head node; - unsigned int start; - unsigned int end; - struct i2c_eeprom_emu_watcher *ops; - void *data; -}; - -#define I2C_EEPROM_EMU_SIZE (256) - -struct i2c_eeprom_emu { - unsigned int size; - unsigned int ptr; - unsigned int seen_start; - struct list_head watch; - - unsigned char bytes[I2C_EEPROM_EMU_SIZE]; -}; - typedef enum i2c_slave_event_e { I2C_SLAVE_EVENT_START_READ, I2C_SLAVE_EVENT_START_WRITE, @@ -37,12 +14,4 @@ struct i2c_slave_client { void (*write)(void *ptr, unsigned int val); }; -extern int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *, void *data, - unsigned int addr, unsigned int size, - struct i2c_eeprom_emu_watcher *); - -extern void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *, void *data, struct i2c_eeprom_emu_watcher *watcher); - -extern struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void); - #endif /* _LINUX_I2C_ALGO_PXA_H */ -- cgit v0.10.2 From 4a5222ca435c2af7466e5d262389609978a8e576 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Nov 2006 14:07:52 +0000 Subject: [ARM] Arrange asm-arm/elf.h so it can be included by assembly Prepare elf.h so that assembly code can include this file. Signed-off-by: Russell King diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index 17f0c65..3094243 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -1,17 +1,22 @@ #ifndef __ASMARM_ELF_H #define __ASMARM_ELF_H - +#ifndef __ASSEMBLY__ /* * ELF register definitions.. */ - #include #include typedef unsigned long elf_greg_t; typedef unsigned long elf_freg_t[3]; +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fp elf_fpregset_t; +#endif + #define EM_ARM 40 #define EF_ARM_APCS26 0x08 #define EF_ARM_SOFT_FLOAT 0x200 @@ -23,11 +28,6 @@ typedef unsigned long elf_freg_t[3]; #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 -#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_fp elf_fpregset_t; - /* * These are used to set parameters in the core dumps. */ @@ -42,10 +42,50 @@ typedef struct user_fp elf_fpregset_t; #ifdef __KERNEL__ #include +#ifndef __ASSEMBLY__ +/* + * This yields a mask that user programs can use to figure out what + * instruction set this cpu supports. + */ +#define ELF_HWCAP (elf_hwcap) +extern unsigned int elf_hwcap; + +/* + * This yields a string that ld.so will use to load implementation + * specific libraries for optimization. This is more specific in + * intent than poking at uname or /proc/cpuinfo. + * + * For now we just provide a fairly general string that describes the + * processor family. This could be made more specific later if someone + * implemented optimisations that require it. 26-bit CPUs give you + * "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't + * supported). 32-bit CPUs give you "v3[lb]" for anything based on an + * ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1 + * core. + */ +#define ELF_PLATFORM_SIZE 8 +#define ELF_PLATFORM (elf_platform) + +extern char elf_platform[]; +#endif + /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) ) +#define elf_check_arch(x) ((x)->e_machine == EM_ARM && ELF_PROC_OK(x)) + +/* + * 32-bit code is always OK. Some cpus can do 26-bit, some can't. + */ +#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) + +#define ELF_THUMB_OK(x) \ + ((elf_hwcap & HWCAP_THUMB && ((x)->e_entry & 1) == 1) || \ + ((x)->e_entry & 3) == 0) + +#define ELF_26BIT_OK(x) \ + ((elf_hwcap & HWCAP_26BIT && (x)->e_flags & EF_ARM_APCS26) || \ + ((x)->e_flags & EF_ARM_APCS26) == 0) #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 4096 @@ -62,40 +102,6 @@ typedef struct user_fp elf_fpregset_t; have no such handler. */ #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 -/* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. */ - -#define ELF_HWCAP (elf_hwcap) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. */ - -/* For now we just provide a fairly general string that describes the - processor family. This could be made more specific later if someone - implemented optimisations that require it. 26-bit CPUs give you - "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't - supported). 32-bit CPUs give you "v3[lb]" for anything based on an - ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1 - core. */ - -#define ELF_PLATFORM_SIZE 8 -extern char elf_platform[]; -#define ELF_PLATFORM (elf_platform) - -/* - * 32-bit code is always OK. Some cpus can do 26-bit, some can't. - */ -#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) - -#define ELF_THUMB_OK(x) \ - (( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \ - ((x)->e_entry & 3) == 0) - -#define ELF_26BIT_OK(x) \ - (( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \ - ((x)->e_flags & EF_ARM_APCS26) == 0) - #ifndef CONFIG_IWMMXT /* Old NetWinder binaries were compiled in such a way that the iBCS @@ -104,7 +110,7 @@ extern char elf_platform[]; there is no other ELF system currently supported by iBCS. @@ Could print a warning message to encourage users to upgrade. */ #define SET_PERSONALITY(ex,ibcs2) \ - set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT)) + set_personality(((ex).e_flags & EF_ARM_APCS26 ? PER_LINUX : PER_LINUX_32BIT)) #else -- cgit v0.10.2 From ee90dabcadd053d5dd69f3a7f8161afa2c751ace Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Nov 2006 14:20:47 +0000 Subject: [ARM] Include asm/elf.h instead of asm/procinfo.h These files want to provide/access ELF hwcap information, so should be including asm/elf.h rather than asm/procinfo.h Signed-off-by: Russell King diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index cc2d58d..3c078e3 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * Make sure that the compiler and target are compatible. diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index f359a18..0119c0d 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index ebc3e74..bda0748 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 48cf7ff..f2b1d61 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/arch/arm/mach-integrator/platsmp.c b/arch/arm/mach-integrator/platsmp.c index 1bc8534..613b841 100644 --- a/arch/arm/mach-integrator/platsmp.c +++ b/arch/arm/mach-integrator/platsmp.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 1d8316f..289b8e6 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 89b1d6d..bed9db6 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index a089528..d2a7c1b 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index d6d84d9..3247ce5 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index 0432e48..ce4f9ee 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include ENTRY(cpu_arm6_dcache_clean_area) diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index c2f0705..c04c194 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -36,9 +36,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S index 4071381..7069f49 100644 --- a/arch/arm/mm/proc-arm740.S +++ b/arch/arm/mm/proc-arm740.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index 22d7e31..d091c25 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 4adb46b..65cbb28 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -28,9 +28,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 571f082..52761b7 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 8d9a9f9..5b74339 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -52,9 +52,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 44a7a65..8628ed2 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -28,9 +28,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 2397f4b6..786c593 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -11,9 +11,9 @@ #include #include #include +#include #include #include -#include #include /* ARM940T has a 4KB DCache comprising 256 lines of 4 words */ diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index e186175..a60c142 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #include /* diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index 918ebf6..4848eea 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index c878064..cd7d865 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index b23b66a..b776653 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 6f72549..b440c8a 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 4ace2d8..c4d778a 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 2749c1f..906e9de 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 04f4d34..b442e8e 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -20,7 +20,6 @@ #ifdef __KERNEL__ #include -#include #include union debug_insn { -- cgit v0.10.2 From 5974eaaedee49c25d7231cc72dc0b7b9d2ef2fd7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Nov 2006 14:37:06 +0000 Subject: [ARM] Move HWCAP_* definitions to asm/elf.h Move HWCAP_* definitions into asm/elf.h, where they should belong. Since userspace wants to get at these definitions by including asm/procinfo.h, include asm/elf.h from this file if __KERNEL__ is not defined, and issue a warning suggesting to fix the program up to use asm/elf.h instead. Signed-off-by: Russell King diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index 3094243..f392930 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -39,9 +39,21 @@ typedef struct user_fp elf_fpregset_t; #endif #define ELF_ARCH EM_ARM -#ifdef __KERNEL__ -#include +/* + * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP + */ +#define HWCAP_SWP 1 +#define HWCAP_HALF 2 +#define HWCAP_THUMB 4 +#define HWCAP_26BIT 8 /* Play it safe */ +#define HWCAP_FAST_MULT 16 +#define HWCAP_FPA 32 +#define HWCAP_VFP 64 +#define HWCAP_EDSP 128 +#define HWCAP_JAVA 256 +#define HWCAP_IWMMXT 512 +#ifdef __KERNEL__ #ifndef __ASSEMBLY__ /* * This yields a mask that user programs can use to figure out what diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h index 91a31ad..4d3c685 100644 --- a/include/asm-arm/procinfo.h +++ b/include/asm-arm/procinfo.h @@ -10,7 +10,7 @@ #ifndef __ASM_PROCINFO_H #define __ASM_PROCINFO_H -#ifndef __ASSEMBLY__ +#ifdef __KERNEL__ struct cpu_tlb_fns; struct cpu_user_fns; @@ -42,19 +42,8 @@ struct proc_info_list { struct cpu_cache_fns *cache; }; -extern unsigned int elf_hwcap; - -#endif /* __ASSEMBLY__ */ - -#define HWCAP_SWP 1 -#define HWCAP_HALF 2 -#define HWCAP_THUMB 4 -#define HWCAP_26BIT 8 /* Play it safe */ -#define HWCAP_FAST_MULT 16 -#define HWCAP_FPA 32 -#define HWCAP_VFP 64 -#define HWCAP_EDSP 128 -#define HWCAP_JAVA 256 -#define HWCAP_IWMMXT 512 - +#else /* __KERNEL__ */ +#include +#warning "Please include asm/elf.h instead" +#endif /* __KERNEL__ */ #endif -- cgit v0.10.2 From 80bcddc19d08a6eee99fb1bf3470ad6257af8721 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Nov 2006 14:45:22 +0000 Subject: [ARM] Convert apm.c to use mutexes instead of semaphores More semaphore-as-mutex to mutex conversions. Signed-off-by: Russell King diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index 845af0b..a11fb9a 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c @@ -102,7 +102,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); static DEFINE_SPINLOCK(kapmd_queue_lock); static struct apm_queue kapmd_queue; -static DECLARE_MUTEX(state_lock); +static DEFINE_MUTEX(state_lock); static const char driver_version[] = "1.13"; /* no spaces */ @@ -176,7 +176,7 @@ static int queue_suspend_event(apm_event_t event, struct apm_user *sender) struct apm_user *as; int ret = 1; - down(&state_lock); + mutex_lock(&state_lock); down_read(&user_list_lock); /* @@ -201,7 +201,7 @@ static int queue_suspend_event(apm_event_t event, struct apm_user *sender) } out: up_read(&user_list_lock); - up(&state_lock); + mutex_unlock(&state_lock); wake_up_interruptible(&apm_waitqueue); return ret; } @@ -220,7 +220,7 @@ static void apm_suspend(void) /* * Finally, wake up anyone who is sleeping on the suspend. */ - down(&state_lock); + mutex_lock(&state_lock); down_read(&user_list_lock); list_for_each_entry(as, &apm_user_list, list) { if (as->suspend_state == SUSPEND_WAIT || @@ -230,7 +230,7 @@ static void apm_suspend(void) } } up_read(&user_list_lock); - up(&state_lock); + mutex_unlock(&state_lock); wake_up(&apm_suspend_waitqueue); } @@ -256,11 +256,11 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t if (copy_to_user(buf, &event, sizeof(event))) break; - down(&state_lock); + mutex_lock(&state_lock); if (as->suspend_state == SUSPEND_PENDING && (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) as->suspend_state = SUSPEND_READ; - up(&state_lock); + mutex_unlock(&state_lock); buf += sizeof(event); i -= sizeof(event); @@ -302,7 +302,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) switch (cmd) { case APM_IOC_SUSPEND: - down(&state_lock); + mutex_lock(&state_lock); as->suspend_result = -EINTR; @@ -317,7 +317,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) as->suspend_state = SUSPEND_ACKED; suspends_pending--; pending = suspends_pending == 0; - up(&state_lock); + mutex_unlock(&state_lock); /* * If there are no further acknowledges required, @@ -341,7 +341,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) as->suspend_state == SUSPEND_DONE); } else { as->suspend_state = SUSPEND_WAIT; - up(&state_lock); + mutex_unlock(&state_lock); /* * Otherwise it is a request to suspend the system. @@ -379,10 +379,10 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) current->flags = flags; - down(&state_lock); + mutex_lock(&state_lock); err = as->suspend_result; as->suspend_state = SUSPEND_NONE; - up(&state_lock); + mutex_unlock(&state_lock); break; } @@ -406,12 +406,12 @@ static int apm_release(struct inode * inode, struct file * filp) * need to balance suspends_pending, which means the * possibility of sleeping. */ - down(&state_lock); + mutex_lock(&state_lock); if (as->suspend_state != SUSPEND_NONE) { suspends_pending -= 1; pending = suspends_pending == 0; } - up(&state_lock); + mutex_unlock(&state_lock); if (pending) apm_suspend(); -- cgit v0.10.2 From eb8b0afc3a228cf6e0e1f9045127da3e72a6866b Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Nov 2006 15:16:16 +0000 Subject: [ARM] Remove DEBUG_WAITQ DEBUG_WAITQ appears to have been removed by others, but no one removed the configuration option from ARM. Remote it from both Kconfig.debug and all default configurations. Signed-off-by: Russell King diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index d22f38b..40c5eb1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -32,10 +32,6 @@ config DEBUG_USER 8 - SIGSEGV faults 16 - SIGBUS faults -config DEBUG_WAITQ - bool "Wait queue debugging" - depends on DEBUG_KERNEL - config DEBUG_ERRORS bool "Verbose kernel error messages" depends on DEBUG_KERNEL diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index b430414..02164c1 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -979,7 +979,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index d96fc83..bee410c 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -968,7 +968,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig index cfe6bd8..821865f 100644 --- a/arch/arm/configs/badge4_defconfig +++ b/arch/arm/configs/badge4_defconfig @@ -1216,7 +1216,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig index 09b7acd..ee130b5 100644 --- a/arch/arm/configs/cerfcube_defconfig +++ b/arch/arm/configs/cerfcube_defconfig @@ -851,7 +851,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index a375891..970c8c7 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig @@ -934,7 +934,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig index c41c04f..e8980a9 100644 --- a/arch/arm/configs/corgi_defconfig +++ b/arch/arm/configs/corgi_defconfig @@ -1513,7 +1513,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index 20e6825..2cadd51 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig @@ -1113,7 +1113,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index df8595a..807f7fc 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -1062,7 +1062,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 3b4802a..58d5974 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -1134,7 +1134,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_WAITQ=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig index 9d62ed1..0e739af 100644 --- a/arch/arm/configs/h7202_defconfig +++ b/arch/arm/configs/h7202_defconfig @@ -702,7 +702,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig index a45b575..1c8fb89 100644 --- a/arch/arm/configs/hackkit_defconfig +++ b/arch/arm/configs/hackkit_defconfig @@ -740,7 +740,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_WAITQ=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 692ab57..3ce96e6 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -835,7 +835,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig index 0d67f66..b275c53 100644 --- a/arch/arm/configs/iop32x_defconfig +++ b/arch/arm/configs/iop32x_defconfig @@ -1204,7 +1204,6 @@ CONFIG_FRAME_POINTER=y # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/iop33x_defconfig b/arch/arm/configs/iop33x_defconfig index 2a8fc15..848e3ac 100644 --- a/arch/arm/configs/iop33x_defconfig +++ b/arch/arm/configs/iop33x_defconfig @@ -1051,7 +1051,6 @@ CONFIG_FRAME_POINTER=y # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig index 27b3e31..bbd2dcf 100644 --- a/arch/arm/configs/ixp2000_defconfig +++ b/arch/arm/configs/ixp2000_defconfig @@ -1026,7 +1026,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig index 7b18997..06deefa 100644 --- a/arch/arm/configs/ixp23xx_defconfig +++ b/arch/arm/configs/ixp23xx_defconfig @@ -1305,7 +1305,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index fac7c3b..fabf74c 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -1243,7 +1243,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig index 80a6fd9..0c55628 100644 --- a/arch/arm/configs/jornada720_defconfig +++ b/arch/arm/configs/jornada720_defconfig @@ -889,7 +889,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig index b4cd4b4..89e116f 100644 --- a/arch/arm/configs/kb9202_defconfig +++ b/arch/arm/configs/kb9202_defconfig @@ -753,7 +753,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig index 4b29e09..e146189 100644 --- a/arch/arm/configs/lpd270_defconfig +++ b/arch/arm/configs/lpd270_defconfig @@ -949,7 +949,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig index bf9cf9c..f8ac29d 100644 --- a/arch/arm/configs/lpd7a400_defconfig +++ b/arch/arm/configs/lpd7a400_defconfig @@ -850,7 +850,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig index 3a57be3..46a0f7f 100644 --- a/arch/arm/configs/lpd7a404_defconfig +++ b/arch/arm/configs/lpd7a404_defconfig @@ -1100,7 +1100,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig index 81daadc..e544bfb 100644 --- a/arch/arm/configs/lubbock_defconfig +++ b/arch/arm/configs/lubbock_defconfig @@ -772,7 +772,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig index b112bd7..cc8c95b 100644 --- a/arch/arm/configs/mainstone_defconfig +++ b/arch/arm/configs/mainstone_defconfig @@ -766,7 +766,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig index d16f6cd..577d7e1 100644 --- a/arch/arm/configs/mx1ads_defconfig +++ b/arch/arm/configs/mx1ads_defconfig @@ -691,7 +691,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig index df8168e..e86794a 100644 --- a/arch/arm/configs/neponset_defconfig +++ b/arch/arm/configs/neponset_defconfig @@ -1115,7 +1115,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/netwinder_defconfig b/arch/arm/configs/netwinder_defconfig index 2cae1ea..c1a63a3 100644 --- a/arch/arm/configs/netwinder_defconfig +++ b/arch/arm/configs/netwinder_defconfig @@ -994,7 +994,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 61115a7..57f32f3 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -872,7 +872,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig index 9b9f215..0498ebd 100644 --- a/arch/arm/configs/onearm_defconfig +++ b/arch/arm/configs/onearm_defconfig @@ -1045,7 +1045,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig index 24e8bdd..a6b47ea 100644 --- a/arch/arm/configs/pleb_defconfig +++ b/arch/arm/configs/pleb_defconfig @@ -721,7 +721,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig index a4989f4..b5e11aa 100644 --- a/arch/arm/configs/pnx4008_defconfig +++ b/arch/arm/configs/pnx4008_defconfig @@ -1604,7 +1604,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig index b71d31a..46e5089 100644 --- a/arch/arm/configs/pxa255-idp_defconfig +++ b/arch/arm/configs/pxa255-idp_defconfig @@ -768,7 +768,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig index ffd905f..fc39ba1 100644 --- a/arch/arm/configs/realview-smp_defconfig +++ b/arch/arm/configs/realview-smp_defconfig @@ -967,7 +967,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index 3f1ec4e..accbf52 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -759,7 +759,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index b498afd..bc09126 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig @@ -910,7 +910,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index c0152393..3b31a33 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1319,7 +1319,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig index c48d170..9b6561d 100644 --- a/arch/arm/configs/shark_defconfig +++ b/arch/arm/configs/shark_defconfig @@ -965,7 +965,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig index 140056a..03f783e 100644 --- a/arch/arm/configs/simpad_defconfig +++ b/arch/arm/configs/simpad_defconfig @@ -934,7 +934,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig index bd03238..aa7a011 100644 --- a/arch/arm/configs/spitz_defconfig +++ b/arch/arm/configs/spitz_defconfig @@ -1406,7 +1406,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index f7bf6ef..48dca69 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -972,7 +972,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set -- cgit v0.10.2 From d94cffe3d3794f70f928c3e5b97c252930775332 Mon Sep 17 00:00:00 2001 From: stanley cai Date: Mon, 16 Oct 2006 15:13:30 +0100 Subject: [ARM] 3893/1: pxa27x: Update UDCISR1 bit definitions This patch updates several bit definitions name in UDCISR1 register. Signed-off-by: Stanley Cai Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index cff752f..9b82531 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -803,12 +803,11 @@ #define UDCISR0 __REG(0x4060000C) /* UDC Interrupt Status Register 0 */ #define UDCISR1 __REG(0x40600010) /* UDC Interrupt Status Register 1 */ #define UDCISR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2)) -#define UDCISR1_IECC (1 << 31) /* IntEn - Configuration Change */ -#define UDCISR1_IESOF (1 << 30) /* IntEn - Start of Frame */ -#define UDCISR1_IERU (1 << 29) /* IntEn - Resume */ -#define UDCISR1_IESU (1 << 28) /* IntEn - Suspend */ -#define UDCISR1_IERS (1 << 27) /* IntEn - Reset */ - +#define UDCISR1_IRCC (1 << 31) /* IntReq - Configuration Change */ +#define UDCISR1_IRSOF (1 << 30) /* IntReq - Start of Frame */ +#define UDCISR1_IRRU (1 << 29) /* IntReq - Resume */ +#define UDCISR1_IRSU (1 << 28) /* IntReq - Suspend */ +#define UDCISR1_IRRS (1 << 27) /* IntReq - Reset */ #define UDCFNR __REG(0x40600014) /* UDC Frame Number Register */ #define UDCOTGICR __REG(0x40600018) /* UDC On-The-Go interrupt control */ -- cgit v0.10.2 From 127e477e0cd8da4d3058709ab2dc7b92dccbcba5 Mon Sep 17 00:00:00 2001 From: stanley cai Date: Mon, 16 Oct 2006 15:13:43 +0100 Subject: [ARM] 3894/1: pxa27x: Update DCSR_EORINTR bit definition in DCSR This patch updates a bit definition name to align with the PXA27x spec.EORINTR(End-Of-Receive Intr) bit in DCSR register (DMA Channel Control/Status Register) Signed-off-by: Stanley Cai Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 9b82531..083e03c 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -99,7 +99,7 @@ #define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ #define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ #define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ -#define DCSR_ENRINTR (1 << 9) /* The end of Receive */ +#define DCSR_EORINTR (1 << 9) /* The end of Receive */ #endif #define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ #define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ -- cgit v0.10.2 From 10dd5ce28d78e2440e8fa1135d17e33399d75340 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 23 Nov 2006 11:41:32 +0000 Subject: [ARM] Remove compatibility layer for ARM irqs set_irq_chipdata -> set_irq_chip_data get_irq_chipdata -> get_irq_chip_data do_level_IRQ -> handle_level_irq do_edge_IRQ -> handle_edge_irq do_simple_IRQ -> handle_simple_irq irqdesc -> irq_desc irqchip -> irq_chip Signed-off-by: Russell King diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index f3e020f..09b9d1b 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -160,7 +160,7 @@ void __init gic_dist_init(void __iomem *base) */ for (i = 29; i < max_irq; i++) { set_irq_chip(i, &gic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 80a72c7..cfe6f46 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -163,11 +163,11 @@ static struct locomo_dev_info locomo_devices[] = { #define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT) #define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR) -static void locomo_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); /* Acknowledge the parent IRQ */ desc->chip->ack(irq); @@ -194,7 +194,7 @@ static void locomo_ack_irq(unsigned int irq) static void locomo_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); @@ -203,7 +203,7 @@ static void locomo_mask_irq(unsigned int irq) static void locomo_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r |= (0x0010 << (irq - LOCOMO_IRQ_START)); @@ -217,10 +217,10 @@ static struct irq_chip locomo_chip = { .unmask = locomo_unmask_irq, }; -static void locomo_key_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_key_handler(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { d = irq_desc + LOCOMO_IRQ_KEY_START; @@ -230,7 +230,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc) static void locomo_key_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); @@ -239,7 +239,7 @@ static void locomo_key_ack_irq(unsigned int irq) static void locomo_key_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -248,7 +248,7 @@ static void locomo_key_mask_irq(unsigned int irq) static void locomo_key_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -262,11 +262,11 @@ static struct irq_chip locomo_key_chip = { .unmask = locomo_key_unmask_irq, }; -static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_GIR) & locomo_readl(mapbase + LOCOMO_GPD) & @@ -285,7 +285,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc) static void locomo_gpio_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GWE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -302,7 +302,7 @@ static void locomo_gpio_ack_irq(unsigned int irq) static void locomo_gpio_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -311,7 +311,7 @@ static void locomo_gpio_mask_irq(unsigned int irq) static void locomo_gpio_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -325,10 +325,10 @@ static struct irq_chip locomo_gpio_chip = { .unmask = locomo_gpio_unmask_irq, }; -static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { d = irq_desc + LOCOMO_IRQ_LT_START; @@ -338,7 +338,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc) static void locomo_lt_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); @@ -347,7 +347,7 @@ static void locomo_lt_ack_irq(unsigned int irq) static void locomo_lt_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -356,7 +356,7 @@ static void locomo_lt_mask_irq(unsigned int irq) static void locomo_lt_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -370,11 +370,11 @@ static struct irq_chip locomo_lt_chip = { .unmask = locomo_lt_unmask_irq, }; -static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F; if (req) { @@ -391,7 +391,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc) static void locomo_spi_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -408,7 +408,7 @@ static void locomo_spi_ack_irq(unsigned int irq) static void locomo_spi_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -417,7 +417,7 @@ static void locomo_spi_mask_irq(unsigned int irq) static void locomo_spi_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -440,55 +440,55 @@ static void locomo_setup_irq(struct locomo *lchip) * Install handler for IRQ_LOCOMO_HW. */ set_irq_type(lchip->irq, IRQT_FALLING); - set_irq_chipdata(lchip->irq, irqbase); + set_irq_chip_data(lchip->irq, irqbase); set_irq_chained_handler(lchip->irq, locomo_handler); /* Install handlers for IRQ_LOCOMO_*_BASE */ set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_KEY_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_GPIO_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler); set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_LT_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler); set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler); set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */ set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip); - set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase); - set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ); + set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase); + set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq); set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */ for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) { set_irq_chip(irq, &locomo_gpio_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */ set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip); - set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase); - set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ); + set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase); + set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq); set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */ for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) { set_irq_chip(irq, &locomo_spi_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index d5f7201..fe3f059 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -147,7 +147,7 @@ void __init sa1111_adjust_zones(int node, unsigned long *size, unsigned long *ho * will call us again if there are more interrupts to process. */ static void -sa1111_irq_handler(unsigned int irq, struct irqdesc *desc) +sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int stat0, stat1, i; void __iomem *base = get_irq_data(irq); @@ -187,7 +187,7 @@ static void sa1111_ack_irq(unsigned int irq) static void sa1111_mask_lowirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -197,7 +197,7 @@ static void sa1111_mask_lowirq(unsigned int irq) static void sa1111_unmask_lowirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -215,7 +215,7 @@ static void sa1111_unmask_lowirq(unsigned int irq) static int sa1111_retrigger_lowirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip0; int i; @@ -236,7 +236,7 @@ static int sa1111_retrigger_lowirq(unsigned int irq) static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip0; if (flags == IRQT_PROBE) @@ -259,7 +259,7 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long we0; we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); @@ -284,7 +284,7 @@ static struct irq_chip sa1111_low_chip = { static void sa1111_mask_highirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -294,7 +294,7 @@ static void sa1111_mask_highirq(unsigned int irq) static void sa1111_unmask_highirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -312,7 +312,7 @@ static void sa1111_unmask_highirq(unsigned int irq) static int sa1111_retrigger_highirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip1; int i; @@ -333,7 +333,7 @@ static int sa1111_retrigger_highirq(unsigned int irq) static int sa1111_type_highirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip1; if (flags == IRQT_PROBE) @@ -356,7 +356,7 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) static int sa1111_wake_highirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long we1; we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); @@ -410,15 +410,15 @@ static void sa1111_setup_irq(struct sa1111 *sachip) for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { set_irq_chip(irq, &sa1111_low_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { set_irq_chip(irq, &sa1111_high_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 43d2781..c026fa2 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -27,14 +27,14 @@ static void vic_mask_irq(unsigned int irq) { - void __iomem *base = get_irq_chipdata(irq); + void __iomem *base = get_irq_chip_data(irq); irq &= 31; writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(unsigned int irq) { - void __iomem *base = get_irq_chipdata(irq); + void __iomem *base = get_irq_chip_data(irq); irq &= 31; writel(1 << irq, base + VIC_INT_ENABLE); } @@ -88,10 +88,10 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, unsigned int irq = irq_start + i; set_irq_chip(irq, &vic_chip); - set_irq_chipdata(irq, base); + set_irq_chip_data(irq, base); if (vic_sources & (1 << i)) { - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index b27513a..a786f76 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -529,7 +529,7 @@ static void ecard_dump_irq_state(void) } } -static void ecard_check_lockup(struct irqdesc *desc) +static void ecard_check_lockup(struct irq_desc *desc) { static unsigned long last; static int lockup; @@ -567,7 +567,7 @@ static void ecard_check_lockup(struct irqdesc *desc) } static void -ecard_irq_handler(unsigned int irq, struct irqdesc *desc) +ecard_irq_handler(unsigned int irq, struct irq_desc *desc) { ecard_t *ec; int called = 0; @@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc) pending = ecard_default_ops.irqpending(ec); if (pending) { - struct irqdesc *d = irq_desc + ec->irq; + struct irq_desc *d = irq_desc + ec->irq; desc_handle_irq(ec->irq, d); called ++; } @@ -609,7 +609,7 @@ static unsigned char first_set[] = }; static void -ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc) +ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc) { const unsigned int statusmask = 15; unsigned int status; @@ -1022,7 +1022,7 @@ ecard_probe(int slot, card_type_t type) if (slot < 8) { ec->irq = 32 + slot; set_irq_chip(ec->irq, &ecard_chip); - set_irq_handler(ec->irq, do_level_IRQ); + set_irq_handler(ec->irq, handle_level_irq); set_irq_flags(ec->irq, IRQF_VALID); } diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 2c4ff1c..ec01f08 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -112,7 +112,7 @@ static struct irq_desc bad_irq_desc = { asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - struct irqdesc *desc = irq_desc + irq; + struct irq_desc *desc = irq_desc + irq; /* * Some hardware gives randomly wrong interrupts. Rather @@ -134,7 +134,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) void set_irq_flags(unsigned int irq, unsigned int iflags) { - struct irqdesc *desc; + struct irq_desc *desc; unsigned long flags; if (irq >= NR_IRQS) { @@ -171,7 +171,7 @@ void __init init_IRQ(void) #ifdef CONFIG_HOTPLUG_CPU -static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) { pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); @@ -190,7 +190,7 @@ void migrate_irqs(void) unsigned int i, cpu = smp_processor_id(); for (i = 0; i < NR_IRQS; i++) { - struct irqdesc *desc = irq_desc + i; + struct irq_desc *desc = irq_desc + i; if (desc->cpu == cpu) { unsigned int newcpu = any_online_cpu(desc->affinity); diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c index fe3d297..a950160 100644 --- a/arch/arm/mach-aaec2000/core.c +++ b/arch/arm/mach-aaec2000/core.c @@ -82,7 +82,7 @@ static void aaec2000_int_unmask(unsigned int irq) IRQ_INTENS |= (1 << irq); } -static struct irqchip aaec2000_irq_chip = { +static struct irq_chip aaec2000_irq_chip = { .ack = aaec2000_int_ack, .mask = aaec2000_int_mask, .unmask = aaec2000_int_unmask, @@ -93,7 +93,7 @@ void __init aaec2000_init_irq(void) unsigned int i; for (i = 0; i < NR_IRQS; i++) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &aaec2000_irq_chip); set_irq_flags(i, IRQF_VALID); } diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 7467d64..cec3862 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -332,10 +332,10 @@ static struct irq_chip gpio_irqchip = { .set_wake = gpio_irq_set_wake, }; -static void gpio_irq_handler(unsigned irq, struct irqdesc *desc) +static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; - struct irqdesc *gpio; + struct irq_desc *gpio; void __iomem *pio; u32 isr; @@ -396,7 +396,7 @@ void __init at91_gpio_irq_setup(void) __raw_writel(~0, controller + PIO_IDR); set_irq_data(id, (void *) pin); - set_irq_chipdata(id, controller); + set_irq_chip_data(id, controller); for (i = 0; i < 32; i++, pin++) { /* @@ -404,7 +404,7 @@ void __init at91_gpio_irq_setup(void) * shorter, and the AIC handles interupts sanely. */ set_irq_chip(pin, &gpio_irqchip); - set_irq_handler(pin, do_simple_IRQ); + set_irq_handler(pin, handle_simple_irq); set_irq_flags(pin, IRQF_VALID); } diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index 3e48811..cab0de9 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -139,7 +139,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); set_irq_chip(i, &at91_aic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ diff --git a/arch/arm/mach-clps711x/irq.c b/arch/arm/mach-clps711x/irq.c index 7ee926e..ca102960 100644 --- a/arch/arm/mach-clps711x/irq.c +++ b/arch/arm/mach-clps711x/irq.c @@ -63,7 +63,7 @@ static void int1_unmask(unsigned int irq) clps_writel(intmr1, INTMR1); } -static struct irqchip int1_chip = { +static struct irq_chip int1_chip = { .ack = int1_ack, .mask = int1_mask, .unmask = int1_unmask, @@ -100,7 +100,7 @@ static void int2_unmask(unsigned int irq) clps_writel(intmr2, INTMR2); } -static struct irqchip int2_chip = { +static struct irq_chip int2_chip = { .ack = int2_ack, .mask = int2_mask, .unmask = int2_unmask, @@ -112,12 +112,12 @@ void __init clps711x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { if (INT1_IRQS & (1 << i)) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &int1_chip); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } if (INT2_IRQS & (1 << i)) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &int2_chip); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index fb10cf2..231b900 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -57,7 +57,7 @@ static void cl7500_unmask_irq_a(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKA); } -static struct irqchip clps7500_a_chip = { +static struct irq_chip clps7500_a_chip = { .ack = cl7500_ack_irq_a, .mask = cl7500_mask_irq_a, .unmask = cl7500_unmask_irq_a, @@ -81,7 +81,7 @@ static void cl7500_unmask_irq_b(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKB); } -static struct irqchip clps7500_b_chip = { +static struct irq_chip clps7500_b_chip = { .ack = cl7500_mask_irq_b, .mask = cl7500_mask_irq_b, .unmask = cl7500_unmask_irq_b, @@ -105,7 +105,7 @@ static void cl7500_unmask_irq_c(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKC); } -static struct irqchip clps7500_c_chip = { +static struct irq_chip clps7500_c_chip = { .ack = cl7500_mask_irq_c, .mask = cl7500_mask_irq_c, .unmask = cl7500_unmask_irq_c, @@ -129,7 +129,7 @@ static void cl7500_unmask_irq_d(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKD); } -static struct irqchip clps7500_d_chip = { +static struct irq_chip clps7500_d_chip = { .ack = cl7500_mask_irq_d, .mask = cl7500_mask_irq_d, .unmask = cl7500_unmask_irq_d, @@ -153,7 +153,7 @@ static void cl7500_unmask_irq_dma(unsigned int irq) iomd_writeb(val | mask, IOMD_DMAMASK); } -static struct irqchip clps7500_dma_chip = { +static struct irq_chip clps7500_dma_chip = { .ack = cl7500_mask_irq_dma, .mask = cl7500_mask_irq_dma, .unmask = cl7500_unmask_irq_dma, @@ -177,7 +177,7 @@ static void cl7500_unmask_irq_fiq(unsigned int irq) iomd_writeb(val | mask, IOMD_FIQMASK); } -static struct irqchip clps7500_fiq_chip = { +static struct irq_chip clps7500_fiq_chip = { .ack = cl7500_mask_irq_fiq, .mask = cl7500_mask_irq_fiq, .unmask = cl7500_unmask_irq_fiq, @@ -187,7 +187,7 @@ static void cl7500_no_action(unsigned int irq) { } -static struct irqchip clps7500_no_chip = { +static struct irq_chip clps7500_no_chip = { .ack = cl7500_no_action, .mask = cl7500_no_action, .unmask = cl7500_no_action, @@ -214,43 +214,43 @@ static void __init clps7500_init_irq(void) switch (irq) { case 0 ... 7: set_irq_chip(irq, &clps7500_a_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 8 ... 15: set_irq_chip(irq, &clps7500_b_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 16 ... 22: set_irq_chip(irq, &clps7500_dma_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 24 ... 31: set_irq_chip(irq, &clps7500_c_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 40 ... 47: set_irq_chip(irq, &clps7500_d_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 48 ... 55: set_irq_chip(irq, &clps7500_no_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 64 ... 72: set_irq_chip(irq, &clps7500_fiq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; } diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 90103ab..8459431 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -45,7 +45,7 @@ static void ebsa110_unmask_irq(unsigned int irq) __raw_writeb(1 << irq, IRQ_MSET); } -static struct irqchip ebsa110_irq_chip = { +static struct irq_chip ebsa110_irq_chip = { .ack = ebsa110_mask_irq, .mask = ebsa110_mask_irq, .unmask = ebsa110_unmask_irq, @@ -67,7 +67,7 @@ static void __init ebsa110_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &ebsa110_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index e3fd1ab..d649b39 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -245,7 +245,7 @@ EXPORT_SYMBOL(gpio_line_set); * EP93xx IRQ handling *************************************************************************/ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned char status; int i; @@ -335,7 +335,7 @@ static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip ep93xx_gpio_ab_irq_chip = { +static struct irq_chip ep93xx_gpio_ab_irq_chip = { .ack = ep93xx_gpio_ab_irq_mask_ack, .mask = ep93xx_gpio_ab_irq_mask, .unmask = ep93xx_gpio_ab_irq_unmask, @@ -352,7 +352,7 @@ void __init ep93xx_init_irq(void) for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index af900f4..ef29fc3 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -78,7 +78,7 @@ static void fb_unmask_irq(unsigned int irq) *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)]; } -static struct irqchip fb_chip = { +static struct irq_chip fb_chip = { .ack = fb_mask_irq, .mask = fb_mask_irq, .unmask = fb_unmask_irq, @@ -96,7 +96,7 @@ static void __init __fb_init_irq(void) for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) { set_irq_chip(irq, &fb_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index 888dedd..79443ff 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -49,7 +49,7 @@ static void isa_unmask_pic_lo_irq(unsigned int irq) outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO); } -static struct irqchip isa_lo_chip = { +static struct irq_chip isa_lo_chip = { .ack = isa_ack_pic_lo_irq, .mask = isa_mask_pic_lo_irq, .unmask = isa_unmask_pic_lo_irq, @@ -78,14 +78,14 @@ static void isa_unmask_pic_hi_irq(unsigned int irq) outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI); } -static struct irqchip isa_hi_chip = { +static struct irq_chip isa_hi_chip = { .ack = isa_ack_pic_hi_irq, .mask = isa_mask_pic_hi_irq, .unmask = isa_unmask_pic_hi_irq, }; static void -isa_irq_handler(unsigned int irq, struct irqdesc *desc) +isa_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE; @@ -150,13 +150,13 @@ void __init isa_init_irq(unsigned int host_irq) if (host_irq != (unsigned int)-1) { for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) { set_irq_chip(irq, &isa_lo_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) { set_irq_chip(irq, &isa_hi_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c index 4719229..7f31816 100644 --- a/arch/arm/mach-h720x/common.c +++ b/arch/arm/mach-h720x/common.c @@ -101,7 +101,7 @@ static void inline unmask_gpio_irq(u32 irq) static void h720x_gpio_handler(unsigned int mask, unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { IRQDBG("%s irq: %d\n",__FUNCTION__,irq); desc = irq_desc + irq; @@ -117,7 +117,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq, } static void -h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -128,7 +128,7 @@ h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT); @@ -138,7 +138,7 @@ h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -149,7 +149,7 @@ h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -161,7 +161,7 @@ h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) #ifdef CONFIG_CPU_H7202 static void -h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioe_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -172,13 +172,13 @@ h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } #endif -static struct irqchip h720x_global_chip = { +static struct irq_chip h720x_global_chip = { .ack = mask_global_irq, .mask = mask_global_irq, .unmask = unmask_global_irq, }; -static struct irqchip h720x_gpio_chip = { +static struct irq_chip h720x_gpio_chip = { .ack = ack_gpio_irq, .mask = mask_gpio_irq, .unmask = unmask_gpio_irq, @@ -203,14 +203,14 @@ void __init h720x_init_irq (void) /* Initialize global IRQ's, fast path */ for (irq = 0; irq < NR_GLBL_IRQS; irq++) { set_irq_chip(irq, &h720x_global_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } /* Initialize multiplexed IRQ's, slow path */ for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) { set_irq_chip(irq, &h720x_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler); @@ -221,7 +221,7 @@ void __init h720x_init_irq (void) #ifdef CONFIG_CPU_H7202 for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) { set_irq_chip(irq, &h720x_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler); diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index 06fecae..703870f 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c @@ -106,7 +106,7 @@ static struct platform_device *devices[] __initdata = { * we have to handle all timer interrupts in one place. */ static void -h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -162,7 +162,7 @@ static void inline unmask_timerx_irq (u32 irq) CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit; } -static struct irqchip h7202_timerx_chip = { +static struct irq_chip h7202_timerx_chip = { .ack = mask_timerx_irq, .mask = mask_timerx_irq, .unmask = unmask_timerx_irq, @@ -202,7 +202,7 @@ void __init h7202_init_irq (void) irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) { mask_timerx_irq(irq); set_irq_chip(irq, &h7202_timerx_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler); diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c index 368b13b..0791b56 100644 --- a/arch/arm/mach-imx/irq.c +++ b/arch/arm/mach-imx/irq.c @@ -146,7 +146,7 @@ imx_gpio_unmask_irq(unsigned int irq) static void imx_gpio_handler(unsigned int mask, unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { desc = irq_desc + irq; while (mask) { @@ -161,7 +161,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq, } static void -imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -171,7 +171,7 @@ imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -181,7 +181,7 @@ imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -191,7 +191,7 @@ imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -230,13 +230,13 @@ imx_init_irq(void) for (irq = 0; irq < IMX_IRQS; irq++) { set_irq_chip(irq, &imx_internal_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) { set_irq_chip(irq, &imx_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 191c57a..7228075 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -183,7 +183,7 @@ static void __init ap_init_irq(void) for (i = 0; i < NR_IRQS; i++) { if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) { set_irq_chip(i, &sc_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 771b65b..913f64b 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -202,7 +202,7 @@ static struct irq_chip sic_chip = { }; static void -sic_handle_irq(unsigned int irq, struct irqdesc *desc) +sic_handle_irq(unsigned int irq, struct irq_desc *desc) { unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS); @@ -238,7 +238,7 @@ static void __init intcp_init_irq(void) if (i == 29) break; set_irq_chip(i, &pic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } @@ -247,7 +247,7 @@ static void __init intcp_init_irq(void) for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) { set_irq_chip(i, &cic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } @@ -256,7 +256,7 @@ static void __init intcp_init_irq(void) for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { set_irq_chip(i, &sic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c index 69d6302..3ec1cd5 100644 --- a/arch/arm/mach-iop32x/irq.c +++ b/arch/arm/mach-iop32x/irq.c @@ -70,7 +70,7 @@ void __init iop32x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { set_irq_chip(i, &ext_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c index 63304b3..00b37f3 100644 --- a/arch/arm/mach-iop33x/irq.c +++ b/arch/arm/mach-iop33x/irq.c @@ -121,7 +121,7 @@ void __init iop33x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 22c98e9..27b7480 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -308,7 +308,7 @@ EXPORT_SYMBOL(gpio_line_config); /************************************************************************* * IRQ handling IXP2000 *************************************************************************/ -static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_GPIO_INST; @@ -373,7 +373,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq) ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0))); } -static struct irqchip ixp2000_GPIO_irq_chip = { +static struct irq_chip ixp2000_GPIO_irq_chip = { .ack = ixp2000_GPIO_irq_mask_ack, .mask = ixp2000_GPIO_irq_mask, .unmask = ixp2000_GPIO_irq_unmask, @@ -401,7 +401,7 @@ static void ixp2000_pci_irq_unmask(unsigned int irq) /* * Error interrupts. These are used extensively by the microengine drivers */ -static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_IRQ_ERR_STATUS; @@ -426,13 +426,13 @@ static void ixp2000_err_irq_unmask(unsigned int irq) (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); } -static struct irqchip ixp2000_err_irq_chip = { +static struct irq_chip ixp2000_err_irq_chip = { .ack = ixp2000_err_irq_mask, .mask = ixp2000_err_irq_mask, .unmask = ixp2000_err_irq_unmask }; -static struct irqchip ixp2000_pci_irq_chip = { +static struct irq_chip ixp2000_pci_irq_chip = { .ack = ixp2000_pci_irq_mask, .mask = ixp2000_pci_irq_mask, .unmask = ixp2000_pci_irq_unmask @@ -448,7 +448,7 @@ static void ixp2000_irq_unmask(unsigned int irq) ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); } -static struct irqchip ixp2000_irq_chip = { +static struct irq_chip ixp2000_irq_chip = { .ack = ixp2000_irq_mask, .mask = ixp2000_irq_mask, .unmask = ixp2000_irq_unmask @@ -484,7 +484,7 @@ void __init ixp2000_init_irq(void) for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { set_irq_chip(irq, &ixp2000_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else set_irq_flags(irq, 0); } @@ -493,7 +493,7 @@ void __init ixp2000_init_irq(void) if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) & IXP2000_VALID_ERR_IRQ_MASK) { set_irq_chip(irq, &ixp2000_err_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else @@ -503,7 +503,7 @@ void __init ixp2000_init_irq(void) for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { set_irq_chip(irq, &ixp2000_GPIO_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler); @@ -516,7 +516,7 @@ void __init ixp2000_init_irq(void) ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI)); for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) { set_irq_chip(irq, &ixp2000_pci_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } } diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c index aa26550..52b368b 100644 --- a/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/arch/arm/mach-ixp2000/ixdp2x00.c @@ -106,7 +106,7 @@ static void ixdp2x00_irq_unmask(unsigned int irq) ixp2000_release_slowport(&old_cfg); } -static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc) { volatile u32 ex_interrupt = 0; static struct slowport_cfg old_cfg; @@ -129,7 +129,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) for(i = 0; i < board_irq_count; i++) { if(ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); @@ -139,7 +139,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2x00_cpld_irq_chip = { +static struct irq_chip ixdp2x00_cpld_irq_chip = { .ack = ixdp2x00_irq_mask, .mask = ixdp2x00_irq_mask, .unmask = ixdp2x00_irq_unmask @@ -162,7 +162,7 @@ void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) { set_irq_chip(irq, &ixdp2x00_cpld_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 9ccae9e..3084a5f 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -63,7 +63,7 @@ static void ixdp2x01_irq_unmask(unsigned int irq) static u32 valid_irq_mask; -static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc) { u32 ex_interrupt; int i; @@ -79,7 +79,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXP2000_BOARD_IRQS; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); @@ -89,7 +89,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2x01_irq_chip = { +static struct irq_chip ixdp2x01_irq_chip = { .mask = ixdp2x01_irq_mask, .ack = ixdp2x01_irq_mask, .unmask = ixdp2x01_irq_unmask @@ -119,7 +119,7 @@ void __init ixdp2x01_init_irq(void) for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) { if (irq & valid_irq_mask) { set_irq_chip(irq, &ixdp2x01_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else { set_irq_flags(irq, 0); diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index a704a18..ce6ad63 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -224,14 +224,14 @@ static void ixp23xx_irq_edge_unmask(unsigned int irq) *intr_reg |= (1 << (irq % 32)); } -static struct irqchip ixp23xx_irq_level_chip = { +static struct irq_chip ixp23xx_irq_level_chip = { .ack = ixp23xx_irq_mask, .mask = ixp23xx_irq_mask, .unmask = ixp23xx_irq_level_unmask, .set_type = ixp23xx_irq_set_type }; -static struct irqchip ixp23xx_irq_edge_chip = { +static struct irq_chip ixp23xx_irq_edge_chip = { .ack = ixp23xx_irq_ack, .mask = ixp23xx_irq_mask, .unmask = ixp23xx_irq_edge_unmask, @@ -251,11 +251,11 @@ static void ixp23xx_pci_irq_unmask(unsigned int irq) /* * TODO: Should this just be done at ASM level? */ -static void pci_handler(unsigned int irq, struct irqdesc *desc) +static void pci_handler(unsigned int irq, struct irq_desc *desc) { u32 pci_interrupt; unsigned int irqno; - struct irqdesc *int_desc; + struct irq_desc *int_desc; pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS; @@ -276,7 +276,7 @@ static void pci_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixp23xx_pci_irq_chip = { +static struct irq_chip ixp23xx_pci_irq_chip = { .ack = ixp23xx_pci_irq_mask, .mask = ixp23xx_pci_irq_mask, .unmask = ixp23xx_pci_irq_unmask @@ -287,11 +287,11 @@ static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type) switch (type) { case IXP23XX_IRQ_LEVEL: set_irq_chip(irq, &ixp23xx_irq_level_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; case IXP23XX_IRQ_EDGE: set_irq_chip(irq, &ixp23xx_irq_edge_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; } set_irq_flags(irq, IRQF_VALID); @@ -322,7 +322,7 @@ void __init ixp23xx_init_irq(void) for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) { set_irq_chip(irq, &ixp23xx_pci_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c index b6ab0e8..7a86a25 100644 --- a/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/arch/arm/mach-ixp23xx/ixdp2351.c @@ -60,7 +60,7 @@ static void ixdp2351_inta_unmask(unsigned int irq) *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq); } -static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc) { u16 ex_interrupt = *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID; @@ -70,7 +70,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; @@ -81,7 +81,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2351_inta_chip = { +static struct irq_chip ixdp2351_inta_chip = { .ack = ixdp2351_inta_mask, .mask = ixdp2351_inta_mask, .unmask = ixdp2351_inta_unmask @@ -97,7 +97,7 @@ static void ixdp2351_intb_unmask(unsigned int irq) *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq); } -static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc) { u16 ex_interrupt = *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID; @@ -107,7 +107,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; @@ -118,7 +118,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2351_intb_chip = { +static struct irq_chip ixdp2351_intb_chip = { .ack = ixdp2351_intb_mask, .mask = ixdp2351_intb_mask, .unmask = ixdp2351_intb_unmask @@ -142,7 +142,7 @@ void ixdp2351_init_irq(void) irq++) { if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) { set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_chip(irq, &ixdp2351_inta_chip); } } @@ -153,7 +153,7 @@ void ixdp2351_init_irq(void) irq++) { if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) { set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_chip(irq, &ixdp2351_intb_chip); } } diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index fbe288a..074c965 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -195,7 +195,7 @@ static void ixp4xx_irq_unmask(unsigned int irq) *IXP4XX_ICMR |= (1 << irq); } -static struct irqchip ixp4xx_irq_chip = { +static struct irq_chip ixp4xx_irq_chip = { .name = "IXP4xx", .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, @@ -224,7 +224,7 @@ void __init ixp4xx_init_irq(void) /* Default to all level triggered */ for(i = 0; i < NR_IRQS; i++) { set_irq_chip(i, &ixp4xx_irq_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } } diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index b7af5640..561a0fe 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -55,7 +55,7 @@ static void l7200_unmask_irq(unsigned int irq) IRQ_ENABLE = 1 << irq; } -static struct irqchip l7200_irq_chip = { +static struct irq_chip l7200_irq_chip = { .ack = l7200_mask_irq, .mask = l7200_mask_irq, .unmask = l7200_unmask_irq @@ -71,7 +71,7 @@ static void __init l7200_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &l7200_irq_chip); set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); } init_FIQ(); diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c index 15fbcc9..6d26661 100644 --- a/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -71,7 +71,7 @@ static struct irq_chip kev7a400_cpld_chip = { }; -static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) { u32 mask = CPLD_LATCHED_INTS; irq = IRQ_KEV7A400_CPLD; @@ -88,7 +88,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_KEV7A400_CPLD; irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &kev7a400_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler); diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 8441e0a..fe64946 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -207,7 +207,7 @@ static struct irq_chip lpd7a40x_cpld_chip = { .unmask = lh7a40x_unmask_cpld_irq, }; -static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) { unsigned int mask = CPLD_INTERRUPTS; @@ -279,7 +279,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_BOARD_START; irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &lpd7a40x_cpld_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); set_irq_flags (irq, IRQF_VALID); } diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c index 6460713..c7433b3 100644 --- a/arch/arm/mach-lh7a40x/irq-kev7a400.c +++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c @@ -51,7 +51,7 @@ irq_chip lh7a400_cpld_chip = { }; static void -lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc) +lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) { u32 mask = CPLD_LATCHED_INTS; irq = IRQ_KEV_7A400_CPLD; @@ -71,7 +71,7 @@ lh7a400_init_board_irq (void) for (irq = IRQ_KEV7A400_CPLD; irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) { set_irq_chip (irq, &lh7a400_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler); diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c index 091b2dc..0b938e8 100644 --- a/arch/arm/mach-lh7a40x/irq-lh7a400.c +++ b/arch/arm/mach-lh7a40x/irq-lh7a400.c @@ -74,11 +74,11 @@ void __init lh7a400_init_irq (void) case IRQ_GPIO6INTR: case IRQ_GPIO7INTR: set_irq_chip (irq, &lh7a400_gpio_chip); - set_irq_handler (irq, do_level_IRQ); /* OK default */ + set_irq_handler (irq, handle_level_irq); /* OK default */ break; default: set_irq_chip (irq, &lh7a400_internal_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); } set_irq_flags (irq, IRQF_VALID); } diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c index 7059b98..5760f8c 100644 --- a/arch/arm/mach-lh7a40x/irq-lh7a404.c +++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c @@ -161,13 +161,13 @@ void __init lh7a404_init_irq (void) set_irq_chip (irq, irq < 32 ? &lh7a404_gpio_vic1_chip : &lh7a404_gpio_vic2_chip); - set_irq_handler (irq, do_level_IRQ); /* OK default */ + set_irq_handler (irq, handle_level_irq); /* OK default */ break; default: set_irq_chip (irq, irq < 32 ? &lh7a404_vic1_chip : &lh7a404_vic2_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); } set_irq_flags (irq, IRQF_VALID); } diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c index b203768..15b9577 100644 --- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c @@ -57,7 +57,7 @@ static struct irq_chip lh7a40x_cpld_chip = { .unmask = lh7a40x_unmask_cpld_irq, }; -static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) { unsigned int mask = CPLD_INTERRUPTS; @@ -118,7 +118,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_BOARD_START; irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &lh7a40x_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index edbbbdc..b9ca8f9 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -69,7 +69,7 @@ static struct platform_device *devices[] __initdata = { #endif static void -netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int irq = NETX_IRQ_HIF_CHAINED(0); unsigned int stat; @@ -160,7 +160,7 @@ netx_hif_unmask_irq(unsigned int _irq) DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); } -static struct irqchip netx_hif_chip = { +static struct irq_chip netx_hif_chip = { .ack = netx_hif_ack_irq, .mask = netx_hif_mask_irq, .unmask = netx_hif_unmask_irq, @@ -175,7 +175,7 @@ void __init netx_init_irq(void) for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { set_irq_chip(irq, &netx_hif_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index 8e40208..30e1881 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c @@ -84,9 +84,9 @@ static void fpga_mask_ack_irq(unsigned int irq) fpga_ack_irq(irq); } -void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc) +void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; + struct irq_desc *d; u32 stat; int fpga_irq; @@ -168,7 +168,7 @@ void omap1510_fpga_init_irq(void) set_irq_chip(i, &omap_fpga_irq); } - set_irq_handler(i, do_edge_IRQ); + set_irq_handler(i, handle_edge_irq); set_irq_flags(i, IRQF_VALID); } diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 3ea140b..6383a12 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -229,7 +229,7 @@ void __init omap_init_irq(void) omap_irq_set_cfg(j, 0, 0, irq_trigger); set_irq_chip(j, &omap_irq_chip); - set_irq_handler(j, do_level_IRQ); + set_irq_handler(j, handle_level_irq); set_irq_flags(j, IRQF_VALID); } } diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 1187009..a39d306 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -130,7 +130,7 @@ void __init omap_init_irq(void) for (i = 0; i < nr_irqs; i++) { set_irq_chip(i, &omap_irq_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } } diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c index 3a4bcf3..968d0b0 100644 --- a/arch/arm/mach-pnx4008/irq.c +++ b/arch/arm/mach-pnx4008/irq.c @@ -59,22 +59,22 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) case IRQT_RISING: __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */ - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; case IRQT_FALLING: __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */ - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; case IRQT_LOW: __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */ - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; case IRQT_HIGH: __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */ - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; /* IRQT_BOTHEDGE is not supported */ @@ -85,7 +85,7 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip pnx4008_irq_chip = { +static struct irq_chip pnx4008_irq_chip = { .ack = pnx4008_mask_ack_irq, .mask = pnx4008_mask_irq, .unmask = pnx4008_unmask_irq, diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index ab1a160..f815678 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -143,7 +143,7 @@ static struct irq_chip pxa_low_gpio_chip = { * Demux handler for GPIO>=2 edge detect interrupts */ -static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc) +static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) { unsigned int mask; int loop; @@ -286,27 +286,27 @@ void __init pxa_init_irq(void) for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { set_irq_chip(irq, &pxa_internal_chip_low); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } #if PXA_INTERNAL_IRQS > 32 for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) { set_irq_chip(irq, &pxa_internal_chip_high); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } #endif for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { set_irq_chip(irq, &pxa_low_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) { set_irq_chip(irq, &pxa_muxed_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index 5749f6b..8e27a64 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -75,7 +75,7 @@ static struct irq_chip lpd270_irq_chip = { .unmask = lpd270_unmask_irq, }; -static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc) +static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending; @@ -105,7 +105,7 @@ static void __init lpd270_init_irq(void) /* setup extra LogicPD PXA270 irqs */ for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) { set_irq_chip(irq, &lpd270_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 142c33c..055de7f 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -85,7 +85,7 @@ static struct irq_chip lubbock_irq_chip = { .unmask = lubbock_unmask_irq, }; -static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc) +static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; do { @@ -108,7 +108,7 @@ static void __init lubbock_init_irq(void) /* setup extra lubbock irqs */ for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) { set_irq_chip(irq, &lubbock_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 49c34d9..56d94d8 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -71,7 +71,7 @@ static struct irq_chip mainstone_irq_chip = { .unmask = mainstone_unmask_irq, }; -static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc) +static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled; do { @@ -94,7 +94,7 @@ static void __init mainstone_init_irq(void) /* setup extra Mainstone irqs */ for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { set_irq_chip(irq, &mainstone_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14)) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN); else diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c index 56b2716..7a02962 100644 --- a/arch/arm/mach-rpc/irq.c +++ b/arch/arm/mach-rpc/irq.c @@ -34,7 +34,7 @@ static void iomd_unmask_irq_a(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKA); } -static struct irqchip iomd_a_chip = { +static struct irq_chip iomd_a_chip = { .ack = iomd_ack_irq_a, .mask = iomd_mask_irq_a, .unmask = iomd_unmask_irq_a, @@ -58,7 +58,7 @@ static void iomd_unmask_irq_b(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKB); } -static struct irqchip iomd_b_chip = { +static struct irq_chip iomd_b_chip = { .ack = iomd_mask_irq_b, .mask = iomd_mask_irq_b, .unmask = iomd_unmask_irq_b, @@ -82,7 +82,7 @@ static void iomd_unmask_irq_dma(unsigned int irq) iomd_writeb(val | mask, IOMD_DMAMASK); } -static struct irqchip iomd_dma_chip = { +static struct irq_chip iomd_dma_chip = { .ack = iomd_mask_irq_dma, .mask = iomd_mask_irq_dma, .unmask = iomd_unmask_irq_dma, @@ -106,7 +106,7 @@ static void iomd_unmask_irq_fiq(unsigned int irq) iomd_writeb(val | mask, IOMD_FIQMASK); } -static struct irqchip iomd_fiq_chip = { +static struct irq_chip iomd_fiq_chip = { .ack = iomd_mask_irq_fiq, .mask = iomd_mask_irq_fiq, .unmask = iomd_unmask_irq_fiq, @@ -134,19 +134,19 @@ void __init rpc_init_irq(void) switch (irq) { case 0 ... 7: set_irq_chip(irq, &iomd_a_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 8 ... 15: set_irq_chip(irq, &iomd_b_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 16 ... 21: set_irq_chip(irq, &iomd_dma_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c index 23d5bee..379efe7 100644 --- a/arch/arm/mach-s3c2410/bast-irq.c +++ b/arch/arm/mach-s3c2410/bast-irq.c @@ -88,7 +88,7 @@ bast_pc104_mask(unsigned int irqno) static void bast_pc104_maskack(unsigned int irqno) { - struct irqdesc *desc = irq_desc + IRQ_ISA; + struct irq_desc *desc = irq_desc + IRQ_ISA; bast_pc104_mask(irqno); desc->chip->ack(IRQ_ISA); @@ -104,7 +104,7 @@ bast_pc104_unmask(unsigned int irqno) __raw_writeb(temp, BAST_VA_PC104_IRQMASK); } -static struct irqchip bast_pc104_chip = { +static struct irq_chip bast_pc104_chip = { .mask = bast_pc104_mask, .unmask = bast_pc104_unmask, .ack = bast_pc104_maskack @@ -112,7 +112,7 @@ static struct irqchip bast_pc104_chip = { static void bast_irq_pc104_demux(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int stat; unsigned int irqno; @@ -157,7 +157,7 @@ static __init int bast_irq_init(void) unsigned int irqno = bast_pc104_irqs[i]; set_irq_chip(irqno, &bast_pc104_chip); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } } diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 683b349..e7d2ad9 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -180,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno) __raw_writel(mask, S3C2410_INTMSK); } -struct irqchip s3c_irq_level_chip = { +struct irq_chip s3c_irq_level_chip = { .name = "s3c-level", .ack = s3c_irq_maskack, .mask = s3c_irq_mask, @@ -188,7 +188,7 @@ struct irqchip s3c_irq_level_chip = { .set_wake = s3c_irq_wake }; -static struct irqchip s3c_irq_chip = { +static struct irq_chip s3c_irq_chip = { .name = "s3c", .ack = s3c_irq_ack, .mask = s3c_irq_mask, @@ -344,7 +344,7 @@ s3c_irqext_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip s3c_irqext_chip = { +static struct irq_chip s3c_irqext_chip = { .name = "s3c-ext", .mask = s3c_irqext_mask, .unmask = s3c_irqext_unmask, @@ -353,7 +353,7 @@ static struct irqchip s3c_irqext_chip = { .set_wake = s3c_irqext_wake }; -static struct irqchip s3c_irq_eint0t4 = { +static struct irq_chip s3c_irq_eint0t4 = { .name = "s3c-ext0", .ack = s3c_irq_ack, .mask = s3c_irq_mask, @@ -390,7 +390,7 @@ s3c_irq_uart0_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); } -static struct irqchip s3c_irq_uart0 = { +static struct irq_chip s3c_irq_uart0 = { .name = "s3c-uart0", .mask = s3c_irq_uart0_mask, .unmask = s3c_irq_uart0_unmask, @@ -417,7 +417,7 @@ s3c_irq_uart1_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); } -static struct irqchip s3c_irq_uart1 = { +static struct irq_chip s3c_irq_uart1 = { .name = "s3c-uart1", .mask = s3c_irq_uart1_mask, .unmask = s3c_irq_uart1_unmask, @@ -444,7 +444,7 @@ s3c_irq_uart2_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); } -static struct irqchip s3c_irq_uart2 = { +static struct irq_chip s3c_irq_uart2 = { .name = "s3c-uart2", .mask = s3c_irq_uart2_mask, .unmask = s3c_irq_uart2_unmask, @@ -471,7 +471,7 @@ s3c_irq_adc_ack(unsigned int irqno) s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); } -static struct irqchip s3c_irq_adc = { +static struct irq_chip s3c_irq_adc = { .name = "s3c-adc", .mask = s3c_irq_adc_mask, .unmask = s3c_irq_adc_unmask, @@ -480,11 +480,11 @@ static struct irqchip s3c_irq_adc = { /* irq demux for adc */ static void s3c_irq_demux_adc(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; unsigned int offset = 9; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -512,7 +512,7 @@ static void s3c_irq_demux_uart(unsigned int start) { unsigned int subsrc, submsk; unsigned int offset = start - IRQ_S3CUART_RX0; - struct irqdesc *desc; + struct irq_desc *desc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -549,7 +549,7 @@ static void s3c_irq_demux_uart(unsigned int start) static void s3c_irq_demux_uart0(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX0); @@ -557,7 +557,7 @@ s3c_irq_demux_uart0(unsigned int irq, static void s3c_irq_demux_uart1(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX1); @@ -565,7 +565,7 @@ s3c_irq_demux_uart1(unsigned int irq, static void s3c_irq_demux_uart2(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX2); @@ -573,7 +573,7 @@ s3c_irq_demux_uart2(unsigned int irq, static void s3c_irq_demux_extint8(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); @@ -595,7 +595,7 @@ s3c_irq_demux_extint8(unsigned int irq, static void s3c_irq_demux_extint4t7(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); @@ -738,7 +738,7 @@ void __init s3c24xx_init_irq(void) case IRQ_UART2: case IRQ_ADCPARENT: set_irq_chip(irqno, &s3c_irq_level_chip); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); break; case IRQ_RESERVED6: @@ -749,7 +749,7 @@ void __init s3c24xx_init_irq(void) default: //irqdbf("registering irq %d (s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_chip); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } } @@ -769,14 +769,14 @@ void __init s3c24xx_init_irq(void) for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { irqdbf("registering irq %d (ext int)\n", irqno); set_irq_chip(irqno, &s3c_irq_eint0t4); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { irqdbf("registering irq %d (extended s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irqext_chip); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } @@ -787,28 +787,28 @@ void __init s3c24xx_init_irq(void) for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart0); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart1); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart2); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { irqdbf("registering irq %d (s3c adc irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_adc); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h index 842a9f4..3686a00 100644 --- a/arch/arm/mach-s3c2410/irq.h +++ b/arch/arm/mach-s3c2410/irq.h @@ -17,7 +17,7 @@ #define EXTINT_OFF (IRQ_EINT4 - 4) -extern struct irqchip s3c_irq_level_chip; +extern struct irq_chip s3c_irq_level_chip; static inline void s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit, diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c index 7f74154..ffcc30b 100644 --- a/arch/arm/mach-s3c2410/s3c2412-irq.c +++ b/arch/arm/mach-s3c2410/s3c2412-irq.c @@ -98,7 +98,7 @@ s3c2412_irq_unmask(unsigned int irqno) __raw_writel(mask & ~bitval, S3C2410_INTMSK); } -static struct irqchip s3c2412_irq_eint0t4 = { +static struct irq_chip s3c2412_irq_eint0t4 = { .ack = s3c2412_irq_ack, .mask = s3c2412_irq_mask, .unmask = s3c2412_irq_unmask, @@ -112,7 +112,7 @@ static int s3c2412_irq_add(struct sys_device *sysdev) for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { set_irq_chip(irqno, &s3c2412_irq_eint0t4); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c index 39db075..1ba19b2 100644 --- a/arch/arm/mach-s3c2410/s3c2440-irq.c +++ b/arch/arm/mach-s3c2410/s3c2440-irq.c @@ -42,10 +42,10 @@ /* WDT/AC97 */ static void s3c_irq_demux_wdtac97(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -90,7 +90,7 @@ s3c_irq_wdtac97_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13); } -static struct irqchip s3c_irq_wdtac97 = { +static struct irq_chip s3c_irq_wdtac97 = { .mask = s3c_irq_wdtac97_mask, .unmask = s3c_irq_wdtac97_unmask, .ack = s3c_irq_wdtac97_ack, @@ -105,12 +105,12 @@ static int s3c2440_irq_add(struct sys_device *sysdev) /* add new chained handler for wdt, ac7 */ set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); - set_irq_handler(IRQ_WDT, do_level_IRQ); + set_irq_handler(IRQ_WDT, handle_level_irq); set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) { set_irq_chip(irqno, &s3c_irq_wdtac97); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c index 146f210..ede9463 100644 --- a/arch/arm/mach-s3c2410/s3c244x-irq.c +++ b/arch/arm/mach-s3c2410/s3c244x-irq.c @@ -42,10 +42,10 @@ /* camera irq */ static void s3c_irq_demux_cam(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -89,7 +89,7 @@ s3c_irq_cam_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); } -static struct irqchip s3c_irq_cam = { +static struct irq_chip s3c_irq_cam = { .mask = s3c_irq_cam_mask, .unmask = s3c_irq_cam_unmask, .ack = s3c_irq_cam_ack, @@ -100,18 +100,18 @@ static int s3c244x_irq_add(struct sys_device *sysdev) unsigned int irqno; set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); - set_irq_handler(IRQ_NFCON, do_level_IRQ); + set_irq_handler(IRQ_NFCON, handle_level_irq); set_irq_flags(IRQ_NFCON, IRQF_VALID); /* add chained handler for camera */ set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); - set_irq_handler(IRQ_CAM, do_level_IRQ); + set_irq_handler(IRQ_CAM, handle_level_irq); set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { set_irq_chip(irqno, &s3c_irq_cam); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index fa6dc71..b034ad6 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -702,7 +702,7 @@ static u32 gpio_irq_mask[] = { GPIO2_SD_CON_SLT, }; -static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc) +static void h3800_IRQ_demux(unsigned int irq, struct irq_desc *desc) { int i; @@ -719,14 +719,14 @@ static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc) if (0) printk("%s KPIO 0x%08X\n", __FUNCTION__, irq); for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++) if (irq & kpio_irq_mask[j]) - do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j); + handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j); /* GPIO2 */ irq = H3800_ASIC2_GPIINTFLAG; if (0) printk("%s GPIO 0x%08X\n", __FUNCTION__, irq); for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++) if (irq & gpio_irq_mask[j]) - do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j); + handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j); } if (i >= MAX_ASIC_ISR_LOOPS) diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index f4c6322..5642aec 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -110,7 +110,7 @@ static struct irq_chip sa1100_low_gpio_chip = { * and call the handler. */ static void -sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc) +sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) { unsigned int mask; @@ -327,19 +327,19 @@ void __init sa1100_init_irq(void) for (irq = 0; irq <= 10; irq++) { set_irq_chip(irq, &sa1100_low_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = 12; irq <= 31; irq++) { set_irq_chip(irq, &sa1100_normal_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } for (irq = 32; irq <= 48; irq++) { set_irq_chip(irq, &sa1100_high_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 354d5e9..075d4d1 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -29,12 +29,12 @@ * is rather unfortunate. */ static void -neponset_irq_handler(unsigned int irq, struct irqdesc *desc) +neponset_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int irr; while (1) { - struct irqdesc *d; + struct irq_desc *d; /* * Acknowledge the parent IRQ. @@ -168,9 +168,9 @@ static int neponset_probe(struct platform_device *dev) * Setup other Neponset IRQs. SA1111 will be done by the * generic SA1111 code. */ - set_irq_handler(IRQ_NEPONSET_SMC9196, do_simple_IRQ); + set_irq_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq); set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE); - set_irq_handler(IRQ_NEPONSET_USAR, do_simple_IRQ); + set_irq_handler(IRQ_NEPONSET_USAR, handle_simple_irq); set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE); /* diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c index 297ecf1..00a6c14 100644 --- a/arch/arm/mach-shark/irq.c +++ b/arch/arm/mach-shark/irq.c @@ -82,7 +82,7 @@ void __init shark_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &fb_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 3b85761..dcc2ca3 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -77,7 +77,7 @@ static struct irq_chip sic_chip = { }; static void -sic_handle_irq(unsigned int irq, struct irqdesc *desc) +sic_handle_irq(unsigned int irq, struct irq_desc *desc) { unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS); @@ -123,7 +123,7 @@ void __init versatile_init_irq(void) for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) { set_irq_chip(i, &sic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 8162eed..4f2fd55 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -410,7 +410,7 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr trigger & __IRQT_RISEDGE); MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, trigger & __IRQT_FALEDGE); - /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level + /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level * triggering requested. */ } @@ -783,7 +783,7 @@ void omap_free_gpio(int gpio) * line's interrupt handler has been run, we may miss some nested * interrupts. */ -static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc) +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { void __iomem *isr_reg = NULL; u32 isr; @@ -853,7 +853,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc) gpio_irq = bank->virtual_irq_start; for (; isr != 0; isr >>= 1, gpio_irq++) { - struct irqdesc *d; + struct irq_desc *d; int irq_mask; if (!(isr & 1)) continue; @@ -1092,7 +1092,7 @@ static int __init _omap_gpio_init(void) set_irq_chip(j, &mpuio_irq_chip); else set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, do_simple_IRQ); + set_irq_handler(j, handle_simple_irq); set_irq_flags(j, IRQF_VALID); } set_irq_chained_handler(bank->irq, gpio_irq_handler); diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h index 0e017ec..eb0bfba 100644 --- a/include/asm-arm/mach/irq.h +++ b/include/asm-arm/mach/irq.h @@ -22,12 +22,6 @@ extern void init_FIQ(void); extern int show_fiq_list(struct seq_file *, void *); /* - * Function wrappers - */ -#define set_irq_chipdata(irq, d) set_irq_chip_data(irq, d) -#define get_irq_chipdata(irq) get_irq_chip_data(irq) - -/* * Obsolete inline function for calling irq descriptor handlers. */ static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc) @@ -44,12 +38,6 @@ void set_irq_flags(unsigned int irq, unsigned int flags); /* * This is for easy migration, but should be changed in the source */ -#define do_level_IRQ handle_level_irq -#define do_edge_IRQ handle_edge_irq -#define do_simple_IRQ handle_simple_irq -#define irqdesc irq_desc -#define irqchip irq_chip - #define do_bad_IRQ(irq,desc) \ do { \ spin_lock(&desc->lock); \ -- cgit v0.10.2 From bf46878c4ef4cf04a3564f0ff2e7daae353ee2e2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Nov 2006 22:17:09 +0100 Subject: [ARM] 3939/1: don't reset SA11x0 clock counter Don't reset OSCR to zero as this prevents us from having a contiguous time source. The value returned by sched_clock() is reset to zero in the middle of the boot process otherwise, making CONFIG_PRINTK_TIME rather messed up. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 4284bd6..29c89f9 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -118,6 +118,7 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { struct timespec tv; + unsigned long flags; set_rtc = sa1100_set_rtc; @@ -126,12 +127,12 @@ static void __init sa1100_timer_init(void) do_settimeofday(&tv); OIER = 0; /* disable any timer interrupts */ - OSCR = LATCH*2; /* push OSCR out of the way */ - OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &sa1100_timer_irq); + local_irq_save(flags); OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer */ + OSMR0 = OSCR + LATCH; /* set initial match */ + local_irq_restore(flags); } #ifdef CONFIG_NO_IDLE_HZ -- cgit v0.10.2 From 46ec0ce8ce7eab6242188ea8a596538753c53b22 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Nov 2006 22:19:29 +0100 Subject: [ARM] 3940/1: don't reset PXA2xx clock counter Don't reset OSCR to zero as this prevents us from having a contiguous time source. The value returned by sched_clock() is reset to zero in the middle of the boot process otherwise, making CONFIG_PRINTK_TIME rather messed up. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 3ac268f..b914668 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -124,6 +124,7 @@ static struct irqaction pxa_timer_irq = { static void __init pxa_timer_init(void) { struct timespec tv; + unsigned long flags; set_rtc = pxa_set_rtc; @@ -132,12 +133,12 @@ static void __init pxa_timer_init(void) do_settimeofday(&tv); OIER = 0; /* disable any timer interrupts */ - OSCR = LATCH*2; /* push OSCR out of the way */ - OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &pxa_timer_irq); + local_irq_save(flags); OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer */ + OSMR0 = OSCR + LATCH; /* set initial match */ + local_irq_restore(flags); } #ifdef CONFIG_NO_IDLE_HZ -- cgit v0.10.2 From 5cd372e170f1827164e3bd267dff80962ded49d6 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Mon, 20 Nov 2006 20:42:44 +0100 Subject: [ARM] 3936/1: [Jornada7xx] - No use for jornada720.h * We don't need this header anymore - there is no data we need to share this way. FB driver gets this data through a resources structure. MCU Driver api will go to a jornada720_mcu.h file. Signed-off-by: Filip Zyzniewski Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King diff --git a/include/asm-arm/arch-sa1100/jornada720.h b/include/asm-arm/arch-sa1100/jornada720.h deleted file mode 100644 index 3f37ca0..0000000 --- a/include/asm-arm/arch-sa1100/jornada720.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * linux/include/asm-arm/arch-sa1100/jornada720.h - * - * Created 2000/11/29 by John Ankcorn - * - * This file contains the hardware specific definitions for HP Jornada 720 - * - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#error "include instead" -#endif - -#define SA1111_BASE (0x40000000) - -#define GPIO_JORNADA720_KEYBOARD GPIO_GPIO(0) -#define GPIO_JORNADA720_MOUSE GPIO_GPIO(9) - -#define GPIO_JORNADA720_KEYBOARD_IRQ IRQ_GPIO0 -#define GPIO_JORNADA720_MOUSE_IRQ IRQ_GPIO9 - -/* MCU COMMANDS */ -#define MCU_GetBatteryData 0xc0 -#define MCU_GetScanKeyCode 0x90 -#define MCU_GetTouchSamples 0xa0 -#define MCU_GetContrast 0xD0 -#define MCU_SetContrast 0xD1 -#define MCU_GetBrightness 0xD2 -#define MCU_SetBrightness 0xD3 -#define MCU_ContrastOff 0xD8 -#define MCU_BrightnessOff 0xD9 -#define MCU_PWMOFF 0xDF -#define MCU_TxDummy 0x11 -#define MCU_ErrorCode 0x00 - -#ifndef __ASSEMBLY__ - -void jornada720_mcu_init(void); -void jornada_contrast(int arg_contrast); -void jornada720_battery(void); -int jornada720_getkey(unsigned char *data, int size); -#endif -- cgit v0.10.2 From 3ff1559eae70d5fb542eaa087389223dce4e364f Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 13:53:54 +0000 Subject: [ARM] Fix nommu build Fix warnings and errors in arch/arm/mm for nommu build. Remove commented out function prototype in pgtable-nommu.h Signed-off-by: Russell King diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index bb2bc9a..a44e309 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -1,4 +1,7 @@ /* the upper-most page table pointer */ + +#ifdef CONFIG_MMU + extern pmd_t *top_pmd; #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) @@ -13,6 +16,8 @@ static inline pmd_t *pmd_off_k(unsigned long virt) return pmd_off(pgd_offset_k(virt), virt); } +#endif + struct map_desc; struct meminfo; struct pglist_data; diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index d0e6642..05818fc 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include +#include #include "mm.h" @@ -76,7 +78,7 @@ void __iomem *__ioremap(unsigned long phys_addr, size_t size, } EXPORT_SYMBOL(__ioremap); -void __iounmap(void __iomem *addr) +void __iounmap(volatile void __iomem *addr) { } EXPORT_SYMBOL(__iounmap); diff --git a/include/asm-arm/pgtable-nommu.h b/include/asm-arm/pgtable-nommu.h index c1b264d..7b1c9ac 100644 --- a/include/asm-arm/pgtable-nommu.h +++ b/include/asm-arm/pgtable-nommu.h @@ -44,7 +44,6 @@ #define PAGE_READONLY __pgprot(0) #define PAGE_KERNEL __pgprot(0) -//extern void paging_init(struct meminfo *, struct machine_desc *); #define swapper_pg_dir ((pgd_t *) 0) #define __swp_type(x) (0) -- cgit v0.10.2 From 96b13f5c074fab56797109aedacc2405544d6f95 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 14:04:49 +0000 Subject: [ARM] Fix __must_check warnings in drivers/bus/amba.c Fix driver model __must_check warnings in drivers/bus/amba.c by rearranging how we add attributes to devices. Signed-off-by: Russell King diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 9e3e2a6..fd54750 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -80,12 +80,38 @@ static int amba_resume(struct device *dev) return ret; } +#define amba_attr_func(name,fmt,arg...) \ +static ssize_t name##_show(struct device *_dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct amba_device *dev = to_amba_device(_dev); \ + return sprintf(buf, fmt, arg); \ +} + +#define amba_attr(name,fmt,arg...) \ +amba_attr_func(name,fmt,arg) \ +static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL) + +amba_attr_func(id, "%08x\n", dev->periphid); +amba_attr(irq0, "%u\n", dev->irq[0]); +amba_attr(irq1, "%u\n", dev->irq[1]); +amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", + (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, + dev->res.flags); + +static struct device_attribute amba_dev_attrs[] = { + __ATTR_RO(id), + __ATTR_RO(resource), + __ATTR_NULL, +}; + /* * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". */ static struct bus_type amba_bustype = { .name = "amba", + .dev_attrs = amba_dev_attrs, .match = amba_match, .uevent = amba_uevent, .suspend = amba_suspend, @@ -169,21 +195,6 @@ static void amba_device_release(struct device *dev) kfree(d); } -#define amba_attr(name,fmt,arg...) \ -static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \ -{ \ - struct amba_device *dev = to_amba_device(_dev); \ - return sprintf(buf, fmt, arg); \ -} \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) - -amba_attr(id, "%08x\n", dev->periphid); -amba_attr(irq0, "%u\n", dev->irq[0]); -amba_attr(irq1, "%u\n", dev->irq[1]); -amba_attr(resource, "\t%016llx\t%016llx\t%016lx\n", - (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, - dev->res.flags); - /** * amba_device_register - register an AMBA device * @dev: AMBA device to register @@ -208,40 +219,46 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) dev_warn(&dev->dev, "coherent dma mask is unset\n"); ret = request_resource(parent, &dev->res); - if (ret == 0) { - tmp = ioremap(dev->res.start, SZ_4K); - if (!tmp) { - ret = -ENOMEM; - goto out; - } - - for (pid = 0, i = 0; i < 4; i++) - pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8); - for (cid = 0, i = 0; i < 4; i++) - cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8); - - iounmap(tmp); - - if (cid == 0xb105f00d) - dev->periphid = pid; - - if (dev->periphid) - ret = device_register(&dev->dev); - else - ret = -ENODEV; - - if (ret == 0) { - device_create_file(&dev->dev, &dev_attr_id); - if (dev->irq[0] != NO_IRQ) - device_create_file(&dev->dev, &dev_attr_irq0); - if (dev->irq[1] != NO_IRQ) - device_create_file(&dev->dev, &dev_attr_irq1); - device_create_file(&dev->dev, &dev_attr_resource); - } else { - out: - release_resource(&dev->res); - } + if (ret) + goto err_out; + + tmp = ioremap(dev->res.start, SZ_4K); + if (!tmp) { + ret = -ENOMEM; + goto err_release; } + + for (pid = 0, i = 0; i < 4; i++) + pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8); + for (cid = 0, i = 0; i < 4; i++) + cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8); + + iounmap(tmp); + + if (cid == 0xb105f00d) + dev->periphid = pid; + + if (!dev->periphid) { + ret = -ENODEV; + goto err_release; + } + + ret = device_register(&dev->dev); + if (ret) + goto err_release; + + if (dev->irq[0] != NO_IRQ) + ret = device_create_file(&dev->dev, &dev_attr_irq0); + if (ret == 0 && dev->irq[1] != NO_IRQ) + ret = device_create_file(&dev->dev, &dev_attr_irq1); + if (ret == 0) + return ret; + + device_unregister(&dev->dev); + + err_release: + release_resource(&dev->res); + err_out: return ret; } -- cgit v0.10.2 From 74af1c227cf17caff3bb8c6547858655a473a39b Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 14:34:46 +0000 Subject: [ARM] L7200: Remove deprecated __io_pci and __arch_(get|put)* These functions have been deprecated for quite some time, and in fact are no longer used. They just add to clutter. Remove them. Signed-off-by: Russell King diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h index d744d97..fb9c6e1 100644 --- a/include/asm-arm/arch-l7200/io.h +++ b/include/asm-arm/arch-l7200/io.h @@ -17,35 +17,8 @@ /* * There are not real ISA nor PCI buses, so we fake it. */ -#define __io_pci(a) ((void __iomem *)(PCIO_BASE + (a))) #define __mem_pci(a) (a) -#define __ioaddr(p) __io_pci(p) - -/* - * Generic virtual read/write - */ -#define __arch_getb(a) (*(volatile unsigned char *)(a)) -#define __arch_getl(a) (*(volatile unsigned int *)(a)) - -static inline unsigned int __arch_getw(unsigned long a) -{ - unsigned int value; - __asm__ __volatile__("ldrh %0, [%1, #0] @ getw" - : "=&r" (value) - : "r" (a) : "cc"); - return value; -} - -#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v)) -#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) - -static inline void __arch_putw(unsigned int value, unsigned long a) -{ - __asm__ __volatile__("strh %0, [%1, #0] @ putw" - : : "r" (value), "r" (a) : "cc"); -} - /* * Translated address IO functions * -- cgit v0.10.2 From 6f4c7e39cb769addf047de8ec395a200cc6eec94 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 14:36:29 +0000 Subject: [ARM] Remove warnings for __io_pci and __arch_(get|put)* Since the last definitions of this macros have been removed, we can remove the warnings in asm/io.h. Signed-off-by: Russell King diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index ae999fd..288f76b16 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -75,14 +75,6 @@ extern void __readwrite_bug(const char *fn); */ #include -#ifdef __io_pci -#warning machine class uses buggy __io_pci -#endif -#if defined(__arch_putb) || defined(__arch_putw) || defined(__arch_putl) || \ - defined(__arch_getb) || defined(__arch_getw) || defined(__arch_getl) -#warning machine class uses old __arch_putw or __arch_getw -#endif - /* * IO port access primitives * ------------------------- -- cgit v0.10.2 From 9b531ce242159bd26e09b55d8fb4be3f4bf75e24 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 14:39:14 +0000 Subject: [ARM] Remove "translated" io macros The "translated" io macros were never really used. Remove them. Preserve the L7200 inb() and friends by defining the __io() macro, so that the generic versions can be used instead. Signed-off-by: Russell King diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h index fb9c6e1..645dbdf 100644 --- a/include/asm-arm/arch-l7200/io.h +++ b/include/asm-arm/arch-l7200/io.h @@ -17,32 +17,11 @@ /* * There are not real ISA nor PCI buses, so we fake it. */ +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)addr; +} +#define __io(a) __io(a) #define __mem_pci(a) (a) -/* - * Translated address IO functions - * - * IO address has already been translated to a virtual address - */ -#define outb_t(v,p) (*(volatile unsigned char *)(p) = (v)) -#define inb_t(p) (*(volatile unsigned char *)(p)) -#define outw_t(v,p) (*(volatile unsigned int *)(p) = (v)) -#define inw_t(p) (*(volatile unsigned int *)(p)) -#define outl_t(v,p) (*(volatile unsigned long *)(p) = (v)) -#define inl_t(p) (*(volatile unsigned long *)(p)) - -/* - * FIXME - These are to allow for linking. On all the other - * ARM platforms, the entire IO space is contiguous. - * The 7200 has three separate IO spaces. The below - * macros will eventually become more involved. Use - * with caution and don't be surprised by kernel oopses!!! - */ -#define inb(p) inb_t(p) -#define inw(p) inw_t(p) -#define inl(p) inl_t(p) -#define outb(v,p) outb_t(v,p) -#define outw(v,p) outw_t(v,p) -#define outl(v,p) outl_t(v,p) - #endif -- cgit v0.10.2 From 122214428a7bfab2c09b417f3acdb06222e81748 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Nov 2006 16:41:18 +0100 Subject: [ARM] 3911/2: Simplify alloc_thread_info on ARM Remove ARM local cache of 4 struct thread_info. Can cause oops under certain circumstances. Russell indicated the original optimization was required on older kernels to avoid thread starvation on memory fragmentation, but may no longer be required. I've updated the patch to 19rc4 and ensured no dain-bramage slipped in this time (sorry about that). Original description follows: I was given some test results which pointed to an Oops in alloc_thread_info (happened 2x), and after looking at the code, I see that ARM has its own local cache of 4 struct thread_info. There wasn't any clear (to me) synchronization between the alloc_thread_info and the free_thread_info. I looked over the other arch, and they all simply allocate them on an as needed basis, so I simplified the ARM to do the same, based on the other arch (e.g. PPC) and the folks doing the testing have indicated that this fixed the oops. Signed-off-by: Paul Gortmaker Signed-off-by: Russell King diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index bf35c17..a9e8f7e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -281,67 +281,6 @@ void show_fpregs(struct user_fp *regs) } /* - * Task structure and kernel stack allocation. - */ -struct thread_info_list { - unsigned long *head; - unsigned int nr; -}; - -static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 }; - -#define EXTRA_TASK_STRUCT 4 - -struct thread_info *alloc_thread_info(struct task_struct *task) -{ - struct thread_info *thread = NULL; - - if (EXTRA_TASK_STRUCT) { - struct thread_info_list *th = &get_cpu_var(thread_info_list); - unsigned long *p = th->head; - - if (p) { - th->head = (unsigned long *)p[0]; - th->nr -= 1; - } - put_cpu_var(thread_info_list); - - thread = (struct thread_info *)p; - } - - if (!thread) - thread = (struct thread_info *) - __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); - -#ifdef CONFIG_DEBUG_STACK_USAGE - /* - * The stack must be cleared if you want SYSRQ-T to - * give sensible stack usage information - */ - if (thread) - memzero(thread, THREAD_SIZE); -#endif - return thread; -} - -void free_thread_info(struct thread_info *thread) -{ - if (EXTRA_TASK_STRUCT) { - struct thread_info_list *th = &get_cpu_var(thread_info_list); - if (th->nr < EXTRA_TASK_STRUCT) { - unsigned long *p = (unsigned long *)thread; - p[0] = (unsigned long)th->head; - th->head = p; - th->nr += 1; - put_cpu_var(thread_info_list); - return; - } - put_cpu_var(thread_info_list); - } - free_pages((unsigned long)thread, THREAD_SIZE_ORDER); -} - -/* * Free current thread data structures etc.. */ void exit_thread(void) diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index f28b236..d9b8bdd 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -94,8 +94,18 @@ static inline struct thread_info *current_thread_info(void) return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); } -extern struct thread_info *alloc_thread_info(struct task_struct *task); -extern void free_thread_info(struct thread_info *); +/* thread information allocation */ +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(tsk) \ + ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \ + THREAD_SIZE_ORDER)) +#else +#define alloc_thread_info(tsk) \ + ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) +#endif + +#define free_thread_info(info) \ + free_pages((unsigned long)info, THREAD_SIZE_ORDER); #define thread_saved_pc(tsk) \ ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc))) -- cgit v0.10.2 From 3ca68df6ee61e1a2034f3307b9edb9b3d87e5ca1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 20:11:25 -0400 Subject: [GFS2] split gfs2_dinode into on-disk and host variants The latter is used as part of gfs2-private part of struct inode. It actually stores a lot of fields differently; for now the declaration is just cloned, inode field is swtiched and changes propagated. Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index d470e52..191a3df 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -48,7 +48,7 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; - struct gfs2_dinode *di = &ip->i_di; + struct gfs2_dinode_host *di = &ip->i_di; inode->i_ino = ip->i_num.no_addr; @@ -98,7 +98,7 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) void gfs2_inode_attr_out(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; - struct gfs2_dinode *di = &ip->i_di; + struct gfs2_dinode_host *di = &ip->i_di; gfs2_assert_withdraw(GFS2_SB(inode), (di->di_mode & S_IFMT) == (inode->i_mode & S_IFMT)); di->di_mode = inode->i_mode; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 1025960..52cb9a2 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -153,7 +153,7 @@ void gfs2_quota_in(struct gfs2_quota *qu, const void *buf) qu->qu_value = be64_to_cpu(str->qu_value); } -void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf) +void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf) { const struct gfs2_dinode *str = buf; @@ -187,7 +187,7 @@ void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf) } -void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf) +void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf) { struct gfs2_dinode *str = buf; @@ -221,7 +221,7 @@ void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf) } -void gfs2_dinode_print(const struct gfs2_dinode *di) +void gfs2_dinode_print(const struct gfs2_dinode_host *di) { gfs2_meta_header_print(&di->di_header); gfs2_inum_print(&di->di_num); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index a7ae7c1..f334b4b 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -270,6 +270,48 @@ struct gfs2_dinode { __u8 di_reserved[56]; }; +struct gfs2_dinode_host { + struct gfs2_meta_header di_header; + + struct gfs2_inum di_num; + + __be32 di_mode; /* mode of file */ + __be32 di_uid; /* owner's user id */ + __be32 di_gid; /* owner's group id */ + __be32 di_nlink; /* number of links to this file */ + __be64 di_size; /* number of bytes in file */ + __be64 di_blocks; /* number of blocks in file */ + __be64 di_atime; /* time last accessed */ + __be64 di_mtime; /* time last modified */ + __be64 di_ctime; /* time last changed */ + __be32 di_major; /* device major number */ + __be32 di_minor; /* device minor number */ + + /* This section varies from gfs1. Padding added to align with + * remainder of dinode + */ + __be64 di_goal_meta; /* rgrp to alloc from next */ + __be64 di_goal_data; /* data block goal */ + __be64 di_generation; /* generation number for NFS */ + + __be32 di_flags; /* GFS2_DIF_... */ + __be32 di_payload_format; /* GFS2_FORMAT_... */ + __u16 __pad1; /* Was ditype in gfs1 */ + __be16 di_height; /* height of metadata */ + __u32 __pad2; /* Unused incarnation number from gfs1 */ + + /* These only apply to directories */ + __u16 __pad3; /* Padding */ + __be16 di_depth; /* Number of bits in the table */ + __be32 di_entries; /* The number of entries in the directory */ + + struct gfs2_inum __pad4; /* Unused even in current gfs1 */ + + __be64 di_eattr; /* extended attribute block number */ + + __u8 di_reserved[56]; +}; + /* * directory structure - many of these per directory file */ @@ -422,8 +464,8 @@ extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf); extern void gfs2_quota_out(const struct gfs2_quota *qu, void *buf); -extern void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf); -extern void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf); +extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); +extern void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); extern void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf); @@ -436,7 +478,7 @@ extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); /* Printing functions */ extern void gfs2_rindex_print(const struct gfs2_rindex *ri); -extern void gfs2_dinode_print(const struct gfs2_dinode *di); +extern void gfs2_dinode_print(const struct gfs2_dinode_host *di); #endif /* __KERNEL__ */ -- cgit v0.10.2 From 5c6edb576f3800723bb65dbfaff82517089e32d0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 20:33:01 -0400 Subject: [GFS2] gfs2_dinode_host fields are host-endian Annotated scalar fields, dropped unused ones. Note that it's not at all obvious that we want to convert all of them to host-endian... Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 118dc69..1c876e0 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -229,7 +229,7 @@ struct gfs2_inode { unsigned long i_flags; /* GIF_... */ u64 i_vn; - struct gfs2_dinode i_di; /* To be replaced by ref to block */ + struct gfs2_dinode_host i_di; /* To be replaced by ref to block */ struct gfs2_glock *i_gl; /* Move into i_gh? */ struct gfs2_holder i_iopen_gh; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index f334b4b..0e67a89 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -275,41 +275,34 @@ struct gfs2_dinode_host { struct gfs2_inum di_num; - __be32 di_mode; /* mode of file */ - __be32 di_uid; /* owner's user id */ - __be32 di_gid; /* owner's group id */ - __be32 di_nlink; /* number of links to this file */ - __be64 di_size; /* number of bytes in file */ - __be64 di_blocks; /* number of blocks in file */ - __be64 di_atime; /* time last accessed */ - __be64 di_mtime; /* time last modified */ - __be64 di_ctime; /* time last changed */ - __be32 di_major; /* device major number */ - __be32 di_minor; /* device minor number */ + __u32 di_mode; /* mode of file */ + __u32 di_uid; /* owner's user id */ + __u32 di_gid; /* owner's group id */ + __u32 di_nlink; /* number of links to this file */ + __u64 di_size; /* number of bytes in file */ + __u64 di_blocks; /* number of blocks in file */ + __u64 di_atime; /* time last accessed */ + __u64 di_mtime; /* time last modified */ + __u64 di_ctime; /* time last changed */ + __u32 di_major; /* device major number */ + __u32 di_minor; /* device minor number */ /* This section varies from gfs1. Padding added to align with * remainder of dinode */ - __be64 di_goal_meta; /* rgrp to alloc from next */ - __be64 di_goal_data; /* data block goal */ - __be64 di_generation; /* generation number for NFS */ + __u64 di_goal_meta; /* rgrp to alloc from next */ + __u64 di_goal_data; /* data block goal */ + __u64 di_generation; /* generation number for NFS */ - __be32 di_flags; /* GFS2_DIF_... */ - __be32 di_payload_format; /* GFS2_FORMAT_... */ - __u16 __pad1; /* Was ditype in gfs1 */ - __be16 di_height; /* height of metadata */ - __u32 __pad2; /* Unused incarnation number from gfs1 */ + __u32 di_flags; /* GFS2_DIF_... */ + __u32 di_payload_format; /* GFS2_FORMAT_... */ + __u16 di_height; /* height of metadata */ /* These only apply to directories */ - __u16 __pad3; /* Padding */ - __be16 di_depth; /* Number of bits in the table */ - __be32 di_entries; /* The number of entries in the directory */ - - struct gfs2_inum __pad4; /* Unused even in current gfs1 */ + __u16 di_depth; /* Number of bits in the table */ + __u32 di_entries; /* The number of entries in the directory */ - __be64 di_eattr; /* extended attribute block number */ - - __u8 di_reserved[56]; + __u64 di_eattr; /* extended attribute block number */ }; /* -- cgit v0.10.2 From f50dfaf78c01df3cc2d8819f07d6661915567bae Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 20:45:02 -0400 Subject: [GFS2] split gfs2_sb Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 1c876e0..bd596ba 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -450,7 +450,7 @@ struct gfs2_sbd { struct super_block *sd_vfs_meta; struct kobject sd_kobj; unsigned long sd_flags; /* SDF_... */ - struct gfs2_sb sd_sb; + struct gfs2_sb_host sd_sb; /* Constants computed on mount */ diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 52cb9a2..5b32f1a 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -79,7 +79,7 @@ static void gfs2_meta_header_print(const struct gfs2_meta_header *mh) pv(mh, mh_format, "%u"); } -void gfs2_sb_in(struct gfs2_sb *sb, const void *buf) +void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) { const struct gfs2_sb *str = buf; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 6a78b1b..52aa322 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -97,7 +97,7 @@ void gfs2_tune_init(struct gfs2_tune *gt) * changed. */ -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent) +int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) { unsigned int x; diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 5bb443a..ac95064 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -14,7 +14,7 @@ void gfs2_tune_init(struct gfs2_tune *gt); -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent); +int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); struct page *gfs2_read_super(struct super_block *sb, sector_t sector); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 0e67a89..b7bdfef 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -128,6 +128,26 @@ struct gfs2_sb { /* In gfs1, quota and license dinodes followed */ }; +struct gfs2_sb_host { + struct gfs2_meta_header sb_header; + + __be32 sb_fs_format; + __be32 sb_multihost_format; + __u32 __pad0; /* Was superblock flags in gfs1 */ + + __be32 sb_bsize; + __be32 sb_bsize_shift; + __u32 __pad1; /* Was journal segment size in gfs1 */ + + struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ + struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ + struct gfs2_inum sb_root_dir; + + char sb_lockproto[GFS2_LOCKNAME_LEN]; + char sb_locktable[GFS2_LOCKNAME_LEN]; + /* In gfs1, quota and license dinodes followed */ +}; + /* * resource index structure */ @@ -450,7 +470,7 @@ struct gfs2_quota_change { extern void gfs2_inum_in(struct gfs2_inum *no, const void *buf); extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf); -extern void gfs2_sb_in(struct gfs2_sb *sb, const void *buf); +extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); extern void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex *ri, void *buf); extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf); -- cgit v0.10.2 From bc558c87bb7e50c4f728d32684a9f4f4c73ebde3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 21:02:41 -0400 Subject: [GFS2] fields of gfs2_sb_host are host-endian ... and several could be killed, but that's another story. Annotate scalar ones, kill completely unused. Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index b7bdfef..a5d36cd 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -131,16 +131,13 @@ struct gfs2_sb { struct gfs2_sb_host { struct gfs2_meta_header sb_header; - __be32 sb_fs_format; - __be32 sb_multihost_format; - __u32 __pad0; /* Was superblock flags in gfs1 */ + __u32 sb_fs_format; + __u32 sb_multihost_format; - __be32 sb_bsize; - __be32 sb_bsize_shift; - __u32 __pad1; /* Was journal segment size in gfs1 */ + __u32 sb_bsize; + __u32 sb_bsize_shift; struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ - struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ struct gfs2_inum sb_root_dir; char sb_lockproto[GFS2_LOCKNAME_LEN]; -- cgit v0.10.2 From 68826664d12827d7a732192e2f00ba46fb899414 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 21:07:22 -0400 Subject: [GFS2] split and annotate gfs2_rgrp Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index bd596ba..8ca7a7f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -68,7 +68,7 @@ struct gfs2_rgrpd { struct list_head rd_recent; /* Recently used rgrps */ struct gfs2_glock *rd_gl; /* Glock for this rgrp */ struct gfs2_rindex rd_ri; - struct gfs2_rgrp rd_rg; + struct gfs2_rgrp_host rd_rg; u64 rd_rg_vn; struct gfs2_bitmap *rd_bits; unsigned int rd_bh_count; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 5b32f1a..3b156a1 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -120,7 +120,7 @@ void gfs2_rindex_print(const struct gfs2_rindex *ri) pv(ri, ri_bitbytes, "%u"); } -void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf) +void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) { const struct gfs2_rgrp *str = buf; @@ -131,7 +131,7 @@ void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf) rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); } -void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf) +void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) { struct gfs2_rgrp *str = buf; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index a5d36cd..e4ca6e4 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -193,6 +193,15 @@ struct gfs2_rgrp { __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */ }; +struct gfs2_rgrp_host { + struct gfs2_meta_header rg_header; + + __u32 rg_flags; + __u32 rg_free; + __u32 rg_dinodes; + __u64 rg_igeneration; +}; + /* * quota structure */ @@ -470,8 +479,8 @@ extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf); extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); extern void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex *ri, void *buf); -extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf); -extern void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf); +extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); +extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf); extern void gfs2_quota_out(const struct gfs2_quota *qu, void *buf); extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); -- cgit v0.10.2 From e697264709c86040271cdd7abee781d7adbb7f91 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 21:29:46 -0400 Subject: [GFS2] split and annotate gfs2_inum_range Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 191a3df..7eb6b44 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -436,7 +436,7 @@ static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) { struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode); struct buffer_head *bh; - struct gfs2_inum_range ir; + struct gfs2_inum_range_host ir; int error; error = gfs2_trans_begin(sdp, RES_DINODE, 0); @@ -479,7 +479,7 @@ static int pick_formal_ino_2(struct gfs2_sbd *sdp, u64 *formal_ino) struct gfs2_inode *m_ip = GFS2_I(sdp->sd_inum_inode); struct gfs2_holder gh; struct buffer_head *bh; - struct gfs2_inum_range ir; + struct gfs2_inum_range_host ir; int error; error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 3b156a1..64f5f0c6 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -263,7 +263,7 @@ void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf) lh->lh_hash = be32_to_cpu(str->lh_hash); } -void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf) +void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf) { const struct gfs2_inum_range *str = buf; @@ -271,7 +271,7 @@ void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf) ir->ir_length = be64_to_cpu(str->ir_length); } -void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf) +void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf) { struct gfs2_inum_range *str = buf; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index e4ca6e4..c035587 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -445,6 +445,11 @@ struct gfs2_inum_range { __be64 ir_length; }; +struct gfs2_inum_range_host { + __u64 ir_start; + __u64 ir_length; +}; + /* * Statfs change * Describes an change to the pool of free and allocated @@ -488,8 +493,8 @@ extern void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); extern void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf); -extern void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf); -extern void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf); +extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf); +extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf); extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf); extern void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf); extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); -- cgit v0.10.2 From 551676226163379c217e8ec54bd287eab9b8521e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 21:47:13 -0400 Subject: [GFS2] split and annotate gfs2_log_head Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 41a6b68..5406b19 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -491,7 +491,7 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); struct gfs2_glock *j_gl = ip->i_gl; - struct gfs2_log_header head; + struct gfs2_log_header_host head; int error; if (gl->gl_state != LM_ST_UNLOCKED && diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 8ca7a7f..e69f339 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -41,7 +41,7 @@ struct gfs2_log_operations { void (*lo_before_commit) (struct gfs2_sbd *sdp); void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); void (*lo_before_scan) (struct gfs2_jdesc *jd, - struct gfs2_log_header *head, int pass); + struct gfs2_log_header_host *head, int pass); int (*lo_scan_elements) (struct gfs2_jdesc *jd, unsigned int start, struct gfs2_log_descriptor *ld, __be64 *ptr, int pass); diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index ab6d111..8a654cd 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -182,7 +182,7 @@ static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) } static void buf_lo_before_scan(struct gfs2_jdesc *jd, - struct gfs2_log_header *head, int pass) + struct gfs2_log_header_host *head, int pass) { struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); @@ -328,7 +328,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) } static void revoke_lo_before_scan(struct gfs2_jdesc *jd, - struct gfs2_log_header *head, int pass) + struct gfs2_log_header_host *head, int pass) { struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index 5839c05..965bc65 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h @@ -60,7 +60,7 @@ static inline void lops_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) } static inline void lops_before_scan(struct gfs2_jdesc *jd, - struct gfs2_log_header *head, + struct gfs2_log_header_host *head, unsigned int pass) { int x; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 64f5f0c6..84b1ebc 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -251,7 +251,7 @@ void gfs2_dinode_print(const struct gfs2_dinode_host *di) printk(KERN_INFO " di_eattr = %llu\n", (unsigned long long)di->di_eattr); } -void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf) +void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf) { const struct gfs2_log_header *str = buf; diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 62cd223..4478162 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -132,10 +132,10 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp) */ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, - struct gfs2_log_header *head) + struct gfs2_log_header_host *head) { struct buffer_head *bh; - struct gfs2_log_header lh; + struct gfs2_log_header_host lh; u32 hash; int error; @@ -143,7 +143,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, if (error) return error; - memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header)); + memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header)); /* XXX */ lh.lh_hash = 0; hash = gfs2_disk_hash((char *)&lh, sizeof(struct gfs2_log_header)); gfs2_log_header_in(&lh, bh->b_data); @@ -174,7 +174,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, */ static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk, - struct gfs2_log_header *head) + struct gfs2_log_header_host *head) { unsigned int orig_blk = *blk; int error; @@ -205,10 +205,10 @@ static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk, * Returns: errno */ -static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head) +static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) { unsigned int blk = head->lh_blkno; - struct gfs2_log_header lh; + struct gfs2_log_header_host lh; int error; for (;;) { @@ -245,9 +245,9 @@ static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head) * Returns: errno */ -int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header *head) +int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) { - struct gfs2_log_header lh_1, lh_m; + struct gfs2_log_header_host lh_1, lh_m; u32 blk_1, blk_2, blk_m; int error; @@ -320,7 +320,7 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start, length = be32_to_cpu(ld->ld_length); if (be32_to_cpu(ld->ld_header.mh_type) == GFS2_METATYPE_LH) { - struct gfs2_log_header lh; + struct gfs2_log_header_host lh; error = get_log_header(jd, start, &lh); if (!error) { gfs2_replay_incr_blk(sdp, &start); @@ -363,7 +363,7 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start, * Returns: errno */ -static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head) +static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) { struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); @@ -425,7 +425,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd) { struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); - struct gfs2_log_header head; + struct gfs2_log_header_host head; struct gfs2_holder j_gh, ji_gh, t_gh; unsigned long t; int ro = 0; diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h index 961feed..f7235e6 100644 --- a/fs/gfs2/recovery.h +++ b/fs/gfs2/recovery.h @@ -26,7 +26,7 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where); void gfs2_revoke_clean(struct gfs2_sbd *sdp); int gfs2_find_jhead(struct gfs2_jdesc *jd, - struct gfs2_log_header *head); + struct gfs2_log_header_host *head); int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd); void gfs2_check_journals(struct gfs2_sbd *sdp); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 52aa322..0faf563 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -508,7 +508,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); struct gfs2_glock *j_gl = ip->i_gl; struct gfs2_holder t_gh; - struct gfs2_log_header head; + struct gfs2_log_header_host head; int error; error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, @@ -873,7 +873,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd; struct lfcc *lfcc; LIST_HEAD(list); - struct gfs2_log_header lh; + struct gfs2_log_header_host lh; int error; error = gfs2_jindex_hold(sdp, &ji_gh); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index c035587..fb69a64 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -405,6 +405,16 @@ struct gfs2_log_header { __be32 lh_hash; }; +struct gfs2_log_header_host { + struct gfs2_meta_header lh_header; + + __u64 lh_sequence; /* Sequence number of this transaction */ + __u32 lh_flags; /* GFS2_LOG_HEAD_... */ + __u32 lh_tail; /* Block number of log tail */ + __u32 lh_blkno; + __u32 lh_hash; +}; + /* * Log type descriptor */ @@ -492,7 +502,7 @@ extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); extern void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); -extern void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf); +extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf); extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf); extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf); extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf); -- cgit v0.10.2 From 2a2c98247b822db8df037a56c27201f9d716ac66 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 14:44:50 -0500 Subject: [GFS2] Fix crc32 calculation in recovery.c Commit "[GFS2] split and annotate gfs2_log_head" resulted in an incorrect checksum calculation for log headers. This patch corrects the problem without resorting to copying the whole log header as the previous code used to. Cc: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 4478162..4acf238 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -136,6 +136,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, { struct buffer_head *bh; struct gfs2_log_header_host lh; +static const u32 nothing = 0; u32 hash; int error; @@ -143,11 +144,11 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, if (error) return error; - memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header)); /* XXX */ - lh.lh_hash = 0; - hash = gfs2_disk_hash((char *)&lh, sizeof(struct gfs2_log_header)); + hash = crc32_le((u32)~0, bh->b_data, sizeof(struct gfs2_log_header) - + sizeof(u32)); + hash = crc32_le(hash, (unsigned char const *)¬hing, sizeof(nothing)); + hash ^= (u32)~0; gfs2_log_header_in(&lh, bh->b_data); - brelse(bh); if (lh.lh_header.mh_magic != GFS2_MAGIC || -- cgit v0.10.2 From e928a76f959e89884f6186bb6f846c533847d5df Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 21:57:23 -0400 Subject: [GFS2] split and annotate gfs2_meta_header Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 84b1ebc..b5aa7ab 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -54,7 +54,7 @@ static void gfs2_inum_print(const struct gfs2_inum *no) printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr); } -static void gfs2_meta_header_in(struct gfs2_meta_header *mh, const void *buf) +static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) { const struct gfs2_meta_header *str = buf; @@ -63,7 +63,7 @@ static void gfs2_meta_header_in(struct gfs2_meta_header *mh, const void *buf) mh->mh_format = be32_to_cpu(str->mh_format); } -static void gfs2_meta_header_out(const struct gfs2_meta_header *mh, void *buf) +static void gfs2_meta_header_out(const struct gfs2_meta_header_host *mh, void *buf) { struct gfs2_meta_header *str = buf; @@ -72,7 +72,7 @@ static void gfs2_meta_header_out(const struct gfs2_meta_header *mh, void *buf) str->mh_format = cpu_to_be32(mh->mh_format); } -static void gfs2_meta_header_print(const struct gfs2_meta_header *mh) +static void gfs2_meta_header_print(const struct gfs2_meta_header_host *mh) { pv(mh, mh_magic, "0x%.8X"); pv(mh, mh_type, "%u"); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index fb69a64..76eb9e1 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -89,6 +89,12 @@ struct gfs2_meta_header { __be32 __pad1; /* Was incarnation number in gfs1 */ }; +struct gfs2_meta_header_host { + __u32 mh_magic; + __u32 mh_type; + __u32 mh_format; +}; + /* * super-block structure * @@ -129,7 +135,7 @@ struct gfs2_sb { }; struct gfs2_sb_host { - struct gfs2_meta_header sb_header; + struct gfs2_meta_header_host sb_header; __u32 sb_fs_format; __u32 sb_multihost_format; @@ -194,7 +200,7 @@ struct gfs2_rgrp { }; struct gfs2_rgrp_host { - struct gfs2_meta_header rg_header; + struct gfs2_meta_header_host rg_header; __u32 rg_flags; __u32 rg_free; @@ -297,7 +303,7 @@ struct gfs2_dinode { }; struct gfs2_dinode_host { - struct gfs2_meta_header di_header; + struct gfs2_meta_header_host di_header; struct gfs2_inum di_num; @@ -406,7 +412,7 @@ struct gfs2_log_header { }; struct gfs2_log_header_host { - struct gfs2_meta_header lh_header; + struct gfs2_meta_header_host lh_header; __u64 lh_sequence; /* Sequence number of this transaction */ __u32 lh_flags; /* GFS2_LOG_HEAD_... */ -- cgit v0.10.2 From 1e81c4c3e0f55c95b6278a827262b80debd0dc7e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 22:51:24 -0400 Subject: [GFS2] split and annotate gfs_rindex Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index e69f339..e4afc2c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -67,7 +67,7 @@ struct gfs2_rgrpd { struct list_head rd_list_mru; struct list_head rd_recent; /* Recently used rgrps */ struct gfs2_glock *rd_gl; /* Glock for this rgrp */ - struct gfs2_rindex rd_ri; + struct gfs2_rindex_host rd_ri; struct gfs2_rgrp_host rd_rg; u64 rd_rg_vn; struct gfs2_bitmap *rd_bits; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index b5aa7ab..c4e099d 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -97,7 +97,7 @@ void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); } -void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf) +void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf) { const struct gfs2_rindex *str = buf; @@ -109,7 +109,7 @@ void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf) } -void gfs2_rindex_print(const struct gfs2_rindex *ri) +void gfs2_rindex_print(const struct gfs2_rindex_host *ri) { printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)ri->ri_addr); pv(ri, ri_length, "%u"); diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index b261385..07dfd63 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -253,7 +253,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) } -static inline int rgrp_contains_block(struct gfs2_rindex *ri, u64 block) +static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block) { u64 first = ri->ri_data0; u64 last = first + ri->ri_data; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 76eb9e1..7dd5e4c 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -168,6 +168,14 @@ struct gfs2_rindex { __u8 ri_reserved[64]; }; +struct gfs2_rindex_host { + __u64 ri_addr; /* grp block disk address */ + __u64 ri_data0; /* first data location */ + __u32 ri_length; /* length of rgrp header in fs blocks */ + __u32 ri_data; /* num of data blocks in rgrp */ + __u32 ri_bitbytes; /* number of bytes in data bitmaps */ +}; + /* * resource group header structure */ @@ -498,8 +506,8 @@ struct gfs2_quota_change { extern void gfs2_inum_in(struct gfs2_inum *no, const void *buf); extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf); extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); -extern void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf); -extern void gfs2_rindex_out(const struct gfs2_rindex *ri, void *buf); +extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); +extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf); @@ -517,7 +525,7 @@ extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); /* Printing functions */ -extern void gfs2_rindex_print(const struct gfs2_rindex *ri); +extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri); extern void gfs2_dinode_print(const struct gfs2_dinode_host *di); #endif /* __KERNEL__ */ -- cgit v0.10.2 From 629a21e7ecedf779c68dcaa9a186069f57a7c652 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 22:51:24 -0400 Subject: [GFS2] split and annotate gfs2_inum Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index e24af28b1..d67a376 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1194,7 +1194,7 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, int *copied) { const struct gfs2_dirent *dent, *dent_next; - struct gfs2_inum inum; + struct gfs2_inum_host inum; u64 off, off_next; unsigned int x, y; int run = 0; @@ -1456,7 +1456,7 @@ out: */ int gfs2_dir_search(struct inode *dir, const struct qstr *name, - struct gfs2_inum *inum, unsigned int *type) + struct gfs2_inum_host *inum, unsigned int *type) { struct buffer_head *bh; struct gfs2_dirent *dent; @@ -1531,7 +1531,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) */ int gfs2_dir_add(struct inode *inode, const struct qstr *name, - const struct gfs2_inum *inum, unsigned type) + const struct gfs2_inum_host *inum, unsigned type) { struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *bh; @@ -1666,7 +1666,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) */ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, - struct gfs2_inum *inum, unsigned int new_type) + struct gfs2_inum_host *inum, unsigned int new_type) { struct buffer_head *bh; struct gfs2_dirent *dent; diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h index 3712334..b21b336 100644 --- a/fs/gfs2/dir.h +++ b/fs/gfs2/dir.h @@ -31,17 +31,17 @@ struct gfs2_inum; typedef int (*gfs2_filldir_t) (void *opaque, const char *name, unsigned int length, u64 offset, - struct gfs2_inum *inum, unsigned int type); + struct gfs2_inum_host *inum, unsigned int type); int gfs2_dir_search(struct inode *dir, const struct qstr *filename, - struct gfs2_inum *inum, unsigned int *type); + struct gfs2_inum_host *inum, unsigned int *type); int gfs2_dir_add(struct inode *inode, const struct qstr *filename, - const struct gfs2_inum *inum, unsigned int type); + const struct gfs2_inum_host *inum, unsigned int type); int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); int gfs2_dir_read(struct inode *inode, u64 * offset, void *opaque, gfs2_filldir_t filldir); int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, - struct gfs2_inum *new_inum, unsigned int new_type); + struct gfs2_inum_host *new_inum, unsigned int new_type); int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index e4afc2c..20c9b4f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -224,7 +224,7 @@ enum { struct gfs2_inode { struct inode i_inode; - struct gfs2_inum i_num; + struct gfs2_inum_host i_num; unsigned long i_flags; /* GIF_... */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 7eb6b44..dadd1f3 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -112,7 +112,7 @@ void gfs2_inode_attr_out(struct gfs2_inode *ip) static int iget_test(struct inode *inode, void *opaque) { struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_inum *inum = opaque; + struct gfs2_inum_host *inum = opaque; if (ip && ip->i_num.no_addr == inum->no_addr) return 1; @@ -123,19 +123,19 @@ static int iget_test(struct inode *inode, void *opaque) static int iget_set(struct inode *inode, void *opaque) { struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_inum *inum = opaque; + struct gfs2_inum_host *inum = opaque; ip->i_num = *inum; return 0; } -struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum) +struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum) { return ilookup5(sb, (unsigned long)inum->no_formal_ino, iget_test, inum); } -static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum) +static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum) { return iget5_locked(sb, (unsigned long)inum->no_formal_ino, iget_test, iget_set, inum); @@ -150,7 +150,7 @@ static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum) * Returns: A VFS inode, or an error */ -struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned int type) +struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type) { struct inode *inode = gfs2_iget(sb, inum); struct gfs2_inode *ip = GFS2_I(inode); @@ -394,7 +394,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, struct super_block *sb = dir->i_sb; struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_holder d_gh; - struct gfs2_inum inum; + struct gfs2_inum_host inum; unsigned int type; int error = 0; struct inode *inode = NULL; @@ -610,7 +610,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, *gid = current->fsgid; } -static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum, +static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum, u64 *generation) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); @@ -650,7 +650,7 @@ out: */ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, - const struct gfs2_inum *inum, unsigned int mode, + const struct gfs2_inum_host *inum, unsigned int mode, unsigned int uid, unsigned int gid, const u64 *generation) { @@ -707,7 +707,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, } static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, - unsigned int mode, const struct gfs2_inum *inum, + unsigned int mode, const struct gfs2_inum_host *inum, const u64 *generation) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); @@ -866,7 +866,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, struct gfs2_inode *dip = ghs->gh_gl->gl_object; struct inode *dir = &dip->i_inode; struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); - struct gfs2_inum inum; + struct gfs2_inum_host inum; int error; u64 generation; @@ -1018,7 +1018,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, struct gfs2_inode *ip) { - struct gfs2_inum inum; + struct gfs2_inum_host inum; unsigned int type; int error; diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index f5d8617..d699b92 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -27,8 +27,8 @@ static inline int gfs2_is_dir(struct gfs2_inode *ip) void gfs2_inode_attr_in(struct gfs2_inode *ip); void gfs2_inode_attr_out(struct gfs2_inode *ip); -struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum, unsigned type); -struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum *inum); +struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type); +struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum); int gfs2_inode_refresh(struct gfs2_inode *ip); diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index c4e099d..32f592f 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -32,7 +32,7 @@ * first arg: the cpu-order structure */ -void gfs2_inum_in(struct gfs2_inum *no, const void *buf) +void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf) { const struct gfs2_inum *str = buf; @@ -40,7 +40,7 @@ void gfs2_inum_in(struct gfs2_inum *no, const void *buf) no->no_addr = be64_to_cpu(str->no_addr); } -void gfs2_inum_out(const struct gfs2_inum *no, void *buf) +void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf) { struct gfs2_inum *str = buf; @@ -48,7 +48,7 @@ void gfs2_inum_out(const struct gfs2_inum *no, void *buf) str->no_addr = cpu_to_be64(no->no_addr); } -static void gfs2_inum_print(const struct gfs2_inum *no) +static void gfs2_inum_print(const struct gfs2_inum_host *no) { printk(KERN_INFO " no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino); printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr); diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index 00041b1..c36f9e3 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c @@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) struct inode *inode = dentry->d_inode; struct gfs2_holder d_gh; struct gfs2_inode *ip; - struct gfs2_inum inum; + struct gfs2_inum_host inum; unsigned int type; int error; diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 86127d9..33423a5 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c @@ -35,7 +35,7 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb, void *context) { struct gfs2_fh_obj fh_obj; - struct gfs2_inum *this, parent; + struct gfs2_inum_host *this, parent; if (fh_type != fh_len) return NULL; @@ -114,12 +114,12 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len, } struct get_name_filldir { - struct gfs2_inum inum; + struct gfs2_inum_host inum; char *name; }; static int get_name_filldir(void *opaque, const char *name, unsigned int length, - u64 offset, struct gfs2_inum *inum, + u64 offset, struct gfs2_inum_host *inum, unsigned int type) { struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque; @@ -202,7 +202,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) { struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj; - struct gfs2_inum *inum = &fh_obj->this; + struct gfs2_inum_host *inum = &fh_obj->this; struct gfs2_holder i_gh, ri_gh, rgd_gh; struct gfs2_rgrpd *rgd; struct inode *inode; diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h index 09aca50..f925a95 100644 --- a/fs/gfs2/ops_export.h +++ b/fs/gfs2/ops_export.h @@ -15,7 +15,7 @@ extern struct export_operations gfs2_export_ops; struct gfs2_fh_obj { - struct gfs2_inum this; + struct gfs2_inum_host this; __u32 imode; }; diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 3064f13..359965c 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -139,7 +139,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) */ static int filldir_func(void *opaque, const char *name, unsigned int length, - u64 offset, struct gfs2_inum *inum, + u64 offset, struct gfs2_inum_host *inum, unsigned int type) { struct filldir_reg *fdr = (struct filldir_reg *)opaque; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 882873a..d14e139 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -237,7 +237,7 @@ fail: } static struct inode *gfs2_lookup_root(struct super_block *sb, - struct gfs2_inum *inum) + struct gfs2_inum_host *inum) { return gfs2_inode_lookup(sb, inum, DT_DIR); } @@ -246,7 +246,7 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) { struct super_block *sb = sdp->sd_vfs; struct gfs2_holder sb_gh; - struct gfs2_inum *inum; + struct gfs2_inum_host *inum; struct inode *inode; int error = 0; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 7dd5e4c..b16df6e 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -54,8 +54,13 @@ struct gfs2_inum { __be64 no_addr; }; -static inline int gfs2_inum_equal(const struct gfs2_inum *ino1, - const struct gfs2_inum *ino2) +struct gfs2_inum_host { + __u64 no_formal_ino; + __u64 no_addr; +}; + +static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1, + const struct gfs2_inum_host *ino2) { return ino1->no_formal_ino == ino2->no_formal_ino && ino1->no_addr == ino2->no_addr; @@ -143,8 +148,8 @@ struct gfs2_sb_host { __u32 sb_bsize; __u32 sb_bsize_shift; - struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ - struct gfs2_inum sb_root_dir; + struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */ + struct gfs2_inum_host sb_root_dir; char sb_lockproto[GFS2_LOCKNAME_LEN]; char sb_locktable[GFS2_LOCKNAME_LEN]; @@ -313,7 +318,7 @@ struct gfs2_dinode { struct gfs2_dinode_host { struct gfs2_meta_header_host di_header; - struct gfs2_inum di_num; + struct gfs2_inum_host di_num; __u32 di_mode; /* mode of file */ __u32 di_uid; /* owner's user id */ @@ -503,8 +508,8 @@ struct gfs2_quota_change { #ifdef __KERNEL__ /* Translation functions */ -extern void gfs2_inum_in(struct gfs2_inum *no, const void *buf); -extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf); +extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf); +extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf); extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); -- cgit v0.10.2 From b5bc9e8b065dbcd4c675e8c158d6e524f221b8e1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 23:31:55 -0400 Subject: [GFS2] split and annotate gfs2_quota Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 32f592f..5db0737 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -144,7 +144,7 @@ void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); } -void gfs2_quota_in(struct gfs2_quota *qu, const void *buf) +void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) { const struct gfs2_quota *str = buf; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index a3deae7..e3f5b8d 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -743,7 +743,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); struct gfs2_holder i_gh; - struct gfs2_quota q; + struct gfs2_quota_host q; char buf[sizeof(struct gfs2_quota)]; struct file_ra_state ra_state; int error; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index b16df6e..431e03b 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -232,6 +232,12 @@ struct gfs2_quota { __u8 qu_reserved[64]; }; +struct gfs2_quota_host { + __u64 qu_limit; + __u64 qu_warn; + __u64 qu_value; +}; + /* * dinode structure */ @@ -515,8 +521,7 @@ extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); -extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf); -extern void gfs2_quota_out(const struct gfs2_quota *qu, void *buf); +extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); extern void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); -- cgit v0.10.2 From bd209cc017f231e8536550bdab1bf5da93c32798 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 23:43:19 -0400 Subject: [GFS2] split and annotate gfs2_statfs_change Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 20c9b4f..c0a8c3b 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -503,8 +503,8 @@ struct gfs2_sbd { spinlock_t sd_statfs_spin; struct mutex sd_statfs_mutex; - struct gfs2_statfs_change sd_statfs_master; - struct gfs2_statfs_change sd_statfs_local; + struct gfs2_statfs_change_host sd_statfs_master; + struct gfs2_statfs_change_host sd_statfs_local; unsigned long sd_statfs_sync_time; /* Resource group stuff */ diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 5db0737..84c59b1 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -279,7 +279,7 @@ void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf) str->ir_length = cpu_to_be64(ir->ir_length); } -void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf) +void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) { const struct gfs2_statfs_change *str = buf; @@ -288,7 +288,7 @@ void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf) sc->sc_dinodes = be64_to_cpu(str->sc_dinodes); } -void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf) +void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf) { struct gfs2_statfs_change *str = buf; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index b47d959..9c786d1 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -215,7 +215,7 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; - struct gfs2_statfs_change sc; + struct gfs2_statfs_change_host sc; int error; if (gfs2_tune_get(sdp, gt_statfs_slow)) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0faf563..0ef8317 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -587,9 +587,9 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp) int gfs2_statfs_init(struct gfs2_sbd *sdp) { struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); - struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master; + struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); - struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local; + struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct buffer_head *m_bh, *l_bh; struct gfs2_holder gh; int error; @@ -634,7 +634,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, s64 dinodes) { struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); - struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local; + struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct buffer_head *l_bh; int error; @@ -660,8 +660,8 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) { struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); - struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master; - struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local; + struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; + struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_holder gh; struct buffer_head *m_bh, *l_bh; int error; @@ -727,10 +727,10 @@ out: * Returns: errno */ -int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc) +int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) { - struct gfs2_statfs_change *m_sc = &sdp->sd_statfs_master; - struct gfs2_statfs_change *l_sc = &sdp->sd_statfs_local; + struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; + struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; spin_lock(&sdp->sd_statfs_spin); @@ -760,7 +760,7 @@ int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc) */ static int statfs_slow_fill(struct gfs2_rgrpd *rgd, - struct gfs2_statfs_change *sc) + struct gfs2_statfs_change_host *sc) { gfs2_rgrp_verify(rgd); sc->sc_total += rgd->rd_ri.ri_data; @@ -782,7 +782,7 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd, * Returns: errno */ -int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc) +int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) { struct gfs2_holder ri_gh; struct gfs2_rgrpd *rgd_next; @@ -792,7 +792,7 @@ int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc) int done; int error = 0, err; - memset(sc, 0, sizeof(struct gfs2_statfs_change)); + memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL); if (!gha) return -ENOMEM; diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index ac95064..e590b2d 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -45,8 +45,8 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp); void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, s64 dinodes); int gfs2_statfs_sync(struct gfs2_sbd *sdp); -int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc); -int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change *sc); +int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc); +int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc); int gfs2_freeze_fs(struct gfs2_sbd *sdp); void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 431e03b..3ce3a47 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -497,6 +497,12 @@ struct gfs2_statfs_change { __be64 sc_dinodes; }; +struct gfs2_statfs_change_host { + __u64 sc_total; + __u64 sc_free; + __u64 sc_dinodes; +}; + /* * Quota change * Describes an allocation change for a particular @@ -529,8 +535,8 @@ extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf); extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf); extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf); -extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf); -extern void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf); +extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf); +extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf); extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); /* Printing functions */ -- cgit v0.10.2 From b62f963e1fdf838fed91faec21228d421a834f2d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 23:46:46 -0400 Subject: [GFS2] split and annotate gfs2_quota_change Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 84c59b1..2d1682d 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -297,7 +297,7 @@ void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf) str->sc_dinodes = cpu_to_be64(sc->sc_dinodes); } -void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf) +void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf) { const struct gfs2_quota_change *str = buf; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index e3f5b8d..009d86c 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1103,7 +1103,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots; y++, slot++) { - struct gfs2_quota_change qc; + struct gfs2_quota_change_host qc; struct gfs2_quota_data *qd; gfs2_quota_change_in(&qc, bh->b_data + diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 3ce3a47..10a507d 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -517,6 +517,12 @@ struct gfs2_quota_change { __be32 qc_id; }; +struct gfs2_quota_change_host { + __u64 qc_change; + __u32 qc_flags; /* GFS2_QCF_... */ + __u32 qc_id; +}; + #ifdef __KERNEL__ /* Translation functions */ @@ -537,7 +543,7 @@ extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf) extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf); extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf); extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf); -extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); +extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf); /* Printing functions */ -- cgit v0.10.2 From b44b84d765b02f813a67b96bf79e3b5d4d621631 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Oct 2006 10:46:30 -0400 Subject: [GFS2] gfs2 misc endianness annotations Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 06e9a8c..51f6356 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -38,8 +38,8 @@ struct metapath { }; typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh, - struct buffer_head *bh, u64 *top, - u64 *bottom, unsigned int height, + struct buffer_head *bh, __be64 *top, + __be64 *bottom, unsigned int height, void *data); struct strip_mine { @@ -230,7 +230,7 @@ static int build_height(struct inode *inode, unsigned height) struct buffer_head *blocks[GFS2_MAX_META_HEIGHT]; struct gfs2_dinode *di; int error; - u64 *bp; + __be64 *bp; u64 bn; unsigned n; @@ -255,7 +255,7 @@ static int build_height(struct inode *inode, unsigned height) GFS2_FORMAT_IN); gfs2_buffer_clear_tail(blocks[n], sizeof(struct gfs2_meta_header)); - bp = (u64 *)(blocks[n]->b_data + + bp = (__be64 *)(blocks[n]->b_data + sizeof(struct gfs2_meta_header)); *bp = cpu_to_be64(blocks[n+1]->b_blocknr); brelse(blocks[n]); @@ -360,15 +360,15 @@ static void find_metapath(struct gfs2_inode *ip, u64 block, * metadata tree. */ -static inline u64 *metapointer(struct buffer_head *bh, int *boundary, +static inline __be64 *metapointer(struct buffer_head *bh, int *boundary, unsigned int height, const struct metapath *mp) { unsigned int head_size = (height > 0) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); - u64 *ptr; + __be64 *ptr; *boundary = 0; - ptr = ((u64 *)(bh->b_data + head_size)) + mp->mp_list[height]; - if (ptr + 1 == (u64 *)(bh->b_data + bh->b_size)) + ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; + if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size)) *boundary = 1; return ptr; } @@ -394,7 +394,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, int *new, u64 *block) { int boundary; - u64 *ptr = metapointer(bh, &boundary, height, mp); + __be64 *ptr = metapointer(bh, &boundary, height, mp); if (*ptr) { *block = be64_to_cpu(*ptr); @@ -600,7 +600,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh, { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *bh = NULL; - u64 *top, *bottom; + __be64 *top, *bottom; u64 bn; int error; int mh_size = sizeof(struct gfs2_meta_header); @@ -611,17 +611,17 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh, return error; dibh = bh; - top = (u64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0]; - bottom = (u64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs; + top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0]; + bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs; } else { error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh); if (error) return error; - top = (u64 *)(bh->b_data + mh_size) + + top = (__be64 *)(bh->b_data + mh_size) + (first ? mp->mp_list[height] : 0); - bottom = (u64 *)(bh->b_data + mh_size) + sdp->sd_inptrs; + bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs; } error = bc(ip, dibh, bh, top, bottom, height, data); @@ -660,7 +660,7 @@ out: */ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, - struct buffer_head *bh, u64 *top, u64 *bottom, + struct buffer_head *bh, __be64 *top, __be64 *bottom, unsigned int height, void *data) { struct strip_mine *sm = data; @@ -668,7 +668,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, struct gfs2_rgrp_list rlist; u64 bn, bstart; u32 blen; - u64 *p; + __be64 *p; unsigned int rg_blocks = 0; int metadata; unsigned int revokes = 0; diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index d67a376..59dc823 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -713,12 +713,12 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no, static int get_leaf_nr(struct gfs2_inode *dip, u32 index, u64 *leaf_out) { - u64 leaf_no; + __be64 leaf_no; int error; error = gfs2_dir_read_data(dip, (char *)&leaf_no, - index * sizeof(u64), - sizeof(u64), 0); + index * sizeof(__be64), + sizeof(__be64), 0); if (error != sizeof(u64)) return (error < 0) ? error : -EIO; @@ -837,7 +837,8 @@ static int dir_make_exhash(struct inode *inode) struct gfs2_leaf *leaf; int y; u32 x; - u64 *lp, bn; + __be64 *lp; + u64 bn; int error; error = gfs2_meta_inode_buffer(dip, &dibh); @@ -893,7 +894,7 @@ static int dir_make_exhash(struct inode *inode) gfs2_trans_add_bh(dip->i_gl, dibh, 1); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); - lp = (u64 *)(dibh->b_data + sizeof(struct gfs2_dinode)); + lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode)); for (x = sdp->sd_hash_ptrs; x--; lp++) *lp = cpu_to_be64(bn); @@ -929,7 +930,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) struct gfs2_leaf *nleaf, *oleaf; struct gfs2_dirent *dent = NULL, *prev = NULL, *next = NULL, *new; u32 start, len, half_len, divider; - u64 bn, *lp, leaf_no; + u64 bn, leaf_no; + __be64 *lp; u32 index; int x, moved = 0; int error; @@ -974,7 +976,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) /* Change the pointers. Don't bother distinguishing stuffed from non-stuffed. This code is complicated enough already. */ - lp = kmalloc(half_len * sizeof(u64), GFP_NOFS | __GFP_NOFAIL); + lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL); /* Change the pointers */ for (x = 0; x < half_len; x++) lp[x] = cpu_to_be64(bn); @@ -1341,7 +1343,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, u32 hsize, len = 0; u32 ht_offset, lp_offset, ht_offset_cur = -1; u32 hash, index; - u64 *lp; + __be64 *lp; int copied = 0; int error = 0; unsigned depth = 0; @@ -1365,7 +1367,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, if (ht_offset_cur != ht_offset) { error = gfs2_dir_read_data(dip, (char *)lp, - ht_offset * sizeof(u64), + ht_offset * sizeof(__be64), sdp->sd_hash_bsize, 1); if (error != sdp->sd_hash_bsize) { if (error >= 0) @@ -1715,7 +1717,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) u32 hsize, len; u32 ht_offset, lp_offset, ht_offset_cur = -1; u32 index = 0; - u64 *lp; + __be64 *lp; u64 leaf_no; int error = 0; @@ -1735,7 +1737,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) if (ht_offset_cur != ht_offset) { error = gfs2_dir_read_data(dip, (char *)lp, - ht_offset * sizeof(u64), + ht_offset * sizeof(__be64), sdp->sd_hash_bsize, 1); if (error != sdp->sd_hash_bsize) { if (error >= 0) diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index a65a4cc..518f0c0 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -112,7 +112,7 @@ fail: static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) { struct buffer_head *bh, *eabh; - u64 *eablk, *end; + __be64 *eablk, *end; int error; error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &bh); @@ -129,7 +129,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) goto out; } - eablk = (u64 *)(bh->b_data + sizeof(struct gfs2_meta_header)); + eablk = (__be64 *)(bh->b_data + sizeof(struct gfs2_meta_header)); end = eablk + GFS2_SB(&ip->i_inode)->sd_inptrs; for (; eablk < end; eablk++) { @@ -224,7 +224,8 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, struct gfs2_rgrpd *rgd; struct gfs2_holder rg_gh; struct buffer_head *dibh; - u64 *dataptrs, bn = 0; + __be64 *dataptrs; + u64 bn = 0; u64 bstart = 0; unsigned int blen = 0; unsigned int blks = 0; @@ -444,7 +445,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, struct buffer_head **bh; unsigned int amount = GFS2_EA_DATA_LEN(ea); unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize); - u64 *dataptrs = GFS2_EA2DATAPTRS(ea); + __be64 *dataptrs = GFS2_EA2DATAPTRS(ea); unsigned int x; int error = 0; @@ -629,7 +630,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, ea->ea_num_ptrs = 0; memcpy(GFS2_EA2DATA(ea), er->er_data, er->er_data_len); } else { - u64 *dataptr = GFS2_EA2DATAPTRS(ea); + __be64 *dataptr = GFS2_EA2DATAPTRS(ea); const char *data = er->er_data; unsigned int data_len = er->er_data_len; unsigned int copy; @@ -931,12 +932,12 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *indbh, *newbh; - u64 *eablk; + __be64 *eablk; int error; int mh_size = sizeof(struct gfs2_meta_header); if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) { - u64 *end; + __be64 *end; error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &indbh); @@ -948,7 +949,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, goto out; } - eablk = (u64 *)(indbh->b_data + mh_size); + eablk = (__be64 *)(indbh->b_data + mh_size); end = eablk + sdp->sd_inptrs; for (; eablk < end; eablk++) @@ -971,7 +972,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); gfs2_buffer_clear_tail(indbh, mh_size); - eablk = (u64 *)(indbh->b_data + mh_size); + eablk = (__be64 *)(indbh->b_data + mh_size); *eablk = cpu_to_be64(ip->i_di.di_eattr); ip->i_di.di_eattr = blk; ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT; @@ -1202,7 +1203,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, struct buffer_head **bh; unsigned int amount = GFS2_EA_DATA_LEN(ea); unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize); - u64 *dataptrs = GFS2_EA2DATAPTRS(ea); + __be64 *dataptrs = GFS2_EA2DATAPTRS(ea); unsigned int x; int error; @@ -1300,7 +1301,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_rgrp_list rlist; struct buffer_head *indbh, *dibh; - u64 *eablk, *end; + __be64 *eablk, *end; unsigned int rg_blocks = 0; u64 bstart = 0; unsigned int blen = 0; @@ -1319,7 +1320,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) goto out; } - eablk = (u64 *)(indbh->b_data + sizeof(struct gfs2_meta_header)); + eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header)); end = eablk + sdp->sd_inptrs; for (; eablk < end; eablk++) { @@ -1363,7 +1364,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) gfs2_trans_add_bh(ip->i_gl, indbh, 1); - eablk = (u64 *)(indbh->b_data + sizeof(struct gfs2_meta_header)); + eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header)); bstart = 0; blen = 0; diff --git a/fs/gfs2/eattr.h b/fs/gfs2/eattr.h index ffa6594..c82dbe0 100644 --- a/fs/gfs2/eattr.h +++ b/fs/gfs2/eattr.h @@ -19,7 +19,7 @@ struct iattr; #define GFS2_EA_SIZE(ea) \ ALIGN(sizeof(struct gfs2_ea_header) + (ea)->ea_name_len + \ ((GFS2_EA_IS_STUFFED(ea)) ? GFS2_EA_DATA_LEN(ea) : \ - (sizeof(u64) * (ea)->ea_num_ptrs)), 8) + (sizeof(__be64) * (ea)->ea_num_ptrs)), 8) #define GFS2_EA_IS_STUFFED(ea) (!(ea)->ea_num_ptrs) #define GFS2_EA_IS_LAST(ea) ((ea)->ea_flags & GFS2_EAFLAG_LAST) @@ -29,13 +29,13 @@ ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + (er)->er_data_len, 8) #define GFS2_EAREQ_SIZE_UNSTUFFED(sdp, er) \ ALIGN(sizeof(struct gfs2_ea_header) + (er)->er_name_len + \ - sizeof(u64) * DIV_ROUND_UP((er)->er_data_len, (sdp)->sd_jbsize), 8) + sizeof(__be64) * DIV_ROUND_UP((er)->er_data_len, (sdp)->sd_jbsize), 8) #define GFS2_EA2NAME(ea) ((char *)((struct gfs2_ea_header *)(ea) + 1)) #define GFS2_EA2DATA(ea) (GFS2_EA2NAME(ea) + (ea)->ea_name_len) #define GFS2_EA2DATAPTRS(ea) \ -((u64 *)(GFS2_EA2NAME(ea) + ALIGN((ea)->ea_name_len, 8))) +((__be64 *)(GFS2_EA2NAME(ea) + ALIGN((ea)->ea_name_len, 8))) #define GFS2_EA2NEXT(ea) \ ((struct gfs2_ea_header *)((char *)(ea) + GFS2_EA_REC_LEN(ea))) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index dadd1f3..fb96930 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -500,21 +500,22 @@ static int pick_formal_ino_2(struct gfs2_sbd *sdp, u64 *formal_ino) if (!ir.ir_length) { struct buffer_head *m_bh; u64 x, y; + __be64 z; error = gfs2_meta_inode_buffer(m_ip, &m_bh); if (error) goto out_brelse; - x = *(u64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)); - x = y = be64_to_cpu(x); + z = *(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)); + x = y = be64_to_cpu(z); ir.ir_start = x; ir.ir_length = GFS2_INUM_QUANTUM; x += GFS2_INUM_QUANTUM; if (x < y) gfs2_consist_inode(m_ip); - x = cpu_to_be64(x); + z = cpu_to_be64(x); gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); - *(u64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)) = x; + *(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)) = z; brelse(m_bh); } diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 33423a5..b4e7b87 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c @@ -27,13 +27,14 @@ #include "util.h" static struct dentry *gfs2_decode_fh(struct super_block *sb, - __u32 *fh, + __u32 *p, int fh_len, int fh_type, int (*acceptable)(void *context, struct dentry *dentry), void *context) { + __be32 *fh = (__force __be32 *)p; struct gfs2_fh_obj fh_obj; struct gfs2_inum_host *this, parent; @@ -65,9 +66,10 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb, acceptable, context); } -static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len, +static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, int connectable) { + __be32 *fh = (__force __be32 *)p; struct inode *inode = dentry->d_inode; struct super_block *sb = inode->i_sb; struct gfs2_inode *ip = GFS2_I(inode); @@ -76,14 +78,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len, (connectable && *len < GFS2_LARGE_FH_SIZE)) return 255; - fh[0] = ip->i_num.no_formal_ino >> 32; - fh[0] = cpu_to_be32(fh[0]); - fh[1] = ip->i_num.no_formal_ino & 0xFFFFFFFF; - fh[1] = cpu_to_be32(fh[1]); - fh[2] = ip->i_num.no_addr >> 32; - fh[2] = cpu_to_be32(fh[2]); - fh[3] = ip->i_num.no_addr & 0xFFFFFFFF; - fh[3] = cpu_to_be32(fh[3]); + fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32); + fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF); + fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32); + fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF); *len = GFS2_SMALL_FH_SIZE; if (!connectable || inode == sb->s_root->d_inode) @@ -95,14 +93,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len, igrab(inode); spin_unlock(&dentry->d_lock); - fh[4] = ip->i_num.no_formal_ino >> 32; - fh[4] = cpu_to_be32(fh[4]); - fh[5] = ip->i_num.no_formal_ino & 0xFFFFFFFF; - fh[5] = cpu_to_be32(fh[5]); - fh[6] = ip->i_num.no_addr >> 32; - fh[6] = cpu_to_be32(fh[6]); - fh[7] = ip->i_num.no_addr & 0xFFFFFFFF; - fh[7] = cpu_to_be32(fh[7]); + fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32); + fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF); + fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32); + fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF); fh[8] = cpu_to_be32(inode->i_mode); fh[9] = 0; /* pad to double word */ diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 009d86c..5d00e9b 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -539,8 +539,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) qc->qc_id = cpu_to_be32(qd->qd_id); } - x = qc->qc_change; - x = be64_to_cpu(x) + change; + x = be64_to_cpu(qc->qc_change) + change; qc->qc_change = cpu_to_be64(x); spin_lock(&sdp->sd_quota_spin); diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 76a5089..ca8667c 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h @@ -83,8 +83,7 @@ static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp, char *file, unsigned int line) { struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data; - u32 magic = mh->mh_magic; - magic = be32_to_cpu(magic); + u32 magic = be32_to_cpu(mh->mh_magic); if (unlikely(magic != GFS2_MAGIC)) return gfs2_meta_check_ii(sdp, bh, "magic number", function, file, line); @@ -107,9 +106,8 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp, char *file, unsigned int line) { struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data; - u32 magic = mh->mh_magic; + u32 magic = be32_to_cpu(mh->mh_magic); u16 t = be32_to_cpu(mh->mh_type); - magic = be32_to_cpu(magic); if (unlikely(magic != GFS2_MAGIC)) return gfs2_meta_check_ii(sdp, bh, "magic number", function, file, line); -- cgit v0.10.2 From 9c9ab3d5414653bfe5e5b9f4dfdaab0c6ab17196 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 23:49:23 -0400 Subject: [GFS2] gfs2 __user misannotation fix Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 359965c..2fc8868 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -71,7 +71,7 @@ static int gfs2_read_actor(read_descriptor_t *desc, struct page *page, size = count; kaddr = kmap(page); - memcpy(desc->arg.buf, kaddr + offset, size); + memcpy(desc->arg.data, kaddr + offset, size); kunmap(page); desc->count = count - size; @@ -86,7 +86,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, struct inode *inode = &ip->i_inode; read_descriptor_t desc; desc.written = 0; - desc.arg.buf = buf; + desc.arg.data = buf; desc.count = size; desc.error = 0; do_generic_mapping_read(inode->i_mapping, ra_state, -- cgit v0.10.2 From 539e5d6b7ae8612c0393fe940d2da5b591318d3d Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 15:07:05 -0500 Subject: [GFS2] Change argument of gfs2_dinode_out Everywhere this was called, a struct gfs2_inode was available, but despite that, it was always called with a struct gfs2_dinode as an argument. By making this change it paves the way to start eliminating fields duplicated between the kernel's struct inode and the struct gfs2_dinode. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 5f959b8..906e403 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -201,7 +201,7 @@ static int munge_mode(struct gfs2_inode *ip, mode_t mode) (ip->i_di.di_mode & S_IFMT) == (mode & S_IFMT)); ip->i_di.di_mode = mode; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 51f6356..8c092ab 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -498,7 +498,7 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } set_buffer_new(bh_map); @@ -780,7 +780,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); up_write(&ip->i_rw_mutex); @@ -860,7 +860,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) goto out_end_trans; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); out_end_trans: @@ -970,7 +970,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) ip->i_di.di_size = size; ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size); error = 1; @@ -983,7 +983,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); } } @@ -1057,7 +1057,7 @@ static int trunc_end(struct gfs2_inode *ip) ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); out: diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 59dc823..0742761 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -132,7 +132,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, if (ip->i_di.di_size < offset + size) ip->i_di.di_size = offset + size; ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -232,7 +232,7 @@ out: ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); return copied; @@ -907,7 +907,7 @@ static int dir_make_exhash(struct inode *inode) for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; dip->i_di.di_depth = y; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); @@ -1039,7 +1039,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { dip->i_di.di_blocks++; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1119,7 +1119,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(sdp, !error)) { dip->i_di.di_depth++; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1517,7 +1517,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) return error; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_blocks++; - gfs2_dinode_out(&ip->i_di, bh->b_data); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); return 0; } @@ -1561,7 +1561,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_entries++; ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&ip->i_di, bh->b_data); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; break; @@ -1647,7 +1647,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) gfs2_trans_add_bh(dip->i_gl, bh, 1); dip->i_di.di_entries--; dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&dip->i_di, bh->b_data); + gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1695,7 +1695,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, } dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&dip->i_di, bh->b_data); + gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; } @@ -1875,7 +1875,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, goto out_end_trans; gfs2_trans_add_bh(dip->i_gl, dibh, 1); - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); out_end_trans: diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 518f0c0..9b7bb56 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -302,7 +302,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, if (!error) { ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -717,7 +717,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, } ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -852,7 +852,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, } ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); out: gfs2_trans_end(GFS2_SB(&ip->i_inode)); @@ -1132,7 +1132,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) if (!error) { ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -1287,7 +1287,7 @@ int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); gfs2_inode_attr_out(ip); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -1397,7 +1397,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -1446,7 +1446,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index fb96930..b861ddb 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -338,7 +338,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) ip->i_inode.i_nlink = nlink; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); mark_inode_dirty(&ip->i_inode); @@ -792,7 +792,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, goto fail_end_trans; ip->i_di.di_nlink = 1; gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); return 0; @@ -1349,7 +1349,7 @@ __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) gfs2_inode_attr_out(ip); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } return error; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 2d1682d..2c50fa0 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -15,6 +15,8 @@ #include "gfs2.h" #include +#include +#include "incore.h" #define pv(struct, member, fmt) printk(KERN_INFO " "#member" = "fmt"\n", \ struct->member); @@ -187,8 +189,9 @@ void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf) } -void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf) +void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) { + const struct gfs2_dinode_host *di = &ip->i_di; struct gfs2_dinode *str = buf; gfs2_meta_header_out(&di->di_header, buf); diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 2fc8868..7ea4175 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -336,7 +336,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) goto out_trans_end; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_flags = new_flags; - gfs2_dinode_out(&ip->i_di, bh->b_data); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); out_trans_end: gfs2_trans_end(sdp); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index ef6e5ed..bd26885 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -339,7 +339,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry, error = gfs2_meta_inode_buffer(ip, &dibh); if (!gfs2_assert_withdraw(sdp, !error)) { - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size); brelse(dibh); @@ -414,7 +414,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) gfs2_inum_out(&dip->i_num, &dent->de_inum); dent->de_type = cpu_to_be16(DT_DIR); - gfs2_dinode_out(&ip->i_di, di); + gfs2_dinode_out(ip, di); brelse(dibh); } @@ -541,7 +541,7 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, error = gfs2_meta_inode_buffer(ip, &dibh); if (!gfs2_assert_withdraw(sdp, !error)) { - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -762,7 +762,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_end_trans; ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -949,7 +949,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) gfs2_inode_attr_out(ip); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 10a507d..550effa 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -535,7 +535,8 @@ extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); -extern void gfs2_dinode_out(const struct gfs2_dinode_host *di, void *buf); +struct gfs2_inode; +extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf); -- cgit v0.10.2 From 891ea14712da68e282de8583e5fa14f0d3f3731e Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 15:22:10 -0500 Subject: [GFS2] Change argument to gfs2_dinode_in This is a preliminary patch to enable the removal of fields in gfs2_dinode_host which are duplicated in struct inode. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index b861ddb..9875e93 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -229,7 +229,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) return -EIO; } - gfs2_dinode_in(&ip->i_di, dibh->b_data); + gfs2_dinode_in(ip, dibh->b_data); brelse(dibh); diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 2c50fa0..edf8756 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -155,8 +155,9 @@ void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) qu->qu_value = be64_to_cpu(str->qu_value); } -void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf) +void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) { + struct gfs2_dinode_host *di = &ip->i_di; const struct gfs2_dinode *str = buf; gfs2_meta_header_in(&di->di_header, buf); @@ -186,7 +187,6 @@ void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf) di->di_entries = be32_to_cpu(str->di_entries); di->di_eattr = be64_to_cpu(str->di_eattr); - } void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 550effa..08d8240 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -534,8 +534,8 @@ extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); -extern void gfs2_dinode_in(struct gfs2_dinode_host *di, const void *buf); struct gfs2_inode; +extern void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf); extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); -- cgit v0.10.2 From ea744d01c6a5acf1f6171b4c6e1658a742063613 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 15:28:00 -0500 Subject: [GFS2] Move gfs2_dinode_in to inode.c gfs2_dinode_in() is only ever called from one place, so move it to that place (in inode.c) and make it static. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 9875e93..b39cfcf 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -208,6 +208,40 @@ fail: return ERR_PTR(error); } +static void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) +{ + struct gfs2_dinode_host *di = &ip->i_di; + const struct gfs2_dinode *str = buf; + + gfs2_meta_header_in(&di->di_header, buf); + gfs2_inum_in(&di->di_num, &str->di_num); + + di->di_mode = be32_to_cpu(str->di_mode); + di->di_uid = be32_to_cpu(str->di_uid); + di->di_gid = be32_to_cpu(str->di_gid); + di->di_nlink = be32_to_cpu(str->di_nlink); + di->di_size = be64_to_cpu(str->di_size); + di->di_blocks = be64_to_cpu(str->di_blocks); + di->di_atime = be64_to_cpu(str->di_atime); + di->di_mtime = be64_to_cpu(str->di_mtime); + di->di_ctime = be64_to_cpu(str->di_ctime); + di->di_major = be32_to_cpu(str->di_major); + di->di_minor = be32_to_cpu(str->di_minor); + + di->di_goal_meta = be64_to_cpu(str->di_goal_meta); + di->di_goal_data = be64_to_cpu(str->di_goal_data); + di->di_generation = be64_to_cpu(str->di_generation); + + di->di_flags = be32_to_cpu(str->di_flags); + di->di_payload_format = be32_to_cpu(str->di_payload_format); + di->di_height = be16_to_cpu(str->di_height); + + di->di_depth = be16_to_cpu(str->di_depth); + di->di_entries = be32_to_cpu(str->di_entries); + + di->di_eattr = be64_to_cpu(str->di_eattr); +} + /** * gfs2_inode_refresh - Refresh the incore copy of the dinode * @ip: The GFS2 inode diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index edf8756..062a44f 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -56,7 +56,7 @@ static void gfs2_inum_print(const struct gfs2_inum_host *no) printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr); } -static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) +void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) { const struct gfs2_meta_header *str = buf; @@ -155,40 +155,6 @@ void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) qu->qu_value = be64_to_cpu(str->qu_value); } -void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) -{ - struct gfs2_dinode_host *di = &ip->i_di; - const struct gfs2_dinode *str = buf; - - gfs2_meta_header_in(&di->di_header, buf); - gfs2_inum_in(&di->di_num, &str->di_num); - - di->di_mode = be32_to_cpu(str->di_mode); - di->di_uid = be32_to_cpu(str->di_uid); - di->di_gid = be32_to_cpu(str->di_gid); - di->di_nlink = be32_to_cpu(str->di_nlink); - di->di_size = be64_to_cpu(str->di_size); - di->di_blocks = be64_to_cpu(str->di_blocks); - di->di_atime = be64_to_cpu(str->di_atime); - di->di_mtime = be64_to_cpu(str->di_mtime); - di->di_ctime = be64_to_cpu(str->di_ctime); - di->di_major = be32_to_cpu(str->di_major); - di->di_minor = be32_to_cpu(str->di_minor); - - di->di_goal_meta = be64_to_cpu(str->di_goal_meta); - di->di_goal_data = be64_to_cpu(str->di_goal_data); - di->di_generation = be64_to_cpu(str->di_generation); - - di->di_flags = be32_to_cpu(str->di_flags); - di->di_payload_format = be32_to_cpu(str->di_payload_format); - di->di_height = be16_to_cpu(str->di_height); - - di->di_depth = be16_to_cpu(str->di_depth); - di->di_entries = be32_to_cpu(str->di_entries); - - di->di_eattr = be64_to_cpu(str->di_eattr); -} - void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) { const struct gfs2_dinode_host *di = &ip->i_di; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 08d8240..4fc297a 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -528,6 +528,7 @@ struct gfs2_quota_change_host { extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf); extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf); +extern void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf); extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); @@ -535,7 +536,6 @@ extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); struct gfs2_inode; -extern void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf); extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); -- cgit v0.10.2 From 4cc14f0b88bf3e0b508143e091eb5a8dff3e3b9c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 19:00:24 -0500 Subject: [GFS2] Change argument to gfs2_dinode_print Change argument for gfs2_dinode_print in order to prepare for removal of duplicate fields between struct inode and struct gfs2_dinode_host. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index b39cfcf..4c5d286 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -269,7 +269,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) if (ip->i_num.no_addr != ip->i_di.di_num.no_addr) { if (gfs2_consist_inode(ip)) - gfs2_dinode_print(&ip->i_di); + gfs2_dinode_print(ip); return -EIO; } if (ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino) @@ -289,7 +289,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) if (ip->i_di.di_blocks != 1) { if (gfs2_consist_inode(ip)) - gfs2_dinode_print(&ip->i_di); + gfs2_dinode_print(ip); return -EIO; } @@ -359,7 +359,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) bigger than the old one, we must have underflowed. */ if (diff < 0 && nlink > ip->i_di.di_nlink) { if (gfs2_consist_inode(ip)) - gfs2_dinode_print(&ip->i_di); + gfs2_dinode_print(ip); return -EIO; } @@ -1010,7 +1010,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, if (ip->i_di.di_entries != 2) { if (gfs2_consist_inode(ip)) - gfs2_dinode_print(&ip->i_di); + gfs2_dinode_print(ip); return -EIO; } diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 062a44f..77bed44 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -190,8 +190,10 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) } -void gfs2_dinode_print(const struct gfs2_dinode_host *di) +void gfs2_dinode_print(const struct gfs2_inode *ip) { + const struct gfs2_dinode_host *di = &ip->i_di; + gfs2_meta_header_print(&di->di_header); gfs2_inum_print(&di->di_num); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index bd26885..b2c2fe6 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -467,7 +467,7 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) if (ip->i_di.di_entries < 2) { if (gfs2_consist_inode(ip)) - gfs2_dinode_print(&ip->i_di); + gfs2_dinode_print(ip); error = -EIO; goto out_gunlock; } @@ -640,7 +640,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (S_ISDIR(nip->i_di.di_mode)) { if (nip->i_di.di_entries < 2) { if (gfs2_consist_inode(nip)) - gfs2_dinode_print(&nip->i_di); + gfs2_dinode_print(nip); error = -EIO; goto out_gunlock; } diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 4fc297a..cf4c655 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -549,7 +549,7 @@ extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void * /* Printing functions */ extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri); -extern void gfs2_dinode_print(const struct gfs2_dinode_host *di); +extern void gfs2_dinode_print(const struct gfs2_inode *ip); #endif /* __KERNEL__ */ -- cgit v0.10.2 From af339c0241d0dd3b35f9097b4f4999bb22ffe502 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 10:34:15 -0500 Subject: [GFS2] Shrink gfs2_inode (1) - di_header/di_num The metadata header doesn't need to be stored in the incore struct gfs2_inode since its constant, and this patch removes it. Also, there is already a field for the inode's number in the struct gfs2_inode, so we don't need one in struct gfs2_dinode_host as well. This saves 28 bytes of space in the struct gfs2_inode. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 4c5d286..7ba05fc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -208,13 +208,18 @@ fail: return ERR_PTR(error); } -static void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) +static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) { struct gfs2_dinode_host *di = &ip->i_di; const struct gfs2_dinode *str = buf; - gfs2_meta_header_in(&di->di_header, buf); - gfs2_inum_in(&di->di_num, &str->di_num); + if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) { + if (gfs2_consist_inode(ip)) + gfs2_dinode_print(ip); + return -EIO; + } + if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino)) + return -ESTALE; di->di_mode = be32_to_cpu(str->di_mode); di->di_uid = be32_to_cpu(str->di_uid); @@ -240,6 +245,7 @@ static void gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_entries = be32_to_cpu(str->di_entries); di->di_eattr = be64_to_cpu(str->di_eattr); + return 0; } /** @@ -263,21 +269,12 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) return -EIO; } - gfs2_dinode_in(ip, dibh->b_data); + error = gfs2_dinode_in(ip, dibh->b_data); brelse(dibh); - - if (ip->i_num.no_addr != ip->i_di.di_num.no_addr) { - if (gfs2_consist_inode(ip)) - gfs2_dinode_print(ip); - return -EIO; - } - if (ip->i_num.no_formal_ino != ip->i_di.di_num.no_formal_ino) - return -ESTALE; - ip->i_vn = ip->i_gl->gl_vn; - return 0; + return error; } int gfs2_dinode_dealloc(struct gfs2_inode *ip) diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 77bed44..4bc590e 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -56,7 +56,7 @@ static void gfs2_inum_print(const struct gfs2_inum_host *no) printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr); } -void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) +static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) { const struct gfs2_meta_header *str = buf; @@ -74,13 +74,6 @@ static void gfs2_meta_header_out(const struct gfs2_meta_header_host *mh, void *b str->mh_format = cpu_to_be32(mh->mh_format); } -static void gfs2_meta_header_print(const struct gfs2_meta_header_host *mh) -{ - pv(mh, mh_magic, "0x%.8X"); - pv(mh, mh_type, "%u"); - pv(mh, mh_format, "%u"); -} - void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) { const struct gfs2_sb *str = buf; @@ -160,8 +153,13 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) const struct gfs2_dinode_host *di = &ip->i_di; struct gfs2_dinode *str = buf; - gfs2_meta_header_out(&di->di_header, buf); - gfs2_inum_out(&di->di_num, (char *)&str->di_num); + str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); + str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); + str->di_header.__pad0 = 0; + str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); + str->di_header.__pad1 = 0; + + gfs2_inum_out(&ip->i_num, &str->di_num); str->di_mode = cpu_to_be32(di->di_mode); str->di_uid = cpu_to_be32(di->di_uid); @@ -187,15 +185,13 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_entries = cpu_to_be32(di->di_entries); str->di_eattr = cpu_to_be64(di->di_eattr); - } void gfs2_dinode_print(const struct gfs2_inode *ip) { const struct gfs2_dinode_host *di = &ip->i_di; - gfs2_meta_header_print(&di->di_header); - gfs2_inum_print(&di->di_num); + gfs2_inum_print(&ip->i_num); pv(di, di_mode, "0%o"); pv(di, di_uid, "%u"); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index cf4c655..c0e76fc 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -322,10 +322,6 @@ struct gfs2_dinode { }; struct gfs2_dinode_host { - struct gfs2_meta_header_host di_header; - - struct gfs2_inum_host di_num; - __u32 di_mode; /* mode of file */ __u32 di_uid; /* owner's user id */ __u32 di_gid; /* owner's group id */ @@ -528,7 +524,6 @@ struct gfs2_quota_change_host { extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf); extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf); -extern void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf); extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); -- cgit v0.10.2 From e7f14f4d094ea1a9ce1953375f5bc1500c760c79 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 21:45:08 -0500 Subject: [GFS2] Shrink gfs2_inode (2) - di_major/di_minor This removes the device numbers from this structure by using inode->i_rdev instead. It also cleans up the code in gfs2_mknod. It results in shrinking the gfs2_inode by 8 bytes. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 7ba05fc..a995919 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -51,17 +51,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) struct gfs2_dinode_host *di = &ip->i_di; inode->i_ino = ip->i_num.no_addr; - - switch (di->di_mode & S_IFMT) { - case S_IFBLK: - case S_IFCHR: - inode->i_rdev = MKDEV(di->di_major, di->di_minor); - break; - default: - inode->i_rdev = 0; - break; - }; - inode->i_mode = di->di_mode; inode->i_nlink = di->di_nlink; inode->i_uid = di->di_uid; @@ -222,6 +211,15 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) return -ESTALE; di->di_mode = be32_to_cpu(str->di_mode); + ip->i_inode.i_rdev = 0; + switch (di->di_mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), + be32_to_cpu(str->di_minor)); + break; + }; + di->di_uid = be32_to_cpu(str->di_uid); di->di_gid = be32_to_cpu(str->di_gid); di->di_nlink = be32_to_cpu(str->di_nlink); @@ -230,8 +228,6 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_atime = be64_to_cpu(str->di_atime); di->di_mtime = be64_to_cpu(str->di_mtime); di->di_ctime = be64_to_cpu(str->di_ctime); - di->di_major = be32_to_cpu(str->di_major); - di->di_minor = be32_to_cpu(str->di_minor); di->di_goal_meta = be64_to_cpu(str->di_goal_meta); di->di_goal_data = be64_to_cpu(str->di_goal_data); @@ -270,7 +266,6 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) } error = gfs2_dinode_in(ip, dibh->b_data); - brelse(dibh); ip->i_vn = ip->i_gl->gl_vn; @@ -684,7 +679,7 @@ out: static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, const struct gfs2_inum_host *inum, unsigned int mode, unsigned int uid, unsigned int gid, - const u64 *generation) + const u64 *generation, dev_t dev) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_dinode *di; @@ -705,7 +700,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, di->di_size = cpu_to_be64(0); di->di_blocks = cpu_to_be64(1); di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds()); - di->di_major = di->di_minor = cpu_to_be32(0); + di->di_major = cpu_to_be32(MAJOR(dev)); + di->di_minor = cpu_to_be32(MINOR(dev)); di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); di->di_generation = cpu_to_be64(*generation); di->di_flags = cpu_to_be32(0); @@ -740,7 +736,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, unsigned int mode, const struct gfs2_inum_host *inum, - const u64 *generation) + const u64 *generation, dev_t dev) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); unsigned int uid, gid; @@ -761,7 +757,7 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, if (error) goto out_quota; - init_dinode(dip, gl, inum, mode, uid, gid, generation); + init_dinode(dip, gl, inum, mode, uid, gid, generation, dev); gfs2_quota_change(dip, +1, uid, gid); gfs2_trans_end(sdp); @@ -892,7 +888,7 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip) */ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, - unsigned int mode) + unsigned int mode, dev_t dev) { struct inode *inode; struct gfs2_inode *dip = ghs->gh_gl->gl_object; @@ -950,7 +946,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, goto fail_gunlock; } - error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation); + error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev); if (error) goto fail_gunlock2; diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index d699b92..33c9ea6 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -37,7 +37,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff); struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, int is_root, struct nameidata *nd); struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, - unsigned int mode); + unsigned int mode, dev_t dev); int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, struct gfs2_inode *ip); int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 4bc590e..60dd943 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -170,8 +170,6 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_atime = cpu_to_be64(di->di_atime); str->di_mtime = cpu_to_be64(di->di_mtime); str->di_ctime = cpu_to_be64(di->di_ctime); - str->di_major = cpu_to_be32(di->di_major); - str->di_minor = cpu_to_be32(di->di_minor); str->di_goal_meta = cpu_to_be64(di->di_goal_meta); str->di_goal_data = cpu_to_be64(di->di_goal_data); @@ -202,8 +200,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) printk(KERN_INFO " di_atime = %lld\n", (long long)di->di_atime); printk(KERN_INFO " di_mtime = %lld\n", (long long)di->di_mtime); printk(KERN_INFO " di_ctime = %lld\n", (long long)di->di_ctime); - pv(di, di_major, "%u"); - pv(di, di_minor, "%u"); printk(KERN_INFO " di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta); printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index b2c2fe6..c10b914 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -59,7 +59,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry, gfs2_holder_init(dip->i_gl, 0, 0, ghs); for (;;) { - inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode); + inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0); if (!IS_ERR(inode)) { gfs2_trans_end(sdp); if (dip->i_alloc.al_rgd) @@ -326,7 +326,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry, gfs2_holder_init(dip->i_gl, 0, 0, ghs); - inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO); + inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0); if (IS_ERR(inode)) { gfs2_holder_uninit(ghs); return PTR_ERR(inode); @@ -379,7 +379,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) gfs2_holder_init(dip->i_gl, 0, 0, ghs); - inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode); + inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0); if (IS_ERR(inode)) { gfs2_holder_uninit(ghs); return PTR_ERR(inode); @@ -504,47 +504,19 @@ out: static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { - struct gfs2_inode *dip = GFS2_I(dir), *ip; + struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_sbd *sdp = GFS2_SB(dir); struct gfs2_holder ghs[2]; struct inode *inode; - struct buffer_head *dibh; - u32 major = 0, minor = 0; - int error; - - switch (mode & S_IFMT) { - case S_IFBLK: - case S_IFCHR: - major = MAJOR(dev); - minor = MINOR(dev); - break; - case S_IFIFO: - case S_IFSOCK: - break; - default: - return -EOPNOTSUPP; - }; gfs2_holder_init(dip->i_gl, 0, 0, ghs); - inode = gfs2_createi(ghs, &dentry->d_name, mode); + inode = gfs2_createi(ghs, &dentry->d_name, mode, dev); if (IS_ERR(inode)) { gfs2_holder_uninit(ghs); return PTR_ERR(inode); } - ip = ghs[1].gh_gl->gl_object; - - ip->i_di.di_major = major; - ip->i_di.di_minor = minor; - - error = gfs2_meta_inode_buffer(ip, &dibh); - - if (!gfs2_assert_withdraw(sdp, !error)) { - gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); - } - gfs2_trans_end(sdp); if (dip->i_alloc.al_rgd) gfs2_inplace_release(dip); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index c0e76fc..5bcf895 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -331,8 +331,6 @@ struct gfs2_dinode_host { __u64 di_atime; /* time last accessed */ __u64 di_mtime; /* time last modified */ __u64 di_ctime; /* time last changed */ - __u32 di_major; /* device major number */ - __u32 di_minor; /* device minor number */ /* This section varies from gfs1. Padding added to align with * remainder of dinode -- cgit v0.10.2 From b60623c238b6a819bd04090139704e2cb57a751f Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 12:22:46 -0500 Subject: [GFS2] Shrink gfs2_inode (3) - di_mode This removes the duplicate di_mode field in favour of using the inode->i_mode field. This saves 4 bytes. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 906e403..87f6304f 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -76,9 +76,9 @@ int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access) return -EOPNOTSUPP; if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER)) return -EPERM; - if (S_ISLNK(ip->i_di.di_mode)) + if (S_ISLNK(ip->i_inode.i_mode)) return -EOPNOTSUPP; - if (!access && !S_ISDIR(ip->i_di.di_mode)) + if (!access && !S_ISDIR(ip->i_inode.i_mode)) return -EACCES; return 0; @@ -198,8 +198,8 @@ static int munge_mode(struct gfs2_inode *ip, mode_t mode) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { gfs2_assert_withdraw(sdp, - (ip->i_di.di_mode & S_IFMT) == (mode & S_IFMT)); - ip->i_di.di_mode = mode; + (ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT)); + ip->i_inode.i_mode = mode; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -215,12 +215,12 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct posix_acl *acl = NULL, *clone; struct gfs2_ea_request er; - mode_t mode = ip->i_di.di_mode; + mode_t mode = ip->i_inode.i_mode; int error; if (!sdp->sd_args.ar_posix_acl) return 0; - if (S_ISLNK(ip->i_di.di_mode)) + if (S_ISLNK(ip->i_inode.i_mode)) return 0; memset(&er, 0, sizeof(struct gfs2_ea_request)); @@ -232,7 +232,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) return error; if (!acl) { mode &= ~current->fs->umask; - if (mode != ip->i_di.di_mode) + if (mode != ip->i_inode.i_mode) error = munge_mode(ip, mode); return error; } @@ -244,7 +244,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) posix_acl_release(acl); acl = clone; - if (S_ISDIR(ip->i_di.di_mode)) { + if (S_ISDIR(ip->i_inode.i_mode)) { er.er_name = GFS2_POSIX_ACL_DEFAULT; er.er_name_len = GFS2_POSIX_ACL_DEFAULT_LEN; error = gfs2_system_eaops.eo_set(ip, &er); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 8c092ab..481a068 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1109,7 +1109,7 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size) { int error; - if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_di.di_mode))) + if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode))) return -EINVAL; if (size > ip->i_di.di_size) diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index 92c54e9..cd747c0 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c @@ -120,7 +120,7 @@ static int system_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er) if (GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len)) { if (!(er->er_flags & GFS2_ERF_MODE)) { - er->er_mode = ip->i_di.di_mode; + er->er_mode = ip->i_inode.i_mode; er->er_flags |= GFS2_ERF_MODE; } error = gfs2_acl_validate_set(ip, 1, er, diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 9b7bb56..5208fa9 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -711,9 +711,9 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, if (!error) { if (er->er_flags & GFS2_ERF_MODE) { gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), - (ip->i_di.di_mode & S_IFMT) == + (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); - ip->i_di.di_mode = er->er_mode; + ip->i_inode.i_mode = er->er_mode; } ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); @@ -847,8 +847,8 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, if (er->er_flags & GFS2_ERF_MODE) { gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), - (ip->i_di.di_mode & S_IFMT) == (er->er_mode & S_IFMT)); - ip->i_di.di_mode = er->er_mode; + (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); + ip->i_inode.i_mode = er->er_mode; } ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 78fe0fa..44633c4 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -2078,7 +2078,7 @@ static int dump_inode(struct gfs2_inode *ip) printk(KERN_INFO " num = %llu %llu\n", (unsigned long long)ip->i_num.no_formal_ino, (unsigned long long)ip->i_num.no_addr); - printk(KERN_INFO " type = %u\n", IF2DT(ip->i_di.di_mode)); + printk(KERN_INFO " type = %u\n", IF2DT(ip->i_inode.i_mode)); printk(KERN_INFO " i_flags ="); for (x = 0; x < 32; x++) if (test_bit(x, &ip->i_flags)) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 5406b19..aad45b7 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -92,7 +92,7 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) ip = gl->gl_object; inode = &ip->i_inode; - if (!ip || !S_ISREG(ip->i_di.di_mode)) + if (!ip || !S_ISREG(inode->i_mode)) return; if (!test_bit(GIF_PAGED, &ip->i_flags)) @@ -119,7 +119,7 @@ static void gfs2_page_inval(struct gfs2_glock *gl) ip = gl->gl_object; inode = &ip->i_inode; - if (!ip || !S_ISREG(ip->i_di.di_mode)) + if (!ip || !S_ISREG(inode->i_mode)) return; truncate_inode_pages(inode->i_mapping, 0); @@ -142,7 +142,7 @@ static void gfs2_page_wait(struct gfs2_glock *gl) struct address_space *mapping = inode->i_mapping; int error; - if (!S_ISREG(ip->i_di.di_mode)) + if (!S_ISREG(inode->i_mode)) return; error = filemap_fdatawait(mapping); @@ -164,7 +164,7 @@ static void gfs2_page_writeback(struct gfs2_glock *gl) struct inode *inode = &ip->i_inode; struct address_space *mapping = inode->i_mapping; - if (!S_ISREG(ip->i_di.di_mode)) + if (!S_ISREG(inode->i_mode)) return; filemap_fdatawrite(mapping); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index a995919..de46604 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -51,7 +51,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) struct gfs2_dinode_host *di = &ip->i_di; inode->i_ino = ip->i_num.no_addr; - inode->i_mode = di->di_mode; inode->i_nlink = di->di_nlink; inode->i_uid = di->di_uid; inode->i_gid = di->di_gid; @@ -88,9 +87,6 @@ void gfs2_inode_attr_out(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; struct gfs2_dinode_host *di = &ip->i_di; - gfs2_assert_withdraw(GFS2_SB(inode), - (di->di_mode & S_IFMT) == (inode->i_mode & S_IFMT)); - di->di_mode = inode->i_mode; di->di_uid = inode->i_uid; di->di_gid = inode->i_gid; di->di_atime = inode->i_atime.tv_sec; @@ -210,9 +206,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino)) return -ESTALE; - di->di_mode = be32_to_cpu(str->di_mode); + ip->i_inode.i_mode = be32_to_cpu(str->di_mode); ip->i_inode.i_rdev = 0; - switch (di->di_mode & S_IFMT) { + switch (ip->i_inode.i_mode & S_IFMT) { case S_IFBLK: case S_IFCHR: ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), @@ -620,7 +616,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, unsigned int *uid, unsigned int *gid) { if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir && - (dip->i_di.di_mode & S_ISUID) && dip->i_di.di_uid) { + (dip->i_inode.i_mode & S_ISUID) && dip->i_di.di_uid) { if (S_ISDIR(*mode)) *mode |= S_ISUID; else if (dip->i_di.di_uid != current->fsuid) @@ -629,7 +625,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, } else *uid = current->fsuid; - if (dip->i_di.di_mode & S_ISGID) { + if (dip->i_inode.i_mode & S_ISGID) { if (S_ISDIR(*mode)) *mode |= S_ISGID; *gid = dip->i_di.di_gid; @@ -810,7 +806,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, goto fail_quota_locks; } - error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_di.di_mode)); + error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode)); if (error) goto fail_end_trans; @@ -1053,7 +1049,7 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode)) return -EPERM; - if ((dip->i_di.di_mode & S_ISVTX) && + if ((dip->i_inode.i_mode & S_ISVTX) && dip->i_di.di_uid != current->fsuid && ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER)) return -EPERM; @@ -1072,7 +1068,7 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, if (!gfs2_inum_equal(&inum, &ip->i_num)) return -ENOENT; - if (IF2DT(ip->i_di.di_mode) != type) { + if (IF2DT(ip->i_inode.i_mode) != type) { gfs2_consist_inode(dip); return -EIO; } diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 33c9ea6..69cbf98 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -22,7 +22,7 @@ static inline int gfs2_is_jdata(struct gfs2_inode *ip) static inline int gfs2_is_dir(struct gfs2_inode *ip) { - return S_ISDIR(ip->i_di.di_mode); + return S_ISDIR(ip->i_inode.i_mode); } void gfs2_inode_attr_in(struct gfs2_inode *ip); diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 60dd943..6b50a57 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -161,7 +161,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) gfs2_inum_out(&ip->i_num, &str->di_num); - str->di_mode = cpu_to_be32(di->di_mode); + str->di_mode = cpu_to_be32(ip->i_inode.i_mode); str->di_uid = cpu_to_be32(di->di_uid); str->di_gid = cpu_to_be32(di->di_gid); str->di_nlink = cpu_to_be32(di->di_nlink); @@ -191,7 +191,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) gfs2_inum_print(&ip->i_num); - pv(di, di_mode, "0%o"); pv(di, di_uid, "%u"); pv(di, di_gid, "%u"); pv(di, di_nlink, "%u"); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 015640b..45a3d85 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -498,7 +498,6 @@ static int gfs2_commit_write(struct file *file, struct page *page, di->di_size = cpu_to_be64(inode->i_size); } - di->di_mode = cpu_to_be32(inode->i_mode); di->di_atime = cpu_to_be64(inode->i_atime.tv_sec); di->di_mtime = cpu_to_be64(inode->i_mtime.tv_sec); di->di_ctime = cpu_to_be64(inode->i_ctime.tv_sec); diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index c36f9e3..d355899 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c @@ -76,7 +76,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) if (!gfs2_inum_equal(&ip->i_num, &inum)) goto invalid_gunlock; - if (IF2DT(ip->i_di.di_mode) != type) { + if (IF2DT(ip->i_inode.i_mode) != type) { gfs2_consist_inode(dip); goto fail_gunlock; } diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 7ea4175..b52b9db 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -425,7 +425,7 @@ static int gfs2_open(struct inode *inode, struct file *file) gfs2_assert_warn(GFS2_SB(inode), !file->private_data); file->private_data = fp; - if (S_ISREG(ip->i_di.di_mode)) { + if (S_ISREG(ip->i_inode.i_mode)) { error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) @@ -515,7 +515,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; if (sdp->sd_args.ar_localflocks) { @@ -617,7 +617,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; if (sdp->sd_args.ar_localflocks) diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index c10b914..cf7a5ba 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -144,7 +144,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, int alloc_required; int error; - if (S_ISDIR(ip->i_di.di_mode)) + if (S_ISDIR(inode->i_mode)) return -EPERM; gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); @@ -220,7 +220,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, } error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num, - IF2DT(ip->i_di.di_mode)); + IF2DT(inode->i_mode)); if (error) goto out_end_trans; @@ -564,11 +564,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, /* Make sure we aren't trying to move a dirctory into it's subdir */ - if (S_ISDIR(ip->i_di.di_mode) && odip != ndip) { + if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) { dir_rename = 1; - error = gfs2_glock_nq_init(sdp->sd_rename_gl, - LM_ST_EXCLUSIVE, 0, + error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0, &r_gh); if (error) goto out; @@ -609,7 +608,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (error) goto out_gunlock; - if (S_ISDIR(nip->i_di.di_mode)) { + if (S_ISDIR(nip->i_inode.i_mode)) { if (nip->i_di.di_entries < 2) { if (gfs2_consist_inode(nip)) gfs2_dinode_print(nip); @@ -646,7 +645,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, error = -EFBIG; goto out_gunlock; } - if (S_ISDIR(ip->i_di.di_mode) && + if (S_ISDIR(ip->i_inode.i_mode) && ndip->i_di.di_nlink == (u32)-1) { error = -EMLINK; goto out_gunlock; @@ -701,7 +700,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, /* Remove the target file, if it exists */ if (nip) { - if (S_ISDIR(nip->i_di.di_mode)) + if (S_ISDIR(nip->i_inode.i_mode)) error = gfs2_rmdiri(ndip, &ndentry->d_name, nip); else { error = gfs2_dir_del(ndip, &ndentry->d_name); @@ -743,7 +742,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_end_trans; error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num, - IF2DT(ip->i_di.di_mode)); + IF2DT(ip->i_inode.i_mode)); if (error) goto out_end_trans; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 9c786d1..8635175 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -407,7 +407,7 @@ static void gfs2_delete_inode(struct inode *inode) if (error) goto out_uninit; - if (S_ISDIR(ip->i_di.di_mode) && + if (S_ISDIR(inode->i_mode) && (ip->i_di.di_flags & GFS2_DIF_EXHASH)) { error = gfs2_dir_exhash_dealloc(ip); if (error) diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 5bcf895..f1ea0b4 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -322,7 +322,6 @@ struct gfs2_dinode { }; struct gfs2_dinode_host { - __u32 di_mode; /* mode of file */ __u32 di_uid; /* owner's user id */ __u32 di_gid; /* owner's group id */ __u32 di_nlink; /* number of links to this file */ -- cgit v0.10.2 From 2933f9254a6af33db25270778c998a42029da668 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 13:23:29 -0500 Subject: [GFS2] Shrink gfs2_inode (4) - di_uid/di_gid Remove duplicate di_uid/di_gid fields in favour of using inode->i_uid/inode->i_gid instead. This saves 8 bytes. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 87f6304f..3908992 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -74,7 +74,7 @@ int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access) { if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl) return -EOPNOTSUPP; - if (current->fsuid != ip->i_di.di_uid && !capable(CAP_FOWNER)) + if (current->fsuid != ip->i_inode.i_uid && !capable(CAP_FOWNER)) return -EPERM; if (S_ISLNK(ip->i_inode.i_mode)) return -EOPNOTSUPP; diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 481a068..0c913ee 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -819,7 +819,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) if (error) goto out; - error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); if (error) goto out_gunlock_q; diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 5208fa9..935cc9a 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -687,7 +687,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, if (error) goto out; - error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); if (error) goto out_gunlock_q; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index de46604..0de9b22 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -52,8 +52,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) inode->i_ino = ip->i_num.no_addr; inode->i_nlink = di->di_nlink; - inode->i_uid = di->di_uid; - inode->i_gid = di->di_gid; i_size_write(inode, di->di_size); inode->i_atime.tv_sec = di->di_atime; inode->i_mtime.tv_sec = di->di_mtime; @@ -87,8 +85,6 @@ void gfs2_inode_attr_out(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; struct gfs2_dinode_host *di = &ip->i_di; - di->di_uid = inode->i_uid; - di->di_gid = inode->i_gid; di->di_atime = inode->i_atime.tv_sec; di->di_mtime = inode->i_mtime.tv_sec; di->di_ctime = inode->i_ctime.tv_sec; @@ -216,8 +212,8 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) break; }; - di->di_uid = be32_to_cpu(str->di_uid); - di->di_gid = be32_to_cpu(str->di_gid); + ip->i_inode.i_uid = be32_to_cpu(str->di_uid); + ip->i_inode.i_gid = be32_to_cpu(str->di_gid); di->di_nlink = be32_to_cpu(str->di_nlink); di->di_size = be64_to_cpu(str->di_size); di->di_blocks = be64_to_cpu(str->di_blocks); @@ -616,19 +612,19 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, unsigned int *uid, unsigned int *gid) { if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir && - (dip->i_inode.i_mode & S_ISUID) && dip->i_di.di_uid) { + (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) { if (S_ISDIR(*mode)) *mode |= S_ISUID; - else if (dip->i_di.di_uid != current->fsuid) + else if (dip->i_inode.i_uid != current->fsuid) *mode &= ~07111; - *uid = dip->i_di.di_uid; + *uid = dip->i_inode.i_uid; } else *uid = current->fsuid; if (dip->i_inode.i_mode & S_ISGID) { if (S_ISDIR(*mode)) *mode |= S_ISGID; - *gid = dip->i_di.di_gid; + *gid = dip->i_inode.i_gid; } else *gid = current->fsgid; } @@ -783,8 +779,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, if (alloc_required < 0) goto fail; if (alloc_required) { - error = gfs2_quota_check(dip, dip->i_di.di_uid, - dip->i_di.di_gid); + error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid); if (error) goto fail_quota_locks; @@ -1050,8 +1045,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, return -EPERM; if ((dip->i_inode.i_mode & S_ISVTX) && - dip->i_di.di_uid != current->fsuid && - ip->i_di.di_uid != current->fsuid && !capable(CAP_FOWNER)) + dip->i_inode.i_uid != current->fsuid && + ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER)) return -EPERM; if (IS_APPEND(&dip->i_inode)) diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 6b50a57..e224f6a 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -162,8 +162,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) gfs2_inum_out(&ip->i_num, &str->di_num); str->di_mode = cpu_to_be32(ip->i_inode.i_mode); - str->di_uid = cpu_to_be32(di->di_uid); - str->di_gid = cpu_to_be32(di->di_gid); + str->di_uid = cpu_to_be32(ip->i_inode.i_uid); + str->di_gid = cpu_to_be32(ip->i_inode.i_gid); str->di_nlink = cpu_to_be32(di->di_nlink); str->di_size = cpu_to_be64(di->di_size); str->di_blocks = cpu_to_be64(di->di_blocks); @@ -191,8 +191,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) gfs2_inum_print(&ip->i_num); - pv(di, di_uid, "%u"); - pv(di, di_gid, "%u"); pv(di, di_nlink, "%u"); printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 45a3d85..38b702a 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -386,7 +386,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page, if (error) goto out_alloc_put; - error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); if (error) goto out_qunlock; diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index cf7a5ba..efbcec3 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -196,8 +196,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, if (error) goto out_alloc; - error = gfs2_quota_check(dip, dip->i_di.di_uid, - dip->i_di.di_gid); + error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid); if (error) goto out_gunlock_q; @@ -673,8 +672,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (error) goto out_alloc; - error = gfs2_quota_check(ndip, ndip->i_di.di_uid, - ndip->i_di.di_gid); + error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid); if (error) goto out_gunlock_q; @@ -885,8 +883,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) u32 ouid, ogid, nuid, ngid; int error; - ouid = ip->i_di.di_uid; - ogid = ip->i_di.di_gid; + ouid = inode->i_uid; + ogid = inode->i_gid; nuid = attr->ia_uid; ngid = attr->ia_gid; diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index 5453d29..45a5f11 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c @@ -76,7 +76,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) if (error) goto out; - error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid); + error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); if (error) goto out_gunlock_q; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 5d00e9b..d0db881 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -452,19 +452,19 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return 0; - error = qdsb_get(sdp, QUOTA_USER, ip->i_di.di_uid, CREATE, qd); + error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, CREATE, qd); if (error) goto out; al->al_qd_num++; qd++; - error = qdsb_get(sdp, QUOTA_GROUP, ip->i_di.di_gid, CREATE, qd); + error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, CREATE, qd); if (error) goto out; al->al_qd_num++; qd++; - if (uid != NO_QUOTA_CHANGE && uid != ip->i_di.di_uid) { + if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { error = qdsb_get(sdp, QUOTA_USER, uid, CREATE, qd); if (error) goto out; @@ -472,7 +472,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) qd++; } - if (gid != NO_QUOTA_CHANGE && gid != ip->i_di.di_gid) { + if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { error = qdsb_get(sdp, QUOTA_GROUP, gid, CREATE, qd); if (error) goto out; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 07dfd63..ff08465 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1217,7 +1217,7 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) al->al_alloced++; gfs2_statfs_change(sdp, 0, -1, 0); - gfs2_quota_change(ip, +1, ip->i_di.di_uid, ip->i_di.di_gid); + gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid); spin_lock(&sdp->sd_rindex_spin); rgd->rd_free_clone--; @@ -1261,7 +1261,7 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip) al->al_alloced++; gfs2_statfs_change(sdp, 0, -1, 0); - gfs2_quota_change(ip, +1, ip->i_di.di_uid, ip->i_di.di_gid); + gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid); gfs2_trans_add_unrevoke(sdp, block); spin_lock(&sdp->sd_rindex_spin); @@ -1337,8 +1337,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen) gfs2_trans_add_rg(rgd); gfs2_statfs_change(sdp, 0, +blen, 0); - gfs2_quota_change(ip, -(s64)blen, - ip->i_di.di_uid, ip->i_di.di_gid); + gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid); } /** @@ -1366,7 +1365,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen) gfs2_trans_add_rg(rgd); gfs2_statfs_change(sdp, 0, +blen, 0); - gfs2_quota_change(ip, -(s64)blen, ip->i_di.di_uid, ip->i_di.di_gid); + gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid); gfs2_meta_wipe(ip, bstart, blen); } @@ -1411,7 +1410,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) { gfs2_free_uninit_di(rgd, ip->i_num.no_addr); - gfs2_quota_change(ip, -1, ip->i_di.di_uid, ip->i_di.di_gid); + gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); gfs2_meta_wipe(ip, ip->i_num.no_addr, 1); } diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index f1ea0b4..896c7f8 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -322,8 +322,6 @@ struct gfs2_dinode { }; struct gfs2_dinode_host { - __u32 di_uid; /* owner's user id */ - __u32 di_gid; /* owner's group id */ __u32 di_nlink; /* number of links to this file */ __u64 di_size; /* number of bytes in file */ __u64 di_blocks; /* number of blocks in file */ -- cgit v0.10.2 From 4f56110a00af5fb2e22fbccfcaf944d62cae8fcf Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 14:04:17 -0500 Subject: [GFS2] Shrink gfs2_inode (5) - di_nlink Remove the di_nlink field in favour of inode->i_nlink and update the nlink handling to use the proper macros. This saves 4 bytes. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 0de9b22..7112039 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -51,7 +51,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) struct gfs2_dinode_host *di = &ip->i_di; inode->i_ino = ip->i_num.no_addr; - inode->i_nlink = di->di_nlink; i_size_write(inode, di->di_size); inode->i_atime.tv_sec = di->di_atime; inode->i_mtime.tv_sec = di->di_mtime; @@ -214,7 +213,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ip->i_inode.i_uid = be32_to_cpu(str->di_uid); ip->i_inode.i_gid = be32_to_cpu(str->di_gid); - di->di_nlink = be32_to_cpu(str->di_nlink); + /* + * We will need to review setting the nlink count here in the + * light of the forthcoming ro bind mount work. This is a reminder + * to do that. + */ + ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); di->di_size = be64_to_cpu(str->di_size); di->di_blocks = be64_to_cpu(str->di_blocks); di->di_atime = be64_to_cpu(str->di_atime); @@ -336,12 +340,12 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) u32 nlink; int error; - BUG_ON(ip->i_di.di_nlink != ip->i_inode.i_nlink); - nlink = ip->i_di.di_nlink + diff; + BUG_ON(diff != 1 && diff != -1); + nlink = ip->i_inode.i_nlink + diff; /* If we are reducing the nlink count, but the new value ends up being bigger than the old one, we must have underflowed. */ - if (diff < 0 && nlink > ip->i_di.di_nlink) { + if (diff < 0 && nlink > ip->i_inode.i_nlink) { if (gfs2_consist_inode(ip)) gfs2_dinode_print(ip); return -EIO; @@ -351,16 +355,19 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) if (error) return error; - ip->i_di.di_nlink = nlink; + if (diff > 0) + inc_nlink(&ip->i_inode); + else + drop_nlink(&ip->i_inode); + ip->i_di.di_ctime = get_seconds(); - ip->i_inode.i_nlink = nlink; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); mark_inode_dirty(&ip->i_inode); - if (ip->i_di.di_nlink == 0) { + if (ip->i_inode.i_nlink == 0) { struct gfs2_rgrpd *rgd; struct gfs2_holder ri_gh, rg_gh; @@ -375,7 +382,6 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) if (error) goto out_norgrp; - clear_nlink(&ip->i_inode); gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ gfs2_glock_dq_uninit(&rg_gh); out_norgrp: @@ -586,7 +592,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, return error; /* Don't create entries in an unlinked directory */ - if (!dip->i_di.di_nlink) + if (!dip->i_inode.i_nlink) return -EPERM; error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL); @@ -602,7 +608,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, if (dip->i_di.di_entries == (u32)-1) return -EFBIG; - if (S_ISDIR(mode) && dip->i_di.di_nlink == (u32)-1) + if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1) return -EMLINK; return 0; @@ -808,7 +814,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, error = gfs2_meta_inode_buffer(ip, &dibh); if (error) goto fail_end_trans; - ip->i_di.di_nlink = 1; + ip->i_inode.i_nlink = 1; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1016,7 +1022,12 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, if (error) return error; - error = gfs2_change_nlink(ip, -2); + /* It looks odd, but it really should be done twice */ + error = gfs2_change_nlink(ip, -1); + if (error) + return error; + + error = gfs2_change_nlink(ip, -1); if (error) return error; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index e224f6a..b4e354b 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -164,7 +164,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_mode = cpu_to_be32(ip->i_inode.i_mode); str->di_uid = cpu_to_be32(ip->i_inode.i_uid); str->di_gid = cpu_to_be32(ip->i_inode.i_gid); - str->di_nlink = cpu_to_be32(di->di_nlink); + str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); str->di_size = cpu_to_be64(di->di_size); str->di_blocks = cpu_to_be64(di->di_blocks); str->di_atime = cpu_to_be64(di->di_atime); @@ -191,7 +191,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) gfs2_inum_print(&ip->i_num); - pv(di, di_nlink, "%u"); printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks); printk(KERN_INFO " di_atime = %lld\n", (long long)di->di_atime); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index efbcec3..06176de 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -169,7 +169,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, } error = -EINVAL; - if (!dip->i_di.di_nlink) + if (!dip->i_inode.i_nlink) goto out_gunlock; error = -EFBIG; if (dip->i_di.di_entries == (u32)-1) @@ -178,10 +178,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_gunlock; error = -EINVAL; - if (!ip->i_di.di_nlink) + if (!ip->i_inode.i_nlink) goto out_gunlock; error = -EMLINK; - if (ip->i_di.di_nlink == (u32)-1) + if (ip->i_inode.i_nlink == (u32)-1) goto out_gunlock; alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name); @@ -386,7 +386,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) ip = ghs[1].gh_gl->gl_object; - ip->i_di.di_nlink = 2; + ip->i_inode.i_nlink = 2; ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); ip->i_di.di_flags |= GFS2_DIF_JDATA; ip->i_di.di_payload_format = GFS2_FORMAT_DE; @@ -636,7 +636,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, }; if (odip != ndip) { - if (!ndip->i_di.di_nlink) { + if (!ndip->i_inode.i_nlink) { error = -EINVAL; goto out_gunlock; } @@ -645,7 +645,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_gunlock; } if (S_ISDIR(ip->i_inode.i_mode) && - ndip->i_di.di_nlink == (u32)-1) { + ndip->i_inode.i_nlink == (u32)-1) { error = -EMLINK; goto out_gunlock; } diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 896c7f8..c61517b 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -322,7 +322,6 @@ struct gfs2_dinode { }; struct gfs2_dinode_host { - __u32 di_nlink; /* number of links to this file */ __u64 di_size; /* number of bytes in file */ __u64 di_blocks; /* number of blocks in file */ __u64 di_atime; /* time last accessed */ -- cgit v0.10.2 From 1a7b1eed5802502fd649e04784becd58557fdcf1 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 14:35:17 -0500 Subject: [GFS2] Shrink gfs2_inode (6) - di_atime/di_mtime/di_ctime Remove the di_[amc]time fields and use inode->i_[amc]time fields instead. This saves 24 bytes from the gfs2_inode. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 0c913ee..692d4a3 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -778,7 +778,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, gfs2_free_data(ip, bstart, blen); } - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, dibh->b_data); @@ -853,7 +853,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) } ip->i_di.di_size = size; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); error = gfs2_meta_inode_buffer(ip, &dibh); if (error) @@ -968,7 +968,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) if (gfs2_is_stuffed(ip)) { ip->i_di.di_size = size; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size); @@ -980,7 +980,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) if (!error) { ip->i_di.di_size = size; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1053,7 +1053,7 @@ static int trunc_end(struct gfs2_inode *ip) ip->i_num.no_addr; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); } - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 0742761..ca23c8b 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -131,7 +131,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); if (ip->i_di.di_size < offset + size) ip->i_di.di_size = offset + size; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -229,7 +229,7 @@ out: if (ip->i_di.di_size < offset + copied) ip->i_di.di_size = offset + copied; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1560,7 +1560,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, break; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_entries++; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; @@ -1646,7 +1646,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) gfs2_consist_inode(dip); gfs2_trans_add_bh(dip->i_gl, bh, 1); dip->i_di.di_entries--; - dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1694,7 +1694,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, gfs2_trans_add_bh(dip->i_gl, bh, 1); } - dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 935cc9a..7dde847 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -300,7 +300,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -715,7 +715,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, (er->er_mode & S_IFMT)); ip->i_inode.i_mode = er->er_mode; } - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -850,7 +850,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); ip->i_inode.i_mode = er->er_mode; } - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1130,7 +1130,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1285,7 +1285,6 @@ int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, if (!error) { error = inode_setattr(&ip->i_inode, attr); gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_inode_attr_out(ip); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 7112039..c22ae3c 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -52,12 +52,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) inode->i_ino = ip->i_num.no_addr; i_size_write(inode, di->di_size); - inode->i_atime.tv_sec = di->di_atime; - inode->i_mtime.tv_sec = di->di_mtime; - inode->i_ctime.tv_sec = di->di_ctime; - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_nsec = 0; - inode->i_ctime.tv_nsec = 0; inode->i_blocks = di->di_blocks << (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); @@ -72,23 +66,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) inode->i_flags &= ~S_APPEND; } -/** - * gfs2_inode_attr_out - Copy attributes from VFS inode into the dinode - * @ip: The GFS2 inode - * - * Only copy out the attributes that we want the VFS layer - * to be able to modify. - */ - -void gfs2_inode_attr_out(struct gfs2_inode *ip) -{ - struct inode *inode = &ip->i_inode; - struct gfs2_dinode_host *di = &ip->i_di; - di->di_atime = inode->i_atime.tv_sec; - di->di_mtime = inode->i_mtime.tv_sec; - di->di_ctime = inode->i_ctime.tv_sec; -} - static int iget_test(struct inode *inode, void *opaque) { struct gfs2_inode *ip = GFS2_I(inode); @@ -221,9 +198,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); di->di_size = be64_to_cpu(str->di_size); di->di_blocks = be64_to_cpu(str->di_blocks); - di->di_atime = be64_to_cpu(str->di_atime); - di->di_mtime = be64_to_cpu(str->di_mtime); - di->di_ctime = be64_to_cpu(str->di_ctime); + ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); + ip->i_inode.i_atime.tv_nsec = 0; + ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); + ip->i_inode.i_mtime.tv_nsec = 0; + ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); + ip->i_inode.i_ctime.tv_nsec = 0; di->di_goal_meta = be64_to_cpu(str->di_goal_meta); di->di_goal_data = be64_to_cpu(str->di_goal_data); @@ -360,7 +340,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) else drop_nlink(&ip->i_inode); - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1224,7 +1204,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) return 0; curtime = get_seconds(); - if (curtime - ip->i_di.di_atime >= quantum) { + if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) { gfs2_glock_dq(gh); gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, gh); @@ -1236,7 +1216,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) trying to get exclusive lock. */ curtime = get_seconds(); - if (curtime - ip->i_di.di_atime >= quantum) { + if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) { struct buffer_head *dibh; struct gfs2_dinode *di; @@ -1250,11 +1230,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) if (error) goto fail_end_trans; - ip->i_di.di_atime = curtime; + ip->i_inode.i_atime.tv_sec = curtime; gfs2_trans_add_bh(ip->i_gl, dibh, 1); di = (struct gfs2_dinode *)dibh->b_data; - di->di_atime = cpu_to_be64(ip->i_di.di_atime); + di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); brelse(dibh); gfs2_trans_end(sdp); @@ -1375,8 +1355,6 @@ __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) if (!error) { error = inode_setattr(&ip->i_inode, attr); gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_inode_attr_out(ip); - gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 69cbf98..54d584e 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -26,7 +26,6 @@ static inline int gfs2_is_dir(struct gfs2_inode *ip) } void gfs2_inode_attr_in(struct gfs2_inode *ip); -void gfs2_inode_attr_out(struct gfs2_inode *ip); struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type); struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum); diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index b4e354b..82003e8 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -167,9 +167,9 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); str->di_size = cpu_to_be64(di->di_size); str->di_blocks = cpu_to_be64(di->di_blocks); - str->di_atime = cpu_to_be64(di->di_atime); - str->di_mtime = cpu_to_be64(di->di_mtime); - str->di_ctime = cpu_to_be64(di->di_ctime); + str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); + str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); + str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); str->di_goal_meta = cpu_to_be64(di->di_goal_meta); str->di_goal_data = cpu_to_be64(di->di_goal_data); @@ -193,10 +193,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks); - printk(KERN_INFO " di_atime = %lld\n", (long long)di->di_atime); - printk(KERN_INFO " di_mtime = %lld\n", (long long)di->di_mtime); - printk(KERN_INFO " di_ctime = %lld\n", (long long)di->di_ctime); - printk(KERN_INFO " di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta); printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 38b702a..5c3962c 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -498,10 +498,6 @@ static int gfs2_commit_write(struct file *file, struct page *page, di->di_size = cpu_to_be64(inode->i_size); } - di->di_atime = cpu_to_be64(inode->i_atime.tv_sec); - di->di_mtime = cpu_to_be64(inode->i_mtime.tv_sec); - di->di_ctime = cpu_to_be64(inode->i_ctime.tv_sec); - brelse(dibh); gfs2_trans_end(sdp); if (al->al_requested) { diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 06176de..585b43a 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -729,7 +729,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, error = gfs2_meta_inode_buffer(ip, &dibh); if (error) goto out_end_trans; - ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -915,7 +915,6 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) error = inode_setattr(inode, attr); gfs2_assert_warn(sdp, !error); - gfs2_inode_attr_out(ip); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index c61517b..7f5a4a1 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -324,9 +324,6 @@ struct gfs2_dinode { struct gfs2_dinode_host { __u64 di_size; /* number of bytes in file */ __u64 di_blocks; /* number of blocks in file */ - __u64 di_atime; /* time last accessed */ - __u64 di_mtime; /* time last modified */ - __u64 di_ctime; /* time last changed */ /* This section varies from gfs1. Padding added to align with * remainder of dinode -- cgit v0.10.2 From a9583c7983cbba9726bfe64ee46613d654fc9e26 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 20:09:14 -0500 Subject: [GFS2] Shrink gfs2_inode (7) - di_payload_format This is almost never used. Its there for backward compatibility with GFS1. It doesn't need its own field since it can always be calculated from the inode mode & flags. This saves a bit more space in the gfs2_inode. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index ca23c8b..c82d7cb 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -902,7 +902,6 @@ static int dir_make_exhash(struct inode *inode) dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; dip->i_di.di_blocks++; dip->i_di.di_flags |= GFS2_DIF_EXHASH; - dip->i_di.di_payload_format = 0; for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; dip->i_di.di_depth = y; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index c22ae3c..f6177fc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -210,7 +210,6 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_generation = be64_to_cpu(str->di_generation); di->di_flags = be32_to_cpu(str->di_flags); - di->di_payload_format = be32_to_cpu(str->di_payload_format); di->di_height = be16_to_cpu(str->di_height); di->di_depth = be16_to_cpu(str->di_depth); @@ -699,7 +698,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, } di->__pad1 = 0; - di->di_payload_format = cpu_to_be32(0); + di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); di->di_height = cpu_to_be32(0); di->__pad2 = 0; di->__pad3 = 0; diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index 82003e8..b2baba5 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -176,9 +176,10 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) str->di_generation = cpu_to_be64(di->di_generation); str->di_flags = cpu_to_be32(di->di_flags); - str->di_payload_format = cpu_to_be32(di->di_payload_format); str->di_height = cpu_to_be16(di->di_height); - + str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && + !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? + GFS2_FORMAT_DE : 0); str->di_depth = cpu_to_be16(di->di_depth); str->di_entries = cpu_to_be32(di->di_entries); @@ -197,7 +198,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data); pv(di, di_flags, "0x%.8X"); - pv(di, di_payload_format, "%u"); pv(di, di_height, "%u"); pv(di, di_depth, "%u"); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 585b43a..0e4eade 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -389,7 +389,6 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) ip->i_inode.i_nlink = 2; ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); ip->i_di.di_flags |= GFS2_DIF_JDATA; - ip->i_di.di_payload_format = GFS2_FORMAT_DE; ip->i_di.di_entries = 2; error = gfs2_meta_inode_buffer(ip, &dibh); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 7f5a4a1..536575e 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -333,7 +333,6 @@ struct gfs2_dinode_host { __u64 di_generation; /* generation number for NFS */ __u32 di_flags; /* GFS2_DIF_... */ - __u32 di_payload_format; /* GFS2_FORMAT_... */ __u16 di_height; /* height of metadata */ /* These only apply to directories */ -- cgit v0.10.2 From bfded27ba010d1c3b0aa3843f97dc9b80de751be Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 16:05:38 -0500 Subject: [GFS2] Shrink gfs2_inode (8) - i_vn This shrinks the size of the gfs2_inode by 8 bytes by replacing the version counter with a one bit valid/invalid flag. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index aad45b7..9c20337 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -305,8 +305,9 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) int data = (flags & DIO_DATA); if (meta) { + struct gfs2_inode *ip = gl->gl_object; gfs2_meta_inval(gl); - gl->gl_vn++; + set_bit(GIF_INVALID, &ip->i_flags); } if (data) gfs2_page_inval(gl); @@ -351,7 +352,7 @@ static int inode_go_lock(struct gfs2_holder *gh) if (!ip) return 0; - if (ip->i_vn != gl->gl_vn) { + if (test_bit(GIF_INVALID, &ip->i_flags)) { error = gfs2_inode_refresh(ip); if (error) return error; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index c0a8c3b..227a74d 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -217,6 +217,7 @@ struct gfs2_alloc { }; enum { + GIF_INVALID = 0, GIF_QD_LOCKED = 1, GIF_PAGED = 2, GIF_SW_PAGED = 3, @@ -228,7 +229,6 @@ struct gfs2_inode { unsigned long i_flags; /* GIF_... */ - u64 i_vn; struct gfs2_dinode_host i_di; /* To be replaced by ref to block */ struct gfs2_glock *i_gl; /* Move into i_gh? */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index f6177fc..e467780 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -145,7 +145,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i if (unlikely(error)) goto fail_put; - ip->i_vn = ip->i_gl->gl_vn - 1; + set_bit(GIF_INVALID, &ip->i_flags); error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); if (unlikely(error)) goto fail_iopen; @@ -242,7 +242,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) error = gfs2_dinode_in(ip, dibh->b_data); brelse(dibh); - ip->i_vn = ip->i_gl->gl_vn; + clear_bit(GIF_INVALID, &ip->i_flags); return error; } diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 0e4eade..b247f25 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -844,7 +844,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) struct gfs2_holder i_gh; int error; - if (ip->i_vn == ip->i_gl->gl_vn) + if (!test_bit(GIF_INVALID, &ip->i_flags)) return generic_permission(inode, mask, gfs2_check_acl); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); -- cgit v0.10.2 From 294caaa3b8304c0a14c5039691caf23363bd9369 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 2 Nov 2006 11:59:28 -0500 Subject: [GFS2] Tidy up 0 initialisations in inode.c We don't need to use endian conversions for 0 initialisations when creating a new on-disk inode. Cc: Christoph Hellwig Cc: Alexey Dobriyan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index e467780..faf9b9e 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -673,15 +673,15 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, di->di_mode = cpu_to_be32(mode); di->di_uid = cpu_to_be32(uid); di->di_gid = cpu_to_be32(gid); - di->di_nlink = cpu_to_be32(0); - di->di_size = cpu_to_be64(0); + di->di_nlink = 0; + di->di_size = 0; di->di_blocks = cpu_to_be64(1); di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds()); di->di_major = cpu_to_be32(MAJOR(dev)); di->di_minor = cpu_to_be32(MINOR(dev)); di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); di->di_generation = cpu_to_be64(*generation); - di->di_flags = cpu_to_be32(0); + di->di_flags = 0; if (S_ISREG(mode)) { if ((dip->i_di.di_flags & GFS2_DIF_INHERIT_JDATA) || @@ -699,13 +699,13 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, di->__pad1 = 0; di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); - di->di_height = cpu_to_be32(0); + di->di_height = 0; di->__pad2 = 0; di->__pad3 = 0; - di->di_depth = cpu_to_be16(0); - di->di_entries = cpu_to_be32(0); + di->di_depth = 0; + di->di_entries = 0; memset(&di->__pad4, 0, sizeof(di->__pad4)); - di->di_eattr = cpu_to_be64(0); + di->di_eattr = 0; memset(&di->di_reserved, 0, sizeof(di->di_reserved)); brelse(dibh); -- cgit v0.10.2 From f6e58f01e8dc869803b9f73b2aa9d5bc3f32ca05 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 7 Nov 2006 15:14:58 -0500 Subject: [GFS2] Don't copy meta_header for rgrp in and out The meta_header for an ondisk rgrp never changes, so there is no point copying it in and back out to disk. Also there is no reason to keep a copy for each rgrp in memory. The code already checks to ensure that the header is correct before it calls the routine to copy the data in, so that we don't even need to check whether its correct on disk in the functions in ondisk.c Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index b2baba5..f2495f1 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c @@ -65,15 +65,6 @@ static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *bu mh->mh_format = be32_to_cpu(str->mh_format); } -static void gfs2_meta_header_out(const struct gfs2_meta_header_host *mh, void *buf) -{ - struct gfs2_meta_header *str = buf; - - str->mh_magic = cpu_to_be32(mh->mh_magic); - str->mh_type = cpu_to_be32(mh->mh_type); - str->mh_format = cpu_to_be32(mh->mh_format); -} - void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) { const struct gfs2_sb *str = buf; @@ -119,7 +110,6 @@ void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) { const struct gfs2_rgrp *str = buf; - gfs2_meta_header_in(&rg->rg_header, buf); rg->rg_flags = be32_to_cpu(str->rg_flags); rg->rg_free = be32_to_cpu(str->rg_free); rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); @@ -130,7 +120,6 @@ void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) { struct gfs2_rgrp *str = buf; - gfs2_meta_header_out(&rg->rg_header, buf); str->rg_flags = cpu_to_be32(rg->rg_flags); str->rg_free = cpu_to_be32(rg->rg_free); str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 536575e..8b7e4c1 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -213,8 +213,6 @@ struct gfs2_rgrp { }; struct gfs2_rgrp_host { - struct gfs2_meta_header_host rg_header; - __u32 rg_flags; __u32 rg_free; __u32 rg_dinodes; -- cgit v0.10.2 From c594d8866460a2710c436839d79f334a0714a2a7 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 09:01:13 -0500 Subject: [GFS2] Remove unused GL_DUMP flag There is no way to set the GL_DUMP flag, and in any case the same thing can be done with systemtap if required for debugging, so this removes it. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 44633c4..746347a 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1244,9 +1244,6 @@ restart: clear_bit(GLF_PREFETCH, &gl->gl_flags); - if (error == GLR_TRYFAILED && (gh->gh_flags & GL_DUMP)) - dump_glock(gl); - return error; } diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 2b2a889..b985627 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -28,7 +28,6 @@ #define GL_NOCACHE 0x00000400 #define GL_NOCANCEL 0x00001000 #define GL_AOP 0x00004000 -#define GL_DUMP 0x00008000 #define GLR_TRYFAILED 13 #define GLR_CANCELED 14 -- cgit v0.10.2 From 2ca99501fa5422e84f18333918a503433449e2b5 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 10:26:54 -0500 Subject: [GFS2] Fix page lock/glock deadlock This fixes a race between the glock and the page lock encountered during truncate in gfs2_readpage and gfs2_prepare_write. The gfs2_readpages function doesn't need the same fix since it only uses a try lock anyway, so it will fail back to gfs2_readpage in the case of a potential deadlock. This bug was spotted by Russell Cattelan. Cc: Russell Cattelan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index b985627..a331bf8 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -27,7 +27,6 @@ #define GL_ATIME 0x00000200 #define GL_NOCACHE 0x00000400 #define GL_NOCANCEL 0x00001000 -#define GL_AOP 0x00004000 #define GLR_TRYFAILED 13 #define GLR_CANCELED 14 diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 5c3962c..3822189 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -230,7 +230,7 @@ static int gfs2_readpage(struct file *file, struct page *page) /* gfs2_sharewrite_nopage has grabbed the ip->i_gl already */ goto skip_lock; } - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); do_unlock = 1; error = gfs2_glock_nq_m_atime(1, &gh); if (unlikely(error)) @@ -254,6 +254,8 @@ skip_lock: out: return error; out_unlock: + if (error == GLR_TRYFAILED) + error = AOP_TRUNCATED_PAGE; unlock_page(page); if (do_unlock) gfs2_holder_uninit(&gh); @@ -293,7 +295,7 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, goto skip_lock; } gfs2_holder_init(ip->i_gl, LM_ST_SHARED, - LM_FLAG_TRY_1CB|GL_ATIME|GL_AOP, &gh); + LM_FLAG_TRY_1CB|GL_ATIME, &gh); do_unlock = 1; ret = gfs2_glock_nq_m_atime(1, &gh); if (ret == GLR_TRYFAILED) @@ -366,10 +368,13 @@ static int gfs2_prepare_write(struct file *file, struct page *page, unsigned int write_len = to - from; - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|GL_AOP, &ip->i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh); error = gfs2_glock_nq_m_atime(1, &ip->i_gh); - if (error) + if (unlikely(error)) { + if (error == GLR_TRYFAILED) + error = AOP_TRUNCATED_PAGE; goto out_uninit; + } gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks); -- cgit v0.10.2 From 6b124d8dba1f46c5f2caf3b3159bbe627f75b9b6 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 12:51:06 -0500 Subject: [GFS2] Only set inode flags when required We were setting the inode flags from GFS2's flags far too often, even when they couldn't possibly have changed. This patch reduces the amount of flag setting going on so that we do it only when the inode is read in or when the flags have changed. The create case is covered by the "when the inode is read in" case. This also fixes a bug where we didn't set S_SYNC correctly. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index faf9b9e..56b39be 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -54,16 +54,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) i_size_write(inode, di->di_size); inode->i_blocks = di->di_blocks << (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); - - if (di->di_flags & GFS2_DIF_IMMUTABLE) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - - if (di->di_flags & GFS2_DIF_APPENDONLY) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; } static int iget_test(struct inode *inode, void *opaque) @@ -210,6 +200,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_generation = be64_to_cpu(str->di_generation); di->di_flags = be32_to_cpu(str->di_flags); + gfs2_set_inode_flags(&ip->i_inode); di->di_height = be16_to_cpu(str->di_height); di->di_depth = be16_to_cpu(str->di_depth); diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index b52b9db..eabf6c6 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -266,6 +266,24 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) return error; } +void gfs2_set_inode_flags(struct inode *inode) +{ + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_dinode_host *di = &ip->i_di; + unsigned int flags = inode->i_flags; + + flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + if (di->di_flags & GFS2_DIF_IMMUTABLE) + flags |= S_IMMUTABLE; + if (di->di_flags & GFS2_DIF_APPENDONLY) + flags |= S_APPEND; + if (di->di_flags & GFS2_DIF_NOATIME) + flags |= S_NOATIME; + if (di->di_flags & GFS2_DIF_SYNC) + flags |= S_SYNC; + inode->i_flags = flags; +} + /* Flags that can be set by user space */ #define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \ GFS2_DIF_DIRECTIO| \ @@ -338,6 +356,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) ip->i_di.di_flags = new_flags; gfs2_dinode_out(ip, bh->b_data); brelse(bh); + gfs2_set_inode_flags(inode); out_trans_end: gfs2_trans_end(sdp); out: diff --git a/fs/gfs2/ops_file.h b/fs/gfs2/ops_file.h index ce319f8..7e5d8ec 100644 --- a/fs/gfs2/ops_file.h +++ b/fs/gfs2/ops_file.h @@ -17,7 +17,7 @@ extern struct file gfs2_internal_file_sentinel; extern int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, char *buf, loff_t *pos, unsigned size); - +extern void gfs2_set_inode_flags(struct inode *inode); extern const struct file_operations gfs2_file_fops; extern const struct file_operations gfs2_dir_fops; -- cgit v0.10.2 From e7c698d74fc9e0e76b3086062b0519df3601ff52 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 13:52:05 -0500 Subject: [GFS2] Inode number is constant Since the inode number is constant, we don't need to keep updating it everytime we refresh the other inode fields. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 56b39be..19b2736 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -50,7 +50,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip) struct inode *inode = &ip->i_inode; struct gfs2_dinode_host *di = &ip->i_di; - inode->i_ino = ip->i_num.no_addr; i_size_write(inode, di->di_size); inode->i_blocks = di->di_blocks << (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); @@ -73,6 +72,7 @@ static int iget_set(struct inode *inode, void *opaque) struct gfs2_inum_host *inum = opaque; ip->i_num = *inum; + inode->i_ino = inum->no_addr; return 0; } -- cgit v0.10.2 From 9e2dbdac3df300516ffdd9a8631f23164d068a50 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 15:45:46 -0500 Subject: [GFS2] Remove gfs2_inode_attr_in This function wasn't really doing the right thing. There was no need to update the inode size at this point and the updating of the i_blocks field has now been moved to the places where di_blocks is updated. A result of this patch and some those preceeding it is that unlocking a glock is now a much more efficient process, since there is no longer any requirement to copy data from the gfs2 inode into the vfs inode at this point. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 692d4a3..06e3447 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -163,6 +163,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) if (ip->i_di.di_size) { *(__be64 *)(di + 1) = cpu_to_be64(block); ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); } @@ -272,6 +273,7 @@ static int build_height(struct inode *inode, unsigned height) *(__be64 *)(di + 1) = cpu_to_be64(bn); ip->i_di.di_height += new_height; ip->i_di.di_blocks += new_height; + gfs2_set_inode_blocks(&ip->i_inode); di->di_height = cpu_to_be16(ip->i_di.di_height); di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); brelse(dibh); @@ -415,6 +417,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, *ptr = cpu_to_be64(*block); ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); *new = 1; return 0; @@ -770,6 +773,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, if (!ip->i_di.di_blocks) gfs2_consist_inode(ip); ip->i_di.di_blocks--; + gfs2_set_inode_blocks(&ip->i_inode); } if (bstart) { if (metadata) diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c82d7cb..a2923fb 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -901,6 +901,7 @@ static int dir_make_exhash(struct inode *inode) dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; dip->i_di.di_blocks++; + gfs2_set_inode_blocks(&dip->i_inode); dip->i_di.di_flags |= GFS2_DIF_EXHASH; for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; @@ -1038,6 +1039,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { dip->i_di.di_blocks++; + gfs2_set_inode_blocks(&dip->i_inode); gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1516,6 +1518,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) return error; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); gfs2_dinode_out(ip, bh->b_data); brelse(bh); return 0; @@ -1860,6 +1863,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, if (!dip->i_di.di_blocks) gfs2_consist_inode(dip); dip->i_di.di_blocks--; + gfs2_set_inode_blocks(&dip->i_inode); } error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size); diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 7dde847..ebebbdc 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -281,6 +281,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, if (!ip->i_di.di_blocks) gfs2_consist_inode(ip); ip->i_di.di_blocks--; + gfs2_set_inode_blocks(&ip->i_inode); } if (bstart) gfs2_free_meta(ip, bstart, blen); @@ -598,6 +599,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) ea->ea_num_ptrs = 0; ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); return 0; } @@ -649,6 +651,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED); ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize : data_len; @@ -977,6 +980,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, ip->i_di.di_eattr = blk; ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT; ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); eablk++; } @@ -1387,6 +1391,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) if (!ip->i_di.di_blocks) gfs2_consist_inode(ip); ip->i_di.di_blocks--; + gfs2_set_inode_blocks(&ip->i_inode); } if (bstart) gfs2_free_meta(ip, bstart, blen); @@ -1441,6 +1446,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip) if (!ip->i_di.di_blocks) gfs2_consist_inode(ip); ip->i_di.di_blocks--; + gfs2_set_inode_blocks(&ip->i_inode); error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 9c20337..b92de0a 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -356,7 +356,6 @@ static int inode_go_lock(struct gfs2_holder *gh) error = gfs2_inode_refresh(ip); if (error) return error; - gfs2_inode_attr_in(ip); } if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) && @@ -380,11 +379,8 @@ static void inode_go_unlock(struct gfs2_holder *gh) struct gfs2_glock *gl = gh->gh_gl; struct gfs2_inode *ip = gl->gl_object; - if (ip == NULL) - return; - if (test_bit(GLF_DIRTY, &gl->gl_flags)) - gfs2_inode_attr_in(ip); - gfs2_meta_cache_flush(ip); + if (ip) + gfs2_meta_cache_flush(ip); } /** diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 19b2736..ea9ca23 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -38,29 +38,12 @@ #include "trans.h" #include "util.h" -/** - * gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode - * @ip: The GFS2 inode (with embedded disk inode data) - * @inode: The Linux VFS inode - * - */ - -void gfs2_inode_attr_in(struct gfs2_inode *ip) -{ - struct inode *inode = &ip->i_inode; - struct gfs2_dinode_host *di = &ip->i_di; - - i_size_write(inode, di->di_size); - inode->i_blocks = di->di_blocks << - (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); -} - static int iget_test(struct inode *inode, void *opaque) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inum_host *inum = opaque; - if (ip && ip->i_num.no_addr == inum->no_addr) + if (ip->i_num.no_addr == inum->no_addr) return 1; return 0; @@ -187,7 +170,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) */ ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); di->di_size = be64_to_cpu(str->di_size); + i_size_write(&ip->i_inode, di->di_size); di->di_blocks = be64_to_cpu(str->di_blocks); + gfs2_set_inode_blocks(&ip->i_inode); ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); ip->i_inode.i_atime.tv_nsec = 0; ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 54d584e..46917ed 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -25,6 +25,13 @@ static inline int gfs2_is_dir(struct gfs2_inode *ip) return S_ISDIR(ip->i_inode.i_mode); } +static inline void gfs2_set_inode_blocks(struct inode *inode) +{ + struct gfs2_inode *ip = GFS2_I(inode); + inode->i_blocks = ip->i_di.di_blocks << + (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); +} + void gfs2_inode_attr_in(struct gfs2_inode *ip); struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type); struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum); -- cgit v0.10.2 From 7020933156ac2a8a7386314933e49948bf0438f7 Mon Sep 17 00:00:00 2001 From: Russell Cattelan Date: Thu, 9 Nov 2006 11:28:08 -0500 Subject: [GFS2] Fix race in logging code The log lock is dropped prior to io submittion, but this exposes a hole in which the log data structures may be going away due to a truncate. Store the buffer head in a local pointer prior to dropping the lock and relay on the buffer_head lock for consitency on the buffer head. Signed-Off-By: Russell Cattelan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 8a654cd..4d7f94d 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -509,7 +509,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) { LIST_HEAD(started); struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; - struct buffer_head *bh = NULL; + struct buffer_head *bh = NULL,*bh1 = NULL; unsigned int offset = sizeof(struct gfs2_log_descriptor); struct gfs2_log_descriptor *ld; unsigned int limit; @@ -537,8 +537,13 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) list_for_each_entry_safe_continue(bd1, bdt, &sdp->sd_log_le_databuf, bd_le.le_list) { + /* store off the buffer head in a local ptr since + * gfs2_bufdata might change when we drop the log lock + */ + bh1 = bd1->bd_bh; + /* An ordered write buffer */ - if (bd1->bd_bh && !buffer_pinned(bd1->bd_bh)) { + if (bh1 && !buffer_pinned(bh1)) { list_move(&bd1->bd_le.le_list, &started); if (bd1 == bd2) { bd2 = NULL; @@ -547,20 +552,21 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) bd_le.le_list); } total_dbuf--; - if (bd1->bd_bh) { - get_bh(bd1->bd_bh); - if (buffer_dirty(bd1->bd_bh)) { + if (bh1) { + if (buffer_dirty(bh1)) { + get_bh(bh1); + gfs2_log_unlock(sdp); - wait_on_buffer(bd1->bd_bh); - ll_rw_block(WRITE, 1, - &bd1->bd_bh); + + ll_rw_block(SWRITE, 1, &bh1); + brelse(bh1); + gfs2_log_lock(sdp); } - brelse(bd1->bd_bh); continue; } continue; - } else if (bd1->bd_bh) { /* A journaled buffer */ + } else if (bh1) { /* A journaled buffer */ int magic; gfs2_log_unlock(sdp); if (!bh) { @@ -582,16 +588,16 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) ld->ld_data2 = cpu_to_be32(0); memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); } - magic = gfs2_check_magic(bd1->bd_bh); - *ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr); + magic = gfs2_check_magic(bh1); + *ptr++ = cpu_to_be64(bh1->b_blocknr); *ptr++ = cpu_to_be64((__u64)magic); - clear_buffer_escaped(bd1->bd_bh); + clear_buffer_escaped(bh1); if (unlikely(magic != 0)) - set_buffer_escaped(bd1->bd_bh); + set_buffer_escaped(bh1); gfs2_log_lock(sdp); if (n++ > num) break; - } else if (!bd1->bd_bh) { + } else if (!bh1) { total_dbuf--; sdp->sd_log_num_databuf--; list_del_init(&bd1->bd_le.le_list); -- cgit v0.10.2 From 61057c6bb3a3d14cf2bea6ca20dc6d367e1d852e Mon Sep 17 00:00:00 2001 From: Russell Cattelan Date: Thu, 9 Nov 2006 11:42:33 -0500 Subject: [GFS2] Remove unused zero_readpage from stuffed_readpage Stuffed files only consist of a maximum of (gfs2 block size - sizeof(struct gfs2_dinode)) bytes. Since the gfs2 block size is always less than page size, we will never see a call to stuffed_readpage for anything other than the first page in the file. Signed-off-by: Russell Cattelan Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 3822189..2f7ef98 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -156,19 +156,6 @@ out_ignore: return 0; } -static int zero_readpage(struct page *page) -{ - void *kaddr; - - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr, 0, PAGE_CACHE_SIZE); - kunmap_atomic(kaddr, KM_USER0); - - SetPageUptodate(page); - - return 0; -} - /** * stuffed_readpage - Fill in a Linux page with stuffed file data * @ip: the inode @@ -183,9 +170,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) void *kaddr; int error; - /* Only the first page of a stuffed file might contain data */ - if (unlikely(page->index)) - return zero_readpage(page); + BUG_ON(page->index); error = gfs2_meta_inode_buffer(ip, &dibh); if (error) @@ -737,6 +722,9 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) if (!atomic_read(&aspace->i_writecount)) return 0; + if (!(gfp_mask & __GFP_WAIT)) + return 0; + if (time_after_eq(jiffies, t)) { stuck_releasepage(bh); /* should we withdraw here? */ -- cgit v0.10.2 From fdda387f73947e6ae511ec601f5b3c6fbb582aac Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Thu, 2 Nov 2006 11:19:21 -0500 Subject: [DLM] Add support for tcp communications The following patch adds a TCP based communications layer to the DLM which is compile time selectable. The existing SCTP layer gives the advantage of allowing multihoming, whereas the TCP layer has been heavily tested in previous versions of the DLM and is known to be robust and therefore can be used as a baseline for performance testing. Signed-off-by: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig index 81b2c64..c5985b8 100644 --- a/fs/dlm/Kconfig +++ b/fs/dlm/Kconfig @@ -9,6 +9,23 @@ config DLM A general purpose distributed lock manager for kernel or userspace applications. +choice + prompt "Select DLM communications protocol" + depends on DLM + default DLM_TCP + help + The DLM Can use TCP or SCTP for it's network communications. + SCTP supports multi-homed operations whereas TCP doesn't. + However, SCTP seems to have stability problems at the moment. + +config DLM_TCP + bool "TCP/IP" + +config DLM_SCTP + bool "SCTP" + +endchoice + config DLM_DEBUG bool "DLM debugging" depends on DLM diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile index 1832e02..6538894 100644 --- a/fs/dlm/Makefile +++ b/fs/dlm/Makefile @@ -4,7 +4,6 @@ dlm-y := ast.o \ dir.o \ lock.o \ lockspace.o \ - lowcomms.o \ main.o \ member.o \ memory.o \ @@ -17,3 +16,6 @@ dlm-y := ast.o \ util.o dlm-$(CONFIG_DLM_DEBUG) += debug_fs.o +dlm-$(CONFIG_DLM_TCP) += lowcomms-tcp.o + +dlm-$(CONFIG_DLM_SCTP) += lowcomms-sctp.o \ No newline at end of file diff --git a/fs/dlm/lowcomms-sctp.c b/fs/dlm/lowcomms-sctp.c new file mode 100644 index 0000000..6da6b14 --- /dev/null +++ b/fs/dlm/lowcomms-sctp.c @@ -0,0 +1,1239 @@ +/****************************************************************************** +******************************************************************************* +** +** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. +** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. +** +** This copyrighted material is made available to anyone wishing to use, +** modify, copy, or redistribute it subject to the terms and conditions +** of the GNU General Public License v.2. +** +******************************************************************************* +******************************************************************************/ + +/* + * lowcomms.c + * + * This is the "low-level" comms layer. + * + * It is responsible for sending/receiving messages + * from other nodes in the cluster. + * + * Cluster nodes are referred to by their nodeids. nodeids are + * simply 32 bit numbers to the locking module - if they need to + * be expanded for the cluster infrastructure then that is it's + * responsibility. It is this layer's + * responsibility to resolve these into IP address or + * whatever it needs for inter-node communication. + * + * The comms level is two kernel threads that deal mainly with + * the receiving of messages from other nodes and passing them + * up to the mid-level comms layer (which understands the + * message format) for execution by the locking core, and + * a send thread which does all the setting up of connections + * to remote nodes and the sending of data. Threads are not allowed + * to send their own data because it may cause them to wait in times + * of high load. Also, this way, the sending thread can collect together + * messages bound for one node and send them in one block. + * + * I don't see any problem with the recv thread executing the locking + * code on behalf of remote processes as the locking code is + * short, efficient and never (well, hardly ever) waits. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dlm_internal.h" +#include "lowcomms.h" +#include "config.h" +#include "midcomms.h" + +static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; +static int dlm_local_count; +static int dlm_local_nodeid; + +/* One of these per connected node */ + +#define NI_INIT_PENDING 1 +#define NI_WRITE_PENDING 2 + +struct nodeinfo { + spinlock_t lock; + sctp_assoc_t assoc_id; + unsigned long flags; + struct list_head write_list; /* nodes with pending writes */ + struct list_head writequeue; /* outgoing writequeue_entries */ + spinlock_t writequeue_lock; + int nodeid; +}; + +static DEFINE_IDR(nodeinfo_idr); +static struct rw_semaphore nodeinfo_lock; +static int max_nodeid; + +struct cbuf { + unsigned base; + unsigned len; + unsigned mask; +}; + +/* Just the one of these, now. But this struct keeps + the connection-specific variables together */ + +#define CF_READ_PENDING 1 + +struct connection { + struct socket *sock; + unsigned long flags; + struct page *rx_page; + atomic_t waiting_requests; + struct cbuf cb; + int eagain_flag; +}; + +/* An entry waiting to be sent */ + +struct writequeue_entry { + struct list_head list; + struct page *page; + int offset; + int len; + int end; + int users; + struct nodeinfo *ni; +}; + +#define CBUF_ADD(cb, n) do { (cb)->len += n; } while(0) +#define CBUF_EMPTY(cb) ((cb)->len == 0) +#define CBUF_MAY_ADD(cb, n) (((cb)->len + (n)) < ((cb)->mask + 1)) +#define CBUF_DATA(cb) (((cb)->base + (cb)->len) & (cb)->mask) + +#define CBUF_INIT(cb, size) \ +do { \ + (cb)->base = (cb)->len = 0; \ + (cb)->mask = ((size)-1); \ +} while(0) + +#define CBUF_EAT(cb, n) \ +do { \ + (cb)->len -= (n); \ + (cb)->base += (n); \ + (cb)->base &= (cb)->mask; \ +} while(0) + + +/* List of nodes which have writes pending */ +static struct list_head write_nodes; +static spinlock_t write_nodes_lock; + +/* Maximum number of incoming messages to process before + * doing a schedule() + */ +#define MAX_RX_MSG_COUNT 25 + +/* Manage daemons */ +static struct task_struct *recv_task; +static struct task_struct *send_task; +static wait_queue_head_t lowcomms_recv_wait; +static atomic_t accepting; + +/* The SCTP connection */ +static struct connection sctp_con; + + +static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) +{ + struct sockaddr_storage addr; + int error; + + if (!dlm_local_count) + return -1; + + error = dlm_nodeid_to_addr(nodeid, &addr); + if (error) + return error; + + if (dlm_local_addr[0]->ss_family == AF_INET) { + struct sockaddr_in *in4 = (struct sockaddr_in *) &addr; + struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr; + ret4->sin_addr.s_addr = in4->sin_addr.s_addr; + } else { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr; + struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr; + memcpy(&ret6->sin6_addr, &in6->sin6_addr, + sizeof(in6->sin6_addr)); + } + + return 0; +} + +static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc) +{ + struct nodeinfo *ni; + int r; + int n; + + down_read(&nodeinfo_lock); + ni = idr_find(&nodeinfo_idr, nodeid); + up_read(&nodeinfo_lock); + + if (!ni && alloc) { + down_write(&nodeinfo_lock); + + ni = idr_find(&nodeinfo_idr, nodeid); + if (ni) + goto out_up; + + r = idr_pre_get(&nodeinfo_idr, alloc); + if (!r) + goto out_up; + + ni = kmalloc(sizeof(struct nodeinfo), alloc); + if (!ni) + goto out_up; + + r = idr_get_new_above(&nodeinfo_idr, ni, nodeid, &n); + if (r) { + kfree(ni); + ni = NULL; + goto out_up; + } + if (n != nodeid) { + idr_remove(&nodeinfo_idr, n); + kfree(ni); + ni = NULL; + goto out_up; + } + memset(ni, 0, sizeof(struct nodeinfo)); + spin_lock_init(&ni->lock); + INIT_LIST_HEAD(&ni->writequeue); + spin_lock_init(&ni->writequeue_lock); + ni->nodeid = nodeid; + + if (nodeid > max_nodeid) + max_nodeid = nodeid; + out_up: + up_write(&nodeinfo_lock); + } + + return ni; +} + +/* Don't call this too often... */ +static struct nodeinfo *assoc2nodeinfo(sctp_assoc_t assoc) +{ + int i; + struct nodeinfo *ni; + + for (i=1; i<=max_nodeid; i++) { + ni = nodeid2nodeinfo(i, 0); + if (ni && ni->assoc_id == assoc) + return ni; + } + return NULL; +} + +/* Data or notification available on socket */ +static void lowcomms_data_ready(struct sock *sk, int count_unused) +{ + atomic_inc(&sctp_con.waiting_requests); + if (test_and_set_bit(CF_READ_PENDING, &sctp_con.flags)) + return; + + wake_up_interruptible(&lowcomms_recv_wait); +} + + +/* Add the port number to an IP6 or 4 sockaddr and return the address length. + Also padd out the struct with zeros to make comparisons meaningful */ + +static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, + int *addr_len) +{ + struct sockaddr_in *local4_addr; + struct sockaddr_in6 *local6_addr; + + if (!dlm_local_count) + return; + + if (!port) { + if (dlm_local_addr[0]->ss_family == AF_INET) { + local4_addr = (struct sockaddr_in *)dlm_local_addr[0]; + port = be16_to_cpu(local4_addr->sin_port); + } else { + local6_addr = (struct sockaddr_in6 *)dlm_local_addr[0]; + port = be16_to_cpu(local6_addr->sin6_port); + } + } + + saddr->ss_family = dlm_local_addr[0]->ss_family; + if (dlm_local_addr[0]->ss_family == AF_INET) { + struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr; + in4_addr->sin_port = cpu_to_be16(port); + memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero)); + memset(in4_addr+1, 0, sizeof(struct sockaddr_storage) - + sizeof(struct sockaddr_in)); + *addr_len = sizeof(struct sockaddr_in); + } else { + struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr; + in6_addr->sin6_port = cpu_to_be16(port); + memset(in6_addr+1, 0, sizeof(struct sockaddr_storage) - + sizeof(struct sockaddr_in6)); + *addr_len = sizeof(struct sockaddr_in6); + } +} + +/* Close the connection and tidy up */ +static void close_connection(void) +{ + if (sctp_con.sock) { + sock_release(sctp_con.sock); + sctp_con.sock = NULL; + } + + if (sctp_con.rx_page) { + __free_page(sctp_con.rx_page); + sctp_con.rx_page = NULL; + } +} + +/* We only send shutdown messages to nodes that are not part of the cluster */ +static void send_shutdown(sctp_assoc_t associd) +{ + static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + struct msghdr outmessage; + struct cmsghdr *cmsg; + struct sctp_sndrcvinfo *sinfo; + int ret; + + outmessage.msg_name = NULL; + outmessage.msg_namelen = 0; + outmessage.msg_control = outcmsg; + outmessage.msg_controllen = sizeof(outcmsg); + outmessage.msg_flags = MSG_EOR; + + cmsg = CMSG_FIRSTHDR(&outmessage); + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + outmessage.msg_controllen = cmsg->cmsg_len; + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); + + sinfo->sinfo_flags |= MSG_EOF; + sinfo->sinfo_assoc_id = associd; + + ret = kernel_sendmsg(sctp_con.sock, &outmessage, NULL, 0, 0); + + if (ret != 0) + log_print("send EOF to node failed: %d", ret); +} + + +/* INIT failed but we don't know which node... + restart INIT on all pending nodes */ +static void init_failed(void) +{ + int i; + struct nodeinfo *ni; + + for (i=1; i<=max_nodeid; i++) { + ni = nodeid2nodeinfo(i, 0); + if (!ni) + continue; + + if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) { + ni->assoc_id = 0; + if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { + spin_lock_bh(&write_nodes_lock); + list_add_tail(&ni->write_list, &write_nodes); + spin_unlock_bh(&write_nodes_lock); + } + } + } + wake_up_process(send_task); +} + +/* Something happened to an association */ +static void process_sctp_notification(struct msghdr *msg, char *buf) +{ + union sctp_notification *sn = (union sctp_notification *)buf; + + if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) { + switch (sn->sn_assoc_change.sac_state) { + + case SCTP_COMM_UP: + case SCTP_RESTART: + { + /* Check that the new node is in the lockspace */ + struct sctp_prim prim; + mm_segment_t fs; + int nodeid; + int prim_len, ret; + int addr_len; + struct nodeinfo *ni; + + /* This seems to happen when we received a connection + * too early... or something... anyway, it happens but + * we always seem to get a real message too, see + * receive_from_sock */ + + if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) { + log_print("COMM_UP for invalid assoc ID %d", + (int)sn->sn_assoc_change.sac_assoc_id); + init_failed(); + return; + } + memset(&prim, 0, sizeof(struct sctp_prim)); + prim_len = sizeof(struct sctp_prim); + prim.ssp_assoc_id = sn->sn_assoc_change.sac_assoc_id; + + fs = get_fs(); + set_fs(get_ds()); + ret = sctp_con.sock->ops->getsockopt(sctp_con.sock, + IPPROTO_SCTP, SCTP_PRIMARY_ADDR, + (char*)&prim, &prim_len); + set_fs(fs); + if (ret < 0) { + struct nodeinfo *ni; + + log_print("getsockopt/sctp_primary_addr on " + "new assoc %d failed : %d", + (int)sn->sn_assoc_change.sac_assoc_id, ret); + + /* Retry INIT later */ + ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id); + if (ni) + clear_bit(NI_INIT_PENDING, &ni->flags); + return; + } + make_sockaddr(&prim.ssp_addr, 0, &addr_len); + if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) { + log_print("reject connect from unknown addr"); + send_shutdown(prim.ssp_assoc_id); + return; + } + + ni = nodeid2nodeinfo(nodeid, GFP_KERNEL); + if (!ni) + return; + + /* Save the assoc ID */ + spin_lock(&ni->lock); + ni->assoc_id = sn->sn_assoc_change.sac_assoc_id; + spin_unlock(&ni->lock); + + log_print("got new/restarted association %d nodeid %d", + (int)sn->sn_assoc_change.sac_assoc_id, nodeid); + + /* Send any pending writes */ + clear_bit(NI_INIT_PENDING, &ni->flags); + if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { + spin_lock_bh(&write_nodes_lock); + list_add_tail(&ni->write_list, &write_nodes); + spin_unlock_bh(&write_nodes_lock); + } + wake_up_process(send_task); + } + break; + + case SCTP_COMM_LOST: + case SCTP_SHUTDOWN_COMP: + { + struct nodeinfo *ni; + + ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id); + if (ni) { + spin_lock(&ni->lock); + ni->assoc_id = 0; + spin_unlock(&ni->lock); + } + } + break; + + /* We don't know which INIT failed, so clear the PENDING flags + * on them all. if assoc_id is zero then it will then try + * again */ + + case SCTP_CANT_STR_ASSOC: + { + log_print("Can't start SCTP association - retrying"); + init_failed(); + } + break; + + default: + log_print("unexpected SCTP assoc change id=%d state=%d", + (int)sn->sn_assoc_change.sac_assoc_id, + sn->sn_assoc_change.sac_state); + } + } +} + +/* Data received from remote end */ +static int receive_from_sock(void) +{ + int ret = 0; + struct msghdr msg; + struct kvec iov[2]; + unsigned len; + int r; + struct sctp_sndrcvinfo *sinfo; + struct cmsghdr *cmsg; + struct nodeinfo *ni; + + /* These two are marginally too big for stack allocation, but this + * function is (currently) only called by dlm_recvd so static should be + * OK. + */ + static struct sockaddr_storage msgname; + static char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + + if (sctp_con.sock == NULL) + goto out; + + if (sctp_con.rx_page == NULL) { + /* + * This doesn't need to be atomic, but I think it should + * improve performance if it is. + */ + sctp_con.rx_page = alloc_page(GFP_ATOMIC); + if (sctp_con.rx_page == NULL) + goto out_resched; + CBUF_INIT(&sctp_con.cb, PAGE_CACHE_SIZE); + } + + memset(&incmsg, 0, sizeof(incmsg)); + memset(&msgname, 0, sizeof(msgname)); + + memset(incmsg, 0, sizeof(incmsg)); + msg.msg_name = &msgname; + msg.msg_namelen = sizeof(msgname); + msg.msg_flags = 0; + msg.msg_control = incmsg; + msg.msg_controllen = sizeof(incmsg); + msg.msg_iovlen = 1; + + /* I don't see why this circular buffer stuff is necessary for SCTP + * which is a packet-based protocol, but the whole thing breaks under + * load without it! The overhead is minimal (and is in the TCP lowcomms + * anyway, of course) so I'll leave it in until I can figure out what's + * really happening. + */ + + /* + * iov[0] is the bit of the circular buffer between the current end + * point (cb.base + cb.len) and the end of the buffer. + */ + iov[0].iov_len = sctp_con.cb.base - CBUF_DATA(&sctp_con.cb); + iov[0].iov_base = page_address(sctp_con.rx_page) + + CBUF_DATA(&sctp_con.cb); + iov[1].iov_len = 0; + + /* + * iov[1] is the bit of the circular buffer between the start of the + * buffer and the start of the currently used section (cb.base) + */ + if (CBUF_DATA(&sctp_con.cb) >= sctp_con.cb.base) { + iov[0].iov_len = PAGE_CACHE_SIZE - CBUF_DATA(&sctp_con.cb); + iov[1].iov_len = sctp_con.cb.base; + iov[1].iov_base = page_address(sctp_con.rx_page); + msg.msg_iovlen = 2; + } + len = iov[0].iov_len + iov[1].iov_len; + + r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, msg.msg_iovlen, len, + MSG_NOSIGNAL | MSG_DONTWAIT); + if (ret <= 0) + goto out_close; + + msg.msg_control = incmsg; + msg.msg_controllen = sizeof(incmsg); + cmsg = CMSG_FIRSTHDR(&msg); + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + + if (msg.msg_flags & MSG_NOTIFICATION) { + process_sctp_notification(&msg, page_address(sctp_con.rx_page)); + return 0; + } + + /* Is this a new association ? */ + ni = nodeid2nodeinfo(le32_to_cpu(sinfo->sinfo_ppid), GFP_KERNEL); + if (ni) { + ni->assoc_id = sinfo->sinfo_assoc_id; + if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) { + + if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { + spin_lock_bh(&write_nodes_lock); + list_add_tail(&ni->write_list, &write_nodes); + spin_unlock_bh(&write_nodes_lock); + } + wake_up_process(send_task); + } + } + + /* INIT sends a message with length of 1 - ignore it */ + if (r == 1) + return 0; + + CBUF_ADD(&sctp_con.cb, ret); + ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid), + page_address(sctp_con.rx_page), + sctp_con.cb.base, sctp_con.cb.len, + PAGE_CACHE_SIZE); + if (ret < 0) + goto out_close; + CBUF_EAT(&sctp_con.cb, ret); + + out: + ret = 0; + goto out_ret; + + out_resched: + lowcomms_data_ready(sctp_con.sock->sk, 0); + ret = 0; + schedule(); + goto out_ret; + + out_close: + if (ret != -EAGAIN) + log_print("error reading from sctp socket: %d", ret); + out_ret: + return ret; +} + +/* Bind to an IP address. SCTP allows multiple address so it can do multi-homing */ +static int add_bind_addr(struct sockaddr_storage *addr, int addr_len, int num) +{ + mm_segment_t fs; + int result = 0; + + fs = get_fs(); + set_fs(get_ds()); + if (num == 1) + result = sctp_con.sock->ops->bind(sctp_con.sock, + (struct sockaddr *) addr, addr_len); + else + result = sctp_con.sock->ops->setsockopt(sctp_con.sock, SOL_SCTP, + SCTP_SOCKOPT_BINDX_ADD, (char *)addr, addr_len); + set_fs(fs); + + if (result < 0) + log_print("Can't bind to port %d addr number %d", + dlm_config.tcp_port, num); + + return result; +} + +static void init_local(void) +{ + struct sockaddr_storage sas, *addr; + int i; + + dlm_local_nodeid = dlm_our_nodeid(); + + for (i = 0; i < DLM_MAX_ADDR_COUNT - 1; i++) { + if (dlm_our_addr(&sas, i)) + break; + + addr = kmalloc(sizeof(*addr), GFP_KERNEL); + if (!addr) + break; + memcpy(addr, &sas, sizeof(*addr)); + dlm_local_addr[dlm_local_count++] = addr; + } +} + +/* Initialise SCTP socket and bind to all interfaces */ +static int init_sock(void) +{ + mm_segment_t fs; + struct socket *sock = NULL; + struct sockaddr_storage localaddr; + struct sctp_event_subscribe subscribe; + int result = -EINVAL, num = 1, i, addr_len; + + if (!dlm_local_count) { + init_local(); + if (!dlm_local_count) { + log_print("no local IP address has been set"); + goto out; + } + } + + result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET, + IPPROTO_SCTP, &sock); + if (result < 0) { + log_print("Can't create comms socket, check SCTP is loaded"); + goto out; + } + + /* Listen for events */ + memset(&subscribe, 0, sizeof(subscribe)); + subscribe.sctp_data_io_event = 1; + subscribe.sctp_association_event = 1; + subscribe.sctp_send_failure_event = 1; + subscribe.sctp_shutdown_event = 1; + subscribe.sctp_partial_delivery_event = 1; + + fs = get_fs(); + set_fs(get_ds()); + result = sock->ops->setsockopt(sock, SOL_SCTP, SCTP_EVENTS, + (char *)&subscribe, sizeof(subscribe)); + set_fs(fs); + + if (result < 0) { + log_print("Failed to set SCTP_EVENTS on socket: result=%d", + result); + goto create_delsock; + } + + /* Init con struct */ + sock->sk->sk_user_data = &sctp_con; + sctp_con.sock = sock; + sctp_con.sock->sk->sk_data_ready = lowcomms_data_ready; + + /* Bind to all interfaces. */ + for (i = 0; i < dlm_local_count; i++) { + memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr)); + make_sockaddr(&localaddr, dlm_config.tcp_port, &addr_len); + + result = add_bind_addr(&localaddr, addr_len, num); + if (result) + goto create_delsock; + ++num; + } + + result = sock->ops->listen(sock, 5); + if (result < 0) { + log_print("Can't set socket listening"); + goto create_delsock; + } + + return 0; + + create_delsock: + sock_release(sock); + sctp_con.sock = NULL; + out: + return result; +} + + +static struct writequeue_entry *new_writequeue_entry(gfp_t allocation) +{ + struct writequeue_entry *entry; + + entry = kmalloc(sizeof(struct writequeue_entry), allocation); + if (!entry) + return NULL; + + entry->page = alloc_page(allocation); + if (!entry->page) { + kfree(entry); + return NULL; + } + + entry->offset = 0; + entry->len = 0; + entry->end = 0; + entry->users = 0; + + return entry; +} + +void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc) +{ + struct writequeue_entry *e; + int offset = 0; + int users = 0; + struct nodeinfo *ni; + + if (!atomic_read(&accepting)) + return NULL; + + ni = nodeid2nodeinfo(nodeid, allocation); + if (!ni) + return NULL; + + spin_lock(&ni->writequeue_lock); + e = list_entry(ni->writequeue.prev, struct writequeue_entry, list); + if (((struct list_head *) e == &ni->writequeue) || + (PAGE_CACHE_SIZE - e->end < len)) { + e = NULL; + } else { + offset = e->end; + e->end += len; + users = e->users++; + } + spin_unlock(&ni->writequeue_lock); + + if (e) { + got_one: + if (users == 0) + kmap(e->page); + *ppc = page_address(e->page) + offset; + return e; + } + + e = new_writequeue_entry(allocation); + if (e) { + spin_lock(&ni->writequeue_lock); + offset = e->end; + e->end += len; + e->ni = ni; + users = e->users++; + list_add_tail(&e->list, &ni->writequeue); + spin_unlock(&ni->writequeue_lock); + goto got_one; + } + return NULL; +} + +void dlm_lowcomms_commit_buffer(void *arg) +{ + struct writequeue_entry *e = (struct writequeue_entry *) arg; + int users; + struct nodeinfo *ni = e->ni; + + if (!atomic_read(&accepting)) + return; + + spin_lock(&ni->writequeue_lock); + users = --e->users; + if (users) + goto out; + e->len = e->end - e->offset; + kunmap(e->page); + spin_unlock(&ni->writequeue_lock); + + if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { + spin_lock_bh(&write_nodes_lock); + list_add_tail(&ni->write_list, &write_nodes); + spin_unlock_bh(&write_nodes_lock); + wake_up_process(send_task); + } + return; + + out: + spin_unlock(&ni->writequeue_lock); + return; +} + +static void free_entry(struct writequeue_entry *e) +{ + __free_page(e->page); + kfree(e); +} + +/* Initiate an SCTP association. In theory we could just use sendmsg() on + the first IP address and it should work, but this allows us to set up the + association before sending any valuable data that we can't afford to lose. + It also keeps the send path clean as it can now always use the association ID */ +static void initiate_association(int nodeid) +{ + struct sockaddr_storage rem_addr; + static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + struct msghdr outmessage; + struct cmsghdr *cmsg; + struct sctp_sndrcvinfo *sinfo; + int ret; + int addrlen; + char buf[1]; + struct kvec iov[1]; + struct nodeinfo *ni; + + log_print("Initiating association with node %d", nodeid); + + ni = nodeid2nodeinfo(nodeid, GFP_KERNEL); + if (!ni) + return; + + if (nodeid_to_addr(nodeid, (struct sockaddr *)&rem_addr)) { + log_print("no address for nodeid %d", nodeid); + return; + } + + make_sockaddr(&rem_addr, dlm_config.tcp_port, &addrlen); + + outmessage.msg_name = &rem_addr; + outmessage.msg_namelen = addrlen; + outmessage.msg_control = outcmsg; + outmessage.msg_controllen = sizeof(outcmsg); + outmessage.msg_flags = MSG_EOR; + + iov[0].iov_base = buf; + iov[0].iov_len = 1; + + /* Real INIT messages seem to cause trouble. Just send a 1 byte message + we can afford to lose */ + cmsg = CMSG_FIRSTHDR(&outmessage); + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); + sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid); + + outmessage.msg_controllen = cmsg->cmsg_len; + ret = kernel_sendmsg(sctp_con.sock, &outmessage, iov, 1, 1); + if (ret < 0) { + log_print("send INIT to node failed: %d", ret); + /* Try again later */ + clear_bit(NI_INIT_PENDING, &ni->flags); + } +} + +/* Send a message */ +static int send_to_sock(struct nodeinfo *ni) +{ + int ret = 0; + struct writequeue_entry *e; + int len, offset; + struct msghdr outmsg; + static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + struct cmsghdr *cmsg; + struct sctp_sndrcvinfo *sinfo; + struct kvec iov; + + /* See if we need to init an association before we start + sending precious messages */ + spin_lock(&ni->lock); + if (!ni->assoc_id && !test_and_set_bit(NI_INIT_PENDING, &ni->flags)) { + spin_unlock(&ni->lock); + initiate_association(ni->nodeid); + return 0; + } + spin_unlock(&ni->lock); + + outmsg.msg_name = NULL; /* We use assoc_id */ + outmsg.msg_namelen = 0; + outmsg.msg_control = outcmsg; + outmsg.msg_controllen = sizeof(outcmsg); + outmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL | MSG_EOR; + + cmsg = CMSG_FIRSTHDR(&outmsg); + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); + sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid); + sinfo->sinfo_assoc_id = ni->assoc_id; + outmsg.msg_controllen = cmsg->cmsg_len; + + spin_lock(&ni->writequeue_lock); + for (;;) { + if (list_empty(&ni->writequeue)) + break; + e = list_entry(ni->writequeue.next, struct writequeue_entry, + list); + len = e->len; + offset = e->offset; + BUG_ON(len == 0 && e->users == 0); + spin_unlock(&ni->writequeue_lock); + kmap(e->page); + + ret = 0; + if (len) { + iov.iov_base = page_address(e->page)+offset; + iov.iov_len = len; + + ret = kernel_sendmsg(sctp_con.sock, &outmsg, &iov, 1, + len); + if (ret == -EAGAIN) { + sctp_con.eagain_flag = 1; + goto out; + } else if (ret < 0) + goto send_error; + } else { + /* Don't starve people filling buffers */ + schedule(); + } + + spin_lock(&ni->writequeue_lock); + e->offset += ret; + e->len -= ret; + + if (e->len == 0 && e->users == 0) { + list_del(&e->list); + free_entry(e); + continue; + } + } + spin_unlock(&ni->writequeue_lock); + out: + return ret; + + send_error: + log_print("Error sending to node %d %d", ni->nodeid, ret); + spin_lock(&ni->lock); + if (!test_and_set_bit(NI_INIT_PENDING, &ni->flags)) { + ni->assoc_id = 0; + spin_unlock(&ni->lock); + initiate_association(ni->nodeid); + } else + spin_unlock(&ni->lock); + + return ret; +} + +/* Try to send any messages that are pending */ +static void process_output_queue(void) +{ + struct list_head *list; + struct list_head *temp; + + spin_lock_bh(&write_nodes_lock); + list_for_each_safe(list, temp, &write_nodes) { + struct nodeinfo *ni = + list_entry(list, struct nodeinfo, write_list); + clear_bit(NI_WRITE_PENDING, &ni->flags); + list_del(&ni->write_list); + + spin_unlock_bh(&write_nodes_lock); + + send_to_sock(ni); + spin_lock_bh(&write_nodes_lock); + } + spin_unlock_bh(&write_nodes_lock); +} + +/* Called after we've had -EAGAIN and been woken up */ +static void refill_write_queue(void) +{ + int i; + + for (i=1; i<=max_nodeid; i++) { + struct nodeinfo *ni = nodeid2nodeinfo(i, 0); + + if (ni) { + if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { + spin_lock_bh(&write_nodes_lock); + list_add_tail(&ni->write_list, &write_nodes); + spin_unlock_bh(&write_nodes_lock); + } + } + } +} + +static void clean_one_writequeue(struct nodeinfo *ni) +{ + struct list_head *list; + struct list_head *temp; + + spin_lock(&ni->writequeue_lock); + list_for_each_safe(list, temp, &ni->writequeue) { + struct writequeue_entry *e = + list_entry(list, struct writequeue_entry, list); + list_del(&e->list); + free_entry(e); + } + spin_unlock(&ni->writequeue_lock); +} + +static void clean_writequeues(void) +{ + int i; + + for (i=1; i<=max_nodeid; i++) { + struct nodeinfo *ni = nodeid2nodeinfo(i, 0); + if (ni) + clean_one_writequeue(ni); + } +} + + +static void dealloc_nodeinfo(void) +{ + int i; + + for (i=1; i<=max_nodeid; i++) { + struct nodeinfo *ni = nodeid2nodeinfo(i, 0); + if (ni) { + idr_remove(&nodeinfo_idr, i); + kfree(ni); + } + } +} + +int dlm_lowcomms_close(int nodeid) +{ + struct nodeinfo *ni; + + ni = nodeid2nodeinfo(nodeid, 0); + if (!ni) + return -1; + + spin_lock(&ni->lock); + if (ni->assoc_id) { + ni->assoc_id = 0; + /* Don't send shutdown here, sctp will just queue it + till the node comes back up! */ + } + spin_unlock(&ni->lock); + + clean_one_writequeue(ni); + clear_bit(NI_INIT_PENDING, &ni->flags); + return 0; +} + +static int write_list_empty(void) +{ + int status; + + spin_lock_bh(&write_nodes_lock); + status = list_empty(&write_nodes); + spin_unlock_bh(&write_nodes_lock); + + return status; +} + +static int dlm_recvd(void *data) +{ + DECLARE_WAITQUEUE(wait, current); + + while (!kthread_should_stop()) { + int count = 0; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&lowcomms_recv_wait, &wait); + if (!test_bit(CF_READ_PENDING, &sctp_con.flags)) + schedule(); + remove_wait_queue(&lowcomms_recv_wait, &wait); + set_current_state(TASK_RUNNING); + + if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) { + int ret; + + do { + ret = receive_from_sock(); + + /* Don't starve out everyone else */ + if (++count >= MAX_RX_MSG_COUNT) { + schedule(); + count = 0; + } + } while (!kthread_should_stop() && ret >=0); + } + schedule(); + } + + return 0; +} + +static int dlm_sendd(void *data) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (write_list_empty()) + schedule(); + set_current_state(TASK_RUNNING); + + if (sctp_con.eagain_flag) { + sctp_con.eagain_flag = 0; + refill_write_queue(); + } + process_output_queue(); + } + + remove_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); + + return 0; +} + +static void daemons_stop(void) +{ + kthread_stop(recv_task); + kthread_stop(send_task); +} + +static int daemons_start(void) +{ + struct task_struct *p; + int error; + + p = kthread_run(dlm_recvd, NULL, "dlm_recvd"); + error = IS_ERR(p); + if (error) { + log_print("can't start dlm_recvd %d", error); + return error; + } + recv_task = p; + + p = kthread_run(dlm_sendd, NULL, "dlm_sendd"); + error = IS_ERR(p); + if (error) { + log_print("can't start dlm_sendd %d", error); + kthread_stop(recv_task); + return error; + } + send_task = p; + + return 0; +} + +/* + * This is quite likely to sleep... + */ +int dlm_lowcomms_start(void) +{ + int error; + + error = init_sock(); + if (error) + goto fail_sock; + error = daemons_start(); + if (error) + goto fail_sock; + atomic_set(&accepting, 1); + return 0; + + fail_sock: + close_connection(); + return error; +} + +/* Set all the activity flags to prevent any socket activity. */ + +void dlm_lowcomms_stop(void) +{ + atomic_set(&accepting, 0); + sctp_con.flags = 0x7; + daemons_stop(); + clean_writequeues(); + close_connection(); + dealloc_nodeinfo(); + max_nodeid = 0; +} + +int dlm_lowcomms_init(void) +{ + init_waitqueue_head(&lowcomms_recv_wait); + spin_lock_init(&write_nodes_lock); + INIT_LIST_HEAD(&write_nodes); + init_rwsem(&nodeinfo_lock); + return 0; +} + +void dlm_lowcomms_exit(void) +{ + int i; + + for (i = 0; i < dlm_local_count; i++) + kfree(dlm_local_addr[i]); + dlm_local_count = 0; + dlm_local_nodeid = 0; +} + diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c new file mode 100644 index 0000000..7289e59 --- /dev/null +++ b/fs/dlm/lowcomms-tcp.c @@ -0,0 +1,1263 @@ +/****************************************************************************** +******************************************************************************* +** +** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. +** Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. +** +** This copyrighted material is made available to anyone wishing to use, +** modify, copy, or redistribute it subject to the terms and conditions +** of the GNU General Public License v.2. +** +******************************************************************************* +******************************************************************************/ + +/* + * lowcomms.c + * + * This is the "low-level" comms layer. + * + * It is responsible for sending/receiving messages + * from other nodes in the cluster. + * + * Cluster nodes are referred to by their nodeids. nodeids are + * simply 32 bit numbers to the locking module - if they need to + * be expanded for the cluster infrastructure then that is it's + * responsibility. It is this layer's + * responsibility to resolve these into IP address or + * whatever it needs for inter-node communication. + * + * The comms level is two kernel threads that deal mainly with + * the receiving of messages from other nodes and passing them + * up to the mid-level comms layer (which understands the + * message format) for execution by the locking core, and + * a send thread which does all the setting up of connections + * to remote nodes and the sending of data. Threads are not allowed + * to send their own data because it may cause them to wait in times + * of high load. Also, this way, the sending thread can collect together + * messages bound for one node and send them in one block. + * + * I don't see any problem with the recv thread executing the locking + * code on behalf of remote processes as the locking code is + * short, efficient and never waits. + * + */ + + +#include +#include +#include +#include + +#include "dlm_internal.h" +#include "lowcomms.h" +#include "midcomms.h" +#include "config.h" + +struct cbuf { + unsigned base; + unsigned len; + unsigned mask; +}; + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif +#define NODE_INCREMENT 32 + +#define CBUF_INIT(cb, size) do { (cb)->base = (cb)->len = 0; (cb)->mask = ((size)-1); } while(0) +#define CBUF_ADD(cb, n) do { (cb)->len += n; } while(0) +#define CBUF_EMPTY(cb) ((cb)->len == 0) +#define CBUF_MAY_ADD(cb, n) (((cb)->len + (n)) < ((cb)->mask + 1)) +#define CBUF_EAT(cb, n) do { (cb)->len -= (n); \ + (cb)->base += (n); (cb)->base &= (cb)->mask; } while(0) +#define CBUF_DATA(cb) (((cb)->base + (cb)->len) & (cb)->mask) + +/* Maximum number of incoming messages to process before + doing a schedule() +*/ +#define MAX_RX_MSG_COUNT 25 + +struct connection { + struct socket *sock; /* NULL if not connected */ + uint32_t nodeid; /* So we know who we are in the list */ + struct rw_semaphore sock_sem; /* Stop connect races */ + struct list_head read_list; /* On this list when ready for reading */ + struct list_head write_list; /* On this list when ready for writing */ + struct list_head state_list; /* On this list when ready to connect */ + unsigned long flags; /* bit 1,2 = We are on the read/write lists */ +#define CF_READ_PENDING 1 +#define CF_WRITE_PENDING 2 +#define CF_CONNECT_PENDING 3 +#define CF_IS_OTHERCON 4 + struct list_head writequeue; /* List of outgoing writequeue_entries */ + struct list_head listenlist; /* List of allocated listening sockets */ + spinlock_t writequeue_lock; + int (*rx_action) (struct connection *); /* What to do when active */ + struct page *rx_page; + struct cbuf cb; + int retries; + atomic_t waiting_requests; +#define MAX_CONNECT_RETRIES 3 + struct connection *othercon; +}; +#define sock2con(x) ((struct connection *)(x)->sk_user_data) + +/* An entry waiting to be sent */ +struct writequeue_entry { + struct list_head list; + struct page *page; + int offset; + int len; + int end; + int users; + struct connection *con; +}; + +static struct sockaddr_storage dlm_local_addr; + +/* Manage daemons */ +static struct task_struct *recv_task; +static struct task_struct *send_task; + +static wait_queue_t lowcomms_send_waitq_head; +static wait_queue_head_t lowcomms_send_waitq; +static wait_queue_t lowcomms_recv_waitq_head; +static wait_queue_head_t lowcomms_recv_waitq; + +/* An array of pointers to connections, indexed by NODEID */ +static struct connection **connections; +static struct semaphore connections_lock; +static kmem_cache_t *con_cache; +static int conn_array_size; +static atomic_t accepting; + +/* List of sockets that have reads pending */ +static struct list_head read_sockets; +static spinlock_t read_sockets_lock; + +/* List of sockets which have writes pending */ +static struct list_head write_sockets; +static spinlock_t write_sockets_lock; + +/* List of sockets which have connects pending */ +static struct list_head state_sockets; +static spinlock_t state_sockets_lock; + +static struct connection *nodeid2con(int nodeid, gfp_t allocation) +{ + struct connection *con = NULL; + + down(&connections_lock); + if (nodeid >= conn_array_size) { + int new_size = nodeid + NODE_INCREMENT; + struct connection **new_conns; + + new_conns = kmalloc(sizeof(struct connection *) * + new_size, allocation); + if (!new_conns) + goto finish; + + memset(new_conns, 0, sizeof(struct connection *) * new_size); + memcpy(new_conns, connections, sizeof(struct connection *) * conn_array_size); + conn_array_size = new_size; + kfree(connections); + connections = new_conns; + + } + + con = connections[nodeid]; + if (con == NULL && allocation) { + con = kmem_cache_alloc(con_cache, allocation); + if (!con) + goto finish; + + memset(con, 0, sizeof(*con)); + con->nodeid = nodeid; + init_rwsem(&con->sock_sem); + INIT_LIST_HEAD(&con->writequeue); + spin_lock_init(&con->writequeue_lock); + + connections[nodeid] = con; + } + + finish: + up(&connections_lock); + return con; +} + +/* Data available on socket or listen socket received a connect */ +static void lowcomms_data_ready(struct sock *sk, int count_unused) +{ + struct connection *con = sock2con(sk); + + atomic_inc(&con->waiting_requests); + if (test_and_set_bit(CF_READ_PENDING, &con->flags)) + return; + + spin_lock_bh(&read_sockets_lock); + list_add_tail(&con->read_list, &read_sockets); + spin_unlock_bh(&read_sockets_lock); + + wake_up_interruptible(&lowcomms_recv_waitq); +} + +static void lowcomms_write_space(struct sock *sk) +{ + struct connection *con = sock2con(sk); + + if (test_and_set_bit(CF_WRITE_PENDING, &con->flags)) + return; + + spin_lock_bh(&write_sockets_lock); + list_add_tail(&con->write_list, &write_sockets); + spin_unlock_bh(&write_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); +} + +static inline void lowcomms_connect_sock(struct connection *con) +{ + if (test_and_set_bit(CF_CONNECT_PENDING, &con->flags)) + return; + if (!atomic_read(&accepting)) + return; + + spin_lock_bh(&state_sockets_lock); + list_add_tail(&con->state_list, &state_sockets); + spin_unlock_bh(&state_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); +} + +static void lowcomms_state_change(struct sock *sk) +{ +/* struct connection *con = sock2con(sk); */ + + switch (sk->sk_state) { + case TCP_ESTABLISHED: + lowcomms_write_space(sk); + break; + + case TCP_FIN_WAIT1: + case TCP_FIN_WAIT2: + case TCP_TIME_WAIT: + case TCP_CLOSE: + case TCP_CLOSE_WAIT: + case TCP_LAST_ACK: + case TCP_CLOSING: + /* FIXME: I think this causes more trouble than it solves. + lowcomms wil reconnect anyway when there is something to + send. This just attempts reconnection if a node goes down! + */ + /* lowcomms_connect_sock(con); */ + break; + + default: + printk("dlm: lowcomms_state_change: state=%d\n", sk->sk_state); + break; + } +} + +/* Make a socket active */ +static int add_sock(struct socket *sock, struct connection *con) +{ + con->sock = sock; + + /* Install a data_ready callback */ + con->sock->sk->sk_data_ready = lowcomms_data_ready; + con->sock->sk->sk_write_space = lowcomms_write_space; + con->sock->sk->sk_state_change = lowcomms_state_change; + + return 0; +} + +/* Add the port number to an IP6 or 4 sockaddr and return the address + length */ +static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, + int *addr_len) +{ + saddr->ss_family = dlm_local_addr.ss_family; + if (saddr->ss_family == AF_INET) { + struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr; + in4_addr->sin_port = cpu_to_be16(port); + *addr_len = sizeof(struct sockaddr_in); + } + else { + struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr; + in6_addr->sin6_port = cpu_to_be16(port); + *addr_len = sizeof(struct sockaddr_in6); + } +} + +/* Close a remote connection and tidy up */ +static void close_connection(struct connection *con, int and_other) +{ + down_write(&con->sock_sem); + + if (con->sock) { + sock_release(con->sock); + con->sock = NULL; + } + if (con->othercon && and_other) { + /* Argh! recursion in kernel code! + Actually, this isn't a list so it + will only re-enter once. + */ + close_connection(con->othercon, FALSE); + } + if (con->rx_page) { + __free_page(con->rx_page); + con->rx_page = NULL; + } + con->retries = 0; + up_write(&con->sock_sem); +} + +/* Data received from remote end */ +static int receive_from_sock(struct connection *con) +{ + int ret = 0; + struct msghdr msg; + struct iovec iov[2]; + mm_segment_t fs; + unsigned len; + int r; + int call_again_soon = 0; + + down_read(&con->sock_sem); + + if (con->sock == NULL) + goto out; + if (con->rx_page == NULL) { + /* + * This doesn't need to be atomic, but I think it should + * improve performance if it is. + */ + con->rx_page = alloc_page(GFP_ATOMIC); + if (con->rx_page == NULL) + goto out_resched; + CBUF_INIT(&con->cb, PAGE_CACHE_SIZE); + } + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_iovlen = 1; + msg.msg_iov = iov; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_flags = 0; + + /* + * iov[0] is the bit of the circular buffer between the current end + * point (cb.base + cb.len) and the end of the buffer. + */ + iov[0].iov_len = con->cb.base - CBUF_DATA(&con->cb); + iov[0].iov_base = page_address(con->rx_page) + CBUF_DATA(&con->cb); + iov[1].iov_len = 0; + + /* + * iov[1] is the bit of the circular buffer between the start of the + * buffer and the start of the currently used section (cb.base) + */ + if (CBUF_DATA(&con->cb) >= con->cb.base) { + iov[0].iov_len = PAGE_CACHE_SIZE - CBUF_DATA(&con->cb); + iov[1].iov_len = con->cb.base; + iov[1].iov_base = page_address(con->rx_page); + msg.msg_iovlen = 2; + } + len = iov[0].iov_len + iov[1].iov_len; + + fs = get_fs(); + set_fs(get_ds()); + r = ret = sock_recvmsg(con->sock, &msg, len, + MSG_DONTWAIT | MSG_NOSIGNAL); + set_fs(fs); + + if (ret <= 0) + goto out_close; + if (ret == len) + call_again_soon = 1; + CBUF_ADD(&con->cb, ret); + ret = dlm_process_incoming_buffer(con->nodeid, + page_address(con->rx_page), + con->cb.base, con->cb.len, + PAGE_CACHE_SIZE); + if (ret == -EBADMSG) { + printk(KERN_INFO "dlm: lowcomms: addr=%p, base=%u, len=%u, " + "iov_len=%u, iov_base[0]=%p, read=%d\n", + page_address(con->rx_page), con->cb.base, con->cb.len, + len, iov[0].iov_base, r); + } + if (ret < 0) + goto out_close; + CBUF_EAT(&con->cb, ret); + + if (CBUF_EMPTY(&con->cb) && !call_again_soon) { + __free_page(con->rx_page); + con->rx_page = NULL; + } + + out: + if (call_again_soon) + goto out_resched; + up_read(&con->sock_sem); + ret = 0; + goto out_ret; + + out_resched: + lowcomms_data_ready(con->sock->sk, 0); + up_read(&con->sock_sem); + ret = 0; + schedule(); + goto out_ret; + + out_close: + up_read(&con->sock_sem); + if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) { + close_connection(con, FALSE); + /* Reconnect when there is something to send */ + } + + out_ret: + return ret; +} + +/* Listening socket is busy, accept a connection */ +static int accept_from_sock(struct connection *con) +{ + int result; + struct sockaddr_storage peeraddr; + struct socket *newsock; + int len; + int nodeid; + struct connection *newcon; + + memset(&peeraddr, 0, sizeof(peeraddr)); + result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, &newsock); + if (result < 0) + return -ENOMEM; + + down_read(&con->sock_sem); + + result = -ENOTCONN; + if (con->sock == NULL) + goto accept_err; + + newsock->type = con->sock->type; + newsock->ops = con->sock->ops; + + result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK); + if (result < 0) + goto accept_err; + + /* Get the connected socket's peer */ + memset(&peeraddr, 0, sizeof(peeraddr)); + if (newsock->ops->getname(newsock, (struct sockaddr *)&peeraddr, + &len, 2)) { + result = -ECONNABORTED; + goto accept_err; + } + + /* Get the new node's NODEID */ + make_sockaddr(&peeraddr, 0, &len); + if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) { + printk("dlm: connect from non cluster node\n"); + sock_release(newsock); + up_read(&con->sock_sem); + return -1; + } + + log_print("got connection from %d", nodeid); + + /* Check to see if we already have a connection to this node. This + * could happen if the two nodes initiate a connection at roughly + * the same time and the connections cross on the wire. + * TEMPORARY FIX: + * In this case we store the incoming one in "othercon" + */ + newcon = nodeid2con(nodeid, GFP_KERNEL); + if (!newcon) { + result = -ENOMEM; + goto accept_err; + } + down_write(&newcon->sock_sem); + if (newcon->sock) { + struct connection *othercon = newcon->othercon; + + if (!othercon) { + othercon = kmem_cache_alloc(con_cache, GFP_KERNEL); + if (!othercon) { + printk("dlm: failed to allocate incoming socket\n"); + up_write(&newcon->sock_sem); + result = -ENOMEM; + goto accept_err; + } + memset(othercon, 0, sizeof(*othercon)); + othercon->nodeid = nodeid; + othercon->rx_action = receive_from_sock; + init_rwsem(&othercon->sock_sem); + set_bit(CF_IS_OTHERCON, &othercon->flags); + newcon->othercon = othercon; + } + othercon->sock = newsock; + newsock->sk->sk_user_data = othercon; + add_sock(newsock, othercon); + } + else { + newsock->sk->sk_user_data = newcon; + newcon->rx_action = receive_from_sock; + add_sock(newsock, newcon); + + } + + up_write(&newcon->sock_sem); + + /* + * Add it to the active queue in case we got data + * beween processing the accept adding the socket + * to the read_sockets list + */ + lowcomms_data_ready(newsock->sk, 0); + up_read(&con->sock_sem); + + return 0; + + accept_err: + up_read(&con->sock_sem); + sock_release(newsock); + + if (result != -EAGAIN) + printk("dlm: error accepting connection from node: %d\n", result); + return result; +} + +/* Connect a new socket to its peer */ +static int connect_to_sock(struct connection *con) +{ + int result = -EHOSTUNREACH; + struct sockaddr_storage saddr; + int addr_len; + struct socket *sock; + + if (con->nodeid == 0) { + log_print("attempt to connect sock 0 foiled"); + return 0; + } + + down_write(&con->sock_sem); + if (con->retries++ > MAX_CONNECT_RETRIES) + goto out; + + /* Some odd races can cause double-connects, ignore them */ + if (con->sock) { + result = 0; + goto out; + } + + /* Create a socket to communicate with */ + result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, &sock); + if (result < 0) + goto out_err; + + memset(&saddr, 0, sizeof(saddr)); + if (dlm_nodeid_to_addr(con->nodeid, &saddr)) + goto out_err; + + sock->sk->sk_user_data = con; + con->rx_action = receive_from_sock; + + make_sockaddr(&saddr, dlm_config.tcp_port, &addr_len); + + add_sock(sock, con); + + log_print("connecting to %d", con->nodeid); + result = + sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len, + O_NONBLOCK); + if (result == -EINPROGRESS) + result = 0; + if (result != 0) + goto out_err; + + out: + up_write(&con->sock_sem); + /* + * Returning an error here means we've given up trying to connect to + * a remote node, otherwise we return 0 and reschedule the connetion + * attempt + */ + return result; + + out_err: + if (con->sock) { + sock_release(con->sock); + con->sock = NULL; + } + /* + * Some errors are fatal and this list might need adjusting. For other + * errors we try again until the max number of retries is reached. + */ + if (result != -EHOSTUNREACH && result != -ENETUNREACH && + result != -ENETDOWN && result != EINVAL + && result != -EPROTONOSUPPORT) { + lowcomms_connect_sock(con); + result = 0; + } + goto out; +} + +static struct socket *create_listen_sock(struct connection *con, struct sockaddr_storage *saddr) +{ + struct socket *sock = NULL; + mm_segment_t fs; + int result = 0; + int one = 1; + int addr_len; + + if (dlm_local_addr.ss_family == AF_INET) + addr_len = sizeof(struct sockaddr_in); + else + addr_len = sizeof(struct sockaddr_in6); + + /* Create a socket to communicate with */ + result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, &sock); + if (result < 0) { + printk("dlm: Can't create listening comms socket\n"); + goto create_out; + } + + fs = get_fs(); + set_fs(get_ds()); + result = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); + set_fs(fs); + if (result < 0) { + printk("dlm: Failed to set SO_REUSEADDR on socket: result=%d\n",result); + } + sock->sk->sk_user_data = con; + con->rx_action = accept_from_sock; + con->sock = sock; + + /* Bind to our port */ + make_sockaddr(saddr, dlm_config.tcp_port, &addr_len); + result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len); + if (result < 0) { + printk("dlm: Can't bind to port %d\n", dlm_config.tcp_port); + sock_release(sock); + sock = NULL; + con->sock = NULL; + goto create_out; + } + + fs = get_fs(); + set_fs(get_ds()); + + result = sock_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof(one)); + set_fs(fs); + if (result < 0) { + printk("dlm: Set keepalive failed: %d\n", result); + } + + result = sock->ops->listen(sock, 5); + if (result < 0) { + printk("dlm: Can't listen on port %d\n", dlm_config.tcp_port); + sock_release(sock); + sock = NULL; + goto create_out; + } + + create_out: + return sock; +} + + +/* Listen on all interfaces */ +static int listen_for_all(void) +{ + struct socket *sock = NULL; + struct connection *con = nodeid2con(0, GFP_KERNEL); + int result = -EINVAL; + + /* We don't support multi-homed hosts */ + memset(con, 0, sizeof(*con)); + init_rwsem(&con->sock_sem); + spin_lock_init(&con->writequeue_lock); + INIT_LIST_HEAD(&con->writequeue); + set_bit(CF_IS_OTHERCON, &con->flags); + + sock = create_listen_sock(con, &dlm_local_addr); + if (sock) { + add_sock(sock, con); + result = 0; + } + else { + result = -EADDRINUSE; + } + + return result; +} + + + +static struct writequeue_entry *new_writequeue_entry(struct connection *con, + gfp_t allocation) +{ + struct writequeue_entry *entry; + + entry = kmalloc(sizeof(struct writequeue_entry), allocation); + if (!entry) + return NULL; + + entry->page = alloc_page(allocation); + if (!entry->page) { + kfree(entry); + return NULL; + } + + entry->offset = 0; + entry->len = 0; + entry->end = 0; + entry->users = 0; + entry->con = con; + + return entry; +} + +void *dlm_lowcomms_get_buffer(int nodeid, int len, + gfp_t allocation, char **ppc) +{ + struct connection *con; + struct writequeue_entry *e; + int offset = 0; + int users = 0; + + if (!atomic_read(&accepting)) + return NULL; + + con = nodeid2con(nodeid, allocation); + if (!con) + return NULL; + + spin_lock(&con->writequeue_lock); + e = list_entry(con->writequeue.prev, struct writequeue_entry, list); + if (((struct list_head *) e == &con->writequeue) || + (PAGE_CACHE_SIZE - e->end < len)) { + e = NULL; + } else { + offset = e->end; + e->end += len; + users = e->users++; + } + spin_unlock(&con->writequeue_lock); + + if (e) { + got_one: + if (users == 0) + kmap(e->page); + *ppc = page_address(e->page) + offset; + return e; + } + + e = new_writequeue_entry(con, allocation); + if (e) { + spin_lock(&con->writequeue_lock); + offset = e->end; + e->end += len; + users = e->users++; + list_add_tail(&e->list, &con->writequeue); + spin_unlock(&con->writequeue_lock); + goto got_one; + } + return NULL; +} + +void dlm_lowcomms_commit_buffer(void *mh) +{ + struct writequeue_entry *e = (struct writequeue_entry *)mh; + struct connection *con = e->con; + int users; + + if (!atomic_read(&accepting)) + return; + + spin_lock(&con->writequeue_lock); + users = --e->users; + if (users) + goto out; + e->len = e->end - e->offset; + kunmap(e->page); + spin_unlock(&con->writequeue_lock); + + if (test_and_set_bit(CF_WRITE_PENDING, &con->flags) == 0) { + spin_lock_bh(&write_sockets_lock); + list_add_tail(&con->write_list, &write_sockets); + spin_unlock_bh(&write_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); + } + return; + + out: + spin_unlock(&con->writequeue_lock); + return; +} + +static void free_entry(struct writequeue_entry *e) +{ + __free_page(e->page); + kfree(e); +} + +/* Send a message */ +static int send_to_sock(struct connection *con) +{ + int ret = 0; + ssize_t(*sendpage) (struct socket *, struct page *, int, size_t, int); + const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL; + struct writequeue_entry *e; + int len, offset; + + down_read(&con->sock_sem); + if (con->sock == NULL) + goto out_connect; + + sendpage = con->sock->ops->sendpage; + + spin_lock(&con->writequeue_lock); + for (;;) { + e = list_entry(con->writequeue.next, struct writequeue_entry, + list); + if ((struct list_head *) e == &con->writequeue) + break; + + len = e->len; + offset = e->offset; + BUG_ON(len == 0 && e->users == 0); + spin_unlock(&con->writequeue_lock); + + ret = 0; + if (len) { + ret = sendpage(con->sock, e->page, offset, len, + msg_flags); + if (ret == -EAGAIN || ret == 0) + goto out; + if (ret <= 0) + goto send_error; + } + else { + /* Don't starve people filling buffers */ + schedule(); + } + + spin_lock(&con->writequeue_lock); + e->offset += ret; + e->len -= ret; + + if (e->len == 0 && e->users == 0) { + list_del(&e->list); + free_entry(e); + continue; + } + } + spin_unlock(&con->writequeue_lock); + out: + up_read(&con->sock_sem); + return ret; + + send_error: + up_read(&con->sock_sem); + close_connection(con, FALSE); + lowcomms_connect_sock(con); + return ret; + + out_connect: + up_read(&con->sock_sem); + lowcomms_connect_sock(con); + return 0; +} + +static void clean_one_writequeue(struct connection *con) +{ + struct list_head *list; + struct list_head *temp; + + spin_lock(&con->writequeue_lock); + list_for_each_safe(list, temp, &con->writequeue) { + struct writequeue_entry *e = + list_entry(list, struct writequeue_entry, list); + list_del(&e->list); + free_entry(e); + } + spin_unlock(&con->writequeue_lock); +} + +/* Called from recovery when it knows that a node has + left the cluster */ +int dlm_lowcomms_close(int nodeid) +{ + struct connection *con; + + if (!connections) + goto out; + + log_print("closing connection to node %d", nodeid); + con = nodeid2con(nodeid, 0); + if (con) { + clean_one_writequeue(con); + close_connection(con, TRUE); + atomic_set(&con->waiting_requests, 0); + } + return 0; + + out: + return -1; +} + +/* API send message call, may queue the request */ +/* N.B. This is the old interface - use the new one for new calls */ +int lowcomms_send_message(int nodeid, char *buf, int len, gfp_t allocation) +{ + struct writequeue_entry *e; + char *b; + + e = dlm_lowcomms_get_buffer(nodeid, len, allocation, &b); + if (e) { + memcpy(b, buf, len); + dlm_lowcomms_commit_buffer(e); + return 0; + } + return -ENOBUFS; +} + +/* Look for activity on active sockets */ +static void process_sockets(void) +{ + struct list_head *list; + struct list_head *temp; + int count = 0; + + spin_lock_bh(&read_sockets_lock); + list_for_each_safe(list, temp, &read_sockets) { + + struct connection *con = + list_entry(list, struct connection, read_list); + list_del(&con->read_list); + clear_bit(CF_READ_PENDING, &con->flags); + + spin_unlock_bh(&read_sockets_lock); + + /* This can reach zero if we are processing requests + * as they come in. + */ + if (atomic_read(&con->waiting_requests) == 0) { + spin_lock_bh(&read_sockets_lock); + continue; + } + + do { + con->rx_action(con); + + /* Don't starve out everyone else */ + if (++count >= MAX_RX_MSG_COUNT) { + schedule(); + count = 0; + } + + } while (!atomic_dec_and_test(&con->waiting_requests) && + !kthread_should_stop()); + + spin_lock_bh(&read_sockets_lock); + } + spin_unlock_bh(&read_sockets_lock); +} + +/* Try to send any messages that are pending + */ +static void process_output_queue(void) +{ + struct list_head *list; + struct list_head *temp; + int ret; + + spin_lock_bh(&write_sockets_lock); + list_for_each_safe(list, temp, &write_sockets) { + struct connection *con = + list_entry(list, struct connection, write_list); + clear_bit(CF_WRITE_PENDING, &con->flags); + list_del(&con->write_list); + + spin_unlock_bh(&write_sockets_lock); + + ret = send_to_sock(con); + if (ret < 0) { + } + spin_lock_bh(&write_sockets_lock); + } + spin_unlock_bh(&write_sockets_lock); +} + +static void process_state_queue(void) +{ + struct list_head *list; + struct list_head *temp; + int ret; + + spin_lock_bh(&state_sockets_lock); + list_for_each_safe(list, temp, &state_sockets) { + struct connection *con = + list_entry(list, struct connection, state_list); + list_del(&con->state_list); + clear_bit(CF_CONNECT_PENDING, &con->flags); + spin_unlock_bh(&state_sockets_lock); + + ret = connect_to_sock(con); + if (ret < 0) { + } + spin_lock_bh(&state_sockets_lock); + } + spin_unlock_bh(&state_sockets_lock); +} + + +/* Discard all entries on the write queues */ +static void clean_writequeues(void) +{ + int nodeid; + + for (nodeid = 1; nodeid < conn_array_size; nodeid++) { + struct connection *con = nodeid2con(nodeid, 0); + + if (con) + clean_one_writequeue(con); + } +} + +static int read_list_empty(void) +{ + int status; + + spin_lock_bh(&read_sockets_lock); + status = list_empty(&read_sockets); + spin_unlock_bh(&read_sockets_lock); + + return status; +} + +/* DLM Transport comms receive daemon */ +static int dlm_recvd(void *data) +{ + init_waitqueue_head(&lowcomms_recv_waitq); + init_waitqueue_entry(&lowcomms_recv_waitq_head, current); + add_wait_queue(&lowcomms_recv_waitq, &lowcomms_recv_waitq_head); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (read_list_empty()) + schedule(); + set_current_state(TASK_RUNNING); + + process_sockets(); + } + + return 0; +} + +static int write_and_state_lists_empty(void) +{ + int status; + + spin_lock_bh(&write_sockets_lock); + status = list_empty(&write_sockets); + spin_unlock_bh(&write_sockets_lock); + + spin_lock_bh(&state_sockets_lock); + if (list_empty(&state_sockets) == 0) + status = 0; + spin_unlock_bh(&state_sockets_lock); + + return status; +} + +/* DLM Transport send daemon */ +static int dlm_sendd(void *data) +{ + init_waitqueue_head(&lowcomms_send_waitq); + init_waitqueue_entry(&lowcomms_send_waitq_head, current); + add_wait_queue(&lowcomms_send_waitq, &lowcomms_send_waitq_head); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (write_and_state_lists_empty()) + schedule(); + set_current_state(TASK_RUNNING); + + process_state_queue(); + process_output_queue(); + } + + return 0; +} + +static void daemons_stop(void) +{ + kthread_stop(recv_task); + kthread_stop(send_task); +} + +static int daemons_start(void) +{ + struct task_struct *p; + int error; + + p = kthread_run(dlm_recvd, NULL, "dlm_recvd"); + error = IS_ERR(p); + if (error) { + log_print("can't start dlm_recvd %d", error); + return error; + } + recv_task = p; + + p = kthread_run(dlm_sendd, NULL, "dlm_sendd"); + error = IS_ERR(p); + if (error) { + log_print("can't start dlm_sendd %d", error); + kthread_stop(recv_task); + return error; + } + send_task = p; + + return 0; +} + +/* + * Return the largest buffer size we can cope with. + */ +int lowcomms_max_buffer_size(void) +{ + return PAGE_CACHE_SIZE; +} + +void dlm_lowcomms_stop(void) +{ + int i; + + atomic_set(&accepting, 0); + + /* Set all the activity flags to prevent any + socket activity. + */ + for (i = 0; i < conn_array_size; i++) { + if (connections[i]) + connections[i]->flags |= 0x7; + } + daemons_stop(); + clean_writequeues(); + + for (i = 0; i < conn_array_size; i++) { + if (connections[i]) { + close_connection(connections[i], TRUE); + if (connections[i]->othercon) + kmem_cache_free(con_cache, connections[i]->othercon); + kmem_cache_free(con_cache, connections[i]); + } + } + + kfree(connections); + connections = NULL; + + kmem_cache_destroy(con_cache); +} + +/* This is quite likely to sleep... */ +int dlm_lowcomms_start(void) +{ + int error = 0; + + error = -ENOTCONN; + + /* + * Temporarily initialise the waitq head so that lowcomms_send_message + * doesn't crash if it gets called before the thread is fully + * initialised + */ + init_waitqueue_head(&lowcomms_send_waitq); + + error = -ENOMEM; + connections = kmalloc(sizeof(struct connection *) * + NODE_INCREMENT, GFP_KERNEL); + if (!connections) + goto out; + + memset(connections, 0, + sizeof(struct connection *) * NODE_INCREMENT); + + conn_array_size = NODE_INCREMENT; + + if (dlm_our_addr(&dlm_local_addr, 0)) { + log_print("no local IP address has been set"); + goto fail_free_conn; + } + if (!dlm_our_addr(&dlm_local_addr, 1)) { + log_print("This dlm comms module does not support multi-homed clustering"); + goto fail_free_conn; + } + + con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection), + __alignof__(struct connection), 0, NULL, NULL); + if (!con_cache) + goto fail_free_conn; + + + /* Start listening */ + error = listen_for_all(); + if (error) + goto fail_unlisten; + + error = daemons_start(); + if (error) + goto fail_unlisten; + + atomic_set(&accepting, 1); + + return 0; + + fail_unlisten: + close_connection(connections[0], 0); + kmem_cache_free(con_cache, connections[0]); + kmem_cache_destroy(con_cache); + + fail_free_conn: + kfree(connections); + + out: + return error; +} + +int dlm_lowcomms_init(void) +{ + INIT_LIST_HEAD(&read_sockets); + INIT_LIST_HEAD(&write_sockets); + INIT_LIST_HEAD(&state_sockets); + + spin_lock_init(&read_sockets_lock); + spin_lock_init(&write_sockets_lock); + spin_lock_init(&state_sockets_lock); + init_MUTEX(&connections_lock); + + return 0; +} + +void dlm_lowcomms_exit(void) +{ +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c deleted file mode 100644 index 6da6b14..0000000 --- a/fs/dlm/lowcomms.c +++ /dev/null @@ -1,1239 +0,0 @@ -/****************************************************************************** -******************************************************************************* -** -** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. -** -** This copyrighted material is made available to anyone wishing to use, -** modify, copy, or redistribute it subject to the terms and conditions -** of the GNU General Public License v.2. -** -******************************************************************************* -******************************************************************************/ - -/* - * lowcomms.c - * - * This is the "low-level" comms layer. - * - * It is responsible for sending/receiving messages - * from other nodes in the cluster. - * - * Cluster nodes are referred to by their nodeids. nodeids are - * simply 32 bit numbers to the locking module - if they need to - * be expanded for the cluster infrastructure then that is it's - * responsibility. It is this layer's - * responsibility to resolve these into IP address or - * whatever it needs for inter-node communication. - * - * The comms level is two kernel threads that deal mainly with - * the receiving of messages from other nodes and passing them - * up to the mid-level comms layer (which understands the - * message format) for execution by the locking core, and - * a send thread which does all the setting up of connections - * to remote nodes and the sending of data. Threads are not allowed - * to send their own data because it may cause them to wait in times - * of high load. Also, this way, the sending thread can collect together - * messages bound for one node and send them in one block. - * - * I don't see any problem with the recv thread executing the locking - * code on behalf of remote processes as the locking code is - * short, efficient and never (well, hardly ever) waits. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "dlm_internal.h" -#include "lowcomms.h" -#include "config.h" -#include "midcomms.h" - -static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; -static int dlm_local_count; -static int dlm_local_nodeid; - -/* One of these per connected node */ - -#define NI_INIT_PENDING 1 -#define NI_WRITE_PENDING 2 - -struct nodeinfo { - spinlock_t lock; - sctp_assoc_t assoc_id; - unsigned long flags; - struct list_head write_list; /* nodes with pending writes */ - struct list_head writequeue; /* outgoing writequeue_entries */ - spinlock_t writequeue_lock; - int nodeid; -}; - -static DEFINE_IDR(nodeinfo_idr); -static struct rw_semaphore nodeinfo_lock; -static int max_nodeid; - -struct cbuf { - unsigned base; - unsigned len; - unsigned mask; -}; - -/* Just the one of these, now. But this struct keeps - the connection-specific variables together */ - -#define CF_READ_PENDING 1 - -struct connection { - struct socket *sock; - unsigned long flags; - struct page *rx_page; - atomic_t waiting_requests; - struct cbuf cb; - int eagain_flag; -}; - -/* An entry waiting to be sent */ - -struct writequeue_entry { - struct list_head list; - struct page *page; - int offset; - int len; - int end; - int users; - struct nodeinfo *ni; -}; - -#define CBUF_ADD(cb, n) do { (cb)->len += n; } while(0) -#define CBUF_EMPTY(cb) ((cb)->len == 0) -#define CBUF_MAY_ADD(cb, n) (((cb)->len + (n)) < ((cb)->mask + 1)) -#define CBUF_DATA(cb) (((cb)->base + (cb)->len) & (cb)->mask) - -#define CBUF_INIT(cb, size) \ -do { \ - (cb)->base = (cb)->len = 0; \ - (cb)->mask = ((size)-1); \ -} while(0) - -#define CBUF_EAT(cb, n) \ -do { \ - (cb)->len -= (n); \ - (cb)->base += (n); \ - (cb)->base &= (cb)->mask; \ -} while(0) - - -/* List of nodes which have writes pending */ -static struct list_head write_nodes; -static spinlock_t write_nodes_lock; - -/* Maximum number of incoming messages to process before - * doing a schedule() - */ -#define MAX_RX_MSG_COUNT 25 - -/* Manage daemons */ -static struct task_struct *recv_task; -static struct task_struct *send_task; -static wait_queue_head_t lowcomms_recv_wait; -static atomic_t accepting; - -/* The SCTP connection */ -static struct connection sctp_con; - - -static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) -{ - struct sockaddr_storage addr; - int error; - - if (!dlm_local_count) - return -1; - - error = dlm_nodeid_to_addr(nodeid, &addr); - if (error) - return error; - - if (dlm_local_addr[0]->ss_family == AF_INET) { - struct sockaddr_in *in4 = (struct sockaddr_in *) &addr; - struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr; - ret4->sin_addr.s_addr = in4->sin_addr.s_addr; - } else { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr; - struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr; - memcpy(&ret6->sin6_addr, &in6->sin6_addr, - sizeof(in6->sin6_addr)); - } - - return 0; -} - -static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc) -{ - struct nodeinfo *ni; - int r; - int n; - - down_read(&nodeinfo_lock); - ni = idr_find(&nodeinfo_idr, nodeid); - up_read(&nodeinfo_lock); - - if (!ni && alloc) { - down_write(&nodeinfo_lock); - - ni = idr_find(&nodeinfo_idr, nodeid); - if (ni) - goto out_up; - - r = idr_pre_get(&nodeinfo_idr, alloc); - if (!r) - goto out_up; - - ni = kmalloc(sizeof(struct nodeinfo), alloc); - if (!ni) - goto out_up; - - r = idr_get_new_above(&nodeinfo_idr, ni, nodeid, &n); - if (r) { - kfree(ni); - ni = NULL; - goto out_up; - } - if (n != nodeid) { - idr_remove(&nodeinfo_idr, n); - kfree(ni); - ni = NULL; - goto out_up; - } - memset(ni, 0, sizeof(struct nodeinfo)); - spin_lock_init(&ni->lock); - INIT_LIST_HEAD(&ni->writequeue); - spin_lock_init(&ni->writequeue_lock); - ni->nodeid = nodeid; - - if (nodeid > max_nodeid) - max_nodeid = nodeid; - out_up: - up_write(&nodeinfo_lock); - } - - return ni; -} - -/* Don't call this too often... */ -static struct nodeinfo *assoc2nodeinfo(sctp_assoc_t assoc) -{ - int i; - struct nodeinfo *ni; - - for (i=1; i<=max_nodeid; i++) { - ni = nodeid2nodeinfo(i, 0); - if (ni && ni->assoc_id == assoc) - return ni; - } - return NULL; -} - -/* Data or notification available on socket */ -static void lowcomms_data_ready(struct sock *sk, int count_unused) -{ - atomic_inc(&sctp_con.waiting_requests); - if (test_and_set_bit(CF_READ_PENDING, &sctp_con.flags)) - return; - - wake_up_interruptible(&lowcomms_recv_wait); -} - - -/* Add the port number to an IP6 or 4 sockaddr and return the address length. - Also padd out the struct with zeros to make comparisons meaningful */ - -static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, - int *addr_len) -{ - struct sockaddr_in *local4_addr; - struct sockaddr_in6 *local6_addr; - - if (!dlm_local_count) - return; - - if (!port) { - if (dlm_local_addr[0]->ss_family == AF_INET) { - local4_addr = (struct sockaddr_in *)dlm_local_addr[0]; - port = be16_to_cpu(local4_addr->sin_port); - } else { - local6_addr = (struct sockaddr_in6 *)dlm_local_addr[0]; - port = be16_to_cpu(local6_addr->sin6_port); - } - } - - saddr->ss_family = dlm_local_addr[0]->ss_family; - if (dlm_local_addr[0]->ss_family == AF_INET) { - struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr; - in4_addr->sin_port = cpu_to_be16(port); - memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero)); - memset(in4_addr+1, 0, sizeof(struct sockaddr_storage) - - sizeof(struct sockaddr_in)); - *addr_len = sizeof(struct sockaddr_in); - } else { - struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr; - in6_addr->sin6_port = cpu_to_be16(port); - memset(in6_addr+1, 0, sizeof(struct sockaddr_storage) - - sizeof(struct sockaddr_in6)); - *addr_len = sizeof(struct sockaddr_in6); - } -} - -/* Close the connection and tidy up */ -static void close_connection(void) -{ - if (sctp_con.sock) { - sock_release(sctp_con.sock); - sctp_con.sock = NULL; - } - - if (sctp_con.rx_page) { - __free_page(sctp_con.rx_page); - sctp_con.rx_page = NULL; - } -} - -/* We only send shutdown messages to nodes that are not part of the cluster */ -static void send_shutdown(sctp_assoc_t associd) -{ - static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; - struct msghdr outmessage; - struct cmsghdr *cmsg; - struct sctp_sndrcvinfo *sinfo; - int ret; - - outmessage.msg_name = NULL; - outmessage.msg_namelen = 0; - outmessage.msg_control = outcmsg; - outmessage.msg_controllen = sizeof(outcmsg); - outmessage.msg_flags = MSG_EOR; - - cmsg = CMSG_FIRSTHDR(&outmessage); - cmsg->cmsg_level = IPPROTO_SCTP; - cmsg->cmsg_type = SCTP_SNDRCV; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); - outmessage.msg_controllen = cmsg->cmsg_len; - sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); - memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); - - sinfo->sinfo_flags |= MSG_EOF; - sinfo->sinfo_assoc_id = associd; - - ret = kernel_sendmsg(sctp_con.sock, &outmessage, NULL, 0, 0); - - if (ret != 0) - log_print("send EOF to node failed: %d", ret); -} - - -/* INIT failed but we don't know which node... - restart INIT on all pending nodes */ -static void init_failed(void) -{ - int i; - struct nodeinfo *ni; - - for (i=1; i<=max_nodeid; i++) { - ni = nodeid2nodeinfo(i, 0); - if (!ni) - continue; - - if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) { - ni->assoc_id = 0; - if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { - spin_lock_bh(&write_nodes_lock); - list_add_tail(&ni->write_list, &write_nodes); - spin_unlock_bh(&write_nodes_lock); - } - } - } - wake_up_process(send_task); -} - -/* Something happened to an association */ -static void process_sctp_notification(struct msghdr *msg, char *buf) -{ - union sctp_notification *sn = (union sctp_notification *)buf; - - if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) { - switch (sn->sn_assoc_change.sac_state) { - - case SCTP_COMM_UP: - case SCTP_RESTART: - { - /* Check that the new node is in the lockspace */ - struct sctp_prim prim; - mm_segment_t fs; - int nodeid; - int prim_len, ret; - int addr_len; - struct nodeinfo *ni; - - /* This seems to happen when we received a connection - * too early... or something... anyway, it happens but - * we always seem to get a real message too, see - * receive_from_sock */ - - if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) { - log_print("COMM_UP for invalid assoc ID %d", - (int)sn->sn_assoc_change.sac_assoc_id); - init_failed(); - return; - } - memset(&prim, 0, sizeof(struct sctp_prim)); - prim_len = sizeof(struct sctp_prim); - prim.ssp_assoc_id = sn->sn_assoc_change.sac_assoc_id; - - fs = get_fs(); - set_fs(get_ds()); - ret = sctp_con.sock->ops->getsockopt(sctp_con.sock, - IPPROTO_SCTP, SCTP_PRIMARY_ADDR, - (char*)&prim, &prim_len); - set_fs(fs); - if (ret < 0) { - struct nodeinfo *ni; - - log_print("getsockopt/sctp_primary_addr on " - "new assoc %d failed : %d", - (int)sn->sn_assoc_change.sac_assoc_id, ret); - - /* Retry INIT later */ - ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id); - if (ni) - clear_bit(NI_INIT_PENDING, &ni->flags); - return; - } - make_sockaddr(&prim.ssp_addr, 0, &addr_len); - if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) { - log_print("reject connect from unknown addr"); - send_shutdown(prim.ssp_assoc_id); - return; - } - - ni = nodeid2nodeinfo(nodeid, GFP_KERNEL); - if (!ni) - return; - - /* Save the assoc ID */ - spin_lock(&ni->lock); - ni->assoc_id = sn->sn_assoc_change.sac_assoc_id; - spin_unlock(&ni->lock); - - log_print("got new/restarted association %d nodeid %d", - (int)sn->sn_assoc_change.sac_assoc_id, nodeid); - - /* Send any pending writes */ - clear_bit(NI_INIT_PENDING, &ni->flags); - if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { - spin_lock_bh(&write_nodes_lock); - list_add_tail(&ni->write_list, &write_nodes); - spin_unlock_bh(&write_nodes_lock); - } - wake_up_process(send_task); - } - break; - - case SCTP_COMM_LOST: - case SCTP_SHUTDOWN_COMP: - { - struct nodeinfo *ni; - - ni = assoc2nodeinfo(sn->sn_assoc_change.sac_assoc_id); - if (ni) { - spin_lock(&ni->lock); - ni->assoc_id = 0; - spin_unlock(&ni->lock); - } - } - break; - - /* We don't know which INIT failed, so clear the PENDING flags - * on them all. if assoc_id is zero then it will then try - * again */ - - case SCTP_CANT_STR_ASSOC: - { - log_print("Can't start SCTP association - retrying"); - init_failed(); - } - break; - - default: - log_print("unexpected SCTP assoc change id=%d state=%d", - (int)sn->sn_assoc_change.sac_assoc_id, - sn->sn_assoc_change.sac_state); - } - } -} - -/* Data received from remote end */ -static int receive_from_sock(void) -{ - int ret = 0; - struct msghdr msg; - struct kvec iov[2]; - unsigned len; - int r; - struct sctp_sndrcvinfo *sinfo; - struct cmsghdr *cmsg; - struct nodeinfo *ni; - - /* These two are marginally too big for stack allocation, but this - * function is (currently) only called by dlm_recvd so static should be - * OK. - */ - static struct sockaddr_storage msgname; - static char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; - - if (sctp_con.sock == NULL) - goto out; - - if (sctp_con.rx_page == NULL) { - /* - * This doesn't need to be atomic, but I think it should - * improve performance if it is. - */ - sctp_con.rx_page = alloc_page(GFP_ATOMIC); - if (sctp_con.rx_page == NULL) - goto out_resched; - CBUF_INIT(&sctp_con.cb, PAGE_CACHE_SIZE); - } - - memset(&incmsg, 0, sizeof(incmsg)); - memset(&msgname, 0, sizeof(msgname)); - - memset(incmsg, 0, sizeof(incmsg)); - msg.msg_name = &msgname; - msg.msg_namelen = sizeof(msgname); - msg.msg_flags = 0; - msg.msg_control = incmsg; - msg.msg_controllen = sizeof(incmsg); - msg.msg_iovlen = 1; - - /* I don't see why this circular buffer stuff is necessary for SCTP - * which is a packet-based protocol, but the whole thing breaks under - * load without it! The overhead is minimal (and is in the TCP lowcomms - * anyway, of course) so I'll leave it in until I can figure out what's - * really happening. - */ - - /* - * iov[0] is the bit of the circular buffer between the current end - * point (cb.base + cb.len) and the end of the buffer. - */ - iov[0].iov_len = sctp_con.cb.base - CBUF_DATA(&sctp_con.cb); - iov[0].iov_base = page_address(sctp_con.rx_page) + - CBUF_DATA(&sctp_con.cb); - iov[1].iov_len = 0; - - /* - * iov[1] is the bit of the circular buffer between the start of the - * buffer and the start of the currently used section (cb.base) - */ - if (CBUF_DATA(&sctp_con.cb) >= sctp_con.cb.base) { - iov[0].iov_len = PAGE_CACHE_SIZE - CBUF_DATA(&sctp_con.cb); - iov[1].iov_len = sctp_con.cb.base; - iov[1].iov_base = page_address(sctp_con.rx_page); - msg.msg_iovlen = 2; - } - len = iov[0].iov_len + iov[1].iov_len; - - r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, msg.msg_iovlen, len, - MSG_NOSIGNAL | MSG_DONTWAIT); - if (ret <= 0) - goto out_close; - - msg.msg_control = incmsg; - msg.msg_controllen = sizeof(incmsg); - cmsg = CMSG_FIRSTHDR(&msg); - sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); - - if (msg.msg_flags & MSG_NOTIFICATION) { - process_sctp_notification(&msg, page_address(sctp_con.rx_page)); - return 0; - } - - /* Is this a new association ? */ - ni = nodeid2nodeinfo(le32_to_cpu(sinfo->sinfo_ppid), GFP_KERNEL); - if (ni) { - ni->assoc_id = sinfo->sinfo_assoc_id; - if (test_and_clear_bit(NI_INIT_PENDING, &ni->flags)) { - - if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { - spin_lock_bh(&write_nodes_lock); - list_add_tail(&ni->write_list, &write_nodes); - spin_unlock_bh(&write_nodes_lock); - } - wake_up_process(send_task); - } - } - - /* INIT sends a message with length of 1 - ignore it */ - if (r == 1) - return 0; - - CBUF_ADD(&sctp_con.cb, ret); - ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid), - page_address(sctp_con.rx_page), - sctp_con.cb.base, sctp_con.cb.len, - PAGE_CACHE_SIZE); - if (ret < 0) - goto out_close; - CBUF_EAT(&sctp_con.cb, ret); - - out: - ret = 0; - goto out_ret; - - out_resched: - lowcomms_data_ready(sctp_con.sock->sk, 0); - ret = 0; - schedule(); - goto out_ret; - - out_close: - if (ret != -EAGAIN) - log_print("error reading from sctp socket: %d", ret); - out_ret: - return ret; -} - -/* Bind to an IP address. SCTP allows multiple address so it can do multi-homing */ -static int add_bind_addr(struct sockaddr_storage *addr, int addr_len, int num) -{ - mm_segment_t fs; - int result = 0; - - fs = get_fs(); - set_fs(get_ds()); - if (num == 1) - result = sctp_con.sock->ops->bind(sctp_con.sock, - (struct sockaddr *) addr, addr_len); - else - result = sctp_con.sock->ops->setsockopt(sctp_con.sock, SOL_SCTP, - SCTP_SOCKOPT_BINDX_ADD, (char *)addr, addr_len); - set_fs(fs); - - if (result < 0) - log_print("Can't bind to port %d addr number %d", - dlm_config.tcp_port, num); - - return result; -} - -static void init_local(void) -{ - struct sockaddr_storage sas, *addr; - int i; - - dlm_local_nodeid = dlm_our_nodeid(); - - for (i = 0; i < DLM_MAX_ADDR_COUNT - 1; i++) { - if (dlm_our_addr(&sas, i)) - break; - - addr = kmalloc(sizeof(*addr), GFP_KERNEL); - if (!addr) - break; - memcpy(addr, &sas, sizeof(*addr)); - dlm_local_addr[dlm_local_count++] = addr; - } -} - -/* Initialise SCTP socket and bind to all interfaces */ -static int init_sock(void) -{ - mm_segment_t fs; - struct socket *sock = NULL; - struct sockaddr_storage localaddr; - struct sctp_event_subscribe subscribe; - int result = -EINVAL, num = 1, i, addr_len; - - if (!dlm_local_count) { - init_local(); - if (!dlm_local_count) { - log_print("no local IP address has been set"); - goto out; - } - } - - result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET, - IPPROTO_SCTP, &sock); - if (result < 0) { - log_print("Can't create comms socket, check SCTP is loaded"); - goto out; - } - - /* Listen for events */ - memset(&subscribe, 0, sizeof(subscribe)); - subscribe.sctp_data_io_event = 1; - subscribe.sctp_association_event = 1; - subscribe.sctp_send_failure_event = 1; - subscribe.sctp_shutdown_event = 1; - subscribe.sctp_partial_delivery_event = 1; - - fs = get_fs(); - set_fs(get_ds()); - result = sock->ops->setsockopt(sock, SOL_SCTP, SCTP_EVENTS, - (char *)&subscribe, sizeof(subscribe)); - set_fs(fs); - - if (result < 0) { - log_print("Failed to set SCTP_EVENTS on socket: result=%d", - result); - goto create_delsock; - } - - /* Init con struct */ - sock->sk->sk_user_data = &sctp_con; - sctp_con.sock = sock; - sctp_con.sock->sk->sk_data_ready = lowcomms_data_ready; - - /* Bind to all interfaces. */ - for (i = 0; i < dlm_local_count; i++) { - memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr)); - make_sockaddr(&localaddr, dlm_config.tcp_port, &addr_len); - - result = add_bind_addr(&localaddr, addr_len, num); - if (result) - goto create_delsock; - ++num; - } - - result = sock->ops->listen(sock, 5); - if (result < 0) { - log_print("Can't set socket listening"); - goto create_delsock; - } - - return 0; - - create_delsock: - sock_release(sock); - sctp_con.sock = NULL; - out: - return result; -} - - -static struct writequeue_entry *new_writequeue_entry(gfp_t allocation) -{ - struct writequeue_entry *entry; - - entry = kmalloc(sizeof(struct writequeue_entry), allocation); - if (!entry) - return NULL; - - entry->page = alloc_page(allocation); - if (!entry->page) { - kfree(entry); - return NULL; - } - - entry->offset = 0; - entry->len = 0; - entry->end = 0; - entry->users = 0; - - return entry; -} - -void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc) -{ - struct writequeue_entry *e; - int offset = 0; - int users = 0; - struct nodeinfo *ni; - - if (!atomic_read(&accepting)) - return NULL; - - ni = nodeid2nodeinfo(nodeid, allocation); - if (!ni) - return NULL; - - spin_lock(&ni->writequeue_lock); - e = list_entry(ni->writequeue.prev, struct writequeue_entry, list); - if (((struct list_head *) e == &ni->writequeue) || - (PAGE_CACHE_SIZE - e->end < len)) { - e = NULL; - } else { - offset = e->end; - e->end += len; - users = e->users++; - } - spin_unlock(&ni->writequeue_lock); - - if (e) { - got_one: - if (users == 0) - kmap(e->page); - *ppc = page_address(e->page) + offset; - return e; - } - - e = new_writequeue_entry(allocation); - if (e) { - spin_lock(&ni->writequeue_lock); - offset = e->end; - e->end += len; - e->ni = ni; - users = e->users++; - list_add_tail(&e->list, &ni->writequeue); - spin_unlock(&ni->writequeue_lock); - goto got_one; - } - return NULL; -} - -void dlm_lowcomms_commit_buffer(void *arg) -{ - struct writequeue_entry *e = (struct writequeue_entry *) arg; - int users; - struct nodeinfo *ni = e->ni; - - if (!atomic_read(&accepting)) - return; - - spin_lock(&ni->writequeue_lock); - users = --e->users; - if (users) - goto out; - e->len = e->end - e->offset; - kunmap(e->page); - spin_unlock(&ni->writequeue_lock); - - if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { - spin_lock_bh(&write_nodes_lock); - list_add_tail(&ni->write_list, &write_nodes); - spin_unlock_bh(&write_nodes_lock); - wake_up_process(send_task); - } - return; - - out: - spin_unlock(&ni->writequeue_lock); - return; -} - -static void free_entry(struct writequeue_entry *e) -{ - __free_page(e->page); - kfree(e); -} - -/* Initiate an SCTP association. In theory we could just use sendmsg() on - the first IP address and it should work, but this allows us to set up the - association before sending any valuable data that we can't afford to lose. - It also keeps the send path clean as it can now always use the association ID */ -static void initiate_association(int nodeid) -{ - struct sockaddr_storage rem_addr; - static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; - struct msghdr outmessage; - struct cmsghdr *cmsg; - struct sctp_sndrcvinfo *sinfo; - int ret; - int addrlen; - char buf[1]; - struct kvec iov[1]; - struct nodeinfo *ni; - - log_print("Initiating association with node %d", nodeid); - - ni = nodeid2nodeinfo(nodeid, GFP_KERNEL); - if (!ni) - return; - - if (nodeid_to_addr(nodeid, (struct sockaddr *)&rem_addr)) { - log_print("no address for nodeid %d", nodeid); - return; - } - - make_sockaddr(&rem_addr, dlm_config.tcp_port, &addrlen); - - outmessage.msg_name = &rem_addr; - outmessage.msg_namelen = addrlen; - outmessage.msg_control = outcmsg; - outmessage.msg_controllen = sizeof(outcmsg); - outmessage.msg_flags = MSG_EOR; - - iov[0].iov_base = buf; - iov[0].iov_len = 1; - - /* Real INIT messages seem to cause trouble. Just send a 1 byte message - we can afford to lose */ - cmsg = CMSG_FIRSTHDR(&outmessage); - cmsg->cmsg_level = IPPROTO_SCTP; - cmsg->cmsg_type = SCTP_SNDRCV; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); - sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); - memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); - sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid); - - outmessage.msg_controllen = cmsg->cmsg_len; - ret = kernel_sendmsg(sctp_con.sock, &outmessage, iov, 1, 1); - if (ret < 0) { - log_print("send INIT to node failed: %d", ret); - /* Try again later */ - clear_bit(NI_INIT_PENDING, &ni->flags); - } -} - -/* Send a message */ -static int send_to_sock(struct nodeinfo *ni) -{ - int ret = 0; - struct writequeue_entry *e; - int len, offset; - struct msghdr outmsg; - static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; - struct cmsghdr *cmsg; - struct sctp_sndrcvinfo *sinfo; - struct kvec iov; - - /* See if we need to init an association before we start - sending precious messages */ - spin_lock(&ni->lock); - if (!ni->assoc_id && !test_and_set_bit(NI_INIT_PENDING, &ni->flags)) { - spin_unlock(&ni->lock); - initiate_association(ni->nodeid); - return 0; - } - spin_unlock(&ni->lock); - - outmsg.msg_name = NULL; /* We use assoc_id */ - outmsg.msg_namelen = 0; - outmsg.msg_control = outcmsg; - outmsg.msg_controllen = sizeof(outcmsg); - outmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL | MSG_EOR; - - cmsg = CMSG_FIRSTHDR(&outmsg); - cmsg->cmsg_level = IPPROTO_SCTP; - cmsg->cmsg_type = SCTP_SNDRCV; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); - sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); - memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); - sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid); - sinfo->sinfo_assoc_id = ni->assoc_id; - outmsg.msg_controllen = cmsg->cmsg_len; - - spin_lock(&ni->writequeue_lock); - for (;;) { - if (list_empty(&ni->writequeue)) - break; - e = list_entry(ni->writequeue.next, struct writequeue_entry, - list); - len = e->len; - offset = e->offset; - BUG_ON(len == 0 && e->users == 0); - spin_unlock(&ni->writequeue_lock); - kmap(e->page); - - ret = 0; - if (len) { - iov.iov_base = page_address(e->page)+offset; - iov.iov_len = len; - - ret = kernel_sendmsg(sctp_con.sock, &outmsg, &iov, 1, - len); - if (ret == -EAGAIN) { - sctp_con.eagain_flag = 1; - goto out; - } else if (ret < 0) - goto send_error; - } else { - /* Don't starve people filling buffers */ - schedule(); - } - - spin_lock(&ni->writequeue_lock); - e->offset += ret; - e->len -= ret; - - if (e->len == 0 && e->users == 0) { - list_del(&e->list); - free_entry(e); - continue; - } - } - spin_unlock(&ni->writequeue_lock); - out: - return ret; - - send_error: - log_print("Error sending to node %d %d", ni->nodeid, ret); - spin_lock(&ni->lock); - if (!test_and_set_bit(NI_INIT_PENDING, &ni->flags)) { - ni->assoc_id = 0; - spin_unlock(&ni->lock); - initiate_association(ni->nodeid); - } else - spin_unlock(&ni->lock); - - return ret; -} - -/* Try to send any messages that are pending */ -static void process_output_queue(void) -{ - struct list_head *list; - struct list_head *temp; - - spin_lock_bh(&write_nodes_lock); - list_for_each_safe(list, temp, &write_nodes) { - struct nodeinfo *ni = - list_entry(list, struct nodeinfo, write_list); - clear_bit(NI_WRITE_PENDING, &ni->flags); - list_del(&ni->write_list); - - spin_unlock_bh(&write_nodes_lock); - - send_to_sock(ni); - spin_lock_bh(&write_nodes_lock); - } - spin_unlock_bh(&write_nodes_lock); -} - -/* Called after we've had -EAGAIN and been woken up */ -static void refill_write_queue(void) -{ - int i; - - for (i=1; i<=max_nodeid; i++) { - struct nodeinfo *ni = nodeid2nodeinfo(i, 0); - - if (ni) { - if (!test_and_set_bit(NI_WRITE_PENDING, &ni->flags)) { - spin_lock_bh(&write_nodes_lock); - list_add_tail(&ni->write_list, &write_nodes); - spin_unlock_bh(&write_nodes_lock); - } - } - } -} - -static void clean_one_writequeue(struct nodeinfo *ni) -{ - struct list_head *list; - struct list_head *temp; - - spin_lock(&ni->writequeue_lock); - list_for_each_safe(list, temp, &ni->writequeue) { - struct writequeue_entry *e = - list_entry(list, struct writequeue_entry, list); - list_del(&e->list); - free_entry(e); - } - spin_unlock(&ni->writequeue_lock); -} - -static void clean_writequeues(void) -{ - int i; - - for (i=1; i<=max_nodeid; i++) { - struct nodeinfo *ni = nodeid2nodeinfo(i, 0); - if (ni) - clean_one_writequeue(ni); - } -} - - -static void dealloc_nodeinfo(void) -{ - int i; - - for (i=1; i<=max_nodeid; i++) { - struct nodeinfo *ni = nodeid2nodeinfo(i, 0); - if (ni) { - idr_remove(&nodeinfo_idr, i); - kfree(ni); - } - } -} - -int dlm_lowcomms_close(int nodeid) -{ - struct nodeinfo *ni; - - ni = nodeid2nodeinfo(nodeid, 0); - if (!ni) - return -1; - - spin_lock(&ni->lock); - if (ni->assoc_id) { - ni->assoc_id = 0; - /* Don't send shutdown here, sctp will just queue it - till the node comes back up! */ - } - spin_unlock(&ni->lock); - - clean_one_writequeue(ni); - clear_bit(NI_INIT_PENDING, &ni->flags); - return 0; -} - -static int write_list_empty(void) -{ - int status; - - spin_lock_bh(&write_nodes_lock); - status = list_empty(&write_nodes); - spin_unlock_bh(&write_nodes_lock); - - return status; -} - -static int dlm_recvd(void *data) -{ - DECLARE_WAITQUEUE(wait, current); - - while (!kthread_should_stop()) { - int count = 0; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&lowcomms_recv_wait, &wait); - if (!test_bit(CF_READ_PENDING, &sctp_con.flags)) - schedule(); - remove_wait_queue(&lowcomms_recv_wait, &wait); - set_current_state(TASK_RUNNING); - - if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) { - int ret; - - do { - ret = receive_from_sock(); - - /* Don't starve out everyone else */ - if (++count >= MAX_RX_MSG_COUNT) { - schedule(); - count = 0; - } - } while (!kthread_should_stop() && ret >=0); - } - schedule(); - } - - return 0; -} - -static int dlm_sendd(void *data) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); - - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - if (write_list_empty()) - schedule(); - set_current_state(TASK_RUNNING); - - if (sctp_con.eagain_flag) { - sctp_con.eagain_flag = 0; - refill_write_queue(); - } - process_output_queue(); - } - - remove_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); - - return 0; -} - -static void daemons_stop(void) -{ - kthread_stop(recv_task); - kthread_stop(send_task); -} - -static int daemons_start(void) -{ - struct task_struct *p; - int error; - - p = kthread_run(dlm_recvd, NULL, "dlm_recvd"); - error = IS_ERR(p); - if (error) { - log_print("can't start dlm_recvd %d", error); - return error; - } - recv_task = p; - - p = kthread_run(dlm_sendd, NULL, "dlm_sendd"); - error = IS_ERR(p); - if (error) { - log_print("can't start dlm_sendd %d", error); - kthread_stop(recv_task); - return error; - } - send_task = p; - - return 0; -} - -/* - * This is quite likely to sleep... - */ -int dlm_lowcomms_start(void) -{ - int error; - - error = init_sock(); - if (error) - goto fail_sock; - error = daemons_start(); - if (error) - goto fail_sock; - atomic_set(&accepting, 1); - return 0; - - fail_sock: - close_connection(); - return error; -} - -/* Set all the activity flags to prevent any socket activity. */ - -void dlm_lowcomms_stop(void) -{ - atomic_set(&accepting, 0); - sctp_con.flags = 0x7; - daemons_stop(); - clean_writequeues(); - close_connection(); - dealloc_nodeinfo(); - max_nodeid = 0; -} - -int dlm_lowcomms_init(void) -{ - init_waitqueue_head(&lowcomms_recv_wait); - spin_lock_init(&write_nodes_lock); - INIT_LIST_HEAD(&write_nodes); - init_rwsem(&nodeinfo_lock); - return 0; -} - -void dlm_lowcomms_exit(void) -{ - int i; - - for (i = 0; i < dlm_local_count; i++) - kfree(dlm_local_addr[i]); - dlm_local_count = 0; - dlm_local_nodeid = 0; -} - -- cgit v0.10.2 From 520698096436f7da5b9142e63e3bed5580c5f14e Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 2 Nov 2006 09:49:02 -0600 Subject: [DLM] res_recover_locks_count not reset when recover_locks is aborted Red Hat BZ 213684 If a node sends an lkb to the new master (RCOM_LOCK message) during recovery and recovery is then aborted on both nodes before it gets a reply, the res_recover_locks_count needs to be reset to 0 so that when the subsequent recovery comes along and sends the lkb to the new master again the assertion doesn't trigger that checks that counter is zero. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index a5e6d18..cf9f683 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -252,6 +252,7 @@ static void recover_list_clear(struct dlm_ls *ls) spin_lock(&ls->ls_recover_list_lock); list_for_each_entry_safe(r, s, &ls->ls_recover_list, res_recover_list) { list_del_init(&r->res_recover_list); + r->res_recover_locks_count = 0; dlm_put_rsb(r); ls->ls_recover_list_count--; } -- cgit v0.10.2 From 435618b75b82b5ee511cc01fcdda9c44adb2f4bd Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 2 Nov 2006 09:45:56 -0600 Subject: [DLM] status messages ping-pong between unmounted nodes Red Hat BZ 213682 If two nodes leave the lockspace (while unmounting the fs in the case of gfs) after one has sent a STATUS message to the other, STATUS/STATUS_REPLY messages will then ping-pong between the nodes when neither of them can find the lockspace in question any longer. We kill this by not sending another STATUS message when we get a STATUS_REPLY for an unknown lockspace. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 518239a..87b12f7 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -412,9 +412,10 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) ls = dlm_find_lockspace_global(hd->h_lockspace); if (!ls) { - log_print("lockspace %x from %d not found", - hd->h_lockspace, nodeid); - send_ls_not_ready(nodeid, rc); + log_print("lockspace %x from %d type %x not found", + hd->h_lockspace, nodeid, rc->rc_type); + if (rc->rc_type == DLM_RCOM_STATUS) + send_ls_not_ready(nodeid, rc); return; } -- cgit v0.10.2 From d4400156d415540086c34a06e5d233122d6bf56a Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 31 Oct 2006 11:55:56 -0600 Subject: [DLM] fix requestqueue race Red Hat BZ 211914 There's a race between dlm_recoverd (1) enabling locking and (2) clearing out the requestqueue, and dlm_recvd (1) checking if locking is enabled and (2) adding a message to the requestqueue. An order of recoverd(1), recvd(1), recvd(2), recoverd(2) will result in a message being left on the requestqueue. The fix is to have dlm_recvd check if dlm_recoverd has enabled locking after taking the mutex for the requestqueue and if it has processing the message instead of queueing it. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 3f2befa..6088a16 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -3028,10 +3028,17 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) while (1) { if (dlm_locking_stopped(ls)) { - if (!recovery) - dlm_add_requestqueue(ls, nodeid, hd); - error = -EINTR; - goto out; + if (recovery) { + error = -EINTR; + goto out; + } + error = dlm_add_requestqueue(ls, nodeid, hd); + if (error == -EAGAIN) + continue; + else { + error = -EINTR; + goto out; + } } if (lock_recovery_try(ls)) diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c index 7b2b089..0226d2a 100644 --- a/fs/dlm/requestqueue.c +++ b/fs/dlm/requestqueue.c @@ -30,26 +30,39 @@ struct rq_entry { * lockspace is enabled on some while still suspended on others. */ -void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) +int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) { struct rq_entry *e; int length = hd->h_length; + int rv = 0; if (dlm_is_removed(ls, nodeid)) - return; + return 0; e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL); if (!e) { log_print("dlm_add_requestqueue: out of memory\n"); - return; + return 0; } e->nodeid = nodeid; memcpy(e->request, hd, length); + /* We need to check dlm_locking_stopped() after taking the mutex to + avoid a race where dlm_recoverd enables locking and runs + process_requestqueue between our earlier dlm_locking_stopped check + and this addition to the requestqueue. */ + mutex_lock(&ls->ls_requestqueue_mutex); - list_add_tail(&e->list, &ls->ls_requestqueue); + if (dlm_locking_stopped(ls)) + list_add_tail(&e->list, &ls->ls_requestqueue); + else { + log_debug(ls, "dlm_add_requestqueue skip from %d", nodeid); + kfree(e); + rv = -EAGAIN; + } mutex_unlock(&ls->ls_requestqueue_mutex); + return rv; } int dlm_process_requestqueue(struct dlm_ls *ls) diff --git a/fs/dlm/requestqueue.h b/fs/dlm/requestqueue.h index 349f0d2..6a53ea0 100644 --- a/fs/dlm/requestqueue.h +++ b/fs/dlm/requestqueue.h @@ -13,7 +13,7 @@ #ifndef __REQUESTQUEUE_DOT_H__ #define __REQUESTQUEUE_DOT_H__ -void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd); +int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd); int dlm_process_requestqueue(struct dlm_ls *ls); void dlm_wait_requestqueue(struct dlm_ls *ls); void dlm_purge_requestqueue(struct dlm_ls *ls); -- cgit v0.10.2 From 91c0dc93a1a6bbdd79707ed311e48b4397df177f Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 31 Oct 2006 11:56:01 -0600 Subject: [DLM] fix aborted recovery during node removal Red Hat BZ 211914 With the new cluster infrastructure, dlm recovery for a node removal can be aborted and restarted for a node addition. When this happens, the restarted recovery isn't aware that it's doing recovery for the earlier removal as well as the addition. So, it then skips the recovery steps only required when nodes are removed. This can result in locks not being purged for failed/removed nodes. The fix is to check for removed nodes for which recovery has not been completed at the start of a new recovery sequence. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/member.c b/fs/dlm/member.c index a3f7de7..85e2897 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c @@ -186,6 +186,14 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) struct dlm_member *memb, *safe; int i, error, found, pos = 0, neg = 0, low = -1; + /* previously removed members that we've not finished removing need to + count as a negative change so the "neg" recovery steps will happen */ + + list_for_each_entry(memb, &ls->ls_nodes_gone, list) { + log_debug(ls, "prev removed member %d", memb->nodeid); + neg++; + } + /* move departed members from ls_nodes to ls_nodes_gone */ list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) { diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 362e3ef..4a1d602 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c @@ -164,6 +164,13 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) */ dlm_recover_rsbs(ls); + } else { + /* + * Other lockspace members may be going through the "neg" steps + * while also adding us to the lockspace, in which case they'll + * be looking for this status bit during dlm_recover_locks(). + */ + dlm_set_recover_status(ls, DLM_RS_LOCKS); } dlm_release_root_list(ls); -- cgit v0.10.2 From 2cdc98aaf072d573df10c503d3b3b0b74e2a6d06 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 31 Oct 2006 11:56:08 -0600 Subject: [DLM] fix stopping unstarted recovery Red Hat BZ 211914 When many nodes are joining a lockspace simultaneously, the dlm gets a quick sequence of stop/start events, a pair for adding each node. dlm_controld in user space sends dlm_recoverd in the kernel each stop and start event. dlm_controld will sometimes send the stop before dlm_recoverd has had a chance to take up the previously queued start. The stop aborts the processing of the previous start by setting the RECOVERY_STOP flag. dlm_recoverd is erroneously clearing this flag and ignoring the stop/abort if it happens to take up the start after the stop meant to abort it. The fix is to check the sequence number that's incremented for each stop/start before clearing the flag. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 4a1d602..6e4ee94 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c @@ -219,6 +219,10 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) return error; } +/* The dlm_ls_start() that created the rv we take here may already have been + stopped via dlm_ls_stop(); in that case we need to leave the RECOVERY_STOP + flag set. */ + static void do_ls_recovery(struct dlm_ls *ls) { struct dlm_recover *rv = NULL; @@ -226,7 +230,8 @@ static void do_ls_recovery(struct dlm_ls *ls) spin_lock(&ls->ls_recover_lock); rv = ls->ls_recover_args; ls->ls_recover_args = NULL; - clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); + if (rv && ls->ls_recover_seq == rv->seq) + clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); spin_unlock(&ls->ls_recover_lock); if (rv) { -- cgit v0.10.2 From 4b77f2c93d052adca8cc8690b9b5e7f8798f4ddd Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 1 Nov 2006 09:31:48 -0600 Subject: [DLM] do full recover_locks barrier Red Hat BZ 211914 The previous patch "[DLM] fix aborted recovery during node removal" was incomplete as discovered with further testing. It set the bit for the RS_LOCKS barrier but did not then wait for the barrier. This is often ok, but sometimes it will cause yet another recovery hang. If it's a new node that also has the lowest nodeid that skips the barrier wait, then it misses the important step of collecting and reporting the barrier status from the other nodes (which is the job of the low nodeid in the barrier wait routine). Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 6e4ee94..8bb895f 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c @@ -168,9 +168,15 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) /* * Other lockspace members may be going through the "neg" steps * while also adding us to the lockspace, in which case they'll - * be looking for this status bit during dlm_recover_locks(). + * be doing the recover_locks (RS_LOCKS) barrier. */ dlm_set_recover_status(ls, DLM_RS_LOCKS); + + error = dlm_recover_locks_wait(ls); + if (error) { + log_error(ls, "recover_locks_wait failed %d", error); + goto fail; + } } dlm_release_root_list(ls); -- cgit v0.10.2 From 6f90a8b1b87f97144911790390d56f695b59db9b Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 10 Nov 2006 14:16:27 -0600 Subject: [DLM] clear sbflags on lock master RH BZ 211622 The ALTMODE flag can be set in the lock master's copy of the lock but never cleared, so ALTMODE will also be returned in a subsequent conversion of the lock when it shouldn't be. This results in lock_dlm incorrectly switching to the alternate lock mode when returning the result to gfs which then asserts when it sees the wrong lock state. The fix is to propagate the cleared sbflags value to the master node when the lock is requested. QA's d_rwrandirectlarge test triggers this bug very quickly. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 6088a16..30878de 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -2372,6 +2372,7 @@ static int send_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms_in, static void receive_flags(struct dlm_lkb *lkb, struct dlm_message *ms) { lkb->lkb_exflags = ms->m_exflags; + lkb->lkb_sbflags = ms->m_sbflags; lkb->lkb_flags = (lkb->lkb_flags & 0xFFFF0000) | (ms->m_flags & 0x0000FFFF); } -- cgit v0.10.2 From b98c95af01c10827e3443157651eb469071391a3 Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Wed, 15 Nov 2006 12:29:24 -0500 Subject: [DLM] Fix DLM config The attached patch fixes the DLM config so that it selects the chosen network transport. It should fix the bug where DLM can be left selected when NET gets unselected. This incorporates all the comments received about this patch. Cc: Adrian Bunk Cc: Andrew Morton Signed-Off-By: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig index c5985b8..b5654a2 100644 --- a/fs/dlm/Kconfig +++ b/fs/dlm/Kconfig @@ -1,10 +1,11 @@ menu "Distributed Lock Manager" - depends on INET && IP_SCTP && EXPERIMENTAL + depends on EXPERIMENTAL && INET config DLM tristate "Distributed Lock Manager (DLM)" depends on IPV6 || IPV6=n select CONFIGFS_FS + select IP_SCTP if DLM_SCTP help A general purpose distributed lock manager for kernel or userspace applications. -- cgit v0.10.2 From ab923031ceb95ec50ef33ccadf28663c660aa94c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 15 Nov 2006 15:17:03 -0500 Subject: [GFS2] Fix memory allocation in glock.c Change from GFP_KERNEL to GFP_NOFS as this was causing a slow down when trying to push inodes from cache. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 746347a..edc21c8 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -769,7 +769,7 @@ restart: } else { spin_unlock(&gl->gl_spin); - new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_KERNEL); + new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_NOFS); if (!new_gh) return; set_bit(HIF_DEMOTE, &new_gh->gh_iflags); -- cgit v0.10.2 From 4cf1ed8144e740de27c6146c25d5d7ea26679cc5 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 15 Nov 2006 15:21:06 -0500 Subject: [GFS2] Tidy up bmap & fix boundary bug This moves the locking for bmap into the bmap function itself rather than using a wrapper function. It also fixes a bug where the boundary flag was set on the wrong bh. Also the flags on the mapped bh are reset earlier in the function to ensure that they are 100% correct on the error path. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 06e3447..8240c1f 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -423,12 +423,29 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, return 0; } +static inline void bmap_lock(struct inode *inode, int create) +{ + struct gfs2_inode *ip = GFS2_I(inode); + if (create) + down_write(&ip->i_rw_mutex); + else + down_read(&ip->i_rw_mutex); +} + +static inline void bmap_unlock(struct inode *inode, int create) +{ + struct gfs2_inode *ip = GFS2_I(inode); + if (create) + up_write(&ip->i_rw_mutex); + else + up_read(&ip->i_rw_mutex); +} + /** - * gfs2_block_pointers - Map a block from an inode to a disk block + * gfs2_block_map - Map a block from an inode to a disk block * @inode: The inode * @lblock: The logical block number - * @map_bh: The bh to be mapped - * @mp: metapath to use + * @bh_map: The bh to be mapped * * Find the block number on the current device which corresponds to an * inode's block. If the block had to be created, "new" will be set. @@ -436,8 +453,8 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, * Returns: errno */ -static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, - struct buffer_head *bh_map, struct metapath *mp) +int gfs2_block_map(struct inode *inode, u64 lblock, int create, + struct buffer_head *bh_map) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); @@ -451,51 +468,55 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, u64 dblock = 0; int boundary; unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; + struct metapath mp; + u64 size; BUG_ON(maxlen == 0); if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) return 0; + bmap_lock(inode, create); + clear_buffer_mapped(bh_map); + clear_buffer_new(bh_map); + clear_buffer_boundary(bh_map); bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; - - height = calc_tree_height(ip, (lblock + 1) * bsize); - if (ip->i_di.di_height < height) { - if (!create) - return 0; - - error = build_height(inode, height); - if (error) - return error; + size = (lblock + 1) * bsize; + + if (size > ip->i_di.di_size) { + height = calc_tree_height(ip, size); + if (ip->i_di.di_height < height) { + if (!create) + goto out_ok; + + error = build_height(inode, height); + if (error) + goto out_fail; + } } - find_metapath(ip, lblock, mp); + find_metapath(ip, lblock, &mp); end_of_metadata = ip->i_di.di_height - 1; - error = gfs2_meta_inode_buffer(ip, &bh); if (error) - return error; + goto out_fail; for (x = 0; x < end_of_metadata; x++) { - lookup_block(ip, bh, x, mp, create, &new, &dblock); + lookup_block(ip, bh, x, &mp, create, &new, &dblock); brelse(bh); if (!dblock) - return 0; + goto out_ok; error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); if (error) - return error; + goto out_fail; } - boundary = lookup_block(ip, bh, end_of_metadata, mp, create, &new, &dblock); - clear_buffer_mapped(bh_map); - clear_buffer_new(bh_map); - clear_buffer_boundary(bh_map); - + boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); if (dblock) { map_bh(bh_map, inode->i_sb, dblock); if (boundary) - set_buffer_boundary(bh); + set_buffer_boundary(bh_map); if (new) { struct buffer_head *dibh; error = gfs2_meta_inode_buffer(ip, &dibh); @@ -510,8 +531,8 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, while(--maxlen && !buffer_boundary(bh_map)) { u64 eblock; - mp->mp_list[end_of_metadata]++; - boundary = lookup_block(ip, bh, end_of_metadata, mp, 0, &new, &eblock); + mp.mp_list[end_of_metadata]++; + boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock); if (eblock != ++dblock) break; bh_map->b_size += (1 << inode->i_blkbits); @@ -521,43 +542,15 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create, } out_brelse: brelse(bh); - return 0; -} - - -static inline void bmap_lock(struct inode *inode, int create) -{ - struct gfs2_inode *ip = GFS2_I(inode); - if (create) - down_write(&ip->i_rw_mutex); - else - down_read(&ip->i_rw_mutex); -} - -static inline void bmap_unlock(struct inode *inode, int create) -{ - struct gfs2_inode *ip = GFS2_I(inode); - if (create) - up_write(&ip->i_rw_mutex); - else - up_read(&ip->i_rw_mutex); -} - -int gfs2_block_map(struct inode *inode, u64 lblock, int create, - struct buffer_head *bh) -{ - struct metapath mp; - int ret; - - bmap_lock(inode, create); - ret = gfs2_block_pointers(inode, lblock, create, bh, &mp); +out_ok: + error = 0; +out_fail: bmap_unlock(inode, create); - return ret; + return error; } int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) { - struct metapath mp; struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; int ret; int create = *new; @@ -567,9 +560,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi BUG_ON(!new); bh.b_size = 1 << (inode->i_blkbits + 5); - bmap_lock(inode, create); - ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp); - bmap_unlock(inode, create); + ret = gfs2_block_map(inode, lblock, create, &bh); *extlen = bh.b_size >> inode->i_blkbits; *dblock = bh.b_blocknr; if (buffer_new(&bh)) -- cgit v0.10.2 From 175011cf6edddea32e5f5e0e04434104cc348de9 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 16 Nov 2006 10:58:55 -0500 Subject: [GFS2] Remove unused sysfs files Four of the sysfs files are unused and can therefore be removed. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 0e0ec98..983eaf1 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -426,9 +426,6 @@ static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\ } \ TUNE_ATTR_2(name, name##_store) -TUNE_ATTR(ilimit, 0); -TUNE_ATTR(ilimit_tries, 0); -TUNE_ATTR(ilimit_min, 0); TUNE_ATTR(demote_secs, 0); TUNE_ATTR(incore_log_blocks, 0); TUNE_ATTR(log_flush_secs, 0); @@ -447,7 +444,6 @@ TUNE_ATTR(quota_simul_sync, 1); TUNE_ATTR(quota_cache_secs, 1); TUNE_ATTR(max_atomic_write, 1); TUNE_ATTR(stall_secs, 1); -TUNE_ATTR(entries_per_readdir, 1); TUNE_ATTR(greedy_default, 1); TUNE_ATTR(greedy_quantum, 1); TUNE_ATTR(greedy_max, 1); @@ -459,9 +455,6 @@ TUNE_ATTR_DAEMON(quotad_secs, quotad_process); TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); static struct attribute *tune_attrs[] = { - &tune_attr_ilimit.attr, - &tune_attr_ilimit_tries.attr, - &tune_attr_ilimit_min.attr, &tune_attr_demote_secs.attr, &tune_attr_incore_log_blocks.attr, &tune_attr_log_flush_secs.attr, @@ -478,7 +471,6 @@ static struct attribute *tune_attrs[] = { &tune_attr_quota_cache_secs.attr, &tune_attr_max_atomic_write.attr, &tune_attr_stall_secs.attr, - &tune_attr_entries_per_readdir.attr, &tune_attr_greedy_default.attr, &tune_attr_greedy_quantum.attr, &tune_attr_greedy_max.attr, -- cgit v0.10.2 From dcd2479959c79d44f5dd77e71672e70f1f8b1f06 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 16 Nov 2006 11:08:16 -0500 Subject: [GFS2] Remove unused function from inode.c The gfs2_glock_nq_m_atime function is unused in so far as its only ever called with num_gh = 1, and this falls through to the gfs2_glock_nq_atime function, so we might as well call that directly. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index ea9ca23..ce7f833 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1234,92 +1234,6 @@ fail: return error; } -/** - * glock_compare_atime - Compare two struct gfs2_glock structures for sort - * @arg_a: the first structure - * @arg_b: the second structure - * - * Returns: 1 if A > B - * -1 if A < B - * 0 if A == B - */ - -static int glock_compare_atime(const void *arg_a, const void *arg_b) -{ - const struct gfs2_holder *gh_a = *(const struct gfs2_holder **)arg_a; - const struct gfs2_holder *gh_b = *(const struct gfs2_holder **)arg_b; - const struct lm_lockname *a = &gh_a->gh_gl->gl_name; - const struct lm_lockname *b = &gh_b->gh_gl->gl_name; - - if (a->ln_number > b->ln_number) - return 1; - if (a->ln_number < b->ln_number) - return -1; - if (gh_a->gh_state == LM_ST_SHARED && gh_b->gh_state == LM_ST_EXCLUSIVE) - return 1; - if (gh_a->gh_state == LM_ST_SHARED && (gh_b->gh_flags & GL_ATIME)) - return 1; - - return 0; -} - -/** - * gfs2_glock_nq_m_atime - acquire multiple glocks where one may need an - * atime update - * @num_gh: the number of structures - * @ghs: an array of struct gfs2_holder structures - * - * Returns: 0 on success (all glocks acquired), - * errno on failure (no glocks acquired) - */ - -int gfs2_glock_nq_m_atime(unsigned int num_gh, struct gfs2_holder *ghs) -{ - struct gfs2_holder **p; - unsigned int x; - int error = 0; - - if (!num_gh) - return 0; - - if (num_gh == 1) { - ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); - if (ghs->gh_flags & GL_ATIME) - error = gfs2_glock_nq_atime(ghs); - else - error = gfs2_glock_nq(ghs); - return error; - } - - p = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL); - if (!p) - return -ENOMEM; - - for (x = 0; x < num_gh; x++) - p[x] = &ghs[x]; - - sort(p, num_gh, sizeof(struct gfs2_holder *), glock_compare_atime,NULL); - - for (x = 0; x < num_gh; x++) { - p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); - - if (p[x]->gh_flags & GL_ATIME) - error = gfs2_glock_nq_atime(p[x]); - else - error = gfs2_glock_nq(p[x]); - - if (error) { - while (x--) - gfs2_glock_dq(p[x]); - break; - } - } - - kfree(p); - return error; -} - - static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 46917ed..b57f448 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -50,12 +50,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, struct gfs2_inode *ip); int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to); int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len); - int gfs2_glock_nq_atime(struct gfs2_holder *gh); -int gfs2_glock_nq_m_atime(unsigned int num_gh, struct gfs2_holder *ghs); - int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); - struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); #endif /* __INODE_DOT_H__ */ diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 2f7ef98..8676c39 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -217,7 +217,7 @@ static int gfs2_readpage(struct file *file, struct page *page) } gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); do_unlock = 1; - error = gfs2_glock_nq_m_atime(1, &gh); + error = gfs2_glock_nq_atime(&gh); if (unlikely(error)) goto out_unlock; } @@ -282,7 +282,7 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_TRY_1CB|GL_ATIME, &gh); do_unlock = 1; - ret = gfs2_glock_nq_m_atime(1, &gh); + ret = gfs2_glock_nq_atime(&gh); if (ret == GLR_TRYFAILED) goto out_noerror; if (unlikely(ret)) @@ -354,7 +354,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page, gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh); - error = gfs2_glock_nq_m_atime(1, &ip->i_gh); + error = gfs2_glock_nq_atime(&ip->i_gh); if (unlikely(error)) { if (error == GLR_TRYFAILED) error = AOP_TRUNCATED_PAGE; @@ -609,7 +609,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, * on this path. All we need change is atime. */ gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - rv = gfs2_glock_nq_m_atime(1, &gh); + rv = gfs2_glock_nq_atime(&gh); if (rv) goto out; diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index eabf6c6..c2be216 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -253,7 +253,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) u32 fsflags; gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - error = gfs2_glock_nq_m_atime(1, &gh); + error = gfs2_glock_nq_atime(&gh); if (error) return error; -- cgit v0.10.2 From 5e7d65cd9d3819512b059f4260de0119b985454c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 17 Nov 2006 12:27:44 -0500 Subject: [GFS2] Make sentinel dirents compatible with gfs1 When deleting directory entries, we set the inum.no_addr to zero in a dirent when its the first dirent in a block and thus cannot be merged into the previous dirent as is the usual case. In gfs1, inum.no_formal_ino was used instead. This patch changes gfs2 to set both inum.no_addr and inum.no_formal_ino to zero. It also changes the test from just looking at inum.no_addr to look at both inum.no_addr and inum.no_formal_ino and a sentinel is now considered to be a dirent in which _either_ (or both) of them is set to zero. This resolves Red Hat bugzillas: #215809, #211465 Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index a2923fb..0fdcb77 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -340,10 +340,15 @@ fail: return (copied) ? copied : error; } +static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) +{ + return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0; +} + static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, const struct qstr *name, int ret) { - if (dent->de_inum.no_addr != 0 && + if (!gfs2_dirent_sentinel(dent) && be32_to_cpu(dent->de_hash) == name->hash && be16_to_cpu(dent->de_name_len) == name->len && memcmp(dent+1, name->name, name->len) == 0) @@ -388,7 +393,7 @@ static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); unsigned totlen = be16_to_cpu(dent->de_rec_len); - if (!dent->de_inum.no_addr) + if (gfs2_dirent_sentinel(dent)) actual = GFS2_DIRENT_SIZE(0); if (totlen - actual >= required) return 1; @@ -405,7 +410,7 @@ static int gfs2_dirent_gather(const struct gfs2_dirent *dent, void *opaque) { struct dirent_gather *g = opaque; - if (dent->de_inum.no_addr) { + if (!gfs2_dirent_sentinel(dent)) { g->pdent[g->offset++] = dent; } return 0; @@ -433,10 +438,10 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset, if (unlikely(offset + size > len)) goto error; msg = "zero inode number"; - if (unlikely(!first && !dent->de_inum.no_addr)) + if (unlikely(!first && gfs2_dirent_sentinel(dent))) goto error; msg = "name length is greater than space in dirent"; - if (dent->de_inum.no_addr && + if (!gfs2_dirent_sentinel(dent) && unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) > size)) goto error; @@ -598,7 +603,7 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh, return ret; /* Only the first dent could ever have de_inum.no_addr == 0 */ - if (!tmp->de_inum.no_addr) { + if (gfs2_dirent_sentinel(tmp)) { gfs2_consist_inode(dip); return -EIO; } @@ -621,7 +626,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, { u16 cur_rec_len, prev_rec_len; - if (!cur->de_inum.no_addr) { + if (gfs2_dirent_sentinel(cur)) { gfs2_consist_inode(dip); return; } @@ -633,7 +638,8 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, out the inode number and return. */ if (!prev) { - cur->de_inum.no_addr = 0; /* No endianess worries */ + cur->de_inum.no_addr = 0; + cur->de_inum.no_formal_ino = 0; return; } @@ -664,7 +670,7 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode, struct gfs2_dirent *ndent; unsigned offset = 0, totlen; - if (dent->de_inum.no_addr) + if (!gfs2_dirent_sentinel(dent)) offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); totlen = be16_to_cpu(dent->de_rec_len); BUG_ON(offset + name->len > totlen); @@ -1002,7 +1008,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) if (dirent_next(dip, obh, &next)) next = NULL; - if (dent->de_inum.no_addr && + if (!gfs2_dirent_sentinel(dent) && be32_to_cpu(dent->de_hash) < divider) { struct qstr str; str.name = (char*)(dent+1); -- cgit v0.10.2 From fa2ecfc5e11b12f25b67f9c84ac6b0e74a6a0115 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 20 Nov 2006 10:04:49 -0500 Subject: [GFS2] Fix Kconfig wrt CRC32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GFS2 requires the CRC32 library function. This was reported by Toralf Förster. Cc: Toralf Förster Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index 8c27de8..c0791cb 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig @@ -2,6 +2,7 @@ config GFS2_FS tristate "GFS2 file system support" depends on EXPERIMENTAL select FS_POSIX_ACL + select CRC32 help A cluster filesystem. -- cgit v0.10.2 From 1a14d3a68f04527546121eb7b45187ff6af63151 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 20 Nov 2006 10:37:45 -0500 Subject: [GFS2] Simplify glops functions The go_sync callback took two flags, but one of them was set on every call, so this patch removes once of the flags and makes the previously conditional operations (on this flag), unconditional. The go_inval callback took three flags, each of which was set on every call to it. This patch removes the flags and makes the operations unconditional, which makes the logic rather more obvious. Two now unused flags are also removed from incore.h. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index edc21c8..b8ba4d5 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -847,12 +847,12 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) { if (glops->go_inval) - glops->go_inval(gl, DIO_METADATA | DIO_DATA); + glops->go_inval(gl, DIO_METADATA); } else if (gl->gl_state == LM_ST_DEFERRED) { /* We might not want to do this here. Look at moving to the inode glops. */ if (glops->go_inval) - glops->go_inval(gl, DIO_DATA); + glops->go_inval(gl, 0); } /* Deal with each possible exit condition */ @@ -954,7 +954,7 @@ void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags) gfs2_assert_warn(sdp, state != gl->gl_state); if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync) - glops->go_sync(gl, DIO_METADATA | DIO_DATA | DIO_RELEASE); + glops->go_sync(gl); gfs2_glock_hold(gl); gl->gl_req_bh = xmote_bh; @@ -995,7 +995,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) state_change(gl, LM_ST_UNLOCKED); if (glops->go_inval) - glops->go_inval(gl, DIO_METADATA | DIO_DATA); + glops->go_inval(gl, DIO_METADATA); if (gh) { spin_lock(&gl->gl_spin); @@ -1041,7 +1041,7 @@ void gfs2_glock_drop_th(struct gfs2_glock *gl) gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED); if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync) - glops->go_sync(gl, DIO_METADATA | DIO_DATA | DIO_RELEASE); + glops->go_sync(gl); gfs2_glock_hold(gl); gl->gl_req_bh = drop_bh; diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index b92de0a..60561ca 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -173,23 +173,18 @@ static void gfs2_page_writeback(struct gfs2_glock *gl) /** * meta_go_sync - sync out the metadata for this glock * @gl: the glock - * @flags: DIO_* * * Called when demoting or unlocking an EX glock. We must flush * to disk all dirty buffers/pages relating to this glock, and must not * not return to caller to demote/unlock the glock until I/O is complete. */ -static void meta_go_sync(struct gfs2_glock *gl, int flags) +static void meta_go_sync(struct gfs2_glock *gl) { - if (!(flags & DIO_METADATA)) - return; - if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { gfs2_log_flush(gl->gl_sbd, gl); gfs2_meta_sync(gl); - if (flags & DIO_RELEASE) - gfs2_ail_empty_gl(gl); + gfs2_ail_empty_gl(gl); } } @@ -264,31 +259,18 @@ static void inode_go_drop_th(struct gfs2_glock *gl) /** * inode_go_sync - Sync the dirty data and/or metadata for an inode glock * @gl: the glock protecting the inode - * @flags: * */ -static void inode_go_sync(struct gfs2_glock *gl, int flags) +static void inode_go_sync(struct gfs2_glock *gl) { - int meta = (flags & DIO_METADATA); - int data = (flags & DIO_DATA); - if (test_bit(GLF_DIRTY, &gl->gl_flags)) { - if (meta && data) { - gfs2_page_writeback(gl); - gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl); - gfs2_page_wait(gl); - clear_bit(GLF_DIRTY, &gl->gl_flags); - } else if (meta) { - gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl); - } else if (data) { - gfs2_page_writeback(gl); - gfs2_page_wait(gl); - } - if (flags & DIO_RELEASE) - gfs2_ail_empty_gl(gl); + gfs2_page_writeback(gl); + gfs2_log_flush(gl->gl_sbd, gl); + gfs2_meta_sync(gl); + gfs2_page_wait(gl); + clear_bit(GLF_DIRTY, &gl->gl_flags); + gfs2_ail_empty_gl(gl); } } @@ -302,15 +284,13 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags) static void inode_go_inval(struct gfs2_glock *gl, int flags) { int meta = (flags & DIO_METADATA); - int data = (flags & DIO_DATA); if (meta) { struct gfs2_inode *ip = gl->gl_object; gfs2_meta_inval(gl); set_bit(GIF_INVALID, &ip->i_flags); } - if (data) - gfs2_page_inval(gl); + gfs2_page_inval(gl); } /** @@ -494,7 +474,7 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) if (gl->gl_state != LM_ST_UNLOCKED && test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode)); - j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); + j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); error = gfs2_find_jhead(sdp->sd_jdesc, &head); if (error) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 227a74d..734421e 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -14,8 +14,6 @@ #define DIO_WAIT 0x00000010 #define DIO_METADATA 0x00000020 -#define DIO_DATA 0x00000040 -#define DIO_RELEASE 0x00000080 #define DIO_ALL 0x00000100 struct gfs2_log_operations; @@ -103,18 +101,17 @@ struct gfs2_bufdata { }; struct gfs2_glock_operations { - void (*go_xmote_th) (struct gfs2_glock * gl, unsigned int state, - int flags); - void (*go_xmote_bh) (struct gfs2_glock * gl); - void (*go_drop_th) (struct gfs2_glock * gl); - void (*go_drop_bh) (struct gfs2_glock * gl); - void (*go_sync) (struct gfs2_glock * gl, int flags); - void (*go_inval) (struct gfs2_glock * gl, int flags); - int (*go_demote_ok) (struct gfs2_glock * gl); - int (*go_lock) (struct gfs2_holder * gh); - void (*go_unlock) (struct gfs2_holder * gh); - void (*go_callback) (struct gfs2_glock * gl, unsigned int state); - void (*go_greedy) (struct gfs2_glock * gl); + void (*go_xmote_th) (struct gfs2_glock *gl, unsigned int state, int flags); + void (*go_xmote_bh) (struct gfs2_glock *gl); + void (*go_drop_th) (struct gfs2_glock *gl); + void (*go_drop_bh) (struct gfs2_glock *gl); + void (*go_sync) (struct gfs2_glock *gl); + void (*go_inval) (struct gfs2_glock *gl, int flags); + int (*go_demote_ok) (struct gfs2_glock *gl); + int (*go_lock) (struct gfs2_holder *gh); + void (*go_unlock) (struct gfs2_holder *gh); + void (*go_callback) (struct gfs2_glock *gl, unsigned int state); + void (*go_greedy) (struct gfs2_glock *gl); const int go_type; }; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0ef8317..1408c5f 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -517,7 +517,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) return error; gfs2_meta_cache_flush(ip); - j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); + j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); error = gfs2_find_jhead(sdp->sd_jdesc, &head); if (error) -- cgit v0.10.2 From 28626e2078571c4b776a17eaa486bbd2b7dfe2cd Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 22 Nov 2006 11:13:21 -0500 Subject: [GFS2] Fix glock ordering on inode creation The lock order here should be parent -> child rather than numeric order. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index ce7f833..d122074c 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -870,33 +870,10 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, if (error) goto fail_gunlock; - if (inum.no_addr < dip->i_num.no_addr) { - gfs2_glock_dq(ghs); - - error = gfs2_glock_nq_num(sdp, inum.no_addr, - &gfs2_inode_glops, LM_ST_EXCLUSIVE, - GL_SKIP, ghs + 1); - if (error) { - return ERR_PTR(error); - } - - gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs); - error = gfs2_glock_nq(ghs); - if (error) { - gfs2_glock_dq_uninit(ghs + 1); - return ERR_PTR(error); - } - - error = create_ok(dip, name, mode); - if (error) - goto fail_gunlock2; - } else { - error = gfs2_glock_nq_num(sdp, inum.no_addr, - &gfs2_inode_glops, LM_ST_EXCLUSIVE, - GL_SKIP, ghs + 1); - if (error) - goto fail_gunlock; - } + error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops, + LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1); + if (error) + goto fail_gunlock; error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev); if (error) -- cgit v0.10.2 From ae619320b22f8e0b2bbe4a3a5ac2f9ccf08d7ec2 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 22 Nov 2006 11:28:47 -0500 Subject: [GFS2] mark_inode_dirty after write to stuffed file Writes to stuffed files were not being marked dirty correctly. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 8676c39..d8d69a7 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -472,8 +472,10 @@ static int gfs2_commit_write(struct file *file, struct page *page, SetPageUptodate(page); - if (inode->i_size < file_size) + if (inode->i_size < file_size) { i_size_write(inode, file_size); + mark_inode_dirty(inode); + } } else { if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) -- cgit v0.10.2 From b004157ab5b374a498a5874cda68c389219d23e7 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 23 Nov 2006 10:51:34 -0500 Subject: [GFS2] Fix journal flush problem This fixes a bug which resulted in poor performance due to flushing the journal too often. The code path in question was via the inode_go_sync() function in glops.c. The solution is not to flush the journal immediately when inodes are ejected from memory, but batch up the work for glockd to deal with later on. This means that glocks may now live on beyond the end of the lifetime of their inodes (but not very much longer in the normal case). Also fixed in this patch is a bug (which was hidden by the bug mentioned above) in calculation of the number of free journal blocks. The gfs2_logd process has been altered to be more responsive to the journal filling up. We now wake it up when the number of uncommitted journal blocks has reached the threshold level rather than trying to flush directly at the end of each transaction. This again means doing fewer, but larger, log flushes in general. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c index cab1f68..683cb5b 100644 --- a/fs/gfs2/daemon.c +++ b/fs/gfs2/daemon.c @@ -112,6 +112,7 @@ int gfs2_logd(void *data) struct gfs2_sbd *sdp = data; struct gfs2_holder ji_gh; unsigned long t; + int need_flush; while (!kthread_should_stop()) { /* Advance the log tail */ @@ -120,8 +121,10 @@ int gfs2_logd(void *data) gfs2_tune_get(sdp, gt_log_flush_secs) * HZ; gfs2_ail1_empty(sdp, DIO_ALL); - - if (time_after_eq(jiffies, t)) { + gfs2_log_lock(sdp); + need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks); + gfs2_log_unlock(sdp); + if (need_flush || time_after_eq(jiffies, t)) { gfs2_log_flush(sdp, NULL); sdp->sd_log_flush_time = jiffies; } diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index b8ba4d5..3c2ff81 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -785,21 +785,6 @@ out: gfs2_holder_put(new_gh); } -void gfs2_glock_inode_squish(struct inode *inode) -{ - struct gfs2_holder gh; - struct gfs2_glock *gl = GFS2_I(inode)->i_gl; - gfs2_holder_init(gl, LM_ST_UNLOCKED, 0, &gh); - set_bit(HIF_DEMOTE, &gh.gh_iflags); - spin_lock(&gl->gl_spin); - gfs2_assert(inode->i_sb->s_fs_info, list_empty(&gl->gl_holders)); - list_add_tail(&gh.gh_list, &gl->gl_waiters2); - run_queue(gl); - spin_unlock(&gl->gl_spin); - wait_for_completion(&gh.gh_wait); - gfs2_holder_uninit(&gh); -} - /** * state_change - record that the glock is now in a different state * @gl: the glock @@ -1920,7 +1905,7 @@ out: static void scan_glock(struct gfs2_glock *gl) { - if (gl->gl_ops == &gfs2_inode_glops) + if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) return; if (gfs2_glmutex_trylock(gl)) { diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index a331bf8..fb39108 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -106,7 +106,6 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs); void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number, const struct gfs2_glock_operations *glops, unsigned int state, int flags); -void gfs2_glock_inode_squish(struct inode *inode); /** * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 60561ca..b068d10 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -107,70 +107,6 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) } /** - * gfs2_page_inval - Invalidate all pages associated with a glock - * @gl: the glock - * - */ - -static void gfs2_page_inval(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip; - struct inode *inode; - - ip = gl->gl_object; - inode = &ip->i_inode; - if (!ip || !S_ISREG(inode->i_mode)) - return; - - truncate_inode_pages(inode->i_mapping, 0); - gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages); - clear_bit(GIF_PAGED, &ip->i_flags); -} - -/** - * gfs2_page_wait - Wait for writeback of data - * @gl: the glock - * - * Syncs data (not metadata) for a regular file. - * No-op for all other types. - */ - -static void gfs2_page_wait(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip = gl->gl_object; - struct inode *inode = &ip->i_inode; - struct address_space *mapping = inode->i_mapping; - int error; - - if (!S_ISREG(inode->i_mode)) - return; - - error = filemap_fdatawait(mapping); - - /* Put back any errors cleared by filemap_fdatawait() - so they can be caught by someone who can pass them - up to user space. */ - - if (error == -ENOSPC) - set_bit(AS_ENOSPC, &mapping->flags); - else if (error) - set_bit(AS_EIO, &mapping->flags); - -} - -static void gfs2_page_writeback(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip = gl->gl_object; - struct inode *inode = &ip->i_inode; - struct address_space *mapping = inode->i_mapping; - - if (!S_ISREG(inode->i_mode)) - return; - - filemap_fdatawrite(mapping); -} - -/** * meta_go_sync - sync out the metadata for this glock * @gl: the glock * @@ -264,11 +200,24 @@ static void inode_go_drop_th(struct gfs2_glock *gl) static void inode_go_sync(struct gfs2_glock *gl) { + struct gfs2_inode *ip = gl->gl_object; + + if (ip && !S_ISREG(ip->i_inode.i_mode)) + ip = NULL; + if (test_bit(GLF_DIRTY, &gl->gl_flags)) { - gfs2_page_writeback(gl); gfs2_log_flush(gl->gl_sbd, gl); + if (ip) + filemap_fdatawrite(ip->i_inode.i_mapping); gfs2_meta_sync(gl); - gfs2_page_wait(gl); + if (ip) { + struct address_space *mapping = ip->i_inode.i_mapping; + int error = filemap_fdatawait(mapping); + if (error == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + else if (error) + set_bit(AS_EIO, &mapping->flags); + } clear_bit(GLF_DIRTY, &gl->gl_flags); gfs2_ail_empty_gl(gl); } @@ -283,14 +232,20 @@ static void inode_go_sync(struct gfs2_glock *gl) static void inode_go_inval(struct gfs2_glock *gl, int flags) { + struct gfs2_inode *ip = gl->gl_object; int meta = (flags & DIO_METADATA); if (meta) { - struct gfs2_inode *ip = gl->gl_object; gfs2_meta_inval(gl); - set_bit(GIF_INVALID, &ip->i_flags); + if (ip) + set_bit(GIF_INVALID, &ip->i_flags); + } + + if (ip && S_ISREG(ip->i_inode.i_mode)) { + truncate_inode_pages(ip->i_inode.i_mapping, 0); + gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages); + clear_bit(GIF_PAGED, &ip->i_flags); } - gfs2_page_inval(gl); } /** diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 0cace3d..6456fc3 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -261,6 +261,12 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) * @sdp: The GFS2 superblock * @blks: The number of blocks to reserve * + * Note that we never give out the last 6 blocks of the journal. Thats + * due to the fact that there is are a small number of header blocks + * associated with each log flush. The exact number can't be known until + * flush time, so we ensure that we have just enough free blocks at all + * times to avoid running out during a log flush. + * * Returns: errno */ @@ -274,7 +280,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) mutex_lock(&sdp->sd_log_reserve_mutex); gfs2_log_lock(sdp); - while(sdp->sd_log_blks_free <= blks) { + while(sdp->sd_log_blks_free <= (blks + 6)) { gfs2_log_unlock(sdp); gfs2_ail1_empty(sdp, 0); gfs2_log_flush(sdp, NULL); @@ -643,12 +649,9 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) up_read(&sdp->sd_log_flush_lock); gfs2_log_lock(sdp); - if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) { - gfs2_log_unlock(sdp); - gfs2_log_flush(sdp, NULL); - } else { - gfs2_log_unlock(sdp); - } + if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) + wake_up_process(sdp->sd_logd_process); + gfs2_log_unlock(sdp); } /** diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 3912d6a..939a09f 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -472,6 +472,9 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height; int in_cache = 0; + BUG_ON(!gl); + BUG_ON(!sdp); + spin_lock(&ip->i_spin); if (*bh_slot && (*bh_slot)->b_blocknr == num) { bh = *bh_slot; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 8635175..7685b46 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -157,7 +157,8 @@ static void gfs2_write_super(struct super_block *sb) static int gfs2_sync_fs(struct super_block *sb, int wait) { sb->s_dirt = 0; - gfs2_log_flush(sb->s_fs_info, NULL); + if (wait) + gfs2_log_flush(sb->s_fs_info, NULL); return 0; } @@ -293,8 +294,6 @@ static void gfs2_clear_inode(struct inode *inode) */ if (inode->i_private) { struct gfs2_inode *ip = GFS2_I(inode); - gfs2_glock_inode_squish(inode); - gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED); ip->i_gl->gl_object = NULL; gfs2_glock_schedule_for_reclaim(ip->i_gl); gfs2_glock_put(ip->i_gl); @@ -395,7 +394,7 @@ static void gfs2_delete_inode(struct inode *inode) if (!inode->i_private) goto out; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh); + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh); if (unlikely(error)) { gfs2_glock_dq_uninit(&ip->i_iopen_gh); goto out; -- cgit v0.10.2 From a25311c8e0b7071b129ca9a9e49e22eeaf620864 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 23 Nov 2006 11:06:35 -0500 Subject: [GFS2] Move gfs2_meta_syncfs() into log.c By moving gfs2_meta_syncfs() into log.c, gfs2_ail1_start() can be made static. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 6456fc3..7713d59 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "gfs2.h" #include "incore.h" @@ -142,7 +143,7 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl return list_empty(&ai->ai_ail1_list); } -void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) +static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) { struct list_head *head = &sdp->sd_ail1_list; u64 sync_gen; @@ -689,3 +690,21 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) up_write(&sdp->sd_log_flush_lock); } + +/** + * gfs2_meta_syncfs - sync all the buffers in a filesystem + * @sdp: the filesystem + * + */ + +void gfs2_meta_syncfs(struct gfs2_sbd *sdp) +{ + gfs2_log_flush(sdp, NULL); + for (;;) { + gfs2_ail1_start(sdp, DIO_ALL); + if (gfs2_ail1_empty(sdp, DIO_ALL)) + break; + msleep(10); + } +} + diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 7f5737d..8e7aa0f 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h @@ -48,7 +48,6 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp, unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, unsigned int ssize); -void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags); int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags); int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); @@ -61,5 +60,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); void gfs2_log_shutdown(struct gfs2_sbd *sdp); +void gfs2_meta_syncfs(struct gfs2_sbd *sdp); #endif /* __LOG_DOT_H__ */ diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 939a09f..fbeba81 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -574,20 +574,3 @@ out: return first_bh; } -/** - * gfs2_meta_syncfs - sync all the buffers in a filesystem - * @sdp: the filesystem - * - */ - -void gfs2_meta_syncfs(struct gfs2_sbd *sdp) -{ - gfs2_log_flush(sdp, NULL); - for (;;) { - gfs2_ail1_start(sdp, DIO_ALL); - if (gfs2_ail1_empty(sdp, DIO_ALL)) - break; - msleep(10); - } -} - diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index 3ec939e..e037425 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h @@ -67,7 +67,6 @@ static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip, } struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); -void gfs2_meta_syncfs(struct gfs2_sbd *sdp); #define buffer_busy(bh) \ ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned))) -- cgit v0.10.2 From cb4c03131836a55bf95e1c165409244ac6b4f39f Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 23 Nov 2006 11:16:32 -0500 Subject: [GFS2] Reduce number of arguments to meta_io.c:getbuf() Since the superblock and the address_space are determined by the glock, we might as well just pass that as the argument since all the callers already have that available. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index fbeba81..0e34d99 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -127,17 +127,17 @@ void gfs2_meta_sync(struct gfs2_glock *gl) /** * getbuf - Get a buffer with a given address space - * @sdp: the filesystem - * @aspace: the address space + * @gl: the glock * @blkno: the block number (filesystem scope) * @create: 1 if the buffer should be created * * Returns: the buffer */ -static struct buffer_head *getbuf(struct gfs2_sbd *sdp, struct inode *aspace, - u64 blkno, int create) +static struct buffer_head *getbuf(struct gfs2_glock *gl, u64 blkno, int create) { + struct address_space *mapping = gl->gl_aspace->i_mapping; + struct gfs2_sbd *sdp = gl->gl_sbd; struct page *page; struct buffer_head *bh; unsigned int shift; @@ -150,13 +150,13 @@ static struct buffer_head *getbuf(struct gfs2_sbd *sdp, struct inode *aspace, if (create) { for (;;) { - page = grab_cache_page(aspace->i_mapping, index); + page = grab_cache_page(mapping, index); if (page) break; yield(); } } else { - page = find_lock_page(aspace->i_mapping, index); + page = find_lock_page(mapping, index); if (!page) return NULL; } @@ -202,7 +202,7 @@ static void meta_prep_new(struct buffer_head *bh) struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) { struct buffer_head *bh; - bh = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); + bh = getbuf(gl, blkno, CREATE); meta_prep_new(bh); return bh; } @@ -220,7 +220,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, struct buffer_head **bhp) { - *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); + *bhp = getbuf(gl, blkno, CREATE); if (!buffer_uptodate(*bhp)) ll_rw_block(READ_META, 1, bhp); if (flags & DIO_WAIT) { @@ -379,11 +379,10 @@ void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct inode *aspace = ip->i_gl->gl_aspace; struct buffer_head *bh; while (blen) { - bh = getbuf(sdp, aspace, bstart, NO_CREATE); + bh = getbuf(ip->i_gl, bstart, NO_CREATE); if (bh) { struct gfs2_bufdata *bd = bh->b_private; @@ -484,7 +483,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, spin_unlock(&ip->i_spin); if (!bh) - bh = getbuf(gl->gl_sbd, gl->gl_aspace, num, CREATE); + bh = getbuf(gl, num, CREATE); if (!bh) return -ENOBUFS; @@ -535,7 +534,6 @@ err: struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) { struct gfs2_sbd *sdp = gl->gl_sbd; - struct inode *aspace = gl->gl_aspace; struct buffer_head *first_bh, *bh; u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >> sdp->sd_sb.sb_bsize_shift; @@ -547,7 +545,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) if (extlen > max_ra) extlen = max_ra; - first_bh = getbuf(sdp, aspace, dblock, CREATE); + first_bh = getbuf(gl, dblock, CREATE); if (buffer_uptodate(first_bh)) goto out; @@ -558,7 +556,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) extlen--; while (extlen) { - bh = getbuf(sdp, aspace, dblock, CREATE); + bh = getbuf(gl, dblock, CREATE); if (!buffer_uptodate(bh) && !buffer_locked(bh)) ll_rw_block(READA, 1, &bh); -- cgit v0.10.2 From 300c7d75f3a5e8edd3e390ccd56b808f3fb14e33 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 27 Nov 2006 09:55:28 -0500 Subject: [GFS2] Fix recursive locking in gfs2_permission Since gfs2_permission may be called either from the VFS (in which case we need to obtain a shared glock) or from GFS2 (in which case we already have a glock) we need to test to see whether or not a lock is required. The original test was buggy due to a potential race. This one should be safe. This fixes Red Hat bugzilla #217129 Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index b247f25..fd9fee2 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -835,6 +835,10 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) * @mask: * @nd: passed from Linux VFS, ignored by us * + * This may be called from the VFS directly, or from within GFS2 with the + * inode locked, so we look to see if the glock is already locked and only + * lock the glock if its not already been done. + * * Returns: errno */ @@ -843,15 +847,18 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder i_gh; int error; + int unlock = 0; - if (!test_bit(GIF_INVALID, &ip->i_flags)) - return generic_permission(inode, mask, gfs2_check_acl); + if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + if (error) + return error; + unlock = 1; + } - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); - if (!error) { - error = generic_permission(inode, mask, gfs2_check_acl_locked); + error = generic_permission(inode, mask, gfs2_check_acl_locked); + if (unlock) gfs2_glock_dq_uninit(&i_gh); - } return error; } -- cgit v0.10.2 From dcf3dd852f554bb0016aa23892596717cc123a26 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 27 Nov 2006 10:12:05 -0500 Subject: [GFS2] Fix recursive locking in gfs2_getattr The readdirplus NFS operation can result in gfs2_getattr being called with the glock already held. In this case we do not want to try and grab the lock again. This fixes Red Hat bugzilla #215727 Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index fd9fee2..fbe38c1 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -992,6 +992,12 @@ out: * @dentry: The dentry to stat * @stat: The inode's stats * + * This may be called from the VFS directly, or from within GFS2 with the + * inode locked, so we look to see if the glock is already locked and only + * lock the glock if its not already been done. Note that its the NFS + * readdirplus operation which causes this to be called (from filldir) + * with the glock already held. + * * Returns: errno */ @@ -1002,14 +1008,20 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int error; + int unlock = 0; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); - if (!error) { - generic_fillattr(inode, stat); - gfs2_glock_dq_uninit(&gh); + if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); + if (error) + return error; + unlock = 1; } - return error; + generic_fillattr(inode, stat); + if (unlock); + gfs2_glock_dq_uninit(&gh); + + return 0; } static int gfs2_setxattr(struct dentry *dentry, const char *name, -- cgit v0.10.2 From 2896ee37ccc1f9acb244c9b02becb74a43661009 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 27 Nov 2006 11:31:22 -0600 Subject: [DLM] fix add_requestqueue checking nodes list Requests that arrive after recovery has started are saved in the requestqueue and processed after recovery is done. Some of these requests are purged during recovery if they are from nodes that have been removed. We move the purging of the requests (dlm_purge_requestqueue) to later in the recovery sequence which allows the routine saving requests (dlm_add_requestqueue) to avoid filtering out requests by nodeid since the same will be done by the purge. The current code has add_requestqueue filtering by nodeid but doesn't hold any locks when accessing the list of current nodes. This also means that we need to call the purge routine when the lockspace is being shut down since the add routine will not be rejecting requests itself any more. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index f8842ca..791388b 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -22,6 +22,7 @@ #include "memory.h" #include "lock.h" #include "recover.h" +#include "requestqueue.h" #ifdef CONFIG_DLM_DEBUG int dlm_create_debug_file(struct dlm_ls *ls); @@ -684,6 +685,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) * Free structures on any other lists */ + dlm_purge_requestqueue(ls); kfree(ls->ls_recover_args); dlm_clear_free_entries(ls); dlm_clear_members(ls); diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 8bb895f..9dc2f91 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c @@ -94,14 +94,6 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) } /* - * Purge directory-related requests that are saved in requestqueue. - * All dir requests from before recovery are invalid now due to the dir - * rebuild and will be resent by the requesting nodes. - */ - - dlm_purge_requestqueue(ls); - - /* * Wait for all nodes to complete directory rebuild. */ @@ -181,6 +173,14 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) dlm_release_root_list(ls); + /* + * Purge directory-related requests that are saved in requestqueue. + * All dir requests from before recovery are invalid now due to the dir + * rebuild and will be resent by the requesting nodes. + */ + + dlm_purge_requestqueue(ls); + dlm_set_recover_status(ls, DLM_RS_DONE); error = dlm_recover_done_wait(ls); if (error) { diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c index 0226d2a..65008d7 100644 --- a/fs/dlm/requestqueue.c +++ b/fs/dlm/requestqueue.c @@ -36,9 +36,6 @@ int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) int length = hd->h_length; int rv = 0; - if (dlm_is_removed(ls, nodeid)) - return 0; - e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL); if (!e) { log_print("dlm_add_requestqueue: out of memory\n"); @@ -133,6 +130,10 @@ static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid) { uint32_t type = ms->m_type; + /* the ls is being cleaned up and freed by release_lockspace */ + if (!ls->ls_count) + return 1; + if (dlm_is_removed(ls, nodeid)) return 1; -- cgit v0.10.2 From aed3255f2267e2d1d95b9cf7f2995ce24e6c873b Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 28 Nov 2006 02:53:22 +0900 Subject: [GFS2] fs/gfs2/log.c:log_bmap() fix printk format warning Fix a printk format warning in fs/gfs2/log.c: fs/gfs2/log.c:322: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type 'sector_t' Signed-off-by: Ryusuke Konishi Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 7713d59..291415d 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -326,7 +326,8 @@ static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) bh_map.b_size = 1 << inode->i_blkbits; error = gfs2_block_map(inode, lbn, 0, &bh_map); if (error || !bh_map.b_blocknr) - printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn); + printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, + (unsigned long long)bh_map.b_blocknr, lbn); gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr); return bh_map.b_blocknr; -- cgit v0.10.2 From 1babdb453138f17b8ed3d1d5711089c4e2fa5ace Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 27 Nov 2006 13:18:41 -0600 Subject: [DLM] fix size of STATUS_REPLY message When the not_ready routine sends a "fake" status reply with blank status flags, it needs to use the correct size for a normal STATUS_REPLY by including the size of the would-be config parameters. We also fill in the non-existant config parameters with an invalid lvblen value so it's easier to notice if these invalid paratmers are ever being used. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 87b12f7..6ac195c 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -370,9 +370,10 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) { struct dlm_rcom *rc; + struct rcom_config *rf; struct dlm_mhandle *mh; char *mb; - int mb_len = sizeof(struct dlm_rcom); + int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb); if (!mh) @@ -391,6 +392,9 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) rc->rc_id = rc_in->rc_id; rc->rc_result = -ESRCH; + rf = (struct rcom_config *) rc->rc_buf; + rf->rf_lvblen = -1; + dlm_rcom_out(rc); dlm_lowcomms_commit_buffer(mh); -- cgit v0.10.2 From 98f176fb32f33795b6d0f83856008b932123ab38 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 27 Nov 2006 13:19:28 -0600 Subject: [DLM] don't accept replies to old recovery messages We often abort a recovery after sending a status request to a remote node. We want to ignore any potential status reply we get from the remote node. If we get one of these unwanted replies, we've often moved on to the next recovery message and incremented the message sequence counter, so the reply will be ignored due to the seq number. In some cases, we've not moved on to the next message so the seq number of the reply we want to ignore is still correct, causing the reply to be accepted. The next recovery message will then mistake this old reply as a new one. To fix this, we add the flag RCOM_WAIT to indicate when we can accept a new reply. We clear this flag if we abort recovery while waiting for a reply. Before the flag is set again (to allow new replies) we know that any old replies will be rejected due to their sequence number. We also initialize the recovery-message sequence number to a random value when a lockspace is first created. This makes it clear when messages are being rejected from an old instance of a lockspace that has since been recreated. Signed-off-by: David Teigland Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 1e5cd67..1ee8195 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -471,6 +471,7 @@ struct dlm_ls { char *ls_recover_buf; int ls_recover_nodeid; /* for debugging */ uint64_t ls_rcom_seq; + spinlock_t ls_rcom_spin; struct list_head ls_recover_list; spinlock_t ls_recover_list_lock; int ls_recover_list_count; @@ -488,7 +489,8 @@ struct dlm_ls { #define LSFL_RUNNING 1 #define LSFL_RECOVERY_STOP 2 #define LSFL_RCOM_READY 3 -#define LSFL_UEVENT_WAIT 4 +#define LSFL_RCOM_WAIT 4 +#define LSFL_UEVENT_WAIT 5 /* much of this is just saving user space pointers associated with the lock that we pass back to the user lib with an ast */ diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 791388b..59012b0 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -479,6 +479,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace, ls->ls_recoverd_task = NULL; mutex_init(&ls->ls_recoverd_active); spin_lock_init(&ls->ls_recover_lock); + spin_lock_init(&ls->ls_rcom_spin); + get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t)); ls->ls_recover_status = 0; ls->ls_recover_seq = 0; ls->ls_recover_args = NULL; diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 6ac195c..c42f2db 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -90,13 +90,28 @@ static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid) return 0; } +static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq) +{ + spin_lock(&ls->ls_rcom_spin); + *new_seq = ++ls->ls_rcom_seq; + set_bit(LSFL_RCOM_WAIT, &ls->ls_flags); + spin_unlock(&ls->ls_rcom_spin); +} + +static void disallow_sync_reply(struct dlm_ls *ls) +{ + spin_lock(&ls->ls_rcom_spin); + clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); + clear_bit(LSFL_RCOM_READY, &ls->ls_flags); + spin_unlock(&ls->ls_rcom_spin); +} + int dlm_rcom_status(struct dlm_ls *ls, int nodeid) { struct dlm_rcom *rc; struct dlm_mhandle *mh; int error = 0; - memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); ls->ls_recover_nodeid = nodeid; if (nodeid == dlm_our_nodeid()) { @@ -108,12 +123,14 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 0, &rc, &mh); if (error) goto out; - rc->rc_id = ++ls->ls_rcom_seq; + + allow_sync_reply(ls, &rc->rc_id); + memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); send_rcom(ls, mh, rc); error = dlm_wait_function(ls, &rcom_response); - clear_bit(LSFL_RCOM_READY, &ls->ls_flags); + disallow_sync_reply(ls); if (error) goto out; @@ -150,14 +167,20 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in) static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) { - if (rc_in->rc_id != ls->ls_rcom_seq) { - log_debug(ls, "reject old reply %d got %llx wanted %llx", - rc_in->rc_type, rc_in->rc_id, ls->ls_rcom_seq); - return; + spin_lock(&ls->ls_rcom_spin); + if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) || + rc_in->rc_id != ls->ls_rcom_seq) { + log_debug(ls, "reject reply %d from %d seq %llx expect %llx", + rc_in->rc_type, rc_in->rc_header.h_nodeid, + rc_in->rc_id, ls->ls_rcom_seq); + goto out; } memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length); set_bit(LSFL_RCOM_READY, &ls->ls_flags); + clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); wake_up(&ls->ls_wait_general); + out: + spin_unlock(&ls->ls_rcom_spin); } static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) @@ -171,7 +194,6 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) struct dlm_mhandle *mh; int error = 0, len = sizeof(struct dlm_rcom); - memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); ls->ls_recover_nodeid = nodeid; if (nodeid == dlm_our_nodeid()) { @@ -185,12 +207,14 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) if (error) goto out; memcpy(rc->rc_buf, last_name, last_len); - rc->rc_id = ++ls->ls_rcom_seq; + + allow_sync_reply(ls, &rc->rc_id); + memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); send_rcom(ls, mh, rc); error = dlm_wait_function(ls, &rcom_response); - clear_bit(LSFL_RCOM_READY, &ls->ls_flags); + disallow_sync_reply(ls); out: return error; } -- cgit v0.10.2 From 0ac230699a0f3f0d15ad4e4ad99446dac5b4a21f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 28 Nov 2006 22:29:19 -0800 Subject: [GFS2] lock function parameter Fix function parameter typing: fs/gfs2/glock.c:100: warning: function declaration isn't a prototype Signed-off-by: Randy Dunlap Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 3c2ff81..f130f98 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -96,7 +96,7 @@ static inline rwlock_t *gl_lock_addr(unsigned int x) return &gl_hash_locks[x & (GL_HASH_LOCK_SZ-1)]; } #else /* not SMP, so no spinlocks required */ -static inline rwlock_t *gl_lock_addr(x) +static inline rwlock_t *gl_lock_addr(unsigned int x) { return NULL; } -- cgit v0.10.2 From 57adf7eede38d315e0e328c52484d6a596e9a238 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 29 Nov 2006 09:33:48 -0500 Subject: [DLM] fix format warnings in rcom.c and recoverd.c This fixes the following gcc warnings generated on the architectures where uint64_t != unsigned long long (e.g. ppc64). fs/dlm/rcom.c:154: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'uint64_t' fs/dlm/rcom.c:154: warning: format '%llx' expects type 'long long unsigned int', but argument 5 has type 'uint64_t' fs/dlm/recoverd.c:48: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'uint64_t' fs/dlm/recoverd.c:202: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'uint64_t' fs/dlm/recoverd.c:210: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'uint64_t' Signed-off-by: Ryusuke Konishi Signed-off-by: Patrick Caulfield Signed-off-by: Steven Whitehouse diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index c42f2db..4cc31be 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -172,7 +172,8 @@ static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) rc_in->rc_id != ls->ls_rcom_seq) { log_debug(ls, "reject reply %d from %d seq %llx expect %llx", rc_in->rc_type, rc_in->rc_header.h_nodeid, - rc_in->rc_id, ls->ls_rcom_seq); + (unsigned long long)rc_in->rc_id, + (unsigned long long)ls->ls_rcom_seq); goto out; } memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length); diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 9dc2f91..650536aa 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c @@ -45,7 +45,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) unsigned long start; int error, neg = 0; - log_debug(ls, "recover %llx", rv->seq); + log_debug(ls, "recover %llx", (unsigned long long)rv->seq); mutex_lock(&ls->ls_recoverd_active); @@ -212,7 +212,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) dlm_astd_wake(); - log_debug(ls, "recover %llx done: %u ms", rv->seq, + log_debug(ls, "recover %llx done: %u ms", + (unsigned long long)rv->seq, jiffies_to_msecs(jiffies - start)); mutex_unlock(&ls->ls_recoverd_active); @@ -220,7 +221,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) fail: dlm_release_root_list(ls); - log_debug(ls, "recover %llx error %d", rv->seq, error); + log_debug(ls, "recover %llx error %d", + (unsigned long long)rv->seq, error); mutex_unlock(&ls->ls_recoverd_active); return error; } -- cgit v0.10.2 From 77386e1f662f104680da7885d32e068e4b11b882 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 29 Nov 2006 10:41:49 -0500 Subject: [GFS2] Remove gfs2_check_acl() As pointed out by Adrian Bunk, the gfs2_check_acl() function is no longer used. This patch removes it and renamed gfs2_check_acl_locked() to gfs2_check_acl() since we only need one variant of that function now. Signed-off-by: Steven Whitehouse Cc: Adrian Bunk diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 3908992..6e80844 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -145,14 +145,14 @@ out: } /** - * gfs2_check_acl_locked - Check an ACL to see if we're allowed to do something + * gfs2_check_acl - Check an ACL to see if we're allowed to do something * @inode: the file we want to do something to * @mask: what we want to do * * Returns: errno */ -int gfs2_check_acl_locked(struct inode *inode, int mask) +int gfs2_check_acl(struct inode *inode, int mask) { struct posix_acl *acl = NULL; int error; @@ -170,21 +170,6 @@ int gfs2_check_acl_locked(struct inode *inode, int mask) return -EAGAIN; } -int gfs2_check_acl(struct inode *inode, int mask) -{ - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_holder i_gh; - int error; - - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); - if (!error) { - error = gfs2_check_acl_locked(inode, mask); - gfs2_glock_dq_uninit(&i_gh); - } - - return error; -} - static int munge_mode(struct gfs2_inode *ip, mode_t mode) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index 05c294f..6751930 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h @@ -31,7 +31,6 @@ int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, struct gfs2_ea_request *er, int *remove, mode_t *mode); int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access); -int gfs2_check_acl_locked(struct inode *inode, int mask); int gfs2_check_acl(struct inode *inode, int mask); int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index fbe38c1..636dda4 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -856,7 +856,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) unlock = 1; } - error = generic_permission(inode, mask, gfs2_check_acl_locked); + error = generic_permission(inode, mask, gfs2_check_acl); if (unlock) gfs2_glock_dq_uninit(&i_gh); -- cgit v0.10.2 From 0da3585e1ef650d3224b4d6f9799558d1d99fa1e Mon Sep 17 00:00:00 2001 From: Srinivasa Ds Date: Thu, 30 Nov 2006 15:04:55 +0530 Subject: [GFS2] Mount problem with the GFS2 code While mounting the gfs2 filesystem,our test team had a problem and we got this error message. ======================================================= GFS2: fsid=: Trying to join cluster "lock_nolock", "dasde1" GFS2: fsid=dasde1.0: Joined cluster. Now mounting FS... GFS2: not a GFS2 filesystem GFS2: fsid=dasde1.0: can't read superblock: -22 ========================================================================== On debugging further we found that problem is while reading the super block(gfs2_read_super) and comparing the magic number in it. When I replace the submit_bio() call(present in gfs2_read_super) with the sb_getblk() and ll_rw_block(), mount operation succeded. On further analysis we found that before calling submit_bio(), bio->bi_sector was set to "sector" variable. This "sector" variable has the same value of bh->b_blocknr(block number). Hence there is a need to multiply this valuwith (blocksize >> 9)(9 because,sector size 2^9,samething happens in ll_rw_block also, before calling submit_bio()). So I have developed the patch which solves this problem. Please let me know your comments. ================================================================ Signed-off-by: Srinivasa DS Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 1408c5f..3b22727 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -199,7 +199,7 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector) return NULL; } - bio->bi_sector = sector; + bio->bi_sector = sector * (sb->s_blocksize >> 9); bio->bi_bdev = sb->s_bdev; bio_add_page(bio, page, PAGE_SIZE, 0); -- cgit v0.10.2 From aac1a3c77a46c2d06f297641760dd740ac2a84af Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 30 Nov 2006 10:02:19 -0500 Subject: [GFS2] Add a comment about reading the super block The comment explains why we use the bio functions to read the super block. Signed-off-by: Steven Whitehouse Cc: Andrew Morton Cc: Srinivasa Ds diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 3b22727..43a24f2 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -180,6 +180,24 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) return 0; } +/** + * gfs2_read_super - Read the gfs2 super block from disk + * @sb: The VFS super block + * @sector: The location of the super block + * + * This uses the bio functions to read the super block from disk + * because we want to be 100% sure that we never read cached data. + * A super block is read twice only during each GFS2 mount and is + * never written to by the filesystem. The first time its read no + * locks are held, and the only details which are looked at are those + * relating to the locking protocol. Once locking is up and working, + * the sb is read again under the lock to establish the location of + * the master directory (contains pointers to journals etc) and the + * root directory. + * + * Returns: A page containing the sb or NULL + */ + struct page *gfs2_read_super(struct super_block *sb, sector_t sector) { struct page *page; -- cgit v0.10.2 From 33c3de32872ef3c075e4dac04c0de8f86ac39f6f Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 30 Nov 2006 10:14:32 -0500 Subject: [GFS2] Don't flush everything on fdatasync The gfs2_fsync() function was doing a journal flush on each and every call. While this is correct, its also a lot of overhead. This patch means that on fdatasync flushes we rely on the VFS to flush the data for us and we don't do a journal flush unless we really need to. We have to do a journal flush for stuffed files though because they have the data and the inode metadata in the same block. Journaled files also need a journal flush too of course. Signed-off-by: Steven Whitehouse diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index c2be216..7bd971b 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "gfs2.h" @@ -503,16 +504,39 @@ static int gfs2_close(struct inode *inode, struct file *file) * @file: the file that points to the dentry (we ignore this) * @dentry: the dentry that points to the inode to sync * + * The VFS will flush "normal" data for us. We only need to worry + * about metadata here. For journaled data, we just do a log flush + * as we can't avoid it. Otherwise we can just bale out if datasync + * is set. For stuffed inodes we must flush the log in order to + * ensure that all data is on disk. + * * Returns: errno */ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) { - struct gfs2_inode *ip = GFS2_I(dentry->d_inode); + struct inode *inode = dentry->d_inode; + int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); + int ret = 0; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 0, + }; + + if (gfs2_is_jdata(GFS2_I(inode))) { + gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); + return 0; + } - gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); + if (sync_state != 0) { + if (!datasync) + ret = sync_inode(inode, &wbc); - return 0; + if (gfs2_is_stuffed(GFS2_I(inode))) + gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); + } + + return ret; } /** -- cgit v0.10.2 From 4e4e520fd52cfdcc7232c4762a78016e7656cad2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 22:42:20 +0000 Subject: [ARM] Fix Versatile PB initialisation to use .init_machine There's no point having the Versatile PB initialisation using an arch_initcall() and then checking whether it's running on a Versatile PB board - this is what the .init_machine function pointer in the machine description is for. Use it. Signed-off-by: Russell King diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index 503725b..be439bb 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -81,22 +81,18 @@ static struct amba_device *amba_devs[] __initdata = { &mmc1_device, }; -static int __init versatile_pb_init(void) +static void __init versatile_pb_init(void) { int i; - if (machine_is_versatile_pb()) { - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - } - } + versatile_init(); - return 0; + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } } -arch_initcall(versatile_pb_init); - MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .phys_io = 0x101f1000, @@ -105,5 +101,5 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .map_io = versatile_map_io, .init_irq = versatile_init_irq, .timer = &versatile_timer, - .init_machine = versatile_init, + .init_machine = versatile_pb_init, MACHINE_END -- cgit v0.10.2 From 20127f6863990e1313178debe8c9cfe32d43b1dc Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 09:33:53 +0100 Subject: [ARM] 3945/1: AT91: Rename devices.c This patch renames the arch/arm/mach-at91rm9200/devices.c file to at91rm9200_devices.c. The file contains AT91RM9200-specific code, so we will need separate files for the SAM9 processors. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index c174805..568d8d7 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := clock.o irq.o gpio.o devices.o +obj-y := clock.o irq.o gpio.o obj-m := obj-n := obj- := @@ -10,7 +10,7 @@ obj- := obj-$(CONFIG_PM) += pm.o # CPU-specific support -obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o +obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.c obj-$(CONFIG_ARCH_AT91SAM9260) += obj-$(CONFIG_ARCH_AT91SAM9261) += diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c new file mode 100644 index 0000000..2b3a236 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c @@ -0,0 +1,813 @@ +/* + * arch/arm/mach-at91rm9200/at91rm9200_devices.c + * + * Copyright (C) 2005 Thibaut VARENE + * Copyright (C) 2005 David Brownell + * + * 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 "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource at91_usbh_resources[] = { + [0] = { + .start = AT91RM9200_UHP_BASE, + .end = AT91RM9200_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_UHP, + .end = AT91RM9200_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = at91_usbh_resources, + .num_resources = ARRAY_SIZE(at91_usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91rm9200_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource at91_udc_resources[] = { + [0] = { + .start = AT91RM9200_BASE_UDP, + .end = AT91RM9200_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_UDP, + .end = AT91RM9200_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = at91_udc_resources, + .num_resources = ARRAY_SIZE(at91_udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + if (data->pullup_pin) + at91_set_gpio_output(data->pullup_pin, 0); + + udc_data = *data; + platform_device_register(&at91rm9200_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct at91_eth_data eth_data; + +static struct resource at91_eth_resources[] = { + [0] = { + .start = AT91_VA_BASE_EMAC, + .end = AT91_VA_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_EMAC, + .end = AT91RM9200_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_eth_device = { + .name = "at91_ether", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .resource = at91_eth_resources, + .num_resources = ARRAY_SIZE(at91_eth_resources), +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* EMDC */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA11, 0); /* ECRS_ECRSDV */ + at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA9, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA8, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* ETXCK_EREFCK */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PB19, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PB18, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PB17, 0); /* ERXDV */ + at91_set_B_periph(AT91_PIN_PB16, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PB15, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PB14, 0); /* ETXER */ + at91_set_B_periph(AT91_PIN_PB13, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PB12, 0); /* ETX2 */ + } + + eth_data = *data; + platform_device_register(&at91rm9200_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Compact Flash / PCMCIA + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) +static struct at91_cf_data cf_data; + +static struct resource at91_cf_resources[] = { + [0] = { + .start = AT91_CF_BASE, + /* ties up CS4, CS5 and CS6 */ + .end = AT91_CF_BASE + (0x30000000 - 1), + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + }, +}; + +static struct platform_device at91rm9200_cf_device = { + .name = "at91_cf", + .id = -1, + .dev = { + .platform_data = &cf_data, + }, + .resource = at91_cf_resources, + .num_resources = ARRAY_SIZE(at91_cf_resources), +}; + +void __init at91_add_device_cf(struct at91_cf_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->irq_pin) { + at91_set_gpio_input(data->irq_pin, 1); + at91_set_deglitch(data->irq_pin, 1); + } + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + + /* outputs, initially off */ + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + at91_set_gpio_output(data->rst_pin, 0); + + /* force poweron defaults for these pins ... */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ + at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + + cf_data = *data; + platform_device_register(&at91rm9200_cf_device); +} +#else +void __init at91_add_device_cf(struct at91_cf_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource at91_mmc_resources[] = { + [0] = { + .start = AT91RM9200_BASE_MCI, + .end = AT91RM9200_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_MCI, + .end = AT91RM9200_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = at91_mmc_resources, + .num_resources = ARRAY_SIZE(at91_mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA27, 0); + + if (data->is_b) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA8, 0); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA9, 0); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA10, 0); + at91_set_B_periph(AT91_PIN_PA11, 0); + at91_set_B_periph(AT91_PIN_PA12, 0); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA28, 0); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA29, 0); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PB3, 0); + at91_set_B_periph(AT91_PIN_PB4, 0); + at91_set_B_periph(AT91_PIN_PB5, 0); + } + } + + mmc_data = *data; + platform_device_register(&at91rm9200_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +static struct resource at91_nand_resources[] = { + { + .start = AT91_SMARTMEDIA_BASE, + .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = at91_nand_resources, + .num_resources = ARRAY_SIZE(at91_nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + if (!data) + return; + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */ + at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ + + nand_data = *data; + platform_device_register(&at91_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +static struct platform_device at91rm9200_twi_device = { + .name = "at91_i2c", + .id = -1, + .num_resources = 0, +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA25, 1); + + at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA26, 1); + + platform_device_register(&at91rm9200_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource at91_spi_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SPI, + .end = AT91RM9200_BASE_SPI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SPI, + .end = AT91RM9200_ID_SPI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_spi_device = { + .name = "at91_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = at91_spi_resources, + .num_resources = ARRAY_SIZE(at91_spi_resources), +}; + +static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + + at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */ + + /* Enable SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else + cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + +#ifdef CONFIG_SPI_AT91_MANUAL_CS + at91_set_gpio_output(cs_pin, 1); +#else + at91_set_A_periph(cs_pin, 0); +#endif + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + platform_device_register(&at91rm9200_spi_device); +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * RTC + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) +static struct platform_device at91rm9200_rtc_device = { + .name = "at91_rtc", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_rtc(void) +{ + platform_device_register(&at91rm9200_rtc_device); +} +#else +static void __init at91_add_device_rtc(void) {} +#endif + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +static struct platform_device at91rm9200_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91rm9200_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91rm9200_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91RM9200_BASE_US0, + .end = AT91RM9200_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_US0, + .end = AT91RM9200_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ + + /* + * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. + * We need to drive the pin manually. Default is off (RTS is active low). + */ + at91_set_gpio_output(AT91_PIN_PA21, 1); +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91RM9200_BASE_US1, + .end = AT91RM9200_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_US1, + .end = AT91RM9200_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ + at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91RM9200_BASE_US2, + .end = AT91RM9200_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_US2, + .end = AT91RM9200_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91RM9200_BASE_US3, + .end = AT91RM9200_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_US3, + .end = AT91RM9200_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart3_device = { + .name = "atmel_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ + at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91rm9200_uart0_device; + at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91rm9200_uart1_device; + at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91rm9200_uart2_device; + at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91rm9200_uart3_device; + at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); + break; + case 4: + configure_dbgu_pins(); + at91_uarts[i] = &at91rm9200_dbgu_device; + at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + at91_add_device_rtc(); + at91_add_device_watchdog(); + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c deleted file mode 100644 index 0598243..0000000 --- a/arch/arm/mach-at91rm9200/devices.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * arch/arm/mach-at91rm9200/devices.c - * - * Copyright (C) 2005 Thibaut VARENE - * Copyright (C) 2005 David Brownell - * - * 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 "generic.h" - -#define SZ_512 0x00000200 -#define SZ_256 0x00000100 -#define SZ_16 0x00000010 - -/* -------------------------------------------------------------------- - * USB Host - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) -static u64 ohci_dmamask = 0xffffffffUL; -static struct at91_usbh_data usbh_data; - -static struct resource at91_usbh_resources[] = { - [0] = { - .start = AT91RM9200_UHP_BASE, - .end = AT91RM9200_UHP_BASE + SZ_1M - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_UHP, - .end = AT91RM9200_ID_UHP, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91rm9200_usbh_device = { - .name = "at91_ohci", - .id = -1, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0xffffffff, - .platform_data = &usbh_data, - }, - .resource = at91_usbh_resources, - .num_resources = ARRAY_SIZE(at91_usbh_resources), -}; - -void __init at91_add_device_usbh(struct at91_usbh_data *data) -{ - if (!data) - return; - - usbh_data = *data; - platform_device_register(&at91rm9200_usbh_device); -} -#else -void __init at91_add_device_usbh(struct at91_usbh_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * USB Device (Gadget) - * -------------------------------------------------------------------- */ - -#ifdef CONFIG_USB_GADGET_AT91 -static struct at91_udc_data udc_data; - -static struct resource at91_udc_resources[] = { - [0] = { - .start = AT91RM9200_BASE_UDP, - .end = AT91RM9200_BASE_UDP + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_UDP, - .end = AT91RM9200_ID_UDP, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91rm9200_udc_device = { - .name = "at91_udc", - .id = -1, - .dev = { - .platform_data = &udc_data, - }, - .resource = at91_udc_resources, - .num_resources = ARRAY_SIZE(at91_udc_resources), -}; - -void __init at91_add_device_udc(struct at91_udc_data *data) -{ - if (!data) - return; - - if (data->vbus_pin) { - at91_set_gpio_input(data->vbus_pin, 0); - at91_set_deglitch(data->vbus_pin, 1); - } - if (data->pullup_pin) - at91_set_gpio_output(data->pullup_pin, 0); - - udc_data = *data; - platform_device_register(&at91rm9200_udc_device); -} -#else -void __init at91_add_device_udc(struct at91_udc_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * Ethernet - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE) -static u64 eth_dmamask = 0xffffffffUL; -static struct at91_eth_data eth_data; - -static struct resource at91_eth_resources[] = { - [0] = { - .start = AT91_VA_BASE_EMAC, - .end = AT91_VA_BASE_EMAC + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_EMAC, - .end = AT91RM9200_ID_EMAC, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91rm9200_eth_device = { - .name = "at91_ether", - .id = -1, - .dev = { - .dma_mask = ð_dmamask, - .coherent_dma_mask = 0xffffffff, - .platform_data = ð_data, - }, - .resource = at91_eth_resources, - .num_resources = ARRAY_SIZE(at91_eth_resources), -}; - -void __init at91_add_device_eth(struct at91_eth_data *data) -{ - if (!data) - return; - - if (data->phy_irq_pin) { - at91_set_gpio_input(data->phy_irq_pin, 0); - at91_set_deglitch(data->phy_irq_pin, 1); - } - - /* Pins used for MII and RMII */ - at91_set_A_periph(AT91_PIN_PA16, 0); /* EMDIO */ - at91_set_A_periph(AT91_PIN_PA15, 0); /* EMDC */ - at91_set_A_periph(AT91_PIN_PA14, 0); /* ERXER */ - at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */ - at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */ - at91_set_A_periph(AT91_PIN_PA11, 0); /* ECRS_ECRSDV */ - at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX1 */ - at91_set_A_periph(AT91_PIN_PA9, 0); /* ETX0 */ - at91_set_A_periph(AT91_PIN_PA8, 0); /* ETXEN */ - at91_set_A_periph(AT91_PIN_PA7, 0); /* ETXCK_EREFCK */ - - if (!data->is_rmii) { - at91_set_B_periph(AT91_PIN_PB19, 0); /* ERXCK */ - at91_set_B_periph(AT91_PIN_PB18, 0); /* ECOL */ - at91_set_B_periph(AT91_PIN_PB17, 0); /* ERXDV */ - at91_set_B_periph(AT91_PIN_PB16, 0); /* ERX3 */ - at91_set_B_periph(AT91_PIN_PB15, 0); /* ERX2 */ - at91_set_B_periph(AT91_PIN_PB14, 0); /* ETXER */ - at91_set_B_periph(AT91_PIN_PB13, 0); /* ETX3 */ - at91_set_B_periph(AT91_PIN_PB12, 0); /* ETX2 */ - } - - eth_data = *data; - platform_device_register(&at91rm9200_eth_device); -} -#else -void __init at91_add_device_eth(struct at91_eth_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * Compact Flash / PCMCIA - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) -static struct at91_cf_data cf_data; - -static struct resource at91_cf_resources[] = { - [0] = { - .start = AT91_CF_BASE, - /* ties up CS4, CS5 and CS6 */ - .end = AT91_CF_BASE + (0x30000000 - 1), - .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, - }, -}; - -static struct platform_device at91rm9200_cf_device = { - .name = "at91_cf", - .id = -1, - .dev = { - .platform_data = &cf_data, - }, - .resource = at91_cf_resources, - .num_resources = ARRAY_SIZE(at91_cf_resources), -}; - -void __init at91_add_device_cf(struct at91_cf_data *data) -{ - if (!data) - return; - - /* input/irq */ - if (data->irq_pin) { - at91_set_gpio_input(data->irq_pin, 1); - at91_set_deglitch(data->irq_pin, 1); - } - at91_set_gpio_input(data->det_pin, 1); - at91_set_deglitch(data->det_pin, 1); - - /* outputs, initially off */ - if (data->vcc_pin) - at91_set_gpio_output(data->vcc_pin, 0); - at91_set_gpio_output(data->rst_pin, 0); - - /* force poweron defaults for these pins ... */ - at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ - at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ - at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ - at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ - - cf_data = *data; - platform_device_register(&at91rm9200_cf_device); -} -#else -void __init at91_add_device_cf(struct at91_cf_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * MMC / SD - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) -static u64 mmc_dmamask = 0xffffffffUL; -static struct at91_mmc_data mmc_data; - -static struct resource at91_mmc_resources[] = { - [0] = { - .start = AT91RM9200_BASE_MCI, - .end = AT91RM9200_BASE_MCI + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_MCI, - .end = AT91RM9200_ID_MCI, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91rm9200_mmc_device = { - .name = "at91_mci", - .id = -1, - .dev = { - .dma_mask = &mmc_dmamask, - .coherent_dma_mask = 0xffffffff, - .platform_data = &mmc_data, - }, - .resource = at91_mmc_resources, - .num_resources = ARRAY_SIZE(at91_mmc_resources), -}; - -void __init at91_add_device_mmc(struct at91_mmc_data *data) -{ - if (!data) - return; - - /* input/irq */ - if (data->det_pin) { - at91_set_gpio_input(data->det_pin, 1); - at91_set_deglitch(data->det_pin, 1); - } - if (data->wp_pin) - at91_set_gpio_input(data->wp_pin, 1); - - /* CLK */ - at91_set_A_periph(AT91_PIN_PA27, 0); - - if (data->is_b) { - /* CMD */ - at91_set_B_periph(AT91_PIN_PA8, 0); - - /* DAT0, maybe DAT1..DAT3 */ - at91_set_B_periph(AT91_PIN_PA9, 0); - if (data->wire4) { - at91_set_B_periph(AT91_PIN_PA10, 0); - at91_set_B_periph(AT91_PIN_PA11, 0); - at91_set_B_periph(AT91_PIN_PA12, 0); - } - } else { - /* CMD */ - at91_set_A_periph(AT91_PIN_PA28, 0); - - /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA29, 0); - if (data->wire4) { - at91_set_B_periph(AT91_PIN_PB3, 0); - at91_set_B_periph(AT91_PIN_PB4, 0); - at91_set_B_periph(AT91_PIN_PB5, 0); - } - } - - mmc_data = *data; - platform_device_register(&at91rm9200_mmc_device); -} -#else -void __init at91_add_device_mmc(struct at91_mmc_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * NAND / SmartMedia - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; - -static struct resource at91_nand_resources[] = { - { - .start = AT91_SMARTMEDIA_BASE, - .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, - .flags = IORESOURCE_MEM, - } -}; - -static struct platform_device at91_nand_device = { - .name = "at91_nand", - .id = -1, - .dev = { - .platform_data = &nand_data, - }, - .resource = at91_nand_resources, - .num_resources = ARRAY_SIZE(at91_nand_resources), -}; - -void __init at91_add_device_nand(struct at91_nand_data *data) -{ - if (!data) - return; - - /* enable pin */ - if (data->enable_pin) - at91_set_gpio_output(data->enable_pin, 1); - - /* ready/busy pin */ - if (data->rdy_pin) - at91_set_gpio_input(data->rdy_pin, 1); - - /* card detect pin */ - if (data->det_pin) - at91_set_gpio_input(data->det_pin, 1); - - at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */ - at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ - - nand_data = *data; - platform_device_register(&at91_nand_device); -} -#else -void __init at91_add_device_nand(struct at91_nand_data *data) {} -#endif - - -/* -------------------------------------------------------------------- - * TWI (i2c) - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) -static struct platform_device at91rm9200_twi_device = { - .name = "at91_i2c", - .id = -1, - .num_resources = 0, -}; - -void __init at91_add_device_i2c(void) -{ - /* pins used for TWI interface */ - at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */ - at91_set_multi_drive(AT91_PIN_PA25, 1); - - at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */ - at91_set_multi_drive(AT91_PIN_PA26, 1); - - platform_device_register(&at91rm9200_twi_device); -} -#else -void __init at91_add_device_i2c(void) {} -#endif - - -/* -------------------------------------------------------------------- - * SPI - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) -static u64 spi_dmamask = 0xffffffffUL; - -static struct resource at91_spi_resources[] = { - [0] = { - .start = AT91RM9200_BASE_SPI, - .end = AT91RM9200_BASE_SPI + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_SPI, - .end = AT91RM9200_ID_SPI, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91rm9200_spi_device = { - .name = "at91_spi", - .id = 0, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .resource = at91_spi_resources, - .num_resources = ARRAY_SIZE(at91_spi_resources), -}; - -static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; - -void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) -{ - int i; - unsigned long cs_pin; - - at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */ - at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */ - at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */ - - /* Enable SPI chip-selects */ - for (i = 0; i < nr_devices; i++) { - if (devices[i].controller_data) - cs_pin = (unsigned long) devices[i].controller_data; - else - cs_pin = at91_spi_standard_cs[devices[i].chip_select]; - -#ifdef CONFIG_SPI_AT91_MANUAL_CS - at91_set_gpio_output(cs_pin, 1); -#else - at91_set_A_periph(cs_pin, 0); -#endif - - /* pass chip-select pin to driver */ - devices[i].controller_data = (void *) cs_pin; - } - - spi_register_board_info(devices, nr_devices); - at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); - platform_device_register(&at91rm9200_spi_device); -} -#else -void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} -#endif - - -/* -------------------------------------------------------------------- - * RTC - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) -static struct platform_device at91rm9200_rtc_device = { - .name = "at91_rtc", - .id = -1, - .num_resources = 0, -}; - -static void __init at91_add_device_rtc(void) -{ - platform_device_register(&at91rm9200_rtc_device); -} -#else -static void __init at91_add_device_rtc(void) {} -#endif - - -/* -------------------------------------------------------------------- - * Watchdog - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) -static struct platform_device at91rm9200_wdt_device = { - .name = "at91_wdt", - .id = -1, - .num_resources = 0, -}; - -static void __init at91_add_device_watchdog(void) -{ - platform_device_register(&at91rm9200_wdt_device); -} -#else -static void __init at91_add_device_watchdog(void) {} -#endif - - -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - -/* -------------------------------------------------------------------- - * UART - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_SERIAL_ATMEL) -static struct resource dbgu_resources[] = { - [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91_ID_SYS, - .end = AT91_ID_SYS, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct atmel_uart_data dbgu_data = { - .use_dma_tx = 0, - .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), -}; - -static struct platform_device at91rm9200_dbgu_device = { - .name = "atmel_usart", - .id = 0, - .dev = { - .platform_data = &dbgu_data, - .coherent_dma_mask = 0xffffffff, - }, - .resource = dbgu_resources, - .num_resources = ARRAY_SIZE(dbgu_resources), -}; - -static inline void configure_dbgu_pins(void) -{ - at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */ - at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */ -} - -static struct resource uart0_resources[] = { - [0] = { - .start = AT91RM9200_BASE_US0, - .end = AT91RM9200_BASE_US0 + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_US0, - .end = AT91RM9200_ID_US0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct atmel_uart_data uart0_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; - -static struct platform_device at91rm9200_uart0_device = { - .name = "atmel_usart", - .id = 1, - .dev = { - .platform_data = &uart0_data, - .coherent_dma_mask = 0xffffffff, - }, - .resource = uart0_resources, - .num_resources = ARRAY_SIZE(uart0_resources), -}; - -static inline void configure_usart0_pins(void) -{ - at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ - at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ - - /* - * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. - * We need to drive the pin manually. Default is off (RTS is active low). - */ - at91_set_gpio_output(AT91_PIN_PA21, 1); -} - -static struct resource uart1_resources[] = { - [0] = { - .start = AT91RM9200_BASE_US1, - .end = AT91RM9200_BASE_US1 + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_US1, - .end = AT91RM9200_ID_US1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct atmel_uart_data uart1_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; - -static struct platform_device at91rm9200_uart1_device = { - .name = "atmel_usart", - .id = 2, - .dev = { - .platform_data = &uart1_data, - .coherent_dma_mask = 0xffffffff, - }, - .resource = uart1_resources, - .num_resources = ARRAY_SIZE(uart1_resources), -}; - -static inline void configure_usart1_pins(void) -{ - at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ - at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ - at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ - at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ - at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ - at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ - at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ - at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ -} - -static struct resource uart2_resources[] = { - [0] = { - .start = AT91RM9200_BASE_US2, - .end = AT91RM9200_BASE_US2 + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_US2, - .end = AT91RM9200_ID_US2, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct atmel_uart_data uart2_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; - -static struct platform_device at91rm9200_uart2_device = { - .name = "atmel_usart", - .id = 3, - .dev = { - .platform_data = &uart2_data, - .coherent_dma_mask = 0xffffffff, - }, - .resource = uart2_resources, - .num_resources = ARRAY_SIZE(uart2_resources), -}; - -static inline void configure_usart2_pins(void) -{ - at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ - at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ -} - -static struct resource uart3_resources[] = { - [0] = { - .start = AT91RM9200_BASE_US3, - .end = AT91RM9200_BASE_US3 + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91RM9200_ID_US3, - .end = AT91RM9200_ID_US3, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct atmel_uart_data uart3_data = { - .use_dma_tx = 1, - .use_dma_rx = 1, -}; - -static struct platform_device at91rm9200_uart3_device = { - .name = "atmel_usart", - .id = 4, - .dev = { - .platform_data = &uart3_data, - .coherent_dma_mask = 0xffffffff, - }, - .resource = uart3_resources, - .num_resources = ARRAY_SIZE(uart3_resources), -}; - -static inline void configure_usart3_pins(void) -{ - at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ - at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ -} - -struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ -struct platform_device *atmel_default_console_device; /* the serial console device */ - -void __init at91_init_serial(struct at91_uart_config *config) -{ - int i; - - /* Fill in list of supported UARTs */ - for (i = 0; i < config->nr_tty; i++) { - switch (config->tty_map[i]) { - case 0: - configure_usart0_pins(); - at91_uarts[i] = &at91rm9200_uart0_device; - at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); - break; - case 1: - configure_usart1_pins(); - at91_uarts[i] = &at91rm9200_uart1_device; - at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); - break; - case 2: - configure_usart2_pins(); - at91_uarts[i] = &at91rm9200_uart2_device; - at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); - break; - case 3: - configure_usart3_pins(); - at91_uarts[i] = &at91rm9200_uart3_device; - at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); - break; - case 4: - configure_dbgu_pins(); - at91_uarts[i] = &at91rm9200_dbgu_device; - at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart"); - break; - default: - continue; - } - at91_uarts[i]->id = i; /* update ID number to mapped ID */ - } - - /* Set serial console device */ - if (config->console_tty < ATMEL_MAX_UART) - atmel_default_console_device = at91_uarts[config->console_tty]; - if (!atmel_default_console_device) - printk(KERN_INFO "AT91: No default serial console defined.\n"); -} - -void __init at91_add_device_serial(void) -{ - int i; - - for (i = 0; i < ATMEL_MAX_UART; i++) { - if (at91_uarts[i]) - platform_device_register(at91_uarts[i]); - } -} -#else -void __init at91_init_serial(struct at91_uart_config *config) {} -void __init at91_add_device_serial(void) {} -#endif - - -/* -------------------------------------------------------------------- */ - -/* - * These devices are always present and don't need any board-specific - * setup. - */ -static int __init at91_add_standard_devices(void) -{ - at91_add_device_rtc(); - at91_add_device_watchdog(); - return 0; -} - -arch_initcall(at91_add_standard_devices); -- cgit v0.10.2 From 1f4fd0a0d28fabf965815755f1a74ef91dfb5ca6 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 10:01:47 +0100 Subject: [ARM] 3946/1: AT91: at91_arch_reset and at91_extern_irq The external interrupt sources are different on the various AT91 processors. This patch introduces the global 'at91_extern_irq' variable that contains a bitset of the available external interrupt sources. The processor reset mechanism also differs on the various AT91 processors. This patch also adds a global 'at91_arch_reset' callback (from system.h) into the processor-specific code to perform the reset. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c index dcf6136..0422593 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -14,6 +14,7 @@ #include #include +#include #include #include "generic.h" @@ -222,6 +223,16 @@ static struct at91_gpio_bank at91rm9200_gpio[] = { } }; +static void at91rm9200_reset(void) +{ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + + /* -------------------------------------------------------------------- * AT91RM9200 processor initialization * -------------------------------------------------------------------- */ @@ -230,6 +241,12 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks /* Map peripherals */ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); + at91_arch_reset = at91rm9200_reset; + at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) + | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) + | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) + | (1 << AT91RM9200_ID_IRQ6); + /* Init clock subsystem */ at91_clock_init(main_clock); diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 694e411..fd98e35 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -39,3 +39,6 @@ struct at91_gpio_bank { }; extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); extern void __init at91_gpio_irq_setup(void); + +extern void (*at91_arch_reset)(void); +extern int at91_extern_irq; diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index 3e48811..2cea07a 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -47,6 +47,10 @@ static void at91_aic_unmask_irq(unsigned int irq) at91_sys_write(AT91_AIC_IECR, 1 << irq); } +unsigned int at91_extern_irq; + +#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) + static int at91_aic_set_type(unsigned irq, unsigned type) { unsigned int smr, srctype; @@ -59,14 +63,16 @@ static int at91_aic_set_type(unsigned irq, unsigned type) srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_LOW; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_FALLING; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_FALLING; break; default: return -EINVAL; diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c index 32c95d8..5e3b6e3 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91rm9200/pm.c @@ -112,7 +112,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock); static void (*slow_clock)(void); - static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); @@ -123,13 +122,7 @@ static int at91_pm_enter(suspend_state_t state) (at91_sys_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) - | (1 << AT91RM9200_ID_IRQ0) - | (1 << AT91RM9200_ID_IRQ1) - | (1 << AT91RM9200_ID_IRQ2) - | (1 << AT91RM9200_ID_IRQ3) - | (1 << AT91RM9200_ID_IRQ4) - | (1 << AT91RM9200_ID_IRQ5) - | (1 << AT91RM9200_ID_IRQ6)) + | (at91_extern_irq)) & at91_sys_read(AT91_AIC_IMR), state); diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 8a2ff47..1d54185 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -39,13 +39,15 @@ static inline void arch_idle(void) cpu_do_idle(); } +void (*at91_arch_reset)(void); + static inline void arch_reset(char mode) { - /* - * Perform a hardware reset with the use of the Watchdog timer. - */ - at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); + /* call the CPU-specific reset function */ + if (at91_arch_reset) + (at91_arch_reset)(); + + for (;;) {} /* wait fovever */ } #define ARCH_ID_AT91RM9200 0x09200080 -- cgit v0.10.2 From 79da7a610a1f81b51a1a77e2ac27438d7a5c5124 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 11:58:14 +0100 Subject: [ARM] 3947/1: AT91: cpu_is_XXX macro's This patch replaces the arch_identify() in system.h with a set of cpu_is_XXX() macro's. This allows for compile-time checking of the target AT91 processor. Original patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 391a1f4..877876e 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -138,7 +138,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) unsigned int mode; #ifdef CONFIG_ARM - if (arch_identify() == ARCH_ID_AT91RM9200) { + if (cpu_is_at91rm9200()) { /* * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. * We need to drive the pin manually. diff --git a/include/asm-arm/arch-at91rm9200/cpu.h b/include/asm-arm/arch-at91rm9200/cpu.h new file mode 100644 index 0000000..6f8d09b --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/cpu.h @@ -0,0 +1,49 @@ +/* + * include/asm-arm/arch-at91rm9200/cpu.h + * + * Copyright (C) 2006 SAN People + * + * 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. + * + */ + +#ifndef __ASM_ARCH_CPU_H +#define __ASM_ARCH_CPU_H + +#include +#include + + +#define ARCH_ID_AT91RM9200 0x09290780 +#define ARCH_ID_AT91SAM9260 0x019803a0 +#define ARCH_ID_AT91SAM9261 0x019703a0 + + +static inline unsigned long at91_cpu_identify(void) +{ + return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION); +} + + +#ifdef CONFIG_ARCH_AT91RM9200 +#define cpu_is_at91rm9200() (at91_cpu_identify() == ARCH_ID_AT91RM9200) +#else +#define cpu_is_at91rm9200() (0) +#endif + +#ifdef CONFIG_ARCH_AT91SAM9260 +#define cpu_is_at91sam9260() (at91_cpu_identify() == ARCH_ID_AT91SAM9260) +#else +#define cpu_is_at91sam9260() (0) +#endif + +#ifdef CONFIG_ARCH_AT91SAM9261 +#define cpu_is_at91sam9261() (at91_cpu_identify() == ARCH_ID_AT91SAM9261) +#else +#define cpu_is_at91sam9261() (0) +#endif + +#endif diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 1d54185..92f3676 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -50,12 +50,4 @@ static inline void arch_reset(char mode) for (;;) {} /* wait fovever */ } -#define ARCH_ID_AT91RM9200 0x09200080 -#define ARCH_ID_AT91SAM9261 0x019000a0 - -static inline unsigned long arch_identify(void) -{ - return at91_sys_read(AT91_DBGU_CIDR) & (AT91_CIDR_EPROC | AT91_CIDR_ARCH); -} - #endif -- cgit v0.10.2 From 62c1660d908c44663c63ad6c679f6afa1d33c5f6 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 12:27:38 +0100 Subject: [ARM] 3948/1: AT91: Initial support for AT91SAM9261 and AT91SAM9260 This patch adds the initial support for the newer Atmel AT91SAM9261 and AT91SAM9260 processors. The code is based on, and makes use of, the existing AT91RM9200 support. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 568d8d7..40e89bf 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -11,10 +11,10 @@ obj-$(CONFIG_PM) += pm.o # CPU-specific support obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.c -obj-$(CONFIG_ARCH_AT91SAM9260) += -obj-$(CONFIG_ARCH_AT91SAM9261) += +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o -# AT91RM9200 Board-specific support +# AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c new file mode 100644 index 0000000..203f073 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9260.c @@ -0,0 +1,294 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260.c + * + * Copyright (C) 2006 SAN People + * + * 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 "generic.h" +#include "clock.h" + +static struct map_desc at91sam9260_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), + .length = AT91SAM9260_SRAM0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), + .length = AT91SAM9260_SRAM1_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk adc_clk = { + .name = "adc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ADC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ether_clk = { + .name = "ether_clk", + .pmc_mask = 1 << AT91SAM9260_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { + .name = "usart3_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart4_clk = { + .name = "usart4_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US4, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart5_clk = { + .name = "usart5_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US5, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &adc_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc + // tc0 .. tc2 + &ohci_clk, + ðer_clk, + &isi_clk, + &usart3_clk, + &usart4_clk, + &usart5_clk, + // tc3 .. tc5 + // irq0 .. irq2 +}; + +/* + * The two programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; + +static void __init at91sam9260_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9260_gpio[] = { + { + .id = AT91SAM9260_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9260_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9260_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9260_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9260 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9260_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); + + at91_arch_reset = at91sam9260_reset; + at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) + | (1 << AT91SAM9260_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9260_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9260_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, /* Analog-to-Digital Converter */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller */ + 0, + 0, + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* Ethernet */ + 0, /* Image Sensor Interface */ + 6, /* USART 3 */ + 6, /* USART 4 */ + 6, /* USART 5 */ + 0, /* Timer Counter 3 */ + 0, /* Timer Counter 4 */ + 0, /* Timer Counter 5 */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9260_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c new file mode 100644 index 0000000..5a82f35 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9261.c @@ -0,0 +1,289 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261.c + * + * Copyright (C) 2005 SAN People + * + * 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 "generic.h" +#include "clock.h" + +static struct map_desc at91sam9261_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE), + .length = AT91SAM9261_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9261_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc 0 .. ssc2 + // tc0 .. tc2 + &ohci_clk, + &lcdc_clk, + // irq0 .. irq2 +}; + +/* + * The four programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +/* HClocks */ +static struct clk hck0 = { + .name = "hck0", + .pmc_mask = AT91_PMC_HCK0, + .type = CLK_TYPE_SYSTEM, + .id = 0, +}; +static struct clk hck1 = { + .name = "hck1", + .pmc_mask = AT91_PMC_HCK1, + .type = CLK_TYPE_SYSTEM, + .id = 1, +}; + +static void __init at91sam9261_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); + + clk_register(&hck0); + clk_register(&hck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9261_gpio[] = { + { + .id = AT91SAM9261_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9261_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9261_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9261_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9261 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9261_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc)); + + at91_arch_reset = at91sam9261_reset; + at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) + | (1 << AT91SAM9261_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9261_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9261_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 5, /* Serial Synchronous Controller 2 */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* LCD Controller */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9261_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index fd98e35..8c4d5a7 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -10,14 +10,19 @@ /* Processors */ extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); +extern void __init at91sam9260_initialize(unsigned long main_clock); +extern void __init at91sam9261_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); +extern void __init at91sam9260_init_interrupts(unsigned int priority[]); +extern void __init at91sam9261_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ struct sys_timer; extern struct sys_timer at91rm9200_timer; +extern struct sys_timer at91sam926x_timer; /* Clocks */ extern int __init at91_clock_init(unsigned long main_clock); diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260.h b/include/asm-arm/arch-at91rm9200/at91sam9260.h new file mode 100644 index 0000000..46f4dd6 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91sam9260.h @@ -0,0 +1,125 @@ +/* + * include/asm-arm/arch-at91rm9200/at91sam9260.h + * + * (C) 2006 Andrew Victor + * + * Common definitions. + * Based on AT91SAM9260 datasheet revision A (Preliminary). + * + * 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. + */ + +#ifndef AT91SAM9260_H +#define AT91SAM9260_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripherals */ +#define AT91SAM9260_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT91SAM9260_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT91SAM9260_ID_PIOC 4 /* Parallel IO Controller C */ +#define AT91SAM9260_ID_ADC 5 /* Analog-to-Digital Converter */ +#define AT91SAM9260_ID_US0 6 /* USART 0 */ +#define AT91SAM9260_ID_US1 7 /* USART 1 */ +#define AT91SAM9260_ID_US2 8 /* USART 2 */ +#define AT91SAM9260_ID_MCI 9 /* Multimedia Card Interface */ +#define AT91SAM9260_ID_UDP 10 /* USB Device Port */ +#define AT91SAM9260_ID_TWI 11 /* Two-Wire Interface */ +#define AT91SAM9260_ID_SPI0 12 /* Serial Peripheral Interface 0 */ +#define AT91SAM9260_ID_SPI1 13 /* Serial Peripheral Interface 1 */ +#define AT91SAM9260_ID_SSC 14 /* Serial Synchronous Controller */ +#define AT91SAM9260_ID_TC0 17 /* Timer Counter 0 */ +#define AT91SAM9260_ID_TC1 18 /* Timer Counter 1 */ +#define AT91SAM9260_ID_TC2 19 /* Timer Counter 2 */ +#define AT91SAM9260_ID_UHP 20 /* USB Host port */ +#define AT91SAM9260_ID_EMAC 21 /* Ethernet */ +#define AT91SAM9260_ID_ISI 22 /* Image Sensor Interface */ +#define AT91SAM9260_ID_US3 23 /* USART 3 */ +#define AT91SAM9260_ID_US4 24 /* USART 4 */ +#define AT91SAM9260_ID_US5 25 /* USART 5 */ +#define AT91SAM9260_ID_TC3 26 /* Timer Counter 3 */ +#define AT91SAM9260_ID_TC4 27 /* Timer Counter 4 */ +#define AT91SAM9260_ID_TC5 28 /* Timer Counter 5 */ +#define AT91SAM9260_ID_IRQ0 29 /* Advanced Interrupt Controller (IRQ0) */ +#define AT91SAM9260_ID_IRQ1 30 /* Advanced Interrupt Controller (IRQ1) */ +#define AT91SAM9260_ID_IRQ2 31 /* Advanced Interrupt Controller (IRQ2) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9260_BASE_TCB0 0xfffa0000 +#define AT91SAM9260_BASE_TC0 0xfffa0000 +#define AT91SAM9260_BASE_TC1 0xfffa0040 +#define AT91SAM9260_BASE_TC2 0xfffa0080 +#define AT91SAM9260_BASE_UDP 0xfffa4000 +#define AT91SAM9260_BASE_MCI 0xfffa8000 +#define AT91SAM9260_BASE_TWI 0xfffac000 +#define AT91SAM9260_BASE_US0 0xfffb0000 +#define AT91SAM9260_BASE_US1 0xfffb4000 +#define AT91SAM9260_BASE_US2 0xfffb8000 +#define AT91SAM9260_BASE_SSC 0xfffbc000 +#define AT91SAM9260_BASE_ISI 0xfffc0000 +#define AT91SAM9260_BASE_EMAC 0xfffc4000 +#define AT91SAM9260_BASE_SPI0 0xfffc8000 +#define AT91SAM9260_BASE_SPI1 0xfffcc000 +#define AT91SAM9260_BASE_US3 0xfffd0000 +#define AT91SAM9260_BASE_US4 0xfffd4000 +#define AT91SAM9260_BASE_US5 0xfffd8000 +#define AT91SAM9260_BASE_TCB1 0xfffdc000 +#define AT91SAM9260_BASE_TC3 0xfffdc000 +#define AT91SAM9260_BASE_TC4 0xfffdc040 +#define AT91SAM9260_BASE_TC5 0xfffdc080 +#define AT91SAM9260_BASE_ADC 0xfffe0000 +#define AT91_BASE_SYS 0xffffe800 + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_ECC (0xffffe800 - AT91_BASE_SYS) +#define AT91_SDRAMC (0xffffea00 - AT91_BASE_SYS) +#define AT91_SMC (0xffffec00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) +#define AT91_CCFG (0xffffef10 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) + + +/* + * Internal Memory. + */ +#define AT91SAM9260_ROM_BASE 0x00100000 /* Internal ROM base address */ +#define AT91SAM9260_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */ + +#define AT91SAM9260_SRAM0_BASE 0x00200000 /* Internal SRAM 0 base address */ +#define AT91SAM9260_SRAM0_SIZE SZ_4K /* Internal SRAM 0 size (4Kb) */ +#define AT91SAM9260_SRAM1_BASE 0x00300000 /* Internal SRAM 1 base address */ +#define AT91SAM9260_SRAM1_SIZE SZ_4K /* Internal SRAM 1 size (4Kb) */ + +#define AT91SAM9260_UHP_BASE 0x00500000 /* USB Host controller */ + +#if 0 +/* + * PIO pin definitions (peripheral A/B multiplexing). + */ + +// TODO: Add + +#endif + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261.h b/include/asm-arm/arch-at91rm9200/at91sam9261.h new file mode 100644 index 0000000..8d39672 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91sam9261.h @@ -0,0 +1,292 @@ +/* + * include/asm-arm/arch-at91rm9200/at91sam9261.h + * + * Copyright (C) SAN People + * + * Common definitions. + * Based on AT91SAM9261 datasheet revision E. (Preliminary) + * + * 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. + */ + +#ifndef AT91SAM9261_H +#define AT91SAM9261_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripherals */ +#define AT91SAM9261_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT91SAM9261_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT91SAM9261_ID_PIOC 4 /* Parallel IO Controller C */ +#define AT91SAM9261_ID_US0 6 /* USART 0 */ +#define AT91SAM9261_ID_US1 7 /* USART 1 */ +#define AT91SAM9261_ID_US2 8 /* USART 2 */ +#define AT91SAM9261_ID_MCI 9 /* Multimedia Card Interface */ +#define AT91SAM9261_ID_UDP 10 /* USB Device Port */ +#define AT91SAM9261_ID_TWI 11 /* Two-Wire Interface */ +#define AT91SAM9261_ID_SPI0 12 /* Serial Peripheral Interface 0 */ +#define AT91SAM9261_ID_SPI1 13 /* Serial Peripheral Interface 1 */ +#define AT91SAM9261_ID_SSC0 14 /* Serial Synchronous Controller 0 */ +#define AT91SAM9261_ID_SSC1 15 /* Serial Synchronous Controller 1 */ +#define AT91SAM9261_ID_SSC2 16 /* Serial Synchronous Controller 2 */ +#define AT91SAM9261_ID_TC0 17 /* Timer Counter 0 */ +#define AT91SAM9261_ID_TC1 18 /* Timer Counter 1 */ +#define AT91SAM9261_ID_TC2 19 /* Timer Counter 2 */ +#define AT91SAM9261_ID_UHP 20 /* USB Host port */ +#define AT91SAM9261_ID_LCDC 21 /* LDC Controller */ +#define AT91SAM9261_ID_IRQ0 29 /* Advanced Interrupt Controller (IRQ0) */ +#define AT91SAM9261_ID_IRQ1 30 /* Advanced Interrupt Controller (IRQ1) */ +#define AT91SAM9261_ID_IRQ2 31 /* Advanced Interrupt Controller (IRQ2) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9261_BASE_TCB0 0xfffa0000 +#define AT91SAM9261_BASE_TC0 0xfffa0000 +#define AT91SAM9261_BASE_TC1 0xfffa0040 +#define AT91SAM9261_BASE_TC2 0xfffa0080 +#define AT91SAM9261_BASE_UDP 0xfffa4000 +#define AT91SAM9261_BASE_MCI 0xfffa8000 +#define AT91SAM9261_BASE_TWI 0xfffac000 +#define AT91SAM9261_BASE_US0 0xfffb0000 +#define AT91SAM9261_BASE_US1 0xfffb4000 +#define AT91SAM9261_BASE_US2 0xfffb8000 +#define AT91SAM9261_BASE_SSC0 0xfffbc000 +#define AT91SAM9261_BASE_SSC1 0xfffc0000 +#define AT91SAM9261_BASE_SSC2 0xfffc4000 +#define AT91SAM9261_BASE_SPI0 0xfffc8000 +#define AT91SAM9261_BASE_SPI1 0xfffcc000 +#define AT91_BASE_SYS 0xffffea00 + + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_SDRAMC (0xffffea00 - AT91_BASE_SYS) +#define AT91_SMC (0xffffec00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) + + +/* + * Internal Memory. + */ +#define AT91SAM9261_SRAM_BASE 0x00300000 /* Internal SRAM base address */ +#define AT91SAM9261_SRAM_SIZE 0x00028000 /* Internal SRAM size (160Kb) */ + +#define AT91SAM9261_ROM_BASE 0x00400000 /* Internal ROM base address */ +#define AT91SAM9261_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */ + +#define AT91SAM9261_UHP_BASE 0x00500000 /* USB Host controller */ +#define AT91SAM9261_LCDC_BASE 0x00600000 /* LDC controller */ + + +#if 0 +/* + * PIO pin definitions (peripheral A/B multiplexing). + */ +#define AT91_PA0_SPI0_MISO (1 << 0) /* A: SPI0 Master In Slave */ +#define AT91_PA0_MCDA0 (1 << 0) /* B: Multimedia Card A Data 0 */ +#define AT91_PA1_SPI0_MOSI (1 << 1) /* A: SPI0 Master Out Slave */ +#define AT91_PA1_MCCDA (1 << 1) /* B: Multimedia Card A Command */ +#define AT91_PA2_SPI0_SPCK (1 << 2) /* A: SPI0 Serial Clock */ +#define AT91_PA2_MCCK (1 << 2) /* B: Multimedia Card Clock */ +#define AT91_PA3_SPI0_NPCS0 (1 << 3) /* A: SPI0 Peripheral Chip Select 0 */ +#define AT91_PA4_SPI0_NPCS1 (1 << 4) /* A: SPI0 Peripheral Chip Select 1 */ +#define AT91_PA4_MCDA1 (1 << 4) /* B: Multimedia Card A Data 1 */ +#define AT91_PA5_SPI0_NPCS2 (1 << 5) /* A: SPI0 Peripheral Chip Select 2 */ +#define AT91_PA5_MCDA2 (1 << 5) /* B: Multimedia Card A Data 2 */ +#define AT91_PA6_SPI0_NPCS3 (1 << 6) /* A: SPI0 Peripheral Chip Select 3 */ +#define AT91_PA6_MCDA3 (1 << 6) /* B: Multimedia Card A Data 3 */ +#define AT91_PA7_TWD (1 << 7) /* A: TWI Two-wire Serial Data */ +#define AT91_PA7_PCK0 (1 << 7) /* B: PMC Programmable clock Output 0 */ +#define AT91_PA8_TWCK (1 << 8) /* A: TWI Two-wire Serial Clock */ +#define AT91_PA8_PCK1 (1 << 8) /* B: PMC Programmable clock Output 1 */ +#define AT91_PA9_DRXD (1 << 9) /* A: DBGU Debug Receive Data */ +#define AT91_PA9_PCK2 (1 << 9) /* B: PMC Programmable clock Output 2 */ +#define AT91_PA10_DTXD (1 << 10) /* A: DBGU Debug Transmit Data */ +#define AT91_PA10_PCK3 (1 << 10) /* B: PMC Programmable clock Output 3 */ +#define AT91_PA11_TSYNC (1 << 11) /* A: Trace Synchronization Signal */ +#define AT91_PA11_SCK1 (1 << 11) /* B: USART1 Serial Clock */ +#define AT91_PA12_TCLK (1 << 12) /* A: Trace Clock */ +#define AT91_PA12_RTS1 (1 << 12) /* B: USART1 Ready To Send */ +#define AT91_PA13_TPS0 (1 << 13) /* A: Trace ARM Pipeline Status 0 */ +#define AT91_PA13_CTS1 (1 << 13) /* B: USART1 Clear To Send */ +#define AT91_PA14_TPS1 (1 << 14) /* A: Trace ARM Pipeline Status 1 */ +#define AT91_PA14_SCK2 (1 << 14) /* B: USART2 Serial Clock */ +#define AT91_PA15_TPS2 (1 << 15) /* A: Trace ARM Pipeline Status 2 */ +#define AT91_PA15_RTS2 (1 << 15) /* B: USART2 Ready To Send */ +#define AT91_PA16_TPK0 (1 << 16) /* A: Trace Packet Port 0 */ +#define AT91_PA16_CTS2 (1 << 16) /* B: USART2 Clear To Send */ +#define AT91_PA17_TPK1 (1 << 17) /* A: Trace Packet Port 1 */ +#define AT91_PA17_TF1 (1 << 17) /* B: SSC1 Transmit Frame Sync */ +#define AT91_PA18_TPK2 (1 << 18) /* A: Trace Packet Port 2 */ +#define AT91_PA18_TK1 (1 << 18) /* B: SSC1 Transmit Clock */ +#define AT91_PA19_TPK3 (1 << 19) /* A: Trace Packet Port 3 */ +#define AT91_PA19_TD1 (1 << 19) /* B: SSC1 Transmit Data */ +#define AT91_PA20_TPK4 (1 << 20) /* A: Trace Packet Port 4 */ +#define AT91_PA20_RD1 (1 << 20) /* B: SSC1 Receive Data */ +#define AT91_PA21_TPK5 (1 << 21) /* A: Trace Packet Port 5 */ +#define AT91_PA21_RK1 (1 << 21) /* B: SSC1 Receive Clock */ +#define AT91_PA22_TPK6 (1 << 22) /* A: Trace Packet Port 6 */ +#define AT91_PA22_RF1 (1 << 22) /* B: SSC1 Receive Frame Sync */ +#define AT91_PA23_TPK7 (1 << 23) /* A: Trace Packet Port 7 */ +#define AT91_PA23_RTS0 (1 << 23) /* B: USART0 Ready To Send */ +#define AT91_PA24_TPK8 (1 << 24) /* A: Trace Packet Port 8 */ +#define AT91_PA24_SPI1_NPCS1 (1 << 24) /* B: SPI1 Peripheral Chip Select 1 */ +#define AT91_PA25_TPK9 (1 << 25) /* A: Trace Packet Port 9 */ +#define AT91_PA25_SPI1_NPCS2 (1 << 25) /* B: SPI1 Peripheral Chip Select 2 */ +#define AT91_PA26_TPK10 (1 << 26) /* A: Trace Packet Port 10 */ +#define AT91_PA26_SPI1_NPCS3 (1 << 26) /* B: SPI1 Peripheral Chip Select 3 */ +#define AT91_PA27_TPK11 (1 << 27) /* A: Trace Packet Port 11 */ +#define AT91_PA27_SPI0_NPCS1 (1 << 27) /* B: SPI0 Peripheral Chip Select 1 */ +#define AT91_PA28_TPK12 (1 << 28) /* A: Trace Packet Port 12 */ +#define AT91_PA28_SPI0_NPCS2 (1 << 28) /* B: SPI0 Peripheral Chip Select 2 */ +#define AT91_PA29_TPK13 (1 << 29) /* A: Trace Packet Port 13 */ +#define AT91_PA29_SPI0_NPCS3 (1 << 29) /* B: SPI0 Peripheral Chip Select 3 */ +#define AT91_PA30_TPK14 (1 << 30) /* A: Trace Packet Port 14 */ +#define AT91_PA30_A23 (1 << 30) /* B: Address Bus bit 23 */ +#define AT91_PA31_TPK15 (1 << 31) /* A: Trace Packet Port 15 */ +#define AT91_PA31_A24 (1 << 31) /* B: Address Bus bit 24 */ + +#define AT91_PB0_LCDVSYNC (1 << 0) /* A: LCD Vertical Synchronization */ +#define AT91_PB1_LCDHSYNC (1 << 1) /* A: LCD Horizontal Synchronization */ +#define AT91_PB2_LCDDOTCK (1 << 2) /* A: LCD Dot Clock */ +#define AT91_PB2_PCK0 (1 << 2) /* B: PMC Programmable clock Output 0 */ +#define AT91_PB3_LCDDEN (1 << 3) /* A: LCD Data Enable */ +#define AT91_PB4_LCDCC (1 << 4) /* A: LCD Contrast Control */ +#define AT91_PB4_LCDD2 (1 << 4) /* B: LCD Data Bus Bit 2 */ +#define AT91_PB5_LCDD0 (1 << 5) /* A: LCD Data Bus Bit 0 */ +#define AT91_PB5_LCDD3 (1 << 5) /* B: LCD Data Bus Bit 3 */ +#define AT91_PB6_LCDD1 (1 << 6) /* A: LCD Data Bus Bit 1 */ +#define AT91_PB6_LCDD4 (1 << 6) /* B: LCD Data Bus Bit 4 */ +#define AT91_PB7_LCDD2 (1 << 7) /* A: LCD Data Bus Bit 2 */ +#define AT91_PB7_LCDD5 (1 << 7) /* B: LCD Data Bus Bit 5 */ +#define AT91_PB8_LCDD3 (1 << 8) /* A: LCD Data Bus Bit 3 */ +#define AT91_PB8_LCDD6 (1 << 8) /* B: LCD Data Bus Bit 6 */ +#define AT91_PB9_LCDD4 (1 << 9) /* A: LCD Data Bus Bit 4 */ +#define AT91_PB9_LCDD7 (1 << 9) /* B: LCD Data Bus Bit 7 */ +#define AT91_PB10_LCDD5 (1 << 10) /* A: LCD Data Bus Bit 5 */ +#define AT91_PB10_LCDD10 (1 << 10) /* B: LCD Data Bus Bit 10 */ +#define AT91_PB11_LCDD6 (1 << 11) /* A: LCD Data Bus Bit 6 */ +#define AT91_PB11_LCDD11 (1 << 11) /* B: LCD Data Bus Bit 11 */ +#define AT91_PB12_LCDD7 (1 << 12) /* A: LCD Data Bus Bit 7 */ +#define AT91_PB12_LCDD12 (1 << 12) /* B: LCD Data Bus Bit 12 */ +#define AT91_PB13_LCDD8 (1 << 13) /* A: LCD Data Bus Bit 8 */ +#define AT91_PB13_LCDD13 (1 << 13) /* B: LCD Data Bus Bit 13 */ +#define AT91_PB14_LCDD9 (1 << 14) /* A: LCD Data Bus Bit 9 */ +#define AT91_PB14_LCDD14 (1 << 14) /* B: LCD Data Bus Bit 14 */ +#define AT91_PB15_LCDD10 (1 << 15) /* A: LCD Data Bus Bit 10 */ +#define AT91_PB15_LCDD15 (1 << 15) /* B: LCD Data Bus Bit 15 */ +#define AT91_PB16_LCDD11 (1 << 16) /* A: LCD Data Bus Bit 11 */ +#define AT91_PB16_LCDD19 (1 << 16) /* B: LCD Data Bus Bit 19 */ +#define AT91_PB17_LCDD12 (1 << 17) /* A: LCD Data Bus Bit 12 */ +#define AT91_PB17_LCDD20 (1 << 17) /* B: LCD Data Bus Bit 20 */ +#define AT91_PB18_LCDD13 (1 << 18) /* A: LCD Data Bus Bit 13 */ +#define AT91_PB18_LCDD21 (1 << 18) /* B: LCD Data Bus Bit 21 */ +#define AT91_PB19_LCDD14 (1 << 19) /* A: LCD Data Bus Bit 14 */ +#define AT91_PB19_LCDD22 (1 << 19) /* B: LCD Data Bus Bit 22 */ +#define AT91_PB20_LCDD15 (1 << 20) /* A: LCD Data Bus Bit 15 */ +#define AT91_PB20_LCDD23 (1 << 20) /* B: LCD Data Bus Bit 23 */ +#define AT91_PB21_TF0 (1 << 21) /* A: SSC0 Transmit Frame Sync */ +#define AT91_PB21_LCDD16 (1 << 21) /* B: LCD Data Bus Bit 16 */ +#define AT91_PB22_TK0 (1 << 22) /* A: SSC0 Transmit Clock */ +#define AT91_PB22_LCDD17 (1 << 22) /* B: LCD Data Bus Bit 17 */ +#define AT91_PB23_TD0 (1 << 23) /* A: SSC0 Transmit Data */ +#define AT91_PB23_LCDD18 (1 << 23) /* B: LCD Data Bus Bit 18 */ +#define AT91_PB24_RD0 (1 << 24) /* A: SSC0 Receive Data */ +#define AT91_PB24_LCDD19 (1 << 24) /* B: LCD Data Bus Bit 19 */ +#define AT91_PB25_RK0 (1 << 25) /* A: SSC0 Receive Clock */ +#define AT91_PB25_LCDD20 (1 << 25) /* B: LCD Data Bus Bit 20 */ +#define AT91_PB26_RF0 (1 << 26) /* A: SSC0 Receive Frame Sync */ +#define AT91_PB26_LCDD21 (1 << 26) /* B: LCD Data Bus Bit 21 */ +#define AT91_PB27_SPI1_NPCS1 (1 << 27) /* A: SPI1 Peripheral Chip Select 1 */ +#define AT91_PB27_LCDD22 (1 << 27) /* B: LCD Data Bus Bit 22 */ +#define AT91_PB28_SPI1_NPCS0 (1 << 28) /* A: SPI1 Peripheral Chip Select 0 */ +#define AT91_PB28_LCDD23 (1 << 28) /* B: LCD Data Bus Bit 23 */ +#define AT91_PB29_SPI1_SPCK (1 << 29) /* A: SPI1 Serial Clock */ +#define AT91_PB29_IRQ2 (1 << 29) /* B: Interrupt input 2 */ +#define AT91_PB30_SPI1_MISO (1 << 30) /* A: SPI1 Master In Slave */ +#define AT91_PB30_IRQ1 (1 << 30) /* B: Interrupt input 1 */ +#define AT91_PB31_SPI1_MOSI (1 << 31) /* A: SPI1 Master Out Slave */ +#define AT91_PB31_PCK2 (1 << 31) /* B: PMC Programmable clock Output 2 */ + +#define AT91_PC0_SMOE (1 << 0) /* A: SmartMedia Output Enable */ +#define AT91_PC0_NCS6 (1 << 0) /* B: Chip Select 6 */ +#define AT91_PC1_SMWE (1 << 1) /* A: SmartMedia Write Enable */ +#define AT91_PC1_NCS7 (1 << 1) /* B: Chip Select 7 */ +#define AT91_PC2_NWAIT (1 << 2) /* A: NWAIT */ +#define AT91_PC2_IRQ0 (1 << 2) /* B: Interrupt input 0 */ +#define AT91_PC3_A25_CFRNW (1 << 3) /* A: Address Bus[25] / Compact Flash Read Not Write */ +#define AT91_PC4_NCS4_CFCS0 (1 << 4) /* A: Chip Select 4 / CompactFlash Chip Select 0 */ +#define AT91_PC5_NCS5_CFCS1 (1 << 5) /* A: Chip Select 5 / CompactFlash Chip Select 1 */ +#define AT91_PC6_CFCE1 (1 << 6) /* A: CompactFlash Chip Enable 1 */ +#define AT91_PC7_CFCE2 (1 << 7) /* A: CompactFlash Chip Enable 2 */ +#define AT91_PC8_TXD0 (1 << 8) /* A: USART0 Transmit Data */ +#define AT91_PC8_PCK2 (1 << 8) /* B: PMC Programmable clock Output 2 */ +#define AT91_PC9_RXD0 (1 << 9) /* A: USART0 Receive Data */ +#define AT91_PC9_PCK3 (1 << 9) /* B: PMC Programmable clock Output 3 */ +#define AT91_PC10_RTS0 (1 << 10) /* A: USART0 Ready To Send */ +#define AT91_PC10_SCK0 (1 << 10) /* B: USART0 Serial Clock */ +#define AT91_PC11_CTS0 (1 << 11) /* A: USART0 Clear To Send */ +#define AT91_PC11_FIQ (1 << 11) /* B: AIC Fast Interrupt Input */ +#define AT91_PC12_TXD1 (1 << 12) /* A: USART1 Transmit Data */ +#define AT91_PC12_NCS6 (1 << 12) /* B: Chip Select 6 */ +#define AT91_PC13_RXD1 (1 << 13) /* A: USART1 Receive Data */ +#define AT91_PC13_NCS7 (1 << 13) /* B: Chip Select 7 */ +#define AT91_PC14_TXD2 (1 << 14) /* A: USART2 Transmit Data */ +#define AT91_PC14_SPI1_NPCS2 (1 << 14) /* B: SPI1 Peripheral Chip Select 2 */ +#define AT91_PC15_RXD2 (1 << 15) /* A: USART2 Receive Data */ +#define AT91_PC15_SPI1_NPCS3 (1 << 15) /* B: SPI1 Peripheral Chip Select 3 */ +#define AT91_PC16_D16 (1 << 16) /* A: Data Bus [16] */ +#define AT91_PC16_TCLK0 (1 << 16) /* B: Timer Counter 0 external clock input */ +#define AT91_PC17_D17 (1 << 17) /* A: Data Bus [17] */ +#define AT91_PC17_TCLK1 (1 << 17) /* B: Timer Counter 1 external clock input */ +#define AT91_PC18_D18 (1 << 18) /* A: Data Bus [18] */ +#define AT91_PC18_TCLK2 (1 << 18) /* B: Timer Counter 2 external clock input */ +#define AT91_PC19_D19 (1 << 19) /* A: Data Bus [19] */ +#define AT91_PC19_TIOA0 (1 << 19) /* B: Timer Counter 0 Multipurpose Timer I/O Pin A */ +#define AT91_PC20_D20 (1 << 20) /* A: Data Bus [20] */ +#define AT91_PC20_TIOB0 (1 << 20) /* B: Timer Counter 0 Multipurpose Timer I/O Pin B */ +#define AT91_PC21_D21 (1 << 21) /* A: Data Bus [21] */ +#define AT91_PC21_TIOA1 (1 << 21) /* B: Timer Counter 1 Multipurpose Timer I/O Pin A */ +#define AT91_PC22_D22 (1 << 22) /* A: Data Bus [22] */ +#define AT91_PC22_TIOB1 (1 << 22) /* B: Timer Counter 1 Multipurpose Timer I/O Pin B */ +#define AT91_PC23_D23 (1 << 23) /* A: Data Bus [23] */ +#define AT91_PC23_TIOA2 (1 << 23) /* B: Timer Counter 2 Multipurpose Timer I/O Pin A */ +#define AT91_PC24_D24 (1 << 24) /* A: Data Bus [24] */ +#define AT91_PC24_TIOB2 (1 << 24) /* B: Timer Counter 2 Multipurpose Timer I/O Pin B */ +#define AT91_PC25_D25 (1 << 25) /* A: Data Bus [25] */ +#define AT91_PC25_TF2 (1 << 25) /* B: SSC2 Transmit Frame Sync */ +#define AT91_PC26_D26 (1 << 26) /* A: Data Bus [26] */ +#define AT91_PC26_TK2 (1 << 26) /* B: SSC2 Transmit Clock */ +#define AT91_PC27_D27 (1 << 27) /* A: Data Bus [27] */ +#define AT91_PC27_TD2 (1 << 27) /* B: SSC2 Transmit Data */ +#define AT91_PC28_D28 (1 << 28) /* A: Data Bus [28] */ +#define AT91_PC28_RD2 (1 << 28) /* B: SSC2 Receive Data */ +#define AT91_PC29_D29 (1 << 29) /* A: Data Bus [29] */ +#define AT91_PC29_RK2 (1 << 29) /* B: SSC2 Receive Clock */ +#define AT91_PC30_D30 (1 << 30) /* A: Data Bus [30] */ +#define AT91_PC30_RF2 (1 << 30) /* B: SSC2 Receive Frame Sync */ +#define AT91_PC31_D31 (1 << 31) /* A: Data Bus [31] */ +#define AT91_PC31_PCK1 (1 << 31) /* B: PMC Programmable clock Output 1 */ +#endif + +#endif -- cgit v0.10.2 From 6171de8f57e80873436345a9c7ba8bae800e577b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 14:34:53 +0100 Subject: [ARM] 3950/1: AT91: Split up system header file The AT91RM9200 system header file (at91rm9200_sys.h) has been split into separate header files for each peripheral. This was necessary since some of the system peripherals are also used on AT91SAM9260 and AT91SAM9261. The new SAM9-specific register bits have also been defined. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/include/asm-arm/arch-at91rm9200/at91_aic.h b/include/asm-arm/arch-at91rm9200/at91_aic.h new file mode 100644 index 0000000..267e698 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_aic.h @@ -0,0 +1,53 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_aic.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Advanced Interrupt Controller (AIC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_AIC_H +#define AT91_AIC_H + +#define AT91_AIC_SMR(n) (AT91_AIC + ((n) * 4)) /* Source Mode Registers 0-31 */ +#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */ +#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */ +#define AT91_AIC_SRCTYPE_LOW (0 << 5) +#define AT91_AIC_SRCTYPE_FALLING (1 << 5) +#define AT91_AIC_SRCTYPE_HIGH (2 << 5) +#define AT91_AIC_SRCTYPE_RISING (3 << 5) + +#define AT91_AIC_SVR(n) (AT91_AIC + 0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */ +#define AT91_AIC_IVR (AT91_AIC + 0x100) /* Interrupt Vector Register */ +#define AT91_AIC_FVR (AT91_AIC + 0x104) /* Fast Interrupt Vector Register */ +#define AT91_AIC_ISR (AT91_AIC + 0x108) /* Interrupt Status Register */ +#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */ + +#define AT91_AIC_IPR (AT91_AIC + 0x10c) /* Interrupt Pending Register */ +#define AT91_AIC_IMR (AT91_AIC + 0x110) /* Interrupt Mask Register */ +#define AT91_AIC_CISR (AT91_AIC + 0x114) /* Core Interrupt Status Register */ +#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */ +#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */ + +#define AT91_AIC_IECR (AT91_AIC + 0x120) /* Interrupt Enable Command Register */ +#define AT91_AIC_IDCR (AT91_AIC + 0x124) /* Interrupt Disable Command Register */ +#define AT91_AIC_ICCR (AT91_AIC + 0x128) /* Interrupt Clear Command Register */ +#define AT91_AIC_ISCR (AT91_AIC + 0x12c) /* Interrupt Set Command Register */ +#define AT91_AIC_EOICR (AT91_AIC + 0x130) /* End of Interrupt Command Register */ +#define AT91_AIC_SPU (AT91_AIC + 0x134) /* Spurious Interrupt Vector Register */ +#define AT91_AIC_DCR (AT91_AIC + 0x138) /* Debug Control Register */ +#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */ +#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */ + +#define AT91_AIC_FFER (AT91_AIC + 0x140) /* Fast Forcing Enable Register [SAM9 only] */ +#define AT91_AIC_FFDR (AT91_AIC + 0x144) /* Fast Forcing Disable Register [SAM9 only] */ +#define AT91_AIC_FFSR (AT91_AIC + 0x148) /* Fast Forcing Status Register [SAM9 only] */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_dbgu.h b/include/asm-arm/arch-at91rm9200/at91_dbgu.h new file mode 100644 index 0000000..e4b8b27 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_dbgu.h @@ -0,0 +1,45 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_dbgu.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Debug Unit (DBGU) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_DBGU_H +#define AT91_DBGU_H + +#define AT91_DBGU_CR (AT91_DBGU + 0x00) /* Control Register */ +#define AT91_DBGU_MR (AT91_DBGU + 0x04) /* Mode Register */ +#define AT91_DBGU_IER (AT91_DBGU + 0x08) /* Interrupt Enable Register */ +#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */ +#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */ +#define AT91_DBGU_IDR (AT91_DBGU + 0x0c) /* Interrupt Disable Register */ +#define AT91_DBGU_IMR (AT91_DBGU + 0x10) /* Interrupt Mask Register */ +#define AT91_DBGU_SR (AT91_DBGU + 0x14) /* Status Register */ +#define AT91_DBGU_RHR (AT91_DBGU + 0x18) /* Receiver Holding Register */ +#define AT91_DBGU_THR (AT91_DBGU + 0x1c) /* Transmitter Holding Register */ +#define AT91_DBGU_BRGR (AT91_DBGU + 0x20) /* Baud Rate Generator Register */ + +#define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */ +#define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */ +#define AT91_CIDR_VERSION (0x1f << 0) /* Version of the Device */ +#define AT91_CIDR_EPROC (7 << 5) /* Embedded Processor */ +#define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */ +#define AT91_CIDR_NVPSIZ2 (0xf << 12) /* Second Nonvolatile Program Memory Size */ +#define AT91_CIDR_SRAMSIZ (0xf << 16) /* Internal SRAM Size */ +#define AT91_CIDR_ARCH (0xff << 20) /* Architecture Identifier */ +#define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */ +#define AT91_CIDR_EXT (1 << 31) /* Extension Flag */ + +#define AT91_DBGU_FNR (AT91_DBGU + 0x48) /* Force NTRST Register [SAM9 only] */ +#define AT91_DBGU_FNTRST (1 << 0) /* Force NTRST */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_pdc.h b/include/asm-arm/arch-at91rm9200/at91_pdc.h new file mode 100644 index 0000000..79d6e02 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_pdc.h @@ -0,0 +1,36 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_pdc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Peripheral Data Controller (PDC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_PDC_H +#define AT91_PDC_H + +#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ +#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ +#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ +#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ +#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ +#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ +#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ +#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ + +#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ +#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ +#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ +#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ +#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ + +#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_pio.h b/include/asm-arm/arch-at91rm9200/at91_pio.h new file mode 100644 index 0000000..680eaa1 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_pio.h @@ -0,0 +1,49 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_pio.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Parallel I/O Controller (PIO) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_PIO_H +#define AT91_PIO_H + +#define PIO_PER 0x00 /* Enable Register */ +#define PIO_PDR 0x04 /* Disable Register */ +#define PIO_PSR 0x08 /* Status Register */ +#define PIO_OER 0x10 /* Output Enable Register */ +#define PIO_ODR 0x14 /* Output Disable Register */ +#define PIO_OSR 0x18 /* Output Status Register */ +#define PIO_IFER 0x20 /* Glitch Input Filter Enable */ +#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */ +#define PIO_IFSR 0x28 /* Glitch Input Filter Status */ +#define PIO_SODR 0x30 /* Set Output Data Register */ +#define PIO_CODR 0x34 /* Clear Output Data Register */ +#define PIO_ODSR 0x38 /* Output Data Status Register */ +#define PIO_PDSR 0x3c /* Pin Data Status Register */ +#define PIO_IER 0x40 /* Interrupt Enable Register */ +#define PIO_IDR 0x44 /* Interrupt Disable Register */ +#define PIO_IMR 0x48 /* Interrupt Mask Register */ +#define PIO_ISR 0x4c /* Interrupt Status Register */ +#define PIO_MDER 0x50 /* Multi-driver Enable Register */ +#define PIO_MDDR 0x54 /* Multi-driver Disable Register */ +#define PIO_MDSR 0x58 /* Multi-driver Status Register */ +#define PIO_PUDR 0x60 /* Pull-up Disable Register */ +#define PIO_PUER 0x64 /* Pull-up Enable Register */ +#define PIO_PUSR 0x68 /* Pull-up Status Register */ +#define PIO_ASR 0x70 /* Peripheral A Select Register */ +#define PIO_BSR 0x74 /* Peripheral B Select Register */ +#define PIO_ABSR 0x78 /* AB Status Register */ +#define PIO_OWER 0xa0 /* Output Write Enable Register */ +#define PIO_OWDR 0xa4 /* Output Write Disable Register */ +#define PIO_OWSR 0xa8 /* Output Write Status Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91rm9200/at91_pmc.h new file mode 100644 index 0000000..de8c3da --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_pmc.h @@ -0,0 +1,92 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_pmc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Power Management Controller (PMC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_PMC_H +#define AT91_PMC_H + +#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */ +#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */ + +#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */ +#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ +#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */ +#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */ +#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */ +#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */ +#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */ +#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ +#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ + +#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */ +#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */ +#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */ + +#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register */ +#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ +#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass [AT91SAM926x only] */ +#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ + +#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */ +#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ +#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ + +#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */ +#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */ +#define AT91_PMC_DIV (0xff << 0) /* Divider */ +#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ +#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ +#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ +#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ + +#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */ +#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ +#define AT91_PMC_CSS_SLOW (0 << 0) +#define AT91_PMC_CSS_MAIN (1 << 0) +#define AT91_PMC_CSS_PLLA (2 << 0) +#define AT91_PMC_CSS_PLLB (3 << 0) +#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */ +#define AT91_PMC_PRES_1 (0 << 2) +#define AT91_PMC_PRES_2 (1 << 2) +#define AT91_PMC_PRES_4 (2 << 2) +#define AT91_PMC_PRES_8 (3 << 2) +#define AT91_PMC_PRES_16 (4 << 2) +#define AT91_PMC_PRES_32 (5 << 2) +#define AT91_PMC_PRES_64 (6 << 2) +#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ +#define AT91_PMC_MDIV_1 (0 << 8) +#define AT91_PMC_MDIV_2 (1 << 8) +#define AT91_PMC_MDIV_3 (2 << 8) +#define AT91_PMC_MDIV_4 (3 << 8) + +#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */ + +#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */ +#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */ +#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */ +#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ +#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ +#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ +#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ +#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91rm9200/at91_rtc.h new file mode 100644 index 0000000..6e5065d --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_rtc.h @@ -0,0 +1,75 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_rtc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Real Time Clock (RTC) - System peripheral registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_RTC_H +#define AT91_RTC_H + +#define AT91_RTC_CR (AT91_RTC + 0x00) /* Control Register */ +#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time Register */ +#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */ +#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */ +#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8) +#define AT91_RTC_TIMEVSEL_HOUR (1 << 8) +#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8) +#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8) +#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */ +#define AT91_RTC_CALEVSEL_WEEK (0 << 16) +#define AT91_RTC_CALEVSEL_MONTH (1 << 16) +#define AT91_RTC_CALEVSEL_YEAR (2 << 16) + +#define AT91_RTC_MR (AT91_RTC + 0x04) /* Mode Register */ +#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */ + +#define AT91_RTC_TIMR (AT91_RTC + 0x08) /* Time Register */ +#define AT91_RTC_SEC (0x7f << 0) /* Current Second */ +#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */ +#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */ +#define AT91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */ + +#define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */ +#define AT91_RTC_CENT (0x7f << 0) /* Current Century */ +#define AT91_RTC_YEAR (0xff << 8) /* Current Year */ +#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */ +#define AT91_RTC_DAY (7 << 21) /* Current Day */ +#define AT91_RTC_DATE (0x3f << 24) /* Current Date */ + +#define AT91_RTC_TIMALR (AT91_RTC + 0x10) /* Time Alarm Register */ +#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enable */ +#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enable */ +#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */ + +#define AT91_RTC_CALALR (AT91_RTC + 0x14) /* Calendar Alarm Register */ +#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */ +#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */ + +#define AT91_RTC_SR (AT91_RTC + 0x18) /* Status Register */ +#define AT91_RTC_ACKUPD (1 << 0) /* Acknowledge for Update */ +#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */ +#define AT91_RTC_SECEV (1 << 2) /* Second Event */ +#define AT91_RTC_TIMEV (1 << 3) /* Time Event */ +#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */ + +#define AT91_RTC_SCCR (AT91_RTC + 0x1c) /* Status Clear Command Register */ +#define AT91_RTC_IER (AT91_RTC + 0x20) /* Interrupt Enable Register */ +#define AT91_RTC_IDR (AT91_RTC + 0x24) /* Interrupt Disable Register */ +#define AT91_RTC_IMR (AT91_RTC + 0x28) /* Interrupt Mask Register */ + +#define AT91_RTC_VER (AT91_RTC + 0x2c) /* Valid Entry Register */ +#define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ +#define AT91_RTC_NVCAL (1 << 1) /* Non valid Calendar */ +#define AT91_RTC_NVTIMALR (1 << 2) /* Non valid Time Alarm */ +#define AT91_RTC_NVCALALR (1 << 3) /* Non valid Calendar Alarm */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_st.h b/include/asm-arm/arch-at91rm9200/at91_st.h new file mode 100644 index 0000000..2432ddf --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_st.h @@ -0,0 +1,49 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_st.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * System Timer (ST) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_ST_H +#define AT91_ST_H + +#define AT91_ST_CR (AT91_ST + 0x00) /* Control Register */ +#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */ + +#define AT91_ST_PIMR (AT91_ST + 0x04) /* Period Interval Mode Register */ +#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */ + +#define AT91_ST_WDMR (AT91_ST + 0x08) /* Watchdog Mode Register */ +#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */ +#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */ +#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */ + +#define AT91_ST_RTMR (AT91_ST + 0x0c) /* Real-time Mode Register */ +#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */ + +#define AT91_ST_SR (AT91_ST + 0x10) /* Status Register */ +#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */ +#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */ +#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */ +#define AT91_ST_ALMS (1 << 3) /* Alarm Status */ + +#define AT91_ST_IER (AT91_ST + 0x14) /* Interrupt Enable Register */ +#define AT91_ST_IDR (AT91_ST + 0x18) /* Interrupt Disable Register */ +#define AT91_ST_IMR (AT91_ST + 0x1c) /* Interrupt Mask Register */ + +#define AT91_ST_RTAR (AT91_ST + 0x20) /* Real-time Alarm Register */ +#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */ + +#define AT91_ST_CRTR (AT91_ST + 0x24) /* Current Real-time Register */ +#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h new file mode 100644 index 0000000..0c0d814 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h @@ -0,0 +1,160 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_mc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91RM9200_MC_H +#define AT91RM9200_MC_H + +/* Memory Controller */ +#define AT91_MC_RCR (AT91_MC + 0x00) /* MC Remap Control Register */ +#define AT91_MC_RCB (1 << 0) /* Remap Command Bit */ + +#define AT91_MC_ASR (AT91_MC + 0x04) /* MC Abort Status Register */ +#define AT91_MC_UNADD (1 << 0) /* Undefined Address Abort Status */ +#define AT91_MC_MISADD (1 << 1) /* Misaligned Address Abort Status */ +#define AT91_MC_ABTSZ (3 << 8) /* Abort Size Status */ +#define AT91_MC_ABTSZ_BYTE (0 << 8) +#define AT91_MC_ABTSZ_HALFWORD (1 << 8) +#define AT91_MC_ABTSZ_WORD (2 << 8) +#define AT91_MC_ABTTYP (3 << 10) /* Abort Type Status */ +#define AT91_MC_ABTTYP_DATAREAD (0 << 10) +#define AT91_MC_ABTTYP_DATAWRITE (1 << 10) +#define AT91_MC_ABTTYP_FETCH (2 << 10) +#define AT91_MC_MST0 (1 << 16) /* ARM920T Abort Source */ +#define AT91_MC_MST1 (1 << 17) /* PDC Abort Source */ +#define AT91_MC_MST2 (1 << 18) /* UHP Abort Source */ +#define AT91_MC_MST3 (1 << 19) /* EMAC Abort Source */ +#define AT91_MC_SVMST0 (1 << 24) /* Saved ARM920T Abort Source */ +#define AT91_MC_SVMST1 (1 << 25) /* Saved PDC Abort Source */ +#define AT91_MC_SVMST2 (1 << 26) /* Saved UHP Abort Source */ +#define AT91_MC_SVMST3 (1 << 27) /* Saved EMAC Abort Source */ + +#define AT91_MC_AASR (AT91_MC + 0x08) /* MC Abort Address Status Register */ + +#define AT91_MC_MPR (AT91_MC + 0x0c) /* MC Master Priority Register */ +#define AT91_MPR_MSTP0 (7 << 0) /* ARM920T Priority */ +#define AT91_MPR_MSTP1 (7 << 4) /* PDC Priority */ +#define AT91_MPR_MSTP2 (7 << 8) /* UHP Priority */ +#define AT91_MPR_MSTP3 (7 << 12) /* EMAC Priority */ + +/* External Bus Interface (EBI) registers */ +#define AT91_EBI_CSA (AT91_MC + 0x60) /* Chip Select Assignment Register */ +#define AT91_EBI_CS0A (1 << 0) /* Chip Select 0 Assignment */ +#define AT91_EBI_CS0A_SMC (0 << 0) +#define AT91_EBI_CS0A_BFC (1 << 0) +#define AT91_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_EBI_CS1A_SMC (0 << 1) +#define AT91_EBI_CS1A_SDRAMC (1 << 1) +#define AT91_EBI_CS3A (1 << 3) /* Chip Select 2 Assignment */ +#define AT91_EBI_CS3A_SMC (0 << 3) +#define AT91_EBI_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_EBI_CS4A (1 << 4) /* Chip Select 3 Assignment */ +#define AT91_EBI_CS4A_SMC (0 << 4) +#define AT91_EBI_CS4A_SMC_COMPACTFLASH (1 << 4) +#define AT91_EBI_CFGR (AT91_MC + 0x64) /* Configuration Register */ +#define AT91_EBI_DBPUC (1 << 0) /* Data Bus Pull-Up Configuration */ + +/* Static Memory Controller (SMC) registers */ +#define AT91_SMC_CSR(n) (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */ +#define AT91_SMC_NWS (0x7f << 0) /* Number of Wait States */ +#define AT91_SMC_NWS_(x) ((x) << 0) +#define AT91_SMC_WSEN (1 << 7) /* Wait State Enable */ +#define AT91_SMC_TDF (0xf << 8) /* Data Float Time */ +#define AT91_SMC_TDF_(x) ((x) << 8) +#define AT91_SMC_BAT (1 << 12) /* Byte Access Type */ +#define AT91_SMC_DBW (3 << 13) /* Data Bus Width */ +#define AT91_SMC_DBW_16 (1 << 13) +#define AT91_SMC_DBW_8 (2 << 13) +#define AT91_SMC_DPR (1 << 15) /* Data Read Protocol */ +#define AT91_SMC_ACSS (3 << 16) /* Address to Chip Select Setup */ +#define AT91_SMC_ACSS_STD (0 << 16) +#define AT91_SMC_ACSS_1 (1 << 16) +#define AT91_SMC_ACSS_2 (2 << 16) +#define AT91_SMC_ACSS_3 (3 << 16) +#define AT91_SMC_RWSETUP (7 << 24) /* Read & Write Signal Time Setup */ +#define AT91_SMC_RWSETUP_(x) ((x) << 24) +#define AT91_SMC_RWHOLD (7 << 28) /* Read & Write Signal Hold Time */ +#define AT91_SMC_RWHOLD_(x) ((x) << 28) + +/* SDRAM Controller registers */ +#define AT91_SDRAMC_MR (AT91_MC + 0x90) /* Mode Register */ +#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */ +#define AT91_SDRAMC_MODE_NORMAL (0 << 0) +#define AT91_SDRAMC_MODE_NOP (1 << 0) +#define AT91_SDRAMC_MODE_PRECHARGE (2 << 0) +#define AT91_SDRAMC_MODE_LMR (3 << 0) +#define AT91_SDRAMC_MODE_REFRESH (4 << 0) +#define AT91_SDRAMC_DBW (1 << 4) /* Data Bus Width */ +#define AT91_SDRAMC_DBW_32 (0 << 4) +#define AT91_SDRAMC_DBW_16 (1 << 4) + +#define AT91_SDRAMC_TR (AT91_MC + 0x94) /* Refresh Timer Register */ +#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Count */ + +#define AT91_SDRAMC_CR (AT91_MC + 0x98) /* Configuration Register */ +#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */ +#define AT91_SDRAMC_NC_8 (0 << 0) +#define AT91_SDRAMC_NC_9 (1 << 0) +#define AT91_SDRAMC_NC_10 (2 << 0) +#define AT91_SDRAMC_NC_11 (3 << 0) +#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */ +#define AT91_SDRAMC_NR_11 (0 << 2) +#define AT91_SDRAMC_NR_12 (1 << 2) +#define AT91_SDRAMC_NR_13 (2 << 2) +#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */ +#define AT91_SDRAMC_NB_2 (0 << 4) +#define AT91_SDRAMC_NB_4 (1 << 4) +#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */ +#define AT91_SDRAMC_CAS_2 (2 << 5) +#define AT91_SDRAMC_TWR (0xf << 7) /* Write Recovery Delay */ +#define AT91_SDRAMC_TRC (0xf << 11) /* Row Cycle Delay */ +#define AT91_SDRAMC_TRP (0xf << 15) /* Row Precharge Delay */ +#define AT91_SDRAMC_TRCD (0xf << 19) /* Row to Column Delay */ +#define AT91_SDRAMC_TRAS (0xf << 23) /* Active to Precharge Delay */ +#define AT91_SDRAMC_TXSR (0xf << 27) /* Exit Self Refresh to Active Delay */ + +#define AT91_SDRAMC_SRR (AT91_MC + 0x9c) /* Self Refresh Register */ +#define AT91_SDRAMC_LPR (AT91_MC + 0xa0) /* Low Power Register */ +#define AT91_SDRAMC_IER (AT91_MC + 0xa4) /* Interrupt Enable Register */ +#define AT91_SDRAMC_IDR (AT91_MC + 0xa8) /* Interrupt Disable Register */ +#define AT91_SDRAMC_IMR (AT91_MC + 0xac) /* Interrupt Mask Register */ +#define AT91_SDRAMC_ISR (AT91_MC + 0xb0) /* Interrupt Status Register */ + +/* Burst Flash Controller register */ +#define AT91_BFC_MR (AT91_MC + 0xc0) /* Mode Register */ +#define AT91_BFC_BFCOM (3 << 0) /* Burst Flash Controller Operating Mode */ +#define AT91_BFC_BFCOM_DISABLED (0 << 0) +#define AT91_BFC_BFCOM_ASYNC (1 << 0) +#define AT91_BFC_BFCOM_BURST (2 << 0) +#define AT91_BFC_BFCC (3 << 2) /* Burst Flash Controller Clock */ +#define AT91_BFC_BFCC_MCK (1 << 2) +#define AT91_BFC_BFCC_DIV2 (2 << 2) +#define AT91_BFC_BFCC_DIV4 (3 << 2) +#define AT91_BFC_AVL (0xf << 4) /* Address Valid Latency */ +#define AT91_BFC_PAGES (7 << 8) /* Page Size */ +#define AT91_BFC_PAGES_NO_PAGE (0 << 8) +#define AT91_BFC_PAGES_16 (1 << 8) +#define AT91_BFC_PAGES_32 (2 << 8) +#define AT91_BFC_PAGES_64 (3 << 8) +#define AT91_BFC_PAGES_128 (4 << 8) +#define AT91_BFC_PAGES_256 (5 << 8) +#define AT91_BFC_PAGES_512 (6 << 8) +#define AT91_BFC_PAGES_1024 (7 << 8) +#define AT91_BFC_OEL (3 << 12) /* Output Enable Latency */ +#define AT91_BFC_BAAEN (1 << 16) /* Burst Address Advance Enable */ +#define AT91_BFC_BFOEH (1 << 17) /* Burst Flash Output Enable Handling */ +#define AT91_BFC_MUXEN (1 << 18) /* Multiplexed Bus Enable */ +#define AT91_BFC_RDYEN (1 << 19) /* Ready Enable Mode */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h deleted file mode 100644 index 73693fe..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_sys.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * System peripherals registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_SYS_H -#define AT91RM9200_SYS_H - -/* - * Advanced Interrupt Controller. - */ -#define AT91_AIC 0x000 - -#define AT91_AIC_SMR(n) (AT91_AIC + ((n) * 4)) /* Source Mode Registers 0-31 */ -#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */ -#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */ -#define AT91_AIC_SRCTYPE_LOW (0 << 5) -#define AT91_AIC_SRCTYPE_FALLING (1 << 5) -#define AT91_AIC_SRCTYPE_HIGH (2 << 5) -#define AT91_AIC_SRCTYPE_RISING (3 << 5) - -#define AT91_AIC_SVR(n) (AT91_AIC + 0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */ -#define AT91_AIC_IVR (AT91_AIC + 0x100) /* Interrupt Vector Register */ -#define AT91_AIC_FVR (AT91_AIC + 0x104) /* Fast Interrupt Vector Register */ -#define AT91_AIC_ISR (AT91_AIC + 0x108) /* Interrupt Status Register */ -#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */ - -#define AT91_AIC_IPR (AT91_AIC + 0x10c) /* Interrupt Pending Register */ -#define AT91_AIC_IMR (AT91_AIC + 0x110) /* Interrupt Mask Register */ -#define AT91_AIC_CISR (AT91_AIC + 0x114) /* Core Interrupt Status Register */ -#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */ -#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */ - -#define AT91_AIC_IECR (AT91_AIC + 0x120) /* Interrupt Enable Command Register */ -#define AT91_AIC_IDCR (AT91_AIC + 0x124) /* Interrupt Disable Command Register */ -#define AT91_AIC_ICCR (AT91_AIC + 0x128) /* Interrupt Clear Command Register */ -#define AT91_AIC_ISCR (AT91_AIC + 0x12c) /* Interrupt Set Command Register */ -#define AT91_AIC_EOICR (AT91_AIC + 0x130) /* End of Interrupt Command Register */ -#define AT91_AIC_SPU (AT91_AIC + 0x134) /* Spurious Interrupt Vector Register */ -#define AT91_AIC_DCR (AT91_AIC + 0x138) /* Debug Control Register */ -#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */ -#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */ - - -/* - * Debug Unit. - */ -#define AT91_DBGU 0x200 - -#define AT91_DBGU_CR (AT91_DBGU + 0x00) /* Control Register */ -#define AT91_DBGU_MR (AT91_DBGU + 0x04) /* Mode Register */ -#define AT91_DBGU_IER (AT91_DBGU + 0x08) /* Interrupt Enable Register */ -#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */ -#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */ -#define AT91_DBGU_IDR (AT91_DBGU + 0x0c) /* Interrupt Disable Register */ -#define AT91_DBGU_IMR (AT91_DBGU + 0x10) /* Interrupt Mask Register */ -#define AT91_DBGU_SR (AT91_DBGU + 0x14) /* Status Register */ -#define AT91_DBGU_RHR (AT91_DBGU + 0x18) /* Receiver Holding Register */ -#define AT91_DBGU_THR (AT91_DBGU + 0x1c) /* Transmitter Holding Register */ -#define AT91_DBGU_BRGR (AT91_DBGU + 0x20) /* Baud Rate Generator Register */ - -#define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */ -#define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */ -#define AT91_CIDR_VERSION (0x1f << 0) /* Version of the Device */ -#define AT91_CIDR_EPROC (7 << 5) /* Embedded Processor */ -#define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */ -#define AT91_CIDR_NVPSIZ2 (0xf << 12) /* Second Nonvolatile Program Memory Size */ -#define AT91_CIDR_SRAMSIZ (0xf << 16) /* Internal SRAM Size */ -#define AT91_CIDR_ARCH (0xff << 20) /* Architecture Identifier */ -#define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */ -#define AT91_CIDR_EXT (1 << 31) /* Extension Flag */ - -#define AT91_AIC_FFER (AT91_AIC + 0x140) /* Fast Forcing Enable Register [SAM9 only] */ -#define AT91_AIC_FFDR (AT91_AIC + 0x144) /* Fast Forcing Disable Register [SAM9 only] */ -#define AT91_AIC_FFSR (AT91_AIC + 0x148) /* Fast Forcing Status Register [SAM9 only] */ - -/* - * PIO Controllers. - */ -#define AT91_PIOA 0x400 -#define AT91_PIOB 0x600 -#define AT91_PIOC 0x800 -#define AT91_PIOD 0xa00 - -#define PIO_PER 0x00 /* Enable Register */ -#define PIO_PDR 0x04 /* Disable Register */ -#define PIO_PSR 0x08 /* Status Register */ -#define PIO_OER 0x10 /* Output Enable Register */ -#define PIO_ODR 0x14 /* Output Disable Register */ -#define PIO_OSR 0x18 /* Output Status Register */ -#define PIO_IFER 0x20 /* Glitch Input Filter Enable */ -#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */ -#define PIO_IFSR 0x28 /* Glitch Input Filter Status */ -#define PIO_SODR 0x30 /* Set Output Data Register */ -#define PIO_CODR 0x34 /* Clear Output Data Register */ -#define PIO_ODSR 0x38 /* Output Data Status Register */ -#define PIO_PDSR 0x3c /* Pin Data Status Register */ -#define PIO_IER 0x40 /* Interrupt Enable Register */ -#define PIO_IDR 0x44 /* Interrupt Disable Register */ -#define PIO_IMR 0x48 /* Interrupt Mask Register */ -#define PIO_ISR 0x4c /* Interrupt Status Register */ -#define PIO_MDER 0x50 /* Multi-driver Enable Register */ -#define PIO_MDDR 0x54 /* Multi-driver Disable Register */ -#define PIO_MDSR 0x58 /* Multi-driver Status Register */ -#define PIO_PUDR 0x60 /* Pull-up Disable Register */ -#define PIO_PUER 0x64 /* Pull-up Enable Register */ -#define PIO_PUSR 0x68 /* Pull-up Status Register */ -#define PIO_ASR 0x70 /* Peripheral A Select Register */ -#define PIO_BSR 0x74 /* Peripheral B Select Register */ -#define PIO_ABSR 0x78 /* AB Status Register */ -#define PIO_OWER 0xa0 /* Output Write Enable Register */ -#define PIO_OWDR 0xa4 /* Output Write Disable Register */ -#define PIO_OWSR 0xa8 /* Output Write Status Register */ - -#define AT91_PIO_P(n) (1 << (n)) - - -/* - * Power Management Controller. - */ -#define AT91_PMC 0xc00 - -#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */ -#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */ - -#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */ -#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ -#define AT91_PMC_UDP (1 << 1) /* USB Devcice Port Clock */ -#define AT91_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend */ -#define AT91_PMC_UHP (1 << 4) /* USB Host Port Clock */ -#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ -#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ -#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ -#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ - -#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */ -#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */ -#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */ - -#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register */ -#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ -#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ - -#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */ -#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ -#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ - -#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */ -#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */ -#define AT91_PMC_DIV (0xff << 0) /* Divider */ -#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ -#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ -#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ -#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ - -#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */ -#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ -#define AT91_PMC_CSS_SLOW (0 << 0) -#define AT91_PMC_CSS_MAIN (1 << 0) -#define AT91_PMC_CSS_PLLA (2 << 0) -#define AT91_PMC_CSS_PLLB (3 << 0) -#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */ -#define AT91_PMC_PRES_1 (0 << 2) -#define AT91_PMC_PRES_2 (1 << 2) -#define AT91_PMC_PRES_4 (2 << 2) -#define AT91_PMC_PRES_8 (3 << 2) -#define AT91_PMC_PRES_16 (4 << 2) -#define AT91_PMC_PRES_32 (5 << 2) -#define AT91_PMC_PRES_64 (6 << 2) -#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ -#define AT91_PMC_MDIV_1 (0 << 8) -#define AT91_PMC_MDIV_2 (1 << 8) -#define AT91_PMC_MDIV_3 (2 << 8) -#define AT91_PMC_MDIV_4 (3 << 8) - -#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */ - -#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */ -#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */ -#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */ -#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ -#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ -#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ -#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ -#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ -#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ -#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ -#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ -#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */ - - -/* - * System Timer. - */ -#define AT91_ST 0xd00 - -#define AT91_ST_CR (AT91_ST + 0x00) /* Control Register */ -#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */ -#define AT91_ST_PIMR (AT91_ST + 0x04) /* Period Interval Mode Register */ -#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */ -#define AT91_ST_WDMR (AT91_ST + 0x08) /* Watchdog Mode Register */ -#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */ -#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */ -#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */ -#define AT91_ST_RTMR (AT91_ST + 0x0c) /* Real-time Mode Register */ -#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */ -#define AT91_ST_SR (AT91_ST + 0x10) /* Status Register */ -#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */ -#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */ -#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */ -#define AT91_ST_ALMS (1 << 3) /* Alarm Status */ -#define AT91_ST_IER (AT91_ST + 0x14) /* Interrupt Enable Register */ -#define AT91_ST_IDR (AT91_ST + 0x18) /* Interrupt Disable Register */ -#define AT91_ST_IMR (AT91_ST + 0x1c) /* Interrupt Mask Register */ -#define AT91_ST_RTAR (AT91_ST + 0x20) /* Real-time Alarm Register */ -#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */ -#define AT91_ST_CRTR (AT91_ST + 0x24) /* Current Real-time Register */ -#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */ - - -/* - * Real-time Clock. - */ -#define AT91_RTC 0xe00 - -#define AT91_RTC_CR (AT91_RTC + 0x00) /* Control Register */ -#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time Register */ -#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */ -#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */ -#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8) -#define AT91_RTC_TIMEVSEL_HOUR (1 << 8) -#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8) -#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8) -#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */ -#define AT91_RTC_CALEVSEL_WEEK (0 << 16) -#define AT91_RTC_CALEVSEL_MONTH (1 << 16) -#define AT91_RTC_CALEVSEL_YEAR (2 << 16) - -#define AT91_RTC_MR (AT91_RTC + 0x04) /* Mode Register */ -#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */ - -#define AT91_RTC_TIMR (AT91_RTC + 0x08) /* Time Register */ -#define AT91_RTC_SEC (0x7f << 0) /* Current Second */ -#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */ -#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */ -#define AT91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */ - -#define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */ -#define AT91_RTC_CENT (0x7f << 0) /* Current Century */ -#define AT91_RTC_YEAR (0xff << 8) /* Current Year */ -#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */ -#define AT91_RTC_DAY (7 << 21) /* Current Day */ -#define AT91_RTC_DATE (0x3f << 24) /* Current Date */ - -#define AT91_RTC_TIMALR (AT91_RTC + 0x10) /* Time Alarm Register */ -#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enable */ -#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enable */ -#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */ - -#define AT91_RTC_CALALR (AT91_RTC + 0x14) /* Calendar Alarm Register */ -#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */ -#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */ - -#define AT91_RTC_SR (AT91_RTC + 0x18) /* Status Register */ -#define AT91_RTC_ACKUPD (1 << 0) /* Acknowledge for Update */ -#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */ -#define AT91_RTC_SECEV (1 << 2) /* Second Event */ -#define AT91_RTC_TIMEV (1 << 3) /* Time Event */ -#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */ - -#define AT91_RTC_SCCR (AT91_RTC + 0x1c) /* Status Clear Command Register */ -#define AT91_RTC_IER (AT91_RTC + 0x20) /* Interrupt Enable Register */ -#define AT91_RTC_IDR (AT91_RTC + 0x24) /* Interrupt Disable Register */ -#define AT91_RTC_IMR (AT91_RTC + 0x28) /* Interrupt Mask Register */ - -#define AT91_RTC_VER (AT91_RTC + 0x2c) /* Valid Entry Register */ -#define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ -#define AT91_RTC_NVCAL (1 << 1) /* Non valid Calendar */ -#define AT91_RTC_NVTIMALR (1 << 2) /* Non valid Time Alarm */ -#define AT91_RTC_NVCALALR (1 << 3) /* Non valid Calendar Alarm */ - - -/* - * Memory Controller. - */ -#define AT91_MC 0xf00 - -#define AT91_MC_RCR (AT91_MC + 0x00) /* MC Remap Control Register */ -#define AT91_MC_RCB (1 << 0) /* Remap Command Bit */ - -#define AT91_MC_ASR (AT91_MC + 0x04) /* MC Abort Status Register */ -#define AT91_MC_UNADD (1 << 0) /* Undefined Address Abort Status */ -#define AT91_MC_MISADD (1 << 1) /* Misaligned Address Abort Status */ -#define AT91_MC_ABTSZ (3 << 8) /* Abort Size Status */ -#define AT91_MC_ABTSZ_BYTE (0 << 8) -#define AT91_MC_ABTSZ_HALFWORD (1 << 8) -#define AT91_MC_ABTSZ_WORD (2 << 8) -#define AT91_MC_ABTTYP (3 << 10) /* Abort Type Status */ -#define AT91_MC_ABTTYP_DATAREAD (0 << 10) -#define AT91_MC_ABTTYP_DATAWRITE (1 << 10) -#define AT91_MC_ABTTYP_FETCH (2 << 10) -#define AT91_MC_MST0 (1 << 16) /* ARM920T Abort Source */ -#define AT91_MC_MST1 (1 << 17) /* PDC Abort Source */ -#define AT91_MC_MST2 (1 << 18) /* UHP Abort Source */ -#define AT91_MC_MST3 (1 << 19) /* EMAC Abort Source */ -#define AT91_MC_SVMST0 (1 << 24) /* Saved ARM920T Abort Source */ -#define AT91_MC_SVMST1 (1 << 25) /* Saved PDC Abort Source */ -#define AT91_MC_SVMST2 (1 << 26) /* Saved UHP Abort Source */ -#define AT91_MC_SVMST3 (1 << 27) /* Saved EMAC Abort Source */ - -#define AT91_MC_AASR (AT91_MC + 0x08) /* MC Abort Address Status Register */ - -#define AT91_MC_MPR (AT91_MC + 0x0c) /* MC Master Priority Register */ -#define AT91_MPR_MSTP0 (7 << 0) /* ARM920T Priority */ -#define AT91_MPR_MSTP1 (7 << 4) /* PDC Priority */ -#define AT91_MPR_MSTP2 (7 << 8) /* UHP Priority */ -#define AT91_MPR_MSTP3 (7 << 12) /* EMAC Priority */ - -/* External Bus Interface (EBI) registers */ -#define AT91_EBI_CSA (AT91_MC + 0x60) /* Chip Select Assignment Register */ -#define AT91_EBI_CS0A (1 << 0) /* Chip Select 0 Assignment */ -#define AT91_EBI_CS0A_SMC (0 << 0) -#define AT91_EBI_CS0A_BFC (1 << 0) -#define AT91_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ -#define AT91_EBI_CS1A_SMC (0 << 1) -#define AT91_EBI_CS1A_SDRAMC (1 << 1) -#define AT91_EBI_CS3A (1 << 3) /* Chip Select 2 Assignment */ -#define AT91_EBI_CS3A_SMC (0 << 3) -#define AT91_EBI_CS3A_SMC_SMARTMEDIA (1 << 3) -#define AT91_EBI_CS4A (1 << 4) /* Chip Select 3 Assignment */ -#define AT91_EBI_CS4A_SMC (0 << 4) -#define AT91_EBI_CS4A_SMC_COMPACTFLASH (1 << 4) -#define AT91_EBI_CFGR (AT91_MC + 0x64) /* Configuration Register */ -#define AT91_EBI_DBPUC (1 << 0) /* Data Bus Pull-Up Configuration */ - -/* Static Memory Controller (SMC) registers */ -#define AT91_SMC_CSR(n) (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */ -#define AT91_SMC_NWS (0x7f << 0) /* Number of Wait States */ -#define AT91_SMC_NWS_(x) ((x) << 0) -#define AT91_SMC_WSEN (1 << 7) /* Wait State Enable */ -#define AT91_SMC_TDF (0xf << 8) /* Data Float Time */ -#define AT91_SMC_TDF_(x) ((x) << 8) -#define AT91_SMC_BAT (1 << 12) /* Byte Access Type */ -#define AT91_SMC_DBW (3 << 13) /* Data Bus Width */ -#define AT91_SMC_DBW_16 (1 << 13) -#define AT91_SMC_DBW_8 (2 << 13) -#define AT91_SMC_DPR (1 << 15) /* Data Read Protocol */ -#define AT91_SMC_ACSS (3 << 16) /* Address to Chip Select Setup */ -#define AT91_SMC_ACSS_STD (0 << 16) -#define AT91_SMC_ACSS_1 (1 << 16) -#define AT91_SMC_ACSS_2 (2 << 16) -#define AT91_SMC_ACSS_3 (3 << 16) -#define AT91_SMC_RWSETUP (7 << 24) /* Read & Write Signal Time Setup */ -#define AT91_SMC_RWSETUP_(x) ((x) << 24) -#define AT91_SMC_RWHOLD (7 << 28) /* Read & Write Signal Hold Time */ -#define AT91_SMC_RWHOLD_(x) ((x) << 28) - -/* SDRAM Controller registers */ -#define AT91_SDRAMC_MR (AT91_MC + 0x90) /* Mode Register */ -#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */ -#define AT91_SDRAMC_MODE_NORMAL (0 << 0) -#define AT91_SDRAMC_MODE_NOP (1 << 0) -#define AT91_SDRAMC_MODE_PRECHARGE (2 << 0) -#define AT91_SDRAMC_MODE_LMR (3 << 0) -#define AT91_SDRAMC_MODE_REFRESH (4 << 0) -#define AT91_SDRAMC_DBW (1 << 4) /* Data Bus Width */ -#define AT91_SDRAMC_DBW_32 (0 << 4) -#define AT91_SDRAMC_DBW_16 (1 << 4) - -#define AT91_SDRAMC_TR (AT91_MC + 0x94) /* Refresh Timer Register */ -#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Count */ - -#define AT91_SDRAMC_CR (AT91_MC + 0x98) /* Configuration Register */ -#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */ -#define AT91_SDRAMC_NC_8 (0 << 0) -#define AT91_SDRAMC_NC_9 (1 << 0) -#define AT91_SDRAMC_NC_10 (2 << 0) -#define AT91_SDRAMC_NC_11 (3 << 0) -#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */ -#define AT91_SDRAMC_NR_11 (0 << 2) -#define AT91_SDRAMC_NR_12 (1 << 2) -#define AT91_SDRAMC_NR_13 (2 << 2) -#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */ -#define AT91_SDRAMC_NB_2 (0 << 4) -#define AT91_SDRAMC_NB_4 (1 << 4) -#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */ -#define AT91_SDRAMC_CAS_2 (2 << 5) -#define AT91_SDRAMC_TWR (0xf << 7) /* Write Recovery Delay */ -#define AT91_SDRAMC_TRC (0xf << 11) /* Row Cycle Delay */ -#define AT91_SDRAMC_TRP (0xf << 15) /* Row Precharge Delay */ -#define AT91_SDRAMC_TRCD (0xf << 19) /* Row to Column Delay */ -#define AT91_SDRAMC_TRAS (0xf << 23) /* Active to Precharge Delay */ -#define AT91_SDRAMC_TXSR (0xf << 27) /* Exit Self Refresh to Active Delay */ - -#define AT91_SDRAMC_SRR (AT91_MC + 0x9c) /* Self Refresh Register */ -#define AT91_SDRAMC_LPR (AT91_MC + 0xa0) /* Low Power Register */ -#define AT91_SDRAMC_IER (AT91_MC + 0xa4) /* Interrupt Enable Register */ -#define AT91_SDRAMC_IDR (AT91_MC + 0xa8) /* Interrupt Disable Register */ -#define AT91_SDRAMC_IMR (AT91_MC + 0xac) /* Interrupt Mask Register */ -#define AT91_SDRAMC_ISR (AT91_MC + 0xb0) /* Interrupt Status Register */ - -/* Burst Flash Controller register */ -#define AT91_BFC_MR (AT91_MC + 0xc0) /* Mode Register */ -#define AT91_BFC_BFCOM (3 << 0) /* Burst Flash Controller Operating Mode */ -#define AT91_BFC_BFCOM_DISABLED (0 << 0) -#define AT91_BFC_BFCOM_ASYNC (1 << 0) -#define AT91_BFC_BFCOM_BURST (2 << 0) -#define AT91_BFC_BFCC (3 << 2) /* Burst Flash Controller Clock */ -#define AT91_BFC_BFCC_MCK (1 << 2) -#define AT91_BFC_BFCC_DIV2 (2 << 2) -#define AT91_BFC_BFCC_DIV4 (3 << 2) -#define AT91_BFC_AVL (0xf << 4) /* Address Valid Latency */ -#define AT91_BFC_PAGES (7 << 8) /* Page Size */ -#define AT91_BFC_PAGES_NO_PAGE (0 << 8) -#define AT91_BFC_PAGES_16 (1 << 8) -#define AT91_BFC_PAGES_32 (2 << 8) -#define AT91_BFC_PAGES_64 (3 << 8) -#define AT91_BFC_PAGES_128 (4 << 8) -#define AT91_BFC_PAGES_256 (5 << 8) -#define AT91_BFC_PAGES_512 (6 << 8) -#define AT91_BFC_PAGES_1024 (7 << 8) -#define AT91_BFC_OEL (3 << 12) /* Output Enable Latency */ -#define AT91_BFC_BAAEN (1 << 16) /* Burst Address Advance Enable */ -#define AT91_BFC_BFOEH (1 << 17) /* Burst Flash Output Enable Handling */ -#define AT91_BFC_MUXEN (1 << 18) /* Multiplexed Bus Enable */ -#define AT91_BFC_RDYEN (1 << 19) /* Ready Enable Mode */ - -#endif -- cgit v0.10.2 From a5c474580b8b7cc8b7b2cca9a2bd27ff5c065e70 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 16:08:49 +0100 Subject: [ARM] 3951/1: AT91: Rename user peripheral header files Most of the AT91RM9200 user peripherals are also integrated into the Atmel SAM9 range of processors. This patch renames the headers from at91rm9200_xx.h to at91_xx.h to indicate they're not at91rm9200-specific. The new SAM9-specific registers and register bits have also been defined. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/include/asm-arm/arch-at91rm9200/at91_mci.h b/include/asm-arm/arch-at91rm9200/at91_mci.h new file mode 100644 index 0000000..9a552cb --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_mci.h @@ -0,0 +1,106 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_mci.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * MultiMedia Card Interface (MCI) registers. + * Based on AT91RM9200 datasheet revision F. + * + * 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. + */ + +#ifndef AT91_MCI_H +#define AT91_MCI_H + +#define AT91_MCI_CR 0x00 /* Control Register */ +#define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */ +#define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */ +#define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */ +#define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */ +#define AT91_MCI_SWRST (1 << 7) /* Software Reset */ + +#define AT91_MCI_MR 0x04 /* Mode Register */ +#define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */ +#define AT91_MCI_PWSDIV (7 << 8) /* Power Saving Divider */ +#define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */ +#define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */ +#define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */ + +#define AT91_MCI_DTOR 0x08 /* Data Timeout Register */ +#define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */ +#define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */ +#define AT91_MCI_DTOMUL_1 (0 << 4) +#define AT91_MCI_DTOMUL_16 (1 << 4) +#define AT91_MCI_DTOMUL_128 (2 << 4) +#define AT91_MCI_DTOMUL_256 (3 << 4) +#define AT91_MCI_DTOMUL_1K (4 << 4) +#define AT91_MCI_DTOMUL_4K (5 << 4) +#define AT91_MCI_DTOMUL_64K (6 << 4) +#define AT91_MCI_DTOMUL_1M (7 << 4) + +#define AT91_MCI_SDCR 0x0c /* SD Card Register */ +#define AT91_MCI_SDCSEL (3 << 0) /* SD Card Selector */ +#define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */ + +#define AT91_MCI_ARGR 0x10 /* Argument Register */ + +#define AT91_MCI_CMDR 0x14 /* Command Register */ +#define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */ +#define AT91_MCI_RSPTYP (3 << 6) /* Response Type */ +#define AT91_MCI_RSPTYP_NONE (0 << 6) +#define AT91_MCI_RSPTYP_48 (1 << 6) +#define AT91_MCI_RSPTYP_136 (2 << 6) +#define AT91_MCI_SPCMD (7 << 8) /* Special Command */ +#define AT91_MCI_SPCMD_NONE (0 << 8) +#define AT91_MCI_SPCMD_INIT (1 << 8) +#define AT91_MCI_SPCMD_SYNC (2 << 8) +#define AT91_MCI_SPCMD_ICMD (4 << 8) +#define AT91_MCI_SPCMD_IRESP (5 << 8) +#define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */ +#define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */ +#define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */ +#define AT91_MCI_TRCMD_NONE (0 << 16) +#define AT91_MCI_TRCMD_START (1 << 16) +#define AT91_MCI_TRCMD_STOP (2 << 16) +#define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */ +#define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */ +#define AT91_MCI_TRTYP_BLOCK (0 << 19) +#define AT91_MCI_TRTYP_MULTIPLE (1 << 19) +#define AT91_MCI_TRTYP_STREAM (2 << 19) + +#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */ +#define AT91_MCR_RDR 0x30 /* Receive Data Register */ +#define AT91_MCR_TDR 0x34 /* Transmit Data Register */ + +#define AT91_MCI_SR 0x40 /* Status Register */ +#define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */ +#define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */ +#define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */ +#define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */ +#define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */ +#define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */ +#define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */ +#define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */ +#define AT91_MCI_SDIOIRQA (1 << 8) /* SDIO Interrupt for Slot A */ +#define At91_MCI_SDIOIRQB (1 << 9) /* SDIO Interrupt for Slot B [AT91RM9200 only] */ +#define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */ +#define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */ +#define AT91_MCI_RINDE (1 << 16) /* Response Index Error */ +#define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */ +#define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */ +#define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */ +#define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */ +#define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */ +#define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */ +#define AT91_MCI_OVRE (1 << 30) /* Overrun */ +#define AT91_MCI_UNRE (1 << 31) /* Underrun */ + +#define AT91_MCI_IER 0x44 /* Interrupt Enable Register */ +#define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */ +#define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_spi.h b/include/asm-arm/arch-at91rm9200/at91_spi.h new file mode 100644 index 0000000..bec48ca --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_spi.h @@ -0,0 +1,81 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_spi.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Serial Peripheral Interface (SPI) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_SPI_H +#define AT91_SPI_H + +#define AT91_SPI_CR 0x00 /* Control Register */ +#define AT91_SPI_SPIEN (1 << 0) /* SPI Enable */ +#define AT91_SPI_SPIDIS (1 << 1) /* SPI Disable */ +#define AT91_SPI_SWRST (1 << 7) /* SPI Software Reset */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_MR 0x04 /* Mode Register */ +#define AT91_SPI_MSTR (1 << 0) /* Master/Slave Mode */ +#define AT91_SPI_PS (1 << 1) /* Peripheral Select */ +#define AT91_SPI_PS_FIXED (0 << 1) +#define AT91_SPI_PS_VARIABLE (1 << 1) +#define AT91_SPI_PCSDEC (1 << 2) /* Chip Select Decode */ +#define AT91_SPI_DIV32 (1 << 3) /* Clock Selection [AT91RM9200 only] */ +#define AT91_SPI_MODFDIS (1 << 4) /* Mode Fault Detection */ +#define AT91_SPI_LLB (1 << 7) /* Local Loopback Enable */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_DLYBCS (0xff << 24) /* Delay Between Chip Selects */ + +#define AT91_SPI_RDR 0x08 /* Receive Data Register */ +#define AT91_SPI_RD (0xffff << 0) /* Receive Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ + +#define AT91_SPI_TDR 0x0c /* Transmit Data Register */ +#define AT91_SPI_TD (0xffff << 0) /* Transmit Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_SR 0x10 /* Status Register */ +#define AT91_SPI_RDRF (1 << 0) /* Receive Data Register Full */ +#define AT91_SPI_TDRE (1 << 1) /* Transmit Data Register Full */ +#define AT91_SPI_MODF (1 << 2) /* Mode Fault Error */ +#define AT91_SPI_OVRES (1 << 3) /* Overrun Error Status */ +#define AT91_SPI_ENDRX (1 << 4) /* End of RX buffer */ +#define AT91_SPI_ENDTX (1 << 5) /* End of TX buffer */ +#define AT91_SPI_RXBUFF (1 << 6) /* RX Buffer Full */ +#define AT91_SPI_TXBUFE (1 << 7) /* TX Buffer Empty */ +#define AT91_SPI_NSSR (1 << 8) /* NSS Rising [SAM9261 only] */ +#define AT91_SPI_TXEMPTY (1 << 9) /* Transmission Register Empty [SAM9261 only] */ +#define AT91_SPI_SPIENS (1 << 16) /* SPI Enable Status */ + +#define AT91_SPI_IER 0x14 /* Interrupt Enable Register */ +#define AT91_SPI_IDR 0x18 /* Interrupt Disable Register */ +#define AT91_SPI_IMR 0x1c /* Interrupt Mask Register */ + +#define AT91_SPI_CSR(n) (0x30 + ((n) * 4)) /* Chip Select Registers 0-3 */ +#define AT91_SPI_CPOL (1 << 0) /* Clock Polarity */ +#define AT91_SPI_NCPHA (1 << 1) /* Clock Phase */ +#define AT91_SPI_CSAAT (1 << 3) /* Chip Select Active After Transfer [SAM9261 only] */ +#define AT91_SPI_BITS (0xf << 4) /* Bits Per Transfer */ +#define AT91_SPI_BITS_8 (0 << 4) +#define AT91_SPI_BITS_9 (1 << 4) +#define AT91_SPI_BITS_10 (2 << 4) +#define AT91_SPI_BITS_11 (3 << 4) +#define AT91_SPI_BITS_12 (4 << 4) +#define AT91_SPI_BITS_13 (5 << 4) +#define AT91_SPI_BITS_14 (6 << 4) +#define AT91_SPI_BITS_15 (7 << 4) +#define AT91_SPI_BITS_16 (8 << 4) +#define AT91_SPI_SCBR (0xff << 8) /* Serial Clock Baud Rate */ +#define AT91_SPI_DLYBS (0xff << 16) /* Delay before SPCK */ +#define AT91_SPI_DLYBCT (0xff << 24) /* Delay between Consecutive Transfers */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_ssc.h b/include/asm-arm/arch-at91rm9200/at91_ssc.h new file mode 100644 index 0000000..694bcaa --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_ssc.h @@ -0,0 +1,106 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_ssc.h + * + * Copyright (C) SAN People + * + * Serial Synchronous Controller (SSC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_SSC_H +#define AT91_SSC_H + +#define AT91_SSC_CR 0x00 /* Control Register */ +#define AT91_SSC_RXEN (1 << 0) /* Receive Enable */ +#define AT91_SSC_RXDIS (1 << 1) /* Receive Disable */ +#define AT91_SSC_TXEN (1 << 8) /* Transmit Enable */ +#define AT91_SSC_TXDIS (1 << 9) /* Transmit Disable */ +#define AT91_SSC_SWRST (1 << 15) /* Software Reset */ + +#define AT91_SSC_CMR 0x04 /* Clock Mode Register */ +#define AT91_SSC_CMR_DIV (0xfff << 0) /* Clock Divider */ + +#define AT91_SSC_RCMR 0x10 /* Receive Clock Mode Register */ +#define AT91_SSC_CKS (3 << 0) /* Clock Selection */ +#define AT91_SSC_CKS_DIV (0 << 0) +#define AT91_SSC_CKS_CLOCK (1 << 0) +#define AT91_SSC_CKS_PIN (2 << 0) +#define AT91_SSC_CKO (7 << 2) /* Clock Output Mode Selection */ +#define AT91_SSC_CKO_NONE (0 << 2) +#define AT91_SSC_CKO_CONTINUOUS (1 << 2) +#define AT91_SSC_CKI (1 << 5) /* Clock Inversion */ +#define AT91_SSC_CKI_FALLING (0 << 5) +#define AT91_SSC_CK_RISING (1 << 5) +#define AT91_SSC_CKG (1 << 6) /* Receive Clock Gating Selection [AT91SAM9261 only] */ +#define AT91_SSC_CKG_NONE (0 << 6) +#define AT91_SSC_CKG_RFLOW (1 << 6) +#define AT91_SSC_CKG_RFHIGH (2 << 6) +#define AT91_SSC_START (0xf << 8) /* Start Selection */ +#define AT91_SSC_START_CONTINUOUS (0 << 8) +#define AT91_SSC_START_TX_RX (1 << 8) +#define AT91_SSC_START_LOW_RF (2 << 8) +#define AT91_SSC_START_HIGH_RF (3 << 8) +#define AT91_SSC_START_FALLING_RF (4 << 8) +#define AT91_SSC_START_RISING_RF (5 << 8) +#define AT91_SSC_START_LEVEL_RF (6 << 8) +#define AT91_SSC_START_EDGE_RF (7 << 8) +#define AT91_SSC_STOP (1 << 12) /* Receive Stop Selection [AT91SAM9261 only] */ +#define AT91_SSC_STTDLY (0xff << 16) /* Start Delay */ +#define AT91_SSC_PERIOD (0xff << 24) /* Period Divider Selection */ + +#define AT91_SSC_RFMR 0x14 /* Receive Frame Mode Register */ +#define AT91_SSC_DATALEN (0x1f << 0) /* Data Length */ +#define AT91_SSC_LOOP (1 << 5) /* Loop Mode */ +#define AT91_SSC_MSBF (1 << 7) /* Most Significant Bit First */ +#define AT91_SSC_DATNB (0xf << 8) /* Data Number per Frame */ +#define AT91_SSC_FSLEN (0xf << 16) /* Frame Sync Length */ +#define AT91_SSC_FSOS (7 << 20) /* Frame Sync Output Selection */ +#define AT91_SSC_FSOS_NONE (0 << 20) +#define AT91_SSC_FSOS_NEGATIVE (1 << 20) +#define AT91_SSC_FSOS_POSITIVE (2 << 20) +#define AT91_SSC_FSOS_LOW (3 << 20) +#define AT91_SSC_FSOS_HIGH (4 << 20) +#define AT91_SSC_FSOS_TOGGLE (5 << 20) +#define AT91_SSC_FSEDGE (1 << 24) /* Frame Sync Edge Detection */ +#define AT91_SSC_FSEDGE_POSITIVE (0 << 24) +#define AT91_SSC_FSEDGE_NEGATIVE (1 << 24) + +#define AT91_SSC_TCMR 0x18 /* Transmit Clock Mode Register */ +#define AT91_SSC_TFMR 0x1c /* Transmit Fram Mode Register */ +#define AT91_SSC_DATDEF (1 << 5) /* Data Default Value */ +#define AT91_SSC_FSDEN (1 << 23) /* Frame Sync Data Enable */ + +#define AT91_SSC_RHR 0x20 /* Receive Holding Register */ +#define AT91_SSC_THR 0x24 /* Transmit Holding Register */ +#define AT91_SSC_RSHR 0x30 /* Receive Sync Holding Register */ +#define AT91_SSC_TSHR 0x34 /* Transmit Sync Holding Register */ + +#define AT91_SSC_RC0R 0x38 /* Receive Compare 0 Register [AT91SAM9261 only] */ +#define AT91_SSC_RC1R 0x3c /* Receive Compare 1 Register [AT91SAM9261 only] */ + +#define AT91_SSC_SR 0x40 /* Status Register */ +#define AT91_SSC_TXRDY (1 << 0) /* Transmit Ready */ +#define AT91_SSC_TXEMPTY (1 << 1) /* Transmit Empty */ +#define AT91_SSC_ENDTX (1 << 2) /* End of Transmission */ +#define AT91_SSC_TXBUFE (1 << 3) /* Transmit Buffer Empty */ +#define AT91_SSC_RXRDY (1 << 4) /* Receive Ready */ +#define AT91_SSC_OVRUN (1 << 5) /* Receive Overrun */ +#define AT91_SSC_ENDRX (1 << 6) /* End of Reception */ +#define AT91_SSC_RXBUFF (1 << 7) /* Receive Buffer Full */ +#define AT91_SSC_CP0 (1 << 8) /* Compare 0 [AT91SAM9261 only] */ +#define AT91_SSC_CP1 (1 << 9) /* Compare 1 [AT91SAM9261 only] */ +#define AT91_SSC_TXSYN (1 << 10) /* Transmit Sync */ +#define AT91_SSC_RXSYN (1 << 11) /* Receive Sync */ +#define AT91_SSC_TXENA (1 << 16) /* Transmit Enable */ +#define AT91_SSC_RXENA (1 << 17) /* Receive Enable */ + +#define AT91_SSC_IER 0x44 /* Interrupt Enable Register */ +#define AT91_SSC_IDR 0x48 /* Interrupt Disable Register */ +#define AT91_SSC_IMR 0x4c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_tc.h b/include/asm-arm/arch-at91rm9200/at91_tc.h new file mode 100644 index 0000000..8d06eb0 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_tc.h @@ -0,0 +1,146 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_tc.h + * + * Copyright (C) SAN People + * + * Timer/Counter Unit (TC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_TC_H +#define AT91_TC_H + +#define AT91_TC_BCR 0xc0 /* TC Block Control Register */ +#define AT91_TC_SYNC (1 << 0) /* Synchro Command */ + +#define AT91_TC_BMR 0xc4 /* TC Block Mode Register */ +#define AT91_TC_TC0XC0S (3 << 0) /* External Clock Signal 0 Selection */ +#define AT91_TC_TC0XC0S_TCLK0 (0 << 0) +#define AT91_TC_TC0XC0S_NONE (1 << 0) +#define AT91_TC_TC0XC0S_TIOA1 (2 << 0) +#define AT91_TC_TC0XC0S_TIOA2 (3 << 0) +#define AT91_TC_TC1XC1S (3 << 2) /* External Clock Signal 1 Selection */ +#define AT91_TC_TC1XC1S_TCLK1 (0 << 2) +#define AT91_TC_TC1XC1S_NONE (1 << 2) +#define AT91_TC_TC1XC1S_TIOA0 (2 << 2) +#define AT91_TC_TC1XC1S_TIOA2 (3 << 2) +#define AT91_TC_TC2XC2S (3 << 4) /* External Clock Signal 2 Selection */ +#define AT91_TC_TC2XC2S_TCLK2 (0 << 4) +#define AT91_TC_TC2XC2S_NONE (1 << 4) +#define AT91_TC_TC2XC2S_TIOA0 (2 << 4) +#define AT91_TC_TC2XC2S_TIOA1 (3 << 4) + + +#define AT91_TC_CCR 0x00 /* Channel Control Register */ +#define AT91_TC_CLKEN (1 << 0) /* Counter Clock Enable Command */ +#define AT91_TC_CLKDIS (1 << 1) /* Counter CLock Disable Command */ +#define AT91_TC_SWTRG (1 << 2) /* Software Trigger Command */ + +#define AT91_TC_CMR 0x04 /* Channel Mode Register */ +#define AT91_TC_TCCLKS (7 << 0) /* Capture/Waveform Mode: Clock Selection */ +#define AT91_TC_TIMER_CLOCK1 (0 << 0) +#define AT91_TC_TIMER_CLOCK2 (1 << 0) +#define AT91_TC_TIMER_CLOCK3 (2 << 0) +#define AT91_TC_TIMER_CLOCK4 (3 << 0) +#define AT91_TC_TIMER_CLOCK5 (4 << 0) +#define AT91_TC_XC0 (5 << 0) +#define AT91_TC_XC1 (6 << 0) +#define AT91_TC_XC2 (7 << 0) +#define AT91_TC_CLKI (1 << 3) /* Capture/Waveform Mode: Clock Invert */ +#define AT91_TC_BURST (3 << 4) /* Capture/Waveform Mode: Burst Signal Selection */ +#define AT91_TC_LDBSTOP (1 << 6) /* Capture Mode: Counter Clock Stopped with TB Loading */ +#define AT91_TC_LDBDIS (1 << 7) /* Capture Mode: Counter Clock Disable with RB Loading */ +#define AT91_TC_ETRGEDG (3 << 8) /* Capture Mode: External Trigger Edge Selection */ +#define AT91_TC_ABETRG (1 << 10) /* Capture Mode: TIOA or TIOB External Trigger Selection */ +#define AT91_TC_CPCTRG (1 << 14) /* Capture Mode: RC Compare Trigger Enable */ +#define AT91_TC_WAVE (1 << 15) /* Capture/Waveform mode */ +#define AT91_TC_LDRA (3 << 16) /* Capture Mode: RA Loading Selection */ +#define AT91_TC_LDRB (3 << 18) /* Capture Mode: RB Loading Selection */ + +#define AT91_TC_CPCSTOP (1 << 6) /* Waveform Mode: Counter Clock Stopped with RC Compare */ +#define AT91_TC_CPCDIS (1 << 7) /* Waveform Mode: Counter Clock Disable with RC Compare */ +#define AT91_TC_EEVTEDG (3 << 8) /* Waveform Mode: External Event Edge Selection */ +#define AT91_TC_EEVTEDG_NONE (0 << 8) +#define AT91_TC_EEVTEDG_RISING (1 << 8) +#define AT91_TC_EEVTEDG_FALLING (2 << 8) +#define AT91_TC_EEVTEDG_BOTH (3 << 8) +#define AT91_TC_EEVT (3 << 10) /* Waveform Mode: External Event Selection */ +#define AT91_TC_EEVT_TIOB (0 << 10) +#define AT91_TC_EEVT_XC0 (1 << 10) +#define AT91_TC_EEVT_XC1 (2 << 10) +#define AT91_TC_EEVT_XC2 (3 << 10) +#define AT91_TC_ENETRG (1 << 12) /* Waveform Mode: External Event Trigger Enable */ +#define AT91_TC_WAVESEL (3 << 13) /* Waveform Mode: Waveform Selection */ +#define AT91_TC_WAVESEL_UP (0 << 13) +#define AT91_TC_WAVESEL_UP_AUTO (2 << 13) +#define AT91_TC_WAVESEL_UPDOWN (1 << 13) +#define AT91_TC_WAVESEL_UPDOWN_AUTO (3 << 13) +#define AT91_TC_ACPA (3 << 16) /* Waveform Mode: RA Compare Effect on TIOA */ +#define AT91_TC_ACPA_NONE (0 << 16) +#define AT91_TC_ACPA_SET (1 << 16) +#define AT91_TC_ACPA_CLEAR (2 << 16) +#define AT91_TC_ACPA_TOGGLE (3 << 16) +#define AT91_TC_ACPC (3 << 18) /* Waveform Mode: RC Compre Effect on TIOA */ +#define AT91_TC_ACPC_NONE (0 << 18) +#define AT91_TC_ACPC_SET (1 << 18) +#define AT91_TC_ACPC_CLEAR (2 << 18) +#define AT91_TC_ACPC_TOGGLE (3 << 18) +#define AT91_TC_AEEVT (3 << 20) /* Waveform Mode: External Event Effect on TIOA */ +#define AT91_TC_AEEVT_NONE (0 << 20) +#define AT91_TC_AEEVT_SET (1 << 20) +#define AT91_TC_AEEVT_CLEAR (2 << 20) +#define AT91_TC_AEEVT_TOGGLE (3 << 20) +#define AT91_TC_ASWTRG (3 << 22) /* Waveform Mode: Software Trigger Effect on TIOA */ +#define AT91_TC_ASWTRG_NONE (0 << 22) +#define AT91_TC_ASWTRG_SET (1 << 22) +#define AT91_TC_ASWTRG_CLEAR (2 << 22) +#define AT91_TC_ASWTRG_TOGGLE (3 << 22) +#define AT91_TC_BCPB (3 << 24) /* Waveform Mode: RB Compare Effect on TIOB */ +#define AT91_TC_BCPB_NONE (0 << 24) +#define AT91_TC_BCPB_SET (1 << 24) +#define AT91_TC_BCPB_CLEAR (2 << 24) +#define AT91_TC_BCPB_TOGGLE (3 << 24) +#define AT91_TC_BCPC (3 << 26) /* Waveform Mode: RC Compare Effect on TIOB */ +#define AT91_TC_BCPC_NONE (0 << 26) +#define AT91_TC_BCPC_SET (1 << 26) +#define AT91_TC_BCPC_CLEAR (2 << 26) +#define AT91_TC_BCPC_TOGGLE (3 << 26) +#define AT91_TC_BEEVT (3 << 28) /* Waveform Mode: External Event Effect on TIOB */ +#define AT91_TC_BEEVT_NONE (0 << 28) +#define AT91_TC_BEEVT_SET (1 << 28) +#define AT91_TC_BEEVT_CLEAR (2 << 28) +#define AT91_TC_BEEVT_TOGGLE (3 << 28) +#define AT91_TC_BSWTRG (3 << 30) /* Waveform Mode: Software Trigger Effect on TIOB */ +#define AT91_TC_BSWTRG_NONE (0 << 30) +#define AT91_TC_BSWTRG_SET (1 << 30) +#define AT91_TC_BSWTRG_CLEAR (2 << 30) +#define AT91_TC_BSWTRG_TOGGLE (3 << 30) + +#define AT91_TC_CV 0x10 /* Counter Value */ +#define AT91_TC_RA 0x14 /* Register A */ +#define AT91_TC_RB 0x18 /* Register B */ +#define AT91_TC_RC 0x1c /* Register C */ + +#define AT91_TC_SR 0x20 /* Status Register */ +#define AT91_TC_COVFS (1 << 0) /* Counter Overflow Status */ +#define AT91_TC_LOVRS (1 << 1) /* Load Overrun Status */ +#define AT91_TC_CPAS (1 << 2) /* RA Compare Status */ +#define AT91_TC_CPBS (1 << 3) /* RB Compare Status */ +#define AT91_TC_CPCS (1 << 4) /* RC Compare Status */ +#define AT91_TC_LDRAS (1 << 5) /* RA Loading Status */ +#define AT91_TC_LDRBS (1 << 6) /* RB Loading Status */ +#define AT91_TC_ETRGS (1 << 7) /* External Trigger Status */ +#define AT91_TC_CLKSTA (1 << 16) /* Clock Enabling Status */ +#define AT91_TC_MTIOA (1 << 17) /* TIOA Mirror */ +#define AT91_TC_MTIOB (1 << 18) /* TIOB Mirror */ + +#define AT91_TC_IER 0x24 /* Interrupt Enable Register */ +#define AT91_TC_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_TC_IMR 0x2c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_twi.h b/include/asm-arm/arch-at91rm9200/at91_twi.h new file mode 100644 index 0000000..cda914f --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_twi.h @@ -0,0 +1,57 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_twi.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Two-wire Interface (TWI) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_TWI_H +#define AT91_TWI_H + +#define AT91_TWI_CR 0x00 /* Control Register */ +#define AT91_TWI_START (1 << 0) /* Send a Start Condition */ +#define AT91_TWI_STOP (1 << 1) /* Send a Stop Condition */ +#define AT91_TWI_MSEN (1 << 2) /* Master Transfer Enable */ +#define AT91_TWI_MSDIS (1 << 3) /* Master Transfer Disable */ +#define AT91_TWI_SWRST (1 << 7) /* Software Reset */ + +#define AT91_TWI_MMR 0x04 /* Master Mode Register */ +#define AT91_TWI_IADRSZ (3 << 8) /* Internal Device Address Size */ +#define AT91_TWI_IADRSZ_NO (0 << 8) +#define AT91_TWI_IADRSZ_1 (1 << 8) +#define AT91_TWI_IADRSZ_2 (2 << 8) +#define AT91_TWI_IADRSZ_3 (3 << 8) +#define AT91_TWI_MREAD (1 << 12) /* Master Read Direction */ +#define AT91_TWI_DADR (0x7f << 16) /* Device Address */ + +#define AT91_TWI_IADR 0x0c /* Internal Address Register */ + +#define AT91_TWI_CWGR 0x10 /* Clock Waveform Generator Register */ +#define AT91_TWI_CLDIV (0xff << 0) /* Clock Low Divisor */ +#define AT91_TWI_CHDIV (0xff << 8) /* Clock High Divisor */ +#define AT91_TWI_CKDIV (7 << 16) /* Clock Divider */ + +#define AT91_TWI_SR 0x20 /* Status Register */ +#define AT91_TWI_TXCOMP (1 << 0) /* Transmission Complete */ +#define AT91_TWI_RXRDY (1 << 1) /* Receive Holding Register Ready */ +#define AT91_TWI_TXRDY (1 << 2) /* Transmit Holding Register Ready */ +#define AT91_TWI_OVRE (1 << 6) /* Overrun Error [AT91RM9200 only] */ +#define AT91_TWI_UNRE (1 << 7) /* Underrun Error [AT91RM9200 only] */ +#define AT91_TWI_NACK (1 << 8) /* Not Acknowledged */ + +#define AT91_TWI_IER 0x24 /* Interrupt Enable Register */ +#define AT91_TWI_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_TWI_IMR 0x2c /* Interrupt Mask Register */ +#define AT91_TWI_RHR 0x30 /* Receive Holding Register */ +#define AT91_TWI_THR 0x34 /* Transmit Holding Register */ + +#endif + diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h deleted file mode 100644 index f28636d..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * MultiMedia Card Interface (MCI) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_MCI_H -#define AT91RM9200_MCI_H - -#define AT91_MCI_CR 0x00 /* Control Register */ -#define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */ -#define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */ -#define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */ -#define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */ -#define AT91_MCI_SWRST (1 << 7) /* Software Reset */ - -#define AT91_MCI_MR 0x04 /* Mode Register */ -#define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */ -#define AT91_MCI_PWSDIV (3 << 8) /* Power Saving Divider */ -#define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */ -#define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */ -#define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */ - -#define AT91_MCI_DTOR 0x08 /* Data Timeout Register */ -#define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */ -#define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */ -#define AT91_MCI_DTOMUL_1 (0 << 4) -#define AT91_MCI_DTOMUL_16 (1 << 4) -#define AT91_MCI_DTOMUL_128 (2 << 4) -#define AT91_MCI_DTOMUL_256 (3 << 4) -#define AT91_MCI_DTOMUL_1K (4 << 4) -#define AT91_MCI_DTOMUL_4K (5 << 4) -#define AT91_MCI_DTOMUL_64K (6 << 4) -#define AT91_MCI_DTOMUL_1M (7 << 4) - -#define AT91_MCI_SDCR 0x0c /* SD Card Register */ -#define AT91_MCI_SDCSEL (0xf << 0) /* SD Card Selector */ -#define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */ - -#define AT91_MCI_ARGR 0x10 /* Argument Register */ - -#define AT91_MCI_CMDR 0x14 /* Command Register */ -#define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */ -#define AT91_MCI_RSPTYP (3 << 6) /* Response Type */ -#define AT91_MCI_RSPTYP_NONE (0 << 6) -#define AT91_MCI_RSPTYP_48 (1 << 6) -#define AT91_MCI_RSPTYP_136 (2 << 6) -#define AT91_MCI_SPCMD (7 << 8) /* Special Command */ -#define AT91_MCI_SPCMD_NONE (0 << 8) -#define AT91_MCI_SPCMD_INIT (1 << 8) -#define AT91_MCI_SPCMD_SYNC (2 << 8) -#define AT91_MCI_SPCMD_ICMD (4 << 8) -#define AT91_MCI_SPCMD_IRESP (5 << 8) -#define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */ -#define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */ -#define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */ -#define AT91_MCI_TRCMD_NONE (0 << 16) -#define AT91_MCI_TRCMD_START (1 << 16) -#define AT91_MCI_TRCMD_STOP (2 << 16) -#define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */ -#define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */ -#define AT91_MCI_TRTYP_BLOCK (0 << 19) -#define AT91_MCI_TRTYP_MULTIPLE (1 << 19) -#define AT91_MCI_TRTYP_STREAM (2 << 19) - -#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */ -#define AT91_MCR_RDR 0x30 /* Receive Data Register */ -#define AT91_MCR_TDR 0x34 /* Transmit Data Register */ - -#define AT91_MCI_SR 0x40 /* Status Register */ -#define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */ -#define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */ -#define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */ -#define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */ -#define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */ -#define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */ -#define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */ -#define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */ -#define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */ -#define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */ -#define AT91_MCI_RINDE (1 << 16) /* Response Index Error */ -#define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */ -#define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */ -#define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */ -#define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */ -#define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */ -#define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */ -#define AT91_MCI_OVRE (1 << 30) /* Overrun */ -#define AT91_MCI_UNRE (1 << 31) /* Underrun */ - -#define AT91_MCI_IER 0x44 /* Interrupt Enable Register */ -#define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */ -#define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */ - -#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h deleted file mode 100644 index ce1150d44..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Peripheral Data Controller (PDC) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_PDC_H -#define AT91RM9200_PDC_H - -#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ -#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ -#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ -#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ -#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ -#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ -#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ -#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ - -#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ -#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ -#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ -#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ -#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ - -#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ - -#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h deleted file mode 100644 index bff5ea4..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Serial Peripheral Interface (SPI) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_SPI_H -#define AT91RM9200_SPI_H - -#define AT91_SPI_CR 0x00 /* Control Register */ -#define AT91_SPI_SPIEN (1 << 0) /* SPI Enable */ -#define AT91_SPI_SPIDIS (1 << 1) /* SPI Disable */ -#define AT91_SPI_SWRST (1 << 7) /* SPI Software Reset */ -#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ - -#define AT91_SPI_MR 0x04 /* Mode Register */ -#define AT91_SPI_MSTR (1 << 0) /* Master/Slave Mode */ -#define AT91_SPI_PS (1 << 1) /* Peripheral Select */ -#define AT91_SPI_PS_FIXED (0 << 1) -#define AT91_SPI_PS_VARIABLE (1 << 1) -#define AT91_SPI_PCSDEC (1 << 2) /* Chip Select Decode */ -#define AT91_SPI_DIV32 (1 << 3) /* Clock Selection */ -#define AT91_SPI_MODFDIS (1 << 4) /* Mode Fault Detection */ -#define AT91_SPI_LLB (1 << 7) /* Local Loopback Enable */ -#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ -#define AT91_SPI_DLYBCS (0xff << 24) /* Delay Between Chip Selects */ - -#define AT91_SPI_RDR 0x08 /* Receive Data Register */ -#define AT91_SPI_RD (0xffff << 0) /* Receive Data */ -#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ - -#define AT91_SPI_TDR 0x0c /* Transmit Data Register */ -#define AT91_SPI_TD (0xffff << 0) /* Transmit Data */ -#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ -#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ - -#define AT91_SPI_SR 0x10 /* Status Register */ -#define AT91_SPI_RDRF (1 << 0) /* Receive Data Register Full */ -#define AT91_SPI_TDRE (1 << 1) /* Transmit Data Register Full */ -#define AT91_SPI_MODF (1 << 2) /* Mode Fault Error */ -#define AT91_SPI_OVRES (1 << 3) /* Overrun Error Status */ -#define AT91_SPI_ENDRX (1 << 4) /* End of RX buffer */ -#define AT91_SPI_ENDTX (1 << 5) /* End of TX buffer */ -#define AT91_SPI_RXBUFF (1 << 6) /* RX Buffer Full */ -#define AT91_SPI_TXBUFE (1 << 7) /* TX Buffer Empty */ -#define AT91_SPI_NSSR (1 << 8) /* NSS Rising [SAM9261 only] */ -#define AT91_SPI_TXEMPTY (1 << 9) /* Transmission Register Empty [SAM9261 only] */ -#define AT91_SPI_SPIENS (1 << 16) /* SPI Enable Status */ - -#define AT91_SPI_IER 0x14 /* Interrupt Enable Register */ -#define AT91_SPI_IDR 0x18 /* Interrupt Disable Register */ -#define AT91_SPI_IMR 0x1c /* Interrupt Mask Register */ - -#define AT91_SPI_CSR(n) (0x30 + ((n) * 4)) /* Chip Select Registers 0-3 */ -#define AT91_SPI_CPOL (1 << 0) /* Clock Polarity */ -#define AT91_SPI_NCPHA (1 << 1) /* Clock Phase */ -#define AT91_SPI_CSAAT (1 << 3) /* Chip Select Active After Transfer [SAM9261 only] */ -#define AT91_SPI_BITS (0xf << 4) /* Bits Per Transfer */ -#define AT91_SPI_BITS_8 (0 << 4) -#define AT91_SPI_BITS_9 (1 << 4) -#define AT91_SPI_BITS_10 (2 << 4) -#define AT91_SPI_BITS_11 (3 << 4) -#define AT91_SPI_BITS_12 (4 << 4) -#define AT91_SPI_BITS_13 (5 << 4) -#define AT91_SPI_BITS_14 (6 << 4) -#define AT91_SPI_BITS_15 (7 << 4) -#define AT91_SPI_BITS_16 (8 << 4) -#define AT91_SPI_SCBR (0xff << 8) /* Serial Clock Baud Rate */ -#define AT91_SPI_DLYBS (0xff << 16) /* Delay before SPCK */ -#define AT91_SPI_DLYBCT (0xff << 24) /* Delay between Consecutive Transfers */ - -#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h deleted file mode 100644 index ac88022..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h - * - * Copyright (C) SAN People - * - * Serial Synchronous Controller (SSC) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_SSC_H -#define AT91RM9200_SSC_H - -#define AT91_SSC_CR 0x00 /* Control Register */ -#define AT91_SSC_RXEN (1 << 0) /* Receive Enable */ -#define AT91_SSC_RXDIS (1 << 1) /* Receive Disable */ -#define AT91_SSC_TXEN (1 << 8) /* Transmit Enable */ -#define AT91_SSC_TXDIS (1 << 9) /* Transmit Disable */ -#define AT91_SSC_SWRST (1 << 15) /* Software Reset */ - -#define AT91_SSC_CMR 0x04 /* Clock Mode Register */ -#define AT91_SSC_CMR_DIV (0xfff << 0) /* Clock Divider */ - -#define AT91_SSC_RCMR 0x10 /* Receive Clock Mode Register */ -#define AT91_SSC_CKS (3 << 0) /* Clock Selection */ -#define AT91_SSC_CKS_DIV (0 << 0) -#define AT91_SSC_CKS_CLOCK (1 << 0) -#define AT91_SSC_CKS_PIN (2 << 0) -#define AT91_SSC_CKO (7 << 2) /* Clock Output Mode Selection */ -#define AT91_SSC_CKO_NONE (0 << 2) -#define AT91_SSC_CKO_CONTINUOUS (1 << 2) -#define AT91_SSC_CKI (1 << 5) /* Clock Inversion */ -#define AT91_SSC_CKI_FALLING (0 << 5) -#define AT91_SSC_CK_RISING (1 << 5) -#define AT91_SSC_START (0xf << 8) /* Start Selection */ -#define AT91_SSC_START_CONTINUOUS (0 << 8) -#define AT91_SSC_START_TX_RX (1 << 8) -#define AT91_SSC_START_LOW_RF (2 << 8) -#define AT91_SSC_START_HIGH_RF (3 << 8) -#define AT91_SSC_START_FALLING_RF (4 << 8) -#define AT91_SSC_START_RISING_RF (5 << 8) -#define AT91_SSC_START_LEVEL_RF (6 << 8) -#define AT91_SSC_START_EDGE_RF (7 << 8) -#define AT91_SSC_STTDLY (0xff << 16) /* Start Delay */ -#define AT91_SSC_PERIOD (0xff << 24) /* Period Divider Selection */ - -#define AT91_SSC_RFMR 0x14 /* Receive Frame Mode Register */ -#define AT91_SSC_DATALEN (0x1f << 0) /* Data Length */ -#define AT91_SSC_LOOP (1 << 5) /* Loop Mode */ -#define AT91_SSC_MSBF (1 << 7) /* Most Significant Bit First */ -#define AT91_SSC_DATNB (0xf << 8) /* Data Number per Frame */ -#define AT91_SSC_FSLEN (0xf << 16) /* Frame Sync Length */ -#define AT91_SSC_FSOS (7 << 20) /* Frame Sync Output Selection */ -#define AT91_SSC_FSOS_NONE (0 << 20) -#define AT91_SSC_FSOS_NEGATIVE (1 << 20) -#define AT91_SSC_FSOS_POSITIVE (2 << 20) -#define AT91_SSC_FSOS_LOW (3 << 20) -#define AT91_SSC_FSOS_HIGH (4 << 20) -#define AT91_SSC_FSOS_TOGGLE (5 << 20) -#define AT91_SSC_FSEDGE (1 << 24) /* Frame Sync Edge Detection */ -#define AT91_SSC_FSEDGE_POSITIVE (0 << 24) -#define AT91_SSC_FSEDGE_NEGATIVE (1 << 24) - -#define AT91_SSC_TCMR 0x18 /* Transmit Clock Mode Register */ -#define AT91_SSC_TFMR 0x1c /* Transmit Fram Mode Register */ -#define AT91_SSC_DATDEF (1 << 5) /* Data Default Value */ -#define AT91_SSC_FSDEN (1 << 23) /* Frame Sync Data Enable */ - -#define AT91_SSC_RHR 0x20 /* Receive Holding Register */ -#define AT91_SSC_THR 0x24 /* Transmit Holding Register */ -#define AT91_SSC_RSHR 0x30 /* Receive Sync Holding Register */ -#define AT91_SSC_TSHR 0x34 /* Transmit Sync Holding Register */ - -#define AT91_SSC_SR 0x40 /* Status Register */ -#define AT91_SSC_TXRDY (1 << 0) /* Transmit Ready */ -#define AT91_SSC_TXEMPTY (1 << 1) /* Transmit Empty */ -#define AT91_SSC_ENDTX (1 << 2) /* End of Transmission */ -#define AT91_SSC_TXBUFE (1 << 3) /* Transmit Buffer Empty */ -#define AT91_SSC_RXRDY (1 << 4) /* Receive Ready */ -#define AT91_SSC_OVRUN (1 << 5) /* Receive Overrun */ -#define AT91_SSC_ENDRX (1 << 6) /* End of Reception */ -#define AT91_SSC_RXBUFF (1 << 7) /* Receive Buffer Full */ -#define AT91_SSC_TXSYN (1 << 10) /* Transmit Sync */ -#define AT91_SSC_RXSYN (1 << 11) /* Receive Sync */ -#define AT91_SSC_TXENA (1 << 16) /* Transmit Enable */ -#define AT91_SSC_RXENA (1 << 17) /* Receive Enable */ - -#define AT91_SSC_IER 0x44 /* Interrupt Enable Register */ -#define AT91_SSC_IDR 0x48 /* Interrupt Disable Register */ -#define AT91_SSC_IMR 0x4c /* Interrupt Mask Register */ - -#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h deleted file mode 100644 index f4da752..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h - * - * Copyright (C) SAN People - * - * Timer/Counter Unit (TC) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_TC_H -#define AT91RM9200_TC_H - -#define AT91_TC_BCR 0xc0 /* TC Block Control Register */ -#define AT91_TC_SYNC (1 << 0) /* Synchro Command */ - -#define AT91_TC_BMR 0xc4 /* TC Block Mode Register */ -#define AT91_TC_TC0XC0S (3 << 0) /* External Clock Signal 0 Selection */ -#define AT91_TC_TC0XC0S_TCLK0 (0 << 0) -#define AT91_TC_TC0XC0S_NONE (1 << 0) -#define AT91_TC_TC0XC0S_TIOA1 (2 << 0) -#define AT91_TC_TC0XC0S_TIOA2 (3 << 0) -#define AT91_TC_TC1XC1S (3 << 2) /* External Clock Signal 1 Selection */ -#define AT91_TC_TC1XC1S_TCLK1 (0 << 2) -#define AT91_TC_TC1XC1S_NONE (1 << 2) -#define AT91_TC_TC1XC1S_TIOA0 (2 << 2) -#define AT91_TC_TC1XC1S_TIOA2 (3 << 2) -#define AT91_TC_TC2XC2S (3 << 4) /* External Clock Signal 2 Selection */ -#define AT91_TC_TC2XC2S_TCLK2 (0 << 4) -#define AT91_TC_TC2XC2S_NONE (1 << 4) -#define AT91_TC_TC2XC2S_TIOA0 (2 << 4) -#define AT91_TC_TC2XC2S_TIOA1 (3 << 4) - - -#define AT91_TC_CCR 0x00 /* Channel Control Register */ -#define AT91_TC_CLKEN (1 << 0) /* Counter Clock Enable Command */ -#define AT91_TC_CLKDIS (1 << 1) /* Counter CLock Disable Command */ -#define AT91_TC_SWTRG (1 << 2) /* Software Trigger Command */ - -#define AT91_TC_CMR 0x04 /* Channel Mode Register */ -#define AT91_TC_TCCLKS (7 << 0) /* Capture/Waveform Mode: Clock Selection */ -#define AT91_TC_TIMER_CLOCK1 (0 << 0) -#define AT91_TC_TIMER_CLOCK2 (1 << 0) -#define AT91_TC_TIMER_CLOCK3 (2 << 0) -#define AT91_TC_TIMER_CLOCK4 (3 << 0) -#define AT91_TC_TIMER_CLOCK5 (4 << 0) -#define AT91_TC_XC0 (5 << 0) -#define AT91_TC_XC1 (6 << 0) -#define AT91_TC_XC2 (7 << 0) -#define AT91_TC_CLKI (1 << 3) /* Capture/Waveform Mode: Clock Invert */ -#define AT91_TC_BURST (3 << 4) /* Capture/Waveform Mode: Burst Signal Selection */ -#define AT91_TC_LDBSTOP (1 << 6) /* Capture Mode: Counter Clock Stopped with TB Loading */ -#define AT91_TC_LDBDIS (1 << 7) /* Capture Mode: Counter Clock Disable with RB Loading */ -#define AT91_TC_ETRGEDG (3 << 8) /* Capture Mode: External Trigger Edge Selection */ -#define AT91_TC_ABETRG (1 << 10) /* Capture Mode: TIOA or TIOB External Trigger Selection */ -#define AT91_TC_CPCTRG (1 << 14) /* Capture Mode: RC Compare Trigger Enable */ -#define AT91_TC_WAVE (1 << 15) /* Capture/Waveform mode */ -#define AT91_TC_LDRA (3 << 16) /* Capture Mode: RA Loading Selection */ -#define AT91_TC_LDRB (3 << 18) /* Capture Mode: RB Loading Selection */ - -#define AT91_TC_CPCSTOP (1 << 6) /* Waveform Mode: Counter Clock Stopped with RC Compare */ -#define AT91_TC_CPCDIS (1 << 7) /* Waveform Mode: Counter Clock Disable with RC Compare */ -#define AT91_TC_EEVTEDG (3 << 8) /* Waveform Mode: External Event Edge Selection */ -#define AT91_TC_EEVTEDG_NONE (0 << 8) -#define AT91_TC_EEVTEDG_RISING (1 << 8) -#define AT91_TC_EEVTEDG_FALLING (2 << 8) -#define AT91_TC_EEVTEDG_BOTH (3 << 8) -#define AT91_TC_EEVT (3 << 10) /* Waveform Mode: External Event Selection */ -#define AT91_TC_EEVT_TIOB (0 << 10) -#define AT91_TC_EEVT_XC0 (1 << 10) -#define AT91_TC_EEVT_XC1 (2 << 10) -#define AT91_TC_EEVT_XC2 (3 << 10) -#define AT91_TC_ENETRG (1 << 12) /* Waveform Mode: External Event Trigger Enable */ -#define AT91_TC_WAVESEL (3 << 13) /* Waveform Mode: Waveform Selection */ -#define AT91_TC_WAVESEL_UP (0 << 13) -#define AT91_TC_WAVESEL_UP_AUTO (2 << 13) -#define AT91_TC_WAVESEL_UPDOWN (1 << 13) -#define AT91_TC_WAVESEL_UPDOWN_AUTO (3 << 13) -#define AT91_TC_ACPA (3 << 16) /* Waveform Mode: RA Compare Effect on TIOA */ -#define AT91_TC_ACPA_NONE (0 << 16) -#define AT91_TC_ACPA_SET (1 << 16) -#define AT91_TC_ACPA_CLEAR (2 << 16) -#define AT91_TC_ACPA_TOGGLE (3 << 16) -#define AT91_TC_ACPC (3 << 18) /* Waveform Mode: RC Compre Effect on TIOA */ -#define AT91_TC_ACPC_NONE (0 << 18) -#define AT91_TC_ACPC_SET (1 << 18) -#define AT91_TC_ACPC_CLEAR (2 << 18) -#define AT91_TC_ACPC_TOGGLE (3 << 18) -#define AT91_TC_AEEVT (3 << 20) /* Waveform Mode: External Event Effect on TIOA */ -#define AT91_TC_AEEVT_NONE (0 << 20) -#define AT91_TC_AEEVT_SET (1 << 20) -#define AT91_TC_AEEVT_CLEAR (2 << 20) -#define AT91_TC_AEEVT_TOGGLE (3 << 20) -#define AT91_TC_ASWTRG (3 << 22) /* Waveform Mode: Software Trigger Effect on TIOA */ -#define AT91_TC_ASWTRG_NONE (0 << 22) -#define AT91_TC_ASWTRG_SET (1 << 22) -#define AT91_TC_ASWTRG_CLEAR (2 << 22) -#define AT91_TC_ASWTRG_TOGGLE (3 << 22) -#define AT91_TC_BCPB (3 << 24) /* Waveform Mode: RB Compare Effect on TIOB */ -#define AT91_TC_BCPB_NONE (0 << 24) -#define AT91_TC_BCPB_SET (1 << 24) -#define AT91_TC_BCPB_CLEAR (2 << 24) -#define AT91_TC_BCPB_TOGGLE (3 << 24) -#define AT91_TC_BCPC (3 << 26) /* Waveform Mode: RC Compare Effect on TIOB */ -#define AT91_TC_BCPC_NONE (0 << 26) -#define AT91_TC_BCPC_SET (1 << 26) -#define AT91_TC_BCPC_CLEAR (2 << 26) -#define AT91_TC_BCPC_TOGGLE (3 << 26) -#define AT91_TC_BEEVT (3 << 28) /* Waveform Mode: External Event Effect on TIOB */ -#define AT91_TC_BEEVT_NONE (0 << 28) -#define AT91_TC_BEEVT_SET (1 << 28) -#define AT91_TC_BEEVT_CLEAR (2 << 28) -#define AT91_TC_BEEVT_TOGGLE (3 << 28) -#define AT91_TC_BSWTRG (3 << 30) /* Waveform Mode: Software Trigger Effect on TIOB */ -#define AT91_TC_BSWTRG_NONE (0 << 30) -#define AT91_TC_BSWTRG_SET (1 << 30) -#define AT91_TC_BSWTRG_CLEAR (2 << 30) -#define AT91_TC_BSWTRG_TOGGLE (3 << 30) - -#define AT91_TC_CV 0x10 /* Counter Value */ -#define AT91_TC_RA 0x14 /* Register A */ -#define AT91_TC_RB 0x18 /* Register B */ -#define AT91_TC_RC 0x1c /* Register C */ - -#define AT91_TC_SR 0x20 /* Status Register */ -#define AT91_TC_COVFS (1 << 0) /* Counter Overflow Status */ -#define AT91_TC_LOVRS (1 << 1) /* Load Overrun Status */ -#define AT91_TC_CPAS (1 << 2) /* RA Compare Status */ -#define AT91_TC_CPBS (1 << 3) /* RB Compare Status */ -#define AT91_TC_CPCS (1 << 4) /* RC Compare Status */ -#define AT91_TC_LDRAS (1 << 5) /* RA Loading Status */ -#define AT91_TC_LDRBS (1 << 6) /* RB Loading Status */ -#define AT91_TC_ETRGS (1 << 7) /* External Trigger Status */ -#define AT91_TC_CLKSTA (1 << 16) /* Clock Enabling Status */ -#define AT91_TC_MTIOA (1 << 17) /* TIOA Mirror */ -#define AT91_TC_MTIOB (1 << 18) /* TIOB Mirror */ - -#define AT91_TC_IER 0x24 /* Interrupt Enable Register */ -#define AT91_TC_IDR 0x28 /* Interrupt Disable Register */ -#define AT91_TC_IMR 0x2c /* Interrupt Mask Register */ - -#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h deleted file mode 100644 index 93547d7..0000000 --- a/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_twi.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Two-wire Interface (TWI) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_TWI_H -#define AT91RM9200_TWI_H - -#define AT91_TWI_CR 0x00 /* Control Register */ -#define AT91_TWI_START (1 << 0) /* Send a Start Condition */ -#define AT91_TWI_STOP (1 << 1) /* Send a Stop Condition */ -#define AT91_TWI_MSEN (1 << 2) /* Master Transfer Enable */ -#define AT91_TWI_MSDIS (1 << 3) /* Master Transfer Disable */ -#define AT91_TWI_SWRST (1 << 7) /* Software Reset */ - -#define AT91_TWI_MMR 0x04 /* Master Mode Register */ -#define AT91_TWI_IADRSZ (3 << 8) /* Internal Device Address Size */ -#define AT91_TWI_IADRSZ_NO (0 << 8) -#define AT91_TWI_IADRSZ_1 (1 << 8) -#define AT91_TWI_IADRSZ_2 (2 << 8) -#define AT91_TWI_IADRSZ_3 (3 << 8) -#define AT91_TWI_MREAD (1 << 12) /* Master Read Direction */ -#define AT91_TWI_DADR (0x7f << 16) /* Device Address */ - -#define AT91_TWI_IADR 0x0c /* Internal Address Register */ - -#define AT91_TWI_CWGR 0x10 /* Clock Waveform Generator Register */ -#define AT91_TWI_CLDIV (0xff << 0) /* Clock Low Divisor */ -#define AT91_TWI_CHDIV (0xff << 8) /* Clock High Divisor */ -#define AT91_TWI_CKDIV (7 << 16) /* Clock Divider */ - -#define AT91_TWI_SR 0x20 /* Status Register */ -#define AT91_TWI_TXCOMP (1 << 0) /* Transmission Complete */ -#define AT91_TWI_RXRDY (1 << 1) /* Receive Holding Register Ready */ -#define AT91_TWI_TXRDY (1 << 2) /* Transmit Holding Register Ready */ -#define AT91_TWI_OVRE (1 << 6) /* Overrun Error */ -#define AT91_TWI_UNRE (1 << 7) /* Underrun Error */ -#define AT91_TWI_NACK (1 << 8) /* Not Acknowledged */ - -#define AT91_TWI_IER 0x24 /* Interrupt Enable Register */ -#define AT91_TWI_IDR 0x28 /* Interrupt Disable Register */ -#define AT91_TWI_IMR 0x2c /* Interrupt Mask Register */ -#define AT91_TWI_RHR 0x30 /* Receive Holding Register */ -#define AT91_TWI_THR 0x34 /* Transmit Holding Register */ - -#endif - -- cgit v0.10.2 From 55d8baee4a0b4709061104f7a56f53a310de76ac Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 17:16:43 +0100 Subject: [ARM] 3954/1: AT91: Update drivers for new headers This patch updates the drivers (and other files) which include the hardware headers. This fixes the breakage introduced in patches 3950/1 and 3951/1 (those patches were getting big). The AVR32 architecture uses the same serial driver and had its own copy of at91rm9200_pdc.h. Renamed it to at91_pdc.h Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c index 0422593..0816a8d 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -15,8 +15,9 @@ #include #include #include +#include +#include -#include #include "generic.h" #include "clock.h" diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c index 07c9cea..8e9c049 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_time.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -30,6 +30,8 @@ #include #include +#include + static unsigned long last_crtr; /* diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index a43b061..1e0000c 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -28,6 +28,7 @@ #include #include +#include #include "clock.h" diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 7467d64..e76422761 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include "generic.h" diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c index 5e3b6e3..5b775fa 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91rm9200/pm.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include "generic.h" diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c index 4e7a114..cb86967 100644 --- a/drivers/char/watchdog/at91rm9200_wdt.c +++ b/drivers/char/watchdog/at91rm9200_wdt.c @@ -21,6 +21,7 @@ #include #include #include +#include #define WDT_DEFAULT_TIME 5 /* seconds */ diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 494b23f..41761f7 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -73,8 +73,8 @@ #include #include #include -#include -#include +#include +#include #define DRIVER_NAME "at91_mci" diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 3bcb7dc..6979667 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -23,9 +23,9 @@ #include #include -#include #include #include +#include /* diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 877876e..f930df0 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -36,9 +36,9 @@ #include -#include #include #include +#include #ifdef CONFIG_ARM #include #include diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h index a5a86b1..4d51177 100644 --- a/include/asm-arm/arch-at91rm9200/at91rm9200.h +++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h @@ -80,6 +80,22 @@ /* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) /* Advanced Interrupt Controller */ +#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) /* Debug Unit */ +#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS) /* PIO Controller A */ +#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS) /* PIO Controller B */ +#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS) /* PIO Controller C */ +#define AT91_PIOD (0xfffffa00 - AT91_BASE_SYS) /* PIO Controller D */ +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) /* Power Management Controller */ +#define AT91_ST (0xfffffd00 - AT91_BASE_SYS) /* System Timer */ +#define AT91_RTC (0xfffffe00 - AT91_BASE_SYS) /* Real-Time Clock */ +#define AT91_MC (0xffffff00 - AT91_BASE_SYS) /* Memory Controllers */ + +#define AT91_MATRIX 0 /* not supported */ + +/* * Internal Memory. */ #define AT91RM9200_ROM_BASE 0x00100000 /* Internal ROM base address */ diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S index f496b54..85cdadf 100644 --- a/include/asm-arm/arch-at91rm9200/debug-macro.S +++ b/include/asm-arm/arch-at91rm9200/debug-macro.S @@ -12,6 +12,7 @@ */ #include +#include .macro addruart,rx mrc p15, 0, \rx, c1, c0 diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S index 61a326e..57248a7 100644 --- a/include/asm-arm/arch-at91rm9200/entry-macro.S +++ b/include/asm-arm/arch-at91rm9200/entry-macro.S @@ -11,6 +11,7 @@ */ #include +#include .macro disable_fiq .endm diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h index 9ca4cc9..d42e310 100644 --- a/include/asm-arm/arch-at91rm9200/hardware.h +++ b/include/asm-arm/arch-at91rm9200/hardware.h @@ -16,8 +16,16 @@ #include +#if defined(CONFIG_ARCH_AT91RM9200) #include -#include +#elif defined(CONFIG_ARCH_AT91SAM9260) +#include +#elif defined(CONFIG_ARCH_AT91SAM9261) +#include +#else +#error "Unsupported AT91 processor" +#endif + /* * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h index 763cb96..c0679ea 100644 --- a/include/asm-arm/arch-at91rm9200/irqs.h +++ b/include/asm-arm/arch-at91rm9200/irqs.h @@ -21,6 +21,8 @@ #ifndef __ASM_ARCH_IRQS_H #define __ASM_ARCH_IRQS_H +#include + #define NR_AIC_IRQS 32 diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 92f3676..053f2e0 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -22,6 +22,8 @@ #define __ASM_ARCH_SYSTEM_H #include +#include +#include static inline void arch_idle(void) { diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h index ec7811a..34b4b93 100644 --- a/include/asm-arm/arch-at91rm9200/uncompress.h +++ b/include/asm-arm/arch-at91rm9200/uncompress.h @@ -22,11 +22,11 @@ #define __ASM_ARCH_UNCOMPRESS_H #include +#include /* * The following code assumes the serial port has already been - * initialized by the bootloader. We search for the first enabled - * port in the most probable order. If you didn't setup a port in + * initialized by the bootloader. If you didn't setup a port in * your bootloader then nothing will appear (which might be desired). * * This does not append a newline diff --git a/include/asm-avr32/arch-at32ap/at91_pdc.h b/include/asm-avr32/arch-at32ap/at91_pdc.h new file mode 100644 index 0000000..79d6e02 --- /dev/null +++ b/include/asm-avr32/arch-at32ap/at91_pdc.h @@ -0,0 +1,36 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_pdc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Peripheral Data Controller (PDC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_PDC_H +#define AT91_PDC_H + +#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ +#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ +#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ +#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ +#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ +#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ +#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ +#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ + +#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ +#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ +#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ +#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ +#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ + +#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ + +#endif diff --git a/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h b/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h deleted file mode 100644 index ce1150d44..0000000 --- a/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Peripheral Data Controller (PDC) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91RM9200_PDC_H -#define AT91RM9200_PDC_H - -#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ -#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ -#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ -#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ -#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ -#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ -#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ -#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ - -#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ -#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ -#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ -#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ -#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ - -#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ - -#endif -- cgit v0.10.2 From eaa595cb881bba043e79638c37cb357f296a7714 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 16:23:18 +0100 Subject: [ARM] 3952/1: AT91: Hardware headers for SAM9 perhipherals This patch adds definitions for the new peripherals integrated in the AT91SAM9260 and AT91SAM9261 processors: ECC, LCD, RSTC, RTT, SHDWC, WDT, MATRIX, SDRAMC, SMC. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91rm9200/at91_ecc.h new file mode 100644 index 0000000..fddf256 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_ecc.h @@ -0,0 +1,38 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_ecc.h + * + * Error Corrected Code Controller (ECC) - System peripherals regsters. + * Based on AT91SAM9260 datasheet revision B. + * + * 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. + */ + +#ifndef AT91_ECC_H +#define AT91_ECC_H + +#define AT91_ECC_CR (AT91_ECC + 0x00) /* Control register */ +#define AT91_ECC_RST (1 << 0) /* Reset parity */ + +#define AT91_ECC_MR (AT91_ECC + 0x04) /* Mode register */ +#define AT91_ECC_PAGESIZE (3 << 0) /* Page Size */ +#define AT91_ECC_PAGESIZE_528 (0) +#define AT91_ECC_PAGESIZE_1056 (1) +#define AT91_ECC_PAGESIZE_2112 (2) +#define AT91_ECC_PAGESIZE_4224 (3) + +#define AT91_ECC_SR (AT91_ECC + 0x08) /* Status register */ +#define AT91_ECC_RECERR (1 << 0) /* Recoverable Error */ +#define AT91_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ +#define AT91_ECC_MULERR (1 << 2) /* Multiple Errors */ + +#define AT91_ECC_PR (AT91_ECC + 0x0c) /* Parity register */ +#define AT91_ECC_BITADDR (0xf << 0) /* Bit Error Address */ +#define AT91_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ + +#define AT91_ECC_NPR (AT91_ECC + 0x10) /* NParity register */ +#define AT91_ECC_NPARITY (0xffff << 0) /* NParity */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_lcdc.h b/include/asm-arm/arch-at91rm9200/at91_lcdc.h new file mode 100644 index 0000000..9cbfcdd --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_lcdc.h @@ -0,0 +1,148 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_lcdc.h + * + * LCD Controller (LCDC). + * Based on AT91SAM9261 datasheet revision E. + * + * 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. + */ + +#ifndef AT91_LCDC_H +#define AT91_LCDC_H + +#define AT91_LCDC_DMABADDR1 0x00 /* DMA Base Address Register 1 */ +#define AT91_LCDC_DMABADDR2 0x04 /* DMA Base Address Register 2 */ +#define AT91_LCDC_DMAFRMPT1 0x08 /* DMA Frame Pointer Register 1 */ +#define AT91_LCDC_DMAFRMPT2 0x0c /* DMA Frame Pointer Register 2 */ +#define AT91_LCDC_DMAFRMADD1 0x10 /* DMA Frame Address Register 1 */ +#define AT91_LCDC_DMAFRMADD2 0x14 /* DMA Frame Address Register 2 */ + +#define AT91_LCDC_DMAFRMCFG 0x18 /* DMA Frame Configuration Register */ +#define AT91_LCDC_FRSIZE (0x7fffff << 0) /* Frame Size */ +#define AT91_LCDC_BLENGTH (0x7f << 24) /* Burst Length */ + +#define AT91_LCDC_DMACON 0x1c /* DMA Control Register */ +#define AT91_LCDC_DMAEN (0x1 << 0) /* DMA Enable */ +#define AT91_LCDC_DMARST (0x1 << 1) /* DMA Reset */ +#define AT91_LCDC_DMABUSY (0x1 << 2) /* DMA Busy */ + +#define AT91_LCDC_LCDCON1 0x0800 /* LCD Control Register 1 */ +#define AT91_LCDC_BYPASS (1 << 0) /* Bypass lcd_dotck divider */ +#define AT91_LCDC_CLKVAL (0x1ff << 12) /* Clock Divider */ +#define AT91_LCDC_LINCNT (0x7ff << 21) /* Line Counter */ + +#define AT91_LCDC_LCDCON2 0x0804 /* LCD Control Register 2 */ +#define AT91_LCDC_DISTYPE (3 << 0) /* Display Type */ +#define AT91_LCDC_DISTYPE_STNMONO (0 << 0) +#define AT91_LCDC_DISTYPE_STNCOLOR (1 << 0) +#define AT91_LCDC_DISTYPE_TFT (2 << 0) +#define AT91_LCDC_SCANMOD (1 << 2) /* Scan Mode */ +#define AT91_LCDC_SCANMOD_SINGLE (0 << 2) +#define AT91_LCDC_SCANMOD_DUAL (1 << 2) +#define AT91_LCDC_IFWIDTH (3 << 3) /*Interface Width */ +#define AT91_LCDC_IFWIDTH_4 (0 << 3) +#define AT91_LCDC_IFWIDTH_8 (1 << 3) +#define AT91_LCDC_IFWIDTH_16 (2 << 3) +#define AT91_LCDC_PIXELSIZE (7 << 5) /* Bits per pixel */ +#define AT91_LCDC_PIXELSIZE_1 (0 << 5) +#define AT91_LCDC_PIXELSIZE_2 (1 << 5) +#define AT91_LCDC_PIXELSIZE_4 (2 << 5) +#define AT91_LCDC_PIXELSIZE_8 (3 << 5) +#define AT91_LCDC_PIXELSIZE_16 (4 << 5) +#define AT91_LCDC_PIXELSIZE_24 (5 << 5) +#define AT91_LCDC_INVVD (1 << 8) /* LCD Data polarity */ +#define AT91_LCDC_INVVD_NORMAL (0 << 8) +#define AT91_LCDC_INVVD_INVERTED (1 << 8) +#define AT91_LCDC_INVFRAME (1 << 9 ) /* LCD VSync polarity */ +#define AT91_LCDC_INVFRAME_NORMAL (0 << 9) +#define AT91_LCDC_INVFRAME_INVERTED (1 << 9) +#define AT91_LCDC_INVLINE (1 << 10) /* LCD HSync polarity */ +#define AT91_LCDC_INVLINE_NORMAL (0 << 10) +#define AT91_LCDC_INVLINE_INVERTED (1 << 10) +#define AT91_LCDC_INVCLK (1 << 11) /* LCD dotclk polarity */ +#define AT91_LCDC_INVCLK_NORMAL (0 << 11) +#define AT91_LCDC_INVCLK_INVERTED (1 << 11) +#define AT91_LCDC_INVDVAL (1 << 12) /* LCD dval polarity */ +#define AT91_LCDC_INVDVAL_NORMAL (0 << 12) +#define AT91_LCDC_INVDVAL_INVERTED (1 << 12) +#define AT91_LCDC_CLKMOD (1 << 15) /* LCD dotclk mode */ +#define AT91_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15) +#define AT91_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15) +#define AT91_LCDC_MEMOR (1 << 31) /* Memory Ordering Format */ +#define AT91_LCDC_MEMOR_BIG (0 << 31) +#define AT91_LCDC_MEMOR_LITTLE (1 << 31) + +#define AT91_LCDC_TIM1 0x0808 /* LCD Timing Register 1 */ +#define AT91_LCDC_VFP (0xff << 0) /* Vertical Front Porch */ +#define AT91_LCDC_VBP (0xff << 8) /* Vertical Back Porch */ +#define AT91_LCDC_VPW (0x3f << 16) /* Vertical Synchronization Pulse Width */ +#define AT91_LCDC_VHDLY (0xf << 24) /* Vertical to Horizontal Delay */ + +#define AT91_LCDC_TIM2 0x080c /* LCD Timing Register 2 */ +#define AT91_LCDC_HBP (0xff << 0) /* Horizontal Back Porch */ +#define AT91_LCDC_HPW (0x3f << 8) /* Horizontal Synchronization Pulse Width */ +#define AT91_LCDC_HFP (0x7ff << 21) /* Horizontal Front Porch */ + +#define AT91_LCDC_LCDFRMCFG 0x0810 /* LCD Frame Configuration Register */ +#define AT91_LCDC_LINEVAL (0x7ff << 0) /* Vertical Size of LCD Module */ +#define AT91_LCDC_HOZVAL (0x7ff << 21) /* Horizontal Size of LCD Module */ + +#define AT91_LCDC_FIFO 0x0814 /* LCD FIFO Register */ +#define AT91_LCDC_FIFOTH (0xffff) /* FIFO Threshold */ + +#define AT91_LCDC_DP1_2 0x081c /* Dithering Pattern DP1_2 Register */ +#define AT91_LCDC_DP4_7 0x0820 /* Dithering Pattern DP4_7 Register */ +#define AT91_LCDC_DP3_5 0x0824 /* Dithering Pattern DP3_5 Register */ +#define AT91_LCDC_DP2_3 0x0828 /* Dithering Pattern DP2_3 Register */ +#define AT91_LCDC_DP5_7 0x082c /* Dithering Pattern DP5_7 Register */ +#define AT91_LCDC_DP3_4 0x0830 /* Dithering Pattern DP3_4 Register */ +#define AT91_LCDC_DP4_5 0x0834 /* Dithering Pattern DP4_5 Register */ +#define AT91_LCDC_DP6_7 0x0838 /* Dithering Pattern DP6_7 Register */ +#define AT91_LCDC_DP1_2_VAL (0xff) +#define AT91_LCDC_DP4_7_VAL (0xfffffff) +#define AT91_LCDC_DP3_5_VAL (0xfffff) +#define AT91_LCDC_DP2_3_VAL (0xfff) +#define AT91_LCDC_DP5_7_VAL (0xfffffff) +#define AT91_LCDC_DP3_4_VAL (0xffff) +#define AT91_LCDC_DP4_5_VAL (0xfffff) +#define AT91_LCDC_DP6_7_VAL (0xfffffff) + +#define AT91_LCDC_PWRCON 0x083c /* Power Control Register */ +#define AT91_LCDC_PWR (1 << 0) /* LCD Module Power Control */ +#define AT91_LCDC_GUARDT (0x7f << 1) /* Delay in Frame Period */ +#define AT91_LCDC_BUSY (1 << 31) /* LCD Busy */ + +#define AT91_LCDC_CONTRAST_CTR 0x0840 /* Contrast Control Register */ +#define AT91_LCDC_PS (3 << 0) /* Contrast Counter Prescaler */ +#define AT91_LCDC_PS_DIV1 (0 << 0) +#define AT91_LCDC_PS_DIV2 (1 << 0) +#define AT91_LCDC_PS_DIV4 (2 << 0) +#define AT91_LCDC_PS_DIV8 (3 << 0) +#define AT91_LCDC_POL (1 << 2) /* Polarity of output Pulse */ +#define AT91_LCDC_POL_NEGATIVE (0 << 2) +#define AT91_LCDC_POL_POSITIVE (1 << 2) +#define AT91_LCDC_ENA (1 << 3) /* PWM generator Control */ +#define AT91_LCDC_ENA_PWMDISABLE (0 << 3) +#define AT91_LCDC_ENA_PWMENABLE (1 << 3) + +#define AT91_LCDC_CONTRAST_VAL 0x0844 /* Contrast Value Register */ +#define AT91_LCDC_CVAL (0xff) /* PWM compare value */ + +#define AT91_LCDC_IER 0x0848 /* Interrupt Enable Register */ +#define AT91_LCDC_IDR 0x084c /* Interrupt Disable Register */ +#define AT91_LCDC_IMR 0x0850 /* Interrupt Mask Register */ +#define AT91_LCDC_ISR 0x0854 /* Interrupt Enable Register */ +#define AT91_LCDC_ICR 0x0858 /* Interrupt Clear Register */ +#define AT91_LCDC_LNI (1 << 0) /* Line Interrupt */ +#define AT91_LCDC_LSTLNI (1 << 1) /* Last Line Interrupt */ +#define AT91_LCDC_EOFI (1 << 2) /* DMA End Of Frame Interrupt */ +#define AT91_LCDC_UFLWI (1 << 4) /* FIFO Underflow Interrupt */ +#define AT91_LCDC_OWRI (1 << 5) /* FIFO Overwrite Interrupt */ +#define AT91_LCDC_MERI (1 << 6) /* DMA Memory Error Interrupt */ + +#define AT91_LCDC_LUT_(n) (0x0c00 + ((n)*4)) /* Palette Entry 0..255 */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91rm9200/at91_rstc.h new file mode 100644 index 0000000..ccdc52d --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_rstc.h @@ -0,0 +1,39 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_rstc.h + * + * Reset Controller (RSTC) - System peripherals regsters. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91_RSTC_H +#define AT91_RSTC_H + +#define AT91_RSTC_CR (AT91_RSTC + 0x00) /* Reset Controller Control Register */ +#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */ +#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */ +#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */ +#define AT01_RSTC_KEY (0xff << 24) /* KEY Password */ + +#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */ +#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */ +#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */ +#define AT91_RSTC_RSTTYP_GENERAL (0 << 8) +#define AT91_RSTC_RSTTYP_WAKEUP (1 << 8) +#define AT91_RSTC_RSTTYP_WATCHDOG (2 << 8) +#define AT91_RSTC_RSTTYP_SOFTWARE (3 << 8) +#define AT91_RSTC_RSTTYP_USER (4 << 8) +#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */ +#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */ + +#define AT91_RSTC_MR (AT91_RSTC + 0x08) /* Reset Controller Mode Register */ +#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */ +#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */ +#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */ +#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_rtt.h b/include/asm-arm/arch-at91rm9200/at91_rtt.h new file mode 100644 index 0000000..c6751ba --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_rtt.h @@ -0,0 +1,32 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_rtt.h + * + * Real-time Timer (RTT) - System peripherals regsters. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91_RTT_H +#define AT91_RTT_H + +#define AT91_RTT_MR (AT91_RTT + 0x00) /* Real-time Mode Register */ +#define AT91_RTT_RTPRES (0xffff << 0) /* Real-time Timer Prescaler Value */ +#define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ +#define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ +#define AT91_RTT_RTTRST (1 << 18) /* Real Time Timer Restart */ + +#define AT91_RTT_AR (AT91_RTT + 0x04) /* Real-time Alarm Register */ +#define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */ + +#define AT91_RTT_VR (AT91_RTT + 0x08) /* Real-time Value Register */ +#define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */ + +#define AT91_RTT_SR (AT91_RTT + 0x0c) /* Real-time Status Register */ +#define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ +#define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_shdwc.h b/include/asm-arm/arch-at91rm9200/at91_shdwc.h new file mode 100644 index 0000000..0439250 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_shdwc.h @@ -0,0 +1,33 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_shdwc.h + * + * Shutdown Controller (SHDWC) - System peripherals regsters. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91_SHDWC_H +#define AT91_SHDWC_H + +#define AT91_SHDW_CR (AT91_SHDWC + 0x00) /* Shut Down Control Register */ +#define AT91_SHDW_SHDW (1 << 0) /* Processor Reset */ +#define AT91_SHDW_KEY (0xff << 24) /* KEY Password */ + +#define AT91_SHDW_MR (AT91_SHDWC + 0x04) /* Shut Down Mode Register */ +#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */ +#define AT91_SHDW_WKMODE0_NONE 0 +#define AT91_SHDW_WKMODE0_HIGH 1 +#define AT91_SHDW_WKMODE0_LOW 2 +#define AT91_SHDW_WKMODE0_ANYLEVEL 3 +#define AT91_SHDW_CPTWK0 (0xf << 4) /* Counter On Wake Up 0 */ +#define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */ + +#define AT91_SHDW_SR (AT91_SHDWC + 0x08) /* Shut Down Status Register */ +#define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */ +#define AT91_SHDW_RTTWK (1 << 16) /* Real-time Timer Wake-up */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91_wdt.h b/include/asm-arm/arch-at91rm9200/at91_wdt.h new file mode 100644 index 0000000..ac63e77 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_wdt.h @@ -0,0 +1,34 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_wdt.h + * + * Watchdog Timer (WDT) - System peripherals regsters. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91_WDT_H +#define AT91_WDT_H + +#define AT91_WDT_CR (AT91_WDT + 0x00) /* Watchdog Control Register */ +#define AT91_WDT_WDRSTT (1 << 0) /* Restart */ +#define AT91_WDT_KEY (0xff << 24) /* KEY Password */ + +#define AT91_WDT_MR (AT91_WDT + 0x04) /* Watchdog Mode Register */ +#define AT91_WDT_WDV (0xfff << 0) /* Counter Value */ +#define AT91_WDT_WDFIEN (1 << 12) /* Fault Interrupt Enable */ +#define AT91_WDT_WDRSTEN (1 << 13) /* Reset Processor */ +#define AT91_WDT_WDRPROC (1 << 14) /* Timer Restart */ +#define AT91_WDT_WDDIS (1 << 15) /* Watchdog Disable */ +#define AT91_WDT_WDD (0xfff << 16) /* Delta Value */ +#define AT91_WDT_WDDBGHLT (1 << 28) /* Debug Halt */ +#define AT91_WDT_WDIDLEHLT (1 << 29) /* Idle Halt */ + +#define AT91_WDT_SR (AT91_WDT + 0x08) /* Watchdog Status Register */ +#define AT91_WDT_WDUNF (1 << 0) /* Watchdog Underflow */ +#define AT91_WDT_WDERR (1 << 1) /* Watchdog Error */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h new file mode 100644 index 0000000..746d9737 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h @@ -0,0 +1,78 @@ +/* + * include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9260 datasheet revision B. + * + * 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. + */ + +#ifndef AT91SAM9260_MATRIX_H +#define AT91SAM9260_MATRIX_H + +#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x04) /* Master Configuration Register 5 */ +#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (7 << 18) /* Fixed Index of Default Master */ +#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */ +#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24) +#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24) + +#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ +#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ +#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ +#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ +#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ +#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ +#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ + +#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ + +#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x11C) /* EBI Chip Select Assignment Register */ +#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_CS1A_SMC (0 << 1) +#define AT91_MATRIX_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_CS3A_SMC (0 << 3) +#define AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_CS4A_SMC (0 << 4) +#define AT91_MATRIX_CS4A_SMC_CF1 (1 << 4) +#define AT91_MATRIX_CS5A (1 << 5 ) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_CS5A_SMC (0 << 5) +#define AT91_MATRIX_CS5A_SMC_CF2 (1 << 5) +#define AT91_MATRIX_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_VDDIOMSEL_3_3V (1 << 16) + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h new file mode 100644 index 0000000..270a5dc --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h @@ -0,0 +1,62 @@ +/* + * include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91SAM9261_MATRIX_H +#define AT91SAM9261_MATRIX_H + +#define AT91_MATRIX_MCFG (AT91_MATRIX + 0x00) /* Master Configuration Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT01_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x04) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x08) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x0C) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x10) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x14) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (7 << 18) /* Fixed Index of Default Master */ + +#define AT91_MATRIX_TCR (AT91_MATRIX + 0x24) /* TCM Configuration Register */ +#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */ +#define AT91_MATRIX_ITCM_0 (0 << 0) +#define AT91_MATRIX_ITCM_16 (5 << 0) +#define AT91_MATRIX_ITCM_32 (6 << 0) +#define AT91_MATRIX_ITCM_64 (7 << 0) +#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */ +#define AT91_MATRIX_DTCM_0 (0 << 4) +#define AT91_MATRIX_DTCM_16 (5 << 4) +#define AT91_MATRIX_DTCM_32 (6 << 4) +#define AT91_MATRIX_DTCM_64 (7 << 4) + +#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x30) /* EBI Chip Select Assignment Register */ +#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_CS1A_SMC (0 << 1) +#define AT91_MATRIX_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_CS3A_SMC (0 << 3) +#define AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_CS4A_SMC (0 << 4) +#define AT91_MATRIX_CS4A_SMC_CF1 (1 << 4) +#define AT91_MATRIX_CS5A (1 << 5) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_CS5A_SMC (0 << 5) +#define AT91_MATRIX_CS5A_SMC_CF2 (1 << 5) +#define AT91_MATRIX_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ + +#define AT91_MATRIX_USBPUCR (AT91_MATRIX + 0x34) /* USB Pad Pull-Up Control Register */ +#define AT91_MATRIX_USBPUCR_PUON (1 << 30) /* USB Device PAD Pull-up Enable */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h new file mode 100644 index 0000000..7d94968 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h @@ -0,0 +1,134 @@ +/* + * include/asm-arm/arch-at91rm9200/at91sam926x_mc.h + * + * Memory Controllers (SMC, SDRAMC) - System peripherals registers. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91SAM926x_MC_H +#define AT91SAM926x_MC_H + +/* SDRAM Controller (SDRAMC) registers */ +#define AT91_SDRAMC_MR (AT91_SDRAMC + 0x00) /* SDRAM Controller Mode Register */ +#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */ +#define AT91_SDRAMC_MODE_NORMAL 0 +#define AT91_SDRAMC_MODE_NOP 1 +#define AT91_SDRAMC_MODE_PRECHARGE 2 +#define AT91_SDRAMC_MODE_LMR 3 +#define AT91_SDRAMC_MODE_REFRESH 4 +#define AT91_SDRAMC_MODE_EXT_LMR 5 +#define AT91_SDRAMC_MODE_DEEP 6 + +#define AT91_SDRAMC_TR (AT91_SDRAMC + 0x04) /* SDRAM Controller Refresh Timer Register */ +#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Counter */ + +#define AT91_SDRAMC_CR (AT91_SDRAMC + 0x08) /* SDRAM Controller Configuration Register */ +#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */ +#define AT91_SDRAMC_NC_8 (0 << 0) +#define AT91_SDRAMC_NC_9 (1 << 0) +#define AT91_SDRAMC_NC_10 (2 << 0) +#define AT91_SDRAMC_NC_11 (3 << 0) +#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */ +#define AT91_SDRAMC_NR_11 (0 << 2) +#define AT91_SDRAMC_NR_12 (1 << 2) +#define AT91_SDRAMC_NR_13 (2 << 2) +#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */ +#define AT91_SDRAMC_NB_2 (0 << 4) +#define AT91_SDRAMC_NB_4 (1 << 4) +#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */ +#define AT91_SDRAMC_CAS_1 (1 << 5) +#define AT91_SDRAMC_CAS_2 (2 << 5) +#define AT91_SDRAMC_CAS_3 (3 << 5) +#define AT91_SDRAMC_DBW (1 << 7) /* Data Bus Width */ +#define AT91_SDRAMC_DBW_32 (0 << 7) +#define AT91_SDRAMC_DBW_16 (1 << 7) +#define AT91_SDRAMC_TWR (0xf << 8) /* Write Recovery Delay */ +#define AT91_SDRAMC_TRC (0xf << 12) /* Row Cycle Delay */ +#define AT91_SDRAMC_TRP (0xf << 16) /* Row Precharge Delay */ +#define AT91_SDRAMC_TRCD (0xf << 20) /* Row to Column Delay */ +#define AT91_SDRAMC_TRAS (0xf << 24) /* Active to Precharge Delay */ +#define AT91_SDRAMC_TXSR (0xf << 28) /* Exit Self Refresh to Active Delay */ + +#define AT91_SDRAMC_LPR (AT91_SDRAMC + 0x10) /* SDRAM Controller Low Power Register */ +#define AT91_SDRAMC_LPCB (3 << 0) /* Low-power Configurations */ +#define AT91_SDRAMC_LPCB_DISABLE 0 +#define AT91_SDRAMC_LPCB_SELF_REFRESH 1 +#define AT91_SDRAMC_LPCB_POWER_DOWN 2 +#define AT91_SDRAMC_LPCB_DEEP_POWER_DOWN 3 +#define AT91_SDRAMC_PASR (7 << 4) /* Partial Array Self Refresh */ +#define AT91_SDRAMC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */ +#define AT91_SDRAMC_DS (3 << 10) /* Drive Strenght */ +#define AT91_SDRAMC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */ +#define AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES (0 << 12) +#define AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES (1 << 12) +#define AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES (2 << 12) + +#define AT91_SDRAMC_IER (AT91_SDRAMC + 0x14) /* SDRAM Controller Interrupt Enable Register */ +#define AT91_SDRAMC_IDR (AT91_SDRAMC + 0x18) /* SDRAM Controller Interrupt Disable Register */ +#define AT91_SDRAMC_IMR (AT91_SDRAMC + 0x1C) /* SDRAM Controller Interrupt Mask Register */ +#define AT91_SDRAMC_ISR (AT91_SDRAMC + 0x20) /* SDRAM Controller Interrupt Status Register */ +#define AT91_SDRAMC_RES (1 << 0) /* Refresh Error Status */ + +#define AT91_SDRAMC_MDR (AT91_SDRAMC + 0x24) /* SDRAM Memory Device Register */ +#define AT91_SDRAMC_MD (3 << 0) /* Memory Device Type */ +#define AT91_SDRAMC_MD_SDRAM 0 +#define AT91_SDRAMC_MD_LOW_POWER_SDRAM 1 + + +/* Static Memory Controller (SMC) registers */ +#define AT91_SMC_SETUP(n) (AT91_SMC + 0x00 + ((n)*0x10)) /* Setup Register for CS n */ +#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */ +#define AT91_SMC_NWESETUP_(x) ((x) << 0) +#define AT91_SMC_NCS_WRSETUP (0x3f << 8) /* NCS Setup Length in Write Access */ +#define AT91_SMC_NCS_WRSETUP_(x) ((x) << 8) +#define AT91_SMC_NRDSETUP (0x3f << 16) /* NRD Setup Length */ +#define AT91_SMC_NRDSETUP_(x) ((x) << 16) +#define AT91_SMC_NCS_RDSETUP (0x3f << 24) /* NCS Setup Length in Read Access */ +#define AT91_SMC_NCS_RDSETUP_(x) ((x) << 24) + +#define AT91_SMC_PULSE(n) (AT91_SMC + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */ +#define AT91_SMC_NWEPULSE (0x7f << 0) /* NWE Pulse Length */ +#define AT91_SMC_NWEPULSE_(x) ((x) << 0) +#define AT91_SMC_NCS_WRPULSE (0x7f << 8) /* NCS Pulse Length in Write Access */ +#define AT91_SMC_NCS_WRPULSE_(x)((x) << 8) +#define AT91_SMC_NRDPULSE (0x7f << 16) /* NRD Pulse Length */ +#define AT91_SMC_NRDPULSE_(x) ((x) << 16) +#define AT91_SMC_NCS_RDPULSE (0x7f << 24) /* NCS Pulse Length in Read Access */ +#define AT91_SMC_NCS_RDPULSE_(x)((x) << 24) + +#define AT91_SMC_CYCLE(n) (AT91_SMC + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */ +#define AT91_SMC_NWECYCLE (0x1ff << 0 ) /* Total Write Cycle Length */ +#define AT91_SMC_NWECYCLE_(x) ((x) << 0) +#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */ +#define AT91_SMC_NRDCYCLE_(x) ((x) << 16) + +#define AT91_SMC_MODE(n) (AT91_SMC + 0x0c + ((n)*0x10)) /* Mode Register for CS n */ +#define AT91_SMC_READMODE (1 << 0) /* Read Mode */ +#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */ +#define AT91_SMC_EXNWMODE (3 << 5) /* NWAIT Mode */ +#define AT91_SMC_EXNWMODE_DISABLE (0 << 5) +#define AT91_SMC_EXNWMODE_FROZEN (2 << 5) +#define AT91_SMC_EXNWMODE_READY (3 << 5) +#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */ +#define AT91_SMC_BAT_SELECT (0 << 8) +#define AT91_SMC_BAT_WRITE (1 << 8) +#define AT91_SMC_DBW (3 << 12) /* Data Bus Width */ +#define AT91_SMC_DBW_8 (0 << 12) +#define AT91_SMC_DBW_16 (1 << 12) +#define AT91_SMC_DBW_32 (2 << 12) +#define AT91_SMC_TDF (0xf << 16) /* Data Float Time. */ +#define AT91_SMC_TDF_(x) ((x) << 16) +#define AT91_SMC_TDFMODE (1 << 20) /* TDF Optimization - Enabled */ +#define AT91_SMC_PMEN (1 << 24) /* Page Mode Enabled */ +#define AT91_SMC_PS (3 << 28) /* Page Size */ +#define AT91_SMC_PS_4 (0 << 28) +#define AT91_SMC_PS_8 (1 << 28) +#define AT91_SMC_PS_16 (2 << 28) +#define AT91_SMC_PS_32 (3 << 28) + +#endif -- cgit v0.10.2 From b7dc96d75309346c1213875be68fdbbec92da5e7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 30 Nov 2006 20:39:18 +0000 Subject: [ARM] Clean up discontigmem support Most architectures have fairly simple discontiguous memory - a simple set of successive regions each containing some memory. These can be described simply as a log2 of their maximum size, along with the base address of the first region and the number of regions. The base address is already described by PHYS_PFN_OFFSET, and the number of regions via the MAX_NUMNODES and the number of online nodes. If we then supply the log2 of their maximum size, all the other discontigmem macros can move into generic code. There is one exception: lh7a40x seems to have a more complicated setup; this is left alone. Signed-off-by: Russell King diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h index 24b51cc..9eceb41 100644 --- a/include/asm-arm/arch-aaec2000/memory.h +++ b/include/asm-arm/arch-aaec2000/memory.h @@ -17,8 +17,6 @@ #define __virt_to_bus(x) __virt_to_phys(x) #define __bus_to_virt(x) __phys_to_virt(x) -#ifdef CONFIG_DISCONTIGMEM - /* * The nodes are the followings: * @@ -27,42 +25,6 @@ * node 2: 0xf800.0000 - 0xfbff.ffff * node 3: 0xfc00.0000 - 0xffff.ffff */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(addr) \ - (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT) - -/* - * Given a page frame number, convert it to a node id. - */ -#define PFN_TO_NID(pfn) \ - (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT)) - -/* - * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory - * and return the mem_map of that node. - */ -#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) - -/* - * Given a page frame number, find the owning node of the memory - * and return the mem_map of that node. - */ -#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) - -/* - * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory - * and returns the index corresponding to the appropriate page in the - * node's mem_map. - */ -#define LOCAL_MAP_NR(addr) \ - (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT) - -#define NODE_MAX_MEM_SHIFT 26 -#define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) - -#endif /* CONFIG_DISCONTIGMEM */ +#define NODE_MEM_SIZE_BITS 26 #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h index c6e8dcf..42768cc 100644 --- a/include/asm-arm/arch-clps711x/memory.h +++ b/include/asm-arm/arch-clps711x/memory.h @@ -62,7 +62,15 @@ * memory bank. For those systems, simply undefine CONFIG_DISCONTIGMEM. */ -#ifdef CONFIG_DISCONTIGMEM +/* + * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211 + * uses only one of the two banks (bank #1). However, even within + * bank #1, memory is discontiguous. + * + * The EDB7211 has two 8MB DRAM areas with 8MB of empty space between + * them, so we use 24 for the node max shift to get 16MB node sizes. + */ + /* * Because of the wide memory address space between physical RAM banks on the * SA1100, it's much more convenient to use Linux's NUMA support to implement @@ -80,48 +88,7 @@ * node 2: 0xd0000000 - 0xd7ffffff * node 3: 0xd8000000 - 0xdfffffff */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(addr) \ - (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT) - -/* - * Given a page frame number, convert it to a node id. - */ -#define PFN_TO_NID(pfn) \ - (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT)) - -/* - * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory - * and returns the mem_map of that node. - */ -#define ADDR_TO_MAPBASE(kaddr) \ - NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr))) - -#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) - -/* - * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory - * and returns the index corresponding to the appropriate page in the - * node's mem_map. - */ -#define LOCAL_MAP_NR(addr) \ - (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT) - -/* - * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211 - * uses only one of the two banks (bank #1). However, even within - * bank #1, memory is discontiguous. - * - * The EDB7211 has two 8MB DRAM areas with 8MB of empty space between - * them, so we use 24 for the node max shift to get 16MB node sizes. - */ -#define NODE_MAX_MEM_SHIFT 24 -#define NODE_MAX_MEM_SIZE (1< 0xc4000000-0xc7ffffff * node 2: 0xa8000000-0xabffffff --> 0xc8000000-0xcbffffff * node 3: 0xac000000-0xafffffff --> 0xcc000000-0xcfffffff + * + * This needs a node mem size of 26 bits. */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 26) - -/* - * Given a page frame number, convert it to a node id. - */ -#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT)) - -/* - * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory - * and returns the mem_map of that node. - */ -#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) - -/* - * Given a page frame number, find the owning node of the memory - * and returns the mem_map of that node. - */ -#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) - -/* - * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory - * and returns the index corresponding to the appropriate page in the - * node's mem_map. - */ -#define LOCAL_MAP_NR(addr) \ - (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT) - -#endif +#define NODE_MEM_SIZE_BITS 26 #endif diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h index 1ff172d..0e907fc 100644 --- a/include/asm-arm/arch-sa1100/memory.h +++ b/include/asm-arm/arch-sa1100/memory.h @@ -39,7 +39,6 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes); #define __virt_to_bus(x) __virt_to_phys(x) #define __bus_to_virt(x) __phys_to_virt(x) -#ifdef CONFIG_DISCONTIGMEM /* * Because of the wide memory address space between physical RAM banks on the * SA1100, it's much convenient to use Linux's NUMA support to implement our @@ -57,38 +56,7 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes); * node 2: 0xd0000000 - 0xd7ffffff * node 3: 0xd8000000 - 0xdfffffff */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 27) - -/* - * Given a page frame number, convert it to a node id. - */ -#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (27 - PAGE_SHIFT)) - -/* - * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory - * and return the mem_map of that node. - */ -#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) - -/* - * Given a page frame number, find the owning node of the memory - * and return the mem_map of that node. - */ -#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) - -/* - * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory - * and returns the index corresponding to the appropriate page in the - * node's mem_map. - */ -#define LOCAL_MAP_NR(addr) \ - (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) - -#endif +#define NODE_MEM_SIZE_BITS 27 /* * Cache flushing area - SA1100 zero bank diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index 91d536c..d9bfb39 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -215,6 +215,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x) * virt_addr_valid(k) indicates whether a virtual address is valid */ #ifndef CONFIG_DISCONTIGMEM + #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) @@ -230,6 +231,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x) * around in memory. */ #include + #define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn) #define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT) @@ -256,6 +258,43 @@ static inline __deprecated void *bus_to_virt(unsigned long x) */ #define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT) +/* + * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory + * and returns the mem_map of that node. + */ +#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) + +/* + * Given a page frame number, find the owning node of the memory + * and returns the mem_map of that node. + */ +#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) + +#ifdef NODE_MEM_SIZE_BITS +#define NODE_MEM_SIZE_MASK ((1 << NODE_MEM_SIZE_BITS) - 1) + +/* + * Given a kernel address, find the home node of the underlying memory. + */ +#define KVADDR_TO_NID(addr) \ + (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MEM_SIZE_BITS) + +/* + * Given a page frame number, convert it to a node id. + */ +#define PFN_TO_NID(pfn) \ + (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MEM_SIZE_BITS - PAGE_SHIFT)) + +/* + * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory + * and returns the index corresponding to the appropriate page in the + * node's mem_map. + */ +#define LOCAL_MAP_NR(addr) \ + (((unsigned long)(addr) & NODE_MEM_SIZE_MASK) >> PAGE_SHIFT) + +#endif /* NODE_MEM_SIZE_BITS */ + #endif /* !CONFIG_DISCONTIGMEM */ /* -- cgit v0.10.2 From be1c63411addba3ad750eb4fdfc50b97bc82825e Mon Sep 17 00:00:00 2001 From: Olaf Kirch Date: Fri, 1 Dec 2006 10:39:12 +0100 Subject: [PATCH] blktrace: add timestamp message This adds a new timestamp message to blktrace, giving the timeofday when we starting tracing. This helps user space correlate block trace events with eg an application strace. This requires a (compatible) update to blkparse. The changed blkparse is still able to process traces generated by older kernels, and older versions of blkparse should silently ignore the new records (because they have a pid of 0). Signed-off-by: Olaf Kirch Signed-off-by: Jens Axboe diff --git a/block/blktrace.c b/block/blktrace.c index 135593c..562ca7c 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -22,30 +22,61 @@ #include #include #include +#include #include static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; static unsigned int blktrace_seq __read_mostly = 1; /* + * Send out a notify message. + */ +static inline unsigned int trace_note(struct blk_trace *bt, + pid_t pid, int action, + const void *data, size_t len) +{ + struct blk_io_trace *t; + int cpu = smp_processor_id(); + + t = relay_reserve(bt->rchan, sizeof(*t) + len); + if (t == NULL) + return 0; + + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu); + t->device = bt->dev; + t->action = action; + t->pid = pid; + t->cpu = cpu; + t->pdu_len = len; + memcpy((void *) t + sizeof(*t), data, len); + return blktrace_seq; +} + +/* * Send out a notify for this process, if we haven't done so since a trace * started */ static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) { - struct blk_io_trace *t; + tsk->btrace_seq = trace_note(bt, tsk->pid, + BLK_TN_PROCESS, + tsk->comm, sizeof(tsk->comm)); +} - t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm)); - if (t) { - t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; - t->device = bt->dev; - t->action = BLK_TC_ACT(BLK_TC_NOTIFY); - t->pid = tsk->pid; - t->cpu = smp_processor_id(); - t->pdu_len = sizeof(tsk->comm); - memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len); - tsk->btrace_seq = blktrace_seq; - } +static void trace_note_time(struct blk_trace *bt) +{ + struct timespec now; + unsigned long flags; + u32 words[2]; + + getnstimeofday(&now); + words[0] = now.tv_sec; + words[1] = now.tv_nsec; + + local_irq_save(flags); + trace_note(bt, 0, BLK_TN_TIMESTAMP, words, sizeof(words)); + local_irq_restore(flags); } static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, @@ -394,6 +425,8 @@ static int blk_trace_startstop(request_queue_t *q, int start) blktrace_seq++; smp_mb(); bt->trace_state = Blktrace_running; + + trace_note_time(bt); ret = 0; } } else { diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index b99a714..3680ff9a 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -50,6 +50,15 @@ enum blktrace_act { }; /* + * Notify events. + */ +enum blktrace_notify { + __BLK_TN_PROCESS = 0, /* establish pid/name mapping */ + __BLK_TN_TIMESTAMP, /* include system clock */ +}; + + +/* * Trace actions in full. Additionally, read or write is masked */ #define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) @@ -68,6 +77,9 @@ enum blktrace_act { #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY)) +#define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY)) + #define BLK_IO_TRACE_MAGIC 0x65617400 #define BLK_IO_TRACE_VERSION 0x07 -- cgit v0.10.2 From ad2d7225709b11da47e092634cbdf0591829ae9c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 1 Dec 2006 10:40:20 +0100 Subject: [PATCH] block: kill length alignment test in bio_map_user() The target mode support is mapping in bios using bio_map_user. The current targets do not need their len to be aligned with a queue limit so this check is causing some problems. Note: pointers passed into the kernel are properly aligned by usersapace tgt code so the uaddr check in bio_map_user is ok. The major user, blk_bio_map_user checks for the len before mapping so it is not affected by this patch. And the semi-newly added user blk_rq_map_user_iov has been failing out when the len is not aligned properly so maybe people have been good and not sending misaligned lens or that path is not used very often and this change will not be very dangerous. st and sg do not check the length and we have not seen any problem reports from those wider used paths so this patch should be fairly safe - for mm and wider testing at least. Signed-off-by: Mike Christie Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley Signed-off-by: Jens Axboe diff --git a/fs/bio.c b/fs/bio.c index f95c874..d91cfbf 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -622,10 +622,9 @@ static struct bio *__bio_map_user_iov(request_queue_t *q, nr_pages += end - start; /* - * transfer and buffer must be aligned to at least hardsector - * size for now, in the future we can relax this restriction + * buffer must be aligned to at least hardsector size for now */ - if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q))) + if (uaddr & queue_dma_alignment(q)) return ERR_PTR(-EINVAL); } -- cgit v0.10.2 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 diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 9eaee66..0f82e12 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 e55a756..5493c2f 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 7ea0f48f..2df5cf4 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 d91cfbf..aa4d09b 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 7bfcde2..e1c7286 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 v0.10.2 From bb37b94c68e7b37eecea8576039ae9396ca07839 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 1 Dec 2006 10:42:33 +0100 Subject: [BLOCK] Cleanup unused variable passing - ->init_queue() does not need the elevator passed in - ->put_request() is a hot path and need not have the queue passed in - cfq_update_io_seektime() does not need cfqd passed in Signed-off-by: Jens Axboe diff --git a/block/as-iosched.c b/block/as-iosched.c index 50b95e4..0024211 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1317,7 +1317,7 @@ static void as_exit_queue(elevator_t *e) /* * initialize elevator private data (as_data). */ -static void *as_init_queue(request_queue_t *q, elevator_t *e) +static void *as_init_queue(request_queue_t *q) { struct as_data *ad; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1d9c3c7..e9019ed 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1464,8 +1464,7 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) } static void -cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, - struct request *rq) +cfq_update_io_seektime(struct cfq_io_context *cic, struct request *rq) { sector_t sdist; u64 total; @@ -1617,7 +1616,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, } cfq_update_io_thinktime(cfqd, cic); - cfq_update_io_seektime(cfqd, cic, rq); + cfq_update_io_seektime(cic, rq); cfq_update_idle_window(cfqd, cfqq, cic); cic->last_queue = jiffies; @@ -1770,7 +1769,7 @@ static int cfq_may_queue(request_queue_t *q, int rw) /* * queue lock held here */ -static void cfq_put_request(request_queue_t *q, struct request *rq) +static void cfq_put_request(struct request *rq) { struct cfq_queue *cfqq = RQ_CFQQ(rq); @@ -1951,7 +1950,7 @@ static void cfq_exit_queue(elevator_t *e) kfree(cfqd); } -static void *cfq_init_queue(request_queue_t *q, elevator_t *e) +static void *cfq_init_queue(request_queue_t *q) { struct cfq_data *cfqd; int i; diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index b7c5b34..6d673e9 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -356,7 +356,7 @@ static void deadline_exit_queue(elevator_t *e) /* * initialize elevator private data (deadline_data). */ -static void *deadline_init_queue(request_queue_t *q, elevator_t *e) +static void *deadline_init_queue(request_queue_t *q) { struct deadline_data *dd; diff --git a/block/elevator.c b/block/elevator.c index 8ccd163..c0063f3 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -129,7 +129,7 @@ static struct elevator_type *elevator_get(const char *name) static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq) { - return eq->ops->elevator_init_fn(q, eq); + return eq->ops->elevator_init_fn(q); } static void elevator_attach(request_queue_t *q, struct elevator_queue *eq, @@ -810,7 +810,7 @@ void elv_put_request(request_queue_t *q, struct request *rq) elevator_t *e = q->elevator; if (e->ops->elevator_put_req_fn) - e->ops->elevator_put_req_fn(q, rq); + e->ops->elevator_put_req_fn(rq); } int elv_may_queue(request_queue_t *q, int rw) diff --git a/block/noop-iosched.c b/block/noop-iosched.c index 79af431..1c3de2b 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c @@ -65,7 +65,7 @@ noop_latter_request(request_queue_t *q, struct request *rq) return list_entry(rq->queuelist.next, struct request, queuelist); } -static void *noop_init_queue(request_queue_t *q, elevator_t *e) +static void *noop_init_queue(request_queue_t *q) { struct noop_data *nd; diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 2fa9f11..a24931d 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -21,11 +21,11 @@ typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); typedef int (elevator_may_queue_fn) (request_queue_t *, int); typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, gfp_t); -typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); +typedef void (elevator_put_req_fn) (struct request *); typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *); typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); -typedef void *(elevator_init_fn) (request_queue_t *, elevator_t *); +typedef void *(elevator_init_fn) (request_queue_t *); typedef void (elevator_exit_fn) (elevator_t *); struct elevator_ops -- cgit v0.10.2 From 1a0ed732afdbd4b960a4b93f78fddc71b8076e61 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 09:04:47 +0100 Subject: [ARM] 3949/2: AT91: SAM9 timer driver Add support for the timer on the Atmel AT91SAM9261 and AT91SAM9260 processors. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 40e89bf..b8684ba 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -11,8 +11,8 @@ obj-$(CONFIG_PM) += pm.o # CPU-specific support obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.c -obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o -obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o # AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91rm9200/at91sam926x_time.c new file mode 100644 index 0000000..99df5f6 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam926x_time.c @@ -0,0 +1,114 @@ +/* + * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c + * + * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France + * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France + * + * 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 + + +#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV) +#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20) + +/* + * Returns number of microseconds since last timer interrupt. Note that interrupts + * will have been disabled by do_gettimeofday() + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy (linux/timex.h). + */ +static unsigned long at91sam926x_gettimeoffset(void) +{ + unsigned long elapsed; + unsigned long t = at91_sys_read(AT91_PIT_PIIR); + + elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ + + return (unsigned long)(elapsed * 1000000) / LATCH; +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id) +{ + volatile long nr_ticks; + + if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + /* Get number to ticks performed before interrupt and clear PIT interrupt */ + nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); + do { + timer_tick(); + nr_ticks--; + } while (nr_ticks); + + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; + } else + return IRQ_NONE; /* not handled */ +} + +static struct irqaction at91sam926x_timer_irq = { + .name = "at91_tick", + .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, + .handler = at91sam926x_timer_interrupt +}; + +void at91sam926x_timer_reset(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); + + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_PIT_PIVR); + + /* Set Period Interval timer and enable its interrupt */ + at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN); +} + +/* + * Set up timer interrupt. + */ +void __init at91sam926x_timer_init(void) +{ + /* Initialize and enable the timer */ + at91sam926x_timer_reset(); + + /* Make IRQs happen for the system timer. */ + setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq); +} + +#ifdef CONFIG_PM +static void at91sam926x_timer_suspend(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); +} +#else +#define at91sam926x_timer_suspend NULL +#endif + +struct sys_timer at91sam926x_timer = { + .init = at91sam926x_timer_init, + .offset = at91sam926x_gettimeoffset, + .suspend = at91sam926x_timer_suspend, + .resume = at91sam926x_timer_reset, +}; + diff --git a/include/asm-arm/arch-at91rm9200/at91_pit.h b/include/asm-arm/arch-at91rm9200/at91_pit.h new file mode 100644 index 0000000..4a30d009 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91_pit.h @@ -0,0 +1,29 @@ +/* + * include/asm-arm/arch-at91rm9200/at91_pit.h + * + * Periodic Interval Timer (PIT) - System peripherals regsters. + * Based on AT91SAM9261 datasheet revision D. + * + * 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. + */ + +#ifndef AT91_PIT_H +#define AT91_PIT_H + +#define AT91_PIT_MR (AT91_PIT + 0x00) /* Mode Register */ +#define AT91_PIT_PITIEN (1 << 25) /* Timer Interrupt Enable */ +#define AT91_PIT_PITEN (1 << 24) /* Timer Enabled */ +#define AT91_PIT_PIV (0xfffff) /* Periodic Interval Value */ + +#define AT91_PIT_SR (AT91_PIT + 0x04) /* Status Register */ +#define AT91_PIT_PITS (1 << 0) /* Timer Status */ + +#define AT91_PIT_PIVR (AT91_PIT + 0x08) /* Periodic Interval Value Register */ +#define AT91_PIT_PIIR (AT91_PIT + 0x0c) /* Periodic Interval Image Register */ +#define AT91_PIT_PICNT (0xfff << 20) /* Interval Counter */ +#define AT91_PIT_CPIV (0xfffff) /* Inverval Value */ + +#endif -- cgit v0.10.2 From 86ad76bb2db7029343f681359c4b328fd8c36ae8 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 16:45:01 +0100 Subject: [ARM] 3953/1: AT91: SAM9 platform devices This patch includes the pin initialization, resource definition and registration of the platform_devices for the SAM9260 and SAM9261 processors. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index b8684ba..6093c31 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -11,8 +11,8 @@ obj-$(CONFIG_PM) += pm.o # CPU-specific support obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.c -obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o -obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o # AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c new file mode 100644 index 0000000..a6c596d --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9260_devices.c @@ -0,0 +1,866 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260_devices.c + * + * Copyright (C) 2006 Atmel + * + * 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 "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9260_UHP_BASE, + .end = AT91SAM9260_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UHP, + .end = AT91SAM9260_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_UDP, + .end = AT91SAM9260_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UDP, + .end = AT91SAM9260_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally by USB device peripheral */ + + udc_data = *data; + platform_device_register(&at91_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct eth_platform_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_EMAC, + .end = AT91SAM9260_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_EMAC, + .end = AT91SAM9260_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct eth_platform_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA21, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PA28, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PA29, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9260_eth_device); +} +#else +void __init at91_add_device_eth(struct eth_platform_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_MCI, + .end = AT91SAM9260_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_MCI, + .end = AT91SAM9260_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA8, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA3, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA6, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } + + mmc_data = *data; + platform_device_register(&at91sam9260_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9260_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + nand_data = *data; + platform_device_register(&at91sam9260_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_TWI, + .end = AT91SAM9260_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_TWI, + .end = AT91SAM9260_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + platform_device_register(&at91sam9260_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI0, + .end = AT91SAM9260_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI0, + .end = AT91SAM9260_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI1, + .end = AT91SAM9260_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI1, + .end = AT91SAM9260_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9260_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB14, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PB15, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US0, + .end = AT91SAM9260_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US0, + .end = AT91SAM9260_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */ + at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US1, + .end = AT91SAM9260_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US1, + .end = AT91SAM9260_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US2, + .end = AT91SAM9260_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US2, + .end = AT91SAM9260_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US3, + .end = AT91SAM9260_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US3, + .end = AT91SAM9260_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart3_device = { + .name = "atmel_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD3 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD3 */ +} + +static struct resource uart4_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US4, + .end = AT91SAM9260_BASE_US4 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US4, + .end = AT91SAM9260_ID_US4, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart4_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart4_device = { + .name = "atmel_usart", + .id = 5, + .dev = { + .platform_data = &uart4_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart4_resources, + .num_resources = ARRAY_SIZE(uart4_resources), +}; + +static inline void configure_usart4_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA31, 1); /* TXD4 */ + at91_set_B_periph(AT91_PIN_PA30, 0); /* RXD4 */ +} + +static struct resource uart5_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US5, + .end = AT91SAM9260_BASE_US5 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US5, + .end = AT91SAM9260_ID_US5, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart5_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart5_device = { + .name = "atmel_usart", + .id = 6, + .dev = { + .platform_data = &uart5_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart5_resources, + .num_resources = ARRAY_SIZE(uart5_resources), +}; + +static inline void configure_usart5_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB12, 1); /* TXD5 */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9260_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9260_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9260_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91sam9260_uart3_device; + at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart"); + break; + case 4: + configure_usart4_pins(); + at91_uarts[i] = &at91sam9260_uart4_device; + at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart"); + break; + case 5: + configure_usart5_pins(); + at91_uarts[i] = &at91sam9260_uart5_device; + at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart"); + break; + case 6: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9260_dbgu_device; + at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91rm9200/at91sam9261_devices.c new file mode 100644 index 0000000..ed1d790 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9261_devices.c @@ -0,0 +1,741 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261_devices.c + * + * Copyright (C) 2005 Thibaut VARENE + * Copyright (C) 2005 David Brownell + * + * 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 "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9261_UHP_BASE, + .end = AT91SAM9261_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UHP, + .end = AT91SAM9261_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91sam9261_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_UDP, + .end = AT91SAM9261_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UDP, + .end = AT91SAM9261_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + unsigned long x; + + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally */ + x = at91_sys_read(AT91_MATRIX_USBPUCR); + at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON); + + udc_data = *data; + platform_device_register(&at91sam9261_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_MCI, + .end = AT91SAM9261_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_MCI, + .end = AT91SAM9261_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_B_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA6, 1); + } + + mmc_data = *data; + platform_device_register(&at91sam9261_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_set_A_periph(AT91_PIN_PC0, 0); /* NANDOE */ + at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */ + + nand_data = *data; + platform_device_register(&at91_nand_device); +} + +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_TWI, + .end = AT91SAM9261_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_TWI, + .end = AT91SAM9261_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA7, 1); + + at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA8, 1); + + platform_device_register(&at91sam9261_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI0, + .end = AT91SAM9261_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI0, + .end = AT91SAM9261_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI1, + .end = AT91SAM9261_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI1, + .end = AT91SAM9261_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB30, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB31, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LCD Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE) +static u64 lcdc_dmamask = 0xffffffffUL; +static struct at91fb_info lcdc_data; + +static struct resource lcdc_resources[] = { + [0] = { + .start = AT91SAM9261_LCDC_BASE, + .end = AT91SAM9261_LCDC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_LCDC, + .end = AT91SAM9261_ID_LCDC, + .flags = IORESOURCE_IRQ, + }, +#if defined(CONFIG_FB_INTSRAM) + [2] = { + .start = AT91SAM9261_SRAM_BASE, + .end = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device at91_lcdc_device = { + .name = "at91-fb", + .id = 0, + .dev = { + .dma_mask = &lcdc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &lcdc_data, + }, + .resource = lcdc_resources, + .num_resources = ARRAY_SIZE(lcdc_resources), +}; + +void __init at91_add_device_lcdc(struct at91fb_info *data) +{ + if (!data) { + return; + } + + at91_set_A_periph(AT91_PIN_PB1, 0); /* LCDHSYNC */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* LCDDOTCK */ + at91_set_A_periph(AT91_PIN_PB3, 0); /* LCDDEN */ + at91_set_A_periph(AT91_PIN_PB4, 0); /* LCDCC */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* LCDD2 */ + at91_set_A_periph(AT91_PIN_PB8, 0); /* LCDD3 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* LCDD4 */ + at91_set_A_periph(AT91_PIN_PB10, 0); /* LCDD5 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* LCDD6 */ + at91_set_A_periph(AT91_PIN_PB12, 0); /* LCDD7 */ + at91_set_A_periph(AT91_PIN_PB15, 0); /* LCDD10 */ + at91_set_A_periph(AT91_PIN_PB16, 0); /* LCDD11 */ + at91_set_A_periph(AT91_PIN_PB17, 0); /* LCDD12 */ + at91_set_A_periph(AT91_PIN_PB18, 0); /* LCDD13 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* LCDD14 */ + at91_set_A_periph(AT91_PIN_PB20, 0); /* LCDD15 */ + at91_set_B_periph(AT91_PIN_PB23, 0); /* LCDD18 */ + at91_set_B_periph(AT91_PIN_PB24, 0); /* LCDD19 */ + at91_set_B_periph(AT91_PIN_PB25, 0); /* LCDD20 */ + at91_set_B_periph(AT91_PIN_PB26, 0); /* LCDD21 */ + at91_set_B_periph(AT91_PIN_PB27, 0); /* LCDD22 */ + at91_set_B_periph(AT91_PIN_PB28, 0); /* LCDD23 */ + + lcdc_data = *data; + platform_device_register(&at91_lcdc_device); +} +#else +void __init at91_add_device_lcdc(struct at91fb_info *data) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9261_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA9, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA10, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US0, + .end = AT91SAM9261_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US0, + .end = AT91SAM9261_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC8, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US1, + .end = AT91SAM9261_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US1, + .end = AT91SAM9261_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC12, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PC13, 0); /* RXD1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US2, + .end = AT91SAM9261_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US2, + .end = AT91SAM9261_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC15, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PC14, 1); /* TXD2 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9261_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9261_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9261_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart"); + break; + case 3: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9261_dbgu_device; + at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); -- cgit v0.10.2 From d100f25956e8626afeafbb38558ca8c58df1cb6b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 10:15:04 +0100 Subject: [ARM] 3955/1: AT91: Clear timer interrupt when resuming Attached is a patch for at91rm9200_time.c which removes the 'BUG: soft lockup detected on CPU#0!' message when exiting suspended states. Patch from Savin Zlobec Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c index 8e9c049..b999e19 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_time.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -101,6 +101,9 @@ void at91rm9200_timer_reset(void) /* Set Period Interval timer */ at91_sys_write(AT91_ST_PIMR, LATCH); + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_ST_SR); + /* Enable Period Interval Timer interrupt */ at91_sys_write(AT91_ST_IER, AT91_ST_PITS); } -- cgit v0.10.2 From 330d741b0632960e7853a2cb3b2899e94e696f12 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 10:31:29 +0100 Subject: [ARM] 3956/1: AT91: Carmeva board update This patch updates the Carmeva board support: * Specify the MMC Write-protect and Detection pins. * Add configuration of SPI devices. Patch from Peer Georgi. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig index d24ae87..d392833 100644 --- a/arch/arm/configs/carmeva_defconfig +++ b/arch/arm/configs/carmeva_defconfig @@ -474,7 +474,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c index 9820874..5cd68e6 100644 --- a/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -65,7 +65,6 @@ static void __init carmeva_init_irq(void) at91rm9200_init_interrupts(NULL); } - static struct at91_eth_data __initdata carmeva_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, @@ -91,6 +90,31 @@ static struct at91_udc_data __initdata carmeva_udc_data = { static struct at91_mmc_data __initdata carmeva_mmc_data = { .is_b = 0, .wire4 = 1, + .det_pin = AT91_PIN_PB10, + .wp_pin = AT91_PIN_PC14, +}; + +static struct spi_board_info carmeva_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + }, + { /* User accessable spi - cs1 (250KHz) */ + .modalias = "spi-cs1", + .chip_select = 1, + .max_speed_hz = 250 * 1000, + }, + { /* User accessable spi - cs2 (1MHz) */ + .modalias = "spi-cs2", + .chip_select = 2, + .max_speed_hz = 1 * 1000 * 1000, + }, + { /* User accessable spi - cs3 (10MHz) */ + .modalias = "spi-cs3", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + }, }; static void __init carmeva_board_init(void) @@ -105,10 +129,10 @@ static void __init carmeva_board_init(void) at91_add_device_udc(&carmeva_udc_data); /* I2C */ at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices)); /* Compact Flash */ // at91_add_device_cf(&carmeva_cf_data); - /* SPI */ -// at91_add_device_spi(NULL, 0); /* MMC */ at91_add_device_mmc(&carmeva_mmc_data); } -- cgit v0.10.2 From fcc63716a5ee93ec3d1043890e38753d53313b80 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 10:55:15 +0100 Subject: [ARM] 3957/1: AT91: Physically mapped flash on DK and EK boards This patch converts the old CONFIG_MTD_PHYSMAP_ options to the new physmap API by creating a physmap platform device for the NOR flash found on the Atmel AT91RM9200-DK and AT91RM9200-EK boards. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index b430414..1d79360 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -357,9 +357,9 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x10000000 -CONFIG_MTD_PHYSMAP_LEN=0x200000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_START=0 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_PLATRAM is not set @@ -585,7 +585,9 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_AT91_RTC=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91RM9200=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index d96fc83..16120bc 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -348,9 +348,9 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x10000000 -CONFIG_MTD_PHYSMAP_LEN=0x800000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_START=0 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_PLATRAM is not set @@ -566,7 +566,9 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_AT91_RTC=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91RM9200=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index c699f39..314e1f7 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "generic.h" @@ -145,6 +147,30 @@ static struct at91_nand_data __initdata dk_nand_data = { .partition_info = nand_partitions, }; +#define DK_FLASH_BASE AT91_CHIPSELECT_0 +#define DK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data dk_flash_data = { + .width = 2, +}; + +static struct resource dk_flash_resource = { + .start = DK_FLASH_BASE, + .end = DK_FLASH_BASE + DK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device dk_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &dk_flash_data, + }, + .resource = &dk_flash_resource, + .num_resources = 1, +}; + + static void __init dk_board_init(void) { /* Serial */ @@ -172,6 +198,8 @@ static void __init dk_board_init(void) #endif /* NAND */ at91_add_device_nand(&dk_nand_data); + /* NOR Flash */ + platform_device_register(&dk_flash); /* VGA */ // dk_add_device_video(); } diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 830eb79..9fcfa06 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "generic.h" @@ -107,6 +109,30 @@ static struct spi_board_info ek_spi_devices[] = { #endif }; +#define EK_FLASH_BASE AT91_CHIPSELECT_0 +#define EK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data ek_flash_data = { + .width = 2, +}; + +static struct resource ek_flash_resource = { + .start = EK_FLASH_BASE, + .end = EK_FLASH_BASE + EK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ek_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ek_flash_data, + }, + .resource = &ek_flash_resource, + .num_resources = 1, +}; + + static void __init ek_board_init(void) { /* Serial */ @@ -130,6 +156,8 @@ static void __init ek_board_init(void) at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ at91_add_device_mmc(&ek_mmc_data); #endif + /* NOR Flash */ + platform_device_register(&ek_flash); /* VGA */ // ek_add_device_video(); } -- cgit v0.10.2 From d481f86449ccd66314b700c78b3a79168df80d02 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 11:27:31 +0100 Subject: [ARM] 3959/1: AT91: Support for SAM9 USB and HCK clocks The bits used to select the USB clocks are different on the SAM9's. Add support for the HCK clocks on the AT91SAM9261. Patch from Patrice Vilchez & Nicolas Ferre Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 1e0000c..4dee21f 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -29,6 +29,7 @@ #include #include +#include #include "clock.h" @@ -42,6 +43,7 @@ #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) #define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE) #define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL) +#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM) static LIST_HEAD(clocks); @@ -115,13 +117,11 @@ static void pmc_sys_mode(struct clk *clk, int is_on) static struct clk udpck = { .name = "udpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UDP, .mode = pmc_sys_mode, }; static struct clk uhpck = { .name = "uhpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UHP, .mode = pmc_sys_mode, }; @@ -435,6 +435,12 @@ int __init clk_register(struct clk *clk) clk->mode = pmc_periph_mode; list_add_tail(&clk->node, &clocks); } + else if (clk_is_sys(clk)) { + clk->parent = &mck; + clk->mode = pmc_sys_mode; + + list_add_tail(&clk->node, &clocks); + } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS else if (clk_is_programmable(clk)) { clk->mode = pmc_sys_mode; @@ -587,9 +593,21 @@ int __init at91_clock_init(unsigned long main_clock) */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); + if (cpu_is_at91rm9200()) { + uhpck.pmc_mask = AT91RM9200_PMC_UHP; + udpck.pmc_mask = AT91RM9200_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); + at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); + } else if (cpu_is_at91sam9260()) { + uhpck.pmc_mask = AT91SAM926x_PMC_UHP; + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); + } else if (cpu_is_at91sam9261()) { + uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); + } at91_sys_write(AT91_CKGR_PLLBR, 0); - at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h index 0592e66..b5c7a2e 100644 --- a/arch/arm/mach-at91rm9200/clock.h +++ b/arch/arm/mach-at91rm9200/clock.h @@ -10,6 +10,7 @@ #define CLK_TYPE_PLL 0x2 #define CLK_TYPE_PROGRAMMABLE 0x4 #define CLK_TYPE_PERIPHERAL 0x8 +#define CLK_TYPE_SYSTEM 0x10 struct clk { diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c index 5b775fa..67aa557 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91rm9200/pm.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "generic.h" @@ -70,9 +71,15 @@ static int at91_pm_verify_clocks(void) scsr = at91_sys_read(AT91_PMC_SCSR); /* USB must not be using PLLB */ - if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { - pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); - return 0; + if (cpu_is_at91rm9200()) { + if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + } else if (cpu_is_at91sam9260()) { +#warning "Check SAM9260 USB clocks" + } else if (cpu_is_at91sam9261()) { +#warning "Check SAM9261 USB clocks" } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS -- cgit v0.10.2 From 05043d08045271eb5655308371dd285a852ef855 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 11:51:19 +0100 Subject: [ARM] 3960/1: AT91: Final SAM9 intergration patches. This patch includes a number of small changes for integrating the AT91SAM9261 and AT91SAM0260 support. * Can only select support for one AT91 processor at a time. * Remove most of the remaining static memory mapping for the AT91RM9200. * Reserve 1Mb of memory below the IO for mapping the internal SRAM and any custom board-specific devices (ie, FPGA). * The SAM9260 has more serial ports, so increase the maximum to 7. * Define the standard chipselect addresses, and define other addresses relative to those. * CLOCK_TICK_RATE is different on the SAM926x's. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 2f85e86..8d44326 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -2,7 +2,8 @@ if ARCH_AT91 menu "Atmel AT91 System-on-Chip" -comment "Atmel AT91 Processors" +choice + prompt "Atmel AT91 Processor" config ARCH_AT91RM9200 bool "AT91RM9200" @@ -13,6 +14,8 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" +endchoice + # ---------------------------------------------------------- if ARCH_AT91RM9200 @@ -33,7 +36,6 @@ config ARCH_AT91RM9200DK Select this if you are using Atmel's AT91RM9200-DK Development board. (Discontinued) - config MACH_AT91RM9200EK bool "Atmel AT91RM9200-EK Evaluation Kit" depends on ARCH_AT91RM9200 diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 6093c31..564ad6e 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -10,7 +10,7 @@ obj- := obj-$(CONFIG_PM) += pm.o # CPU-specific support -obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.c +obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c index 0816a8d..a92e9a4 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -28,32 +28,12 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = AT91_VA_BASE_SPI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_SPI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { .virtual = AT91_VA_BASE_EMAC, .pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC), .length = SZ_16K, .type = MT_DEVICE, }, { - .virtual = AT91_VA_BASE_TWI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_TWI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_MCI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_MCI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_UDP, - .pfn = __phys_to_pfn(AT91RM9200_BASE_UDP), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_SRAM_VIRT_BASE, + .virtual = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE, .pfn = __phys_to_pfn(AT91RM9200_SRAM_BASE), .length = AT91RM9200_SRAM_SIZE, .type = MT_DEVICE, diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h index d42e310..9ea5bfe 100644 --- a/include/asm-arm/arch-at91rm9200/hardware.h +++ b/include/asm-arm/arch-at91rm9200/hardware.h @@ -42,29 +42,27 @@ * Virtual to Physical Address mapping for IO devices. */ #define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS) -#define AT91_VA_BASE_SPI AT91_IO_P2V(AT91RM9200_BASE_SPI) #define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91RM9200_BASE_EMAC) -#define AT91_VA_BASE_TWI AT91_IO_P2V(AT91RM9200_BASE_TWI) -#define AT91_VA_BASE_MCI AT91_IO_P2V(AT91RM9200_BASE_MCI) -#define AT91_VA_BASE_UDP AT91_IO_P2V(AT91RM9200_BASE_UDP) /* Internal SRAM is mapped below the IO devices */ -#define AT91_SRAM_VIRT_BASE (AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE) +#define AT91_SRAM_MAX SZ_1M +#define AT91_VIRT_BASE (AT91_IO_VIRT_BASE - AT91_SRAM_MAX) /* Serial ports */ -#define ATMEL_MAX_UART 5 /* 4 USART3's and one DBGU port */ - -/* FLASH */ -#define AT91_FLASH_BASE 0x10000000 /* NCS0: Flash physical base address */ +#define ATMEL_MAX_UART 7 /* 6 USART3's and one DBGU port (SAM9260) */ + +/* External Memory Map */ +#define AT91_CHIPSELECT_0 0x10000000 +#define AT91_CHIPSELECT_1 0x20000000 +#define AT91_CHIPSELECT_2 0x30000000 +#define AT91_CHIPSELECT_3 0x40000000 +#define AT91_CHIPSELECT_4 0x50000000 +#define AT91_CHIPSELECT_5 0x60000000 +#define AT91_CHIPSELECT_6 0x70000000 +#define AT91_CHIPSELECT_7 0x80000000 /* SDRAM */ -#define AT91_SDRAM_BASE 0x20000000 /* NCS1: SDRAM physical base address */ - -/* SmartMedia */ -#define AT91_SMARTMEDIA_BASE 0x40000000 /* NCS3: Smartmedia physical base address */ - -/* Compact Flash */ -#define AT91_CF_BASE 0x50000000 /* NCS4-NCS6: Compact Flash physical base address */ +#define AT91_SDRAM_BASE AT91_CHIPSELECT_1 /* Clocks */ #define AT91_SLOW_CLOCK 32768 /* slow clock */ diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91rm9200/timex.h index 88687ce..faeca45 100644 --- a/include/asm-arm/arch-at91rm9200/timex.h +++ b/include/asm-arm/arch-at91rm9200/timex.h @@ -23,6 +23,15 @@ #include +#if defined(CONFIG_ARCH_AT91RM9200) + #define CLOCK_TICK_RATE (AT91_SLOW_CLOCK) +#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261) + +#define AT91SAM9_MASTER_CLOCK 99300000 +#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) + +#endif + #endif diff --git a/include/asm-arm/arch-at91rm9200/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h index 4c367eb..0a23b8c 100644 --- a/include/asm-arm/arch-at91rm9200/vmalloc.h +++ b/include/asm-arm/arch-at91rm9200/vmalloc.h @@ -21,6 +21,6 @@ #ifndef __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END (AT91_SRAM_VIRT_BASE & PGDIR_MASK) +#define VMALLOC_END (AT91_VIRT_BASE & PGDIR_MASK) #endif -- cgit v0.10.2 From 5283304bdcb4af47c46280ac21100d037d31fcf0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 1 Dec 2006 15:15:55 +0100 Subject: [ARM] 3964/1: ep93xx: add ads sphere support Add initial board support for the ADS Sphere board. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 3b4802a..2c67344 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -125,6 +125,7 @@ CONFIG_CRUNCH=y # # EP93xx Platforms # +CONFIG_MACH_ADSSPHERE=y CONFIG_MACH_EDB9302=y CONFIG_MACH_EDB9312=y CONFIG_MACH_EDB9315=y diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index e346b03..fcc5e25 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -9,6 +9,12 @@ config CRUNCH comment "EP93xx Platforms" +config MACH_ADSSPHERE + bool "Support ADS Sphere" + help + Say 'Y' here if you want your kernel to support the ADS + Sphere board. + config MACH_EDB9302 bool "Support Cirrus Logic EDB9302" help diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index c2eb18b..bd09cdd 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -6,6 +6,7 @@ obj-m := obj-n := obj- := +obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o obj-$(CONFIG_MACH_EDB9302) += edb9302.o obj-$(CONFIG_MACH_EDB9312) += edb9312.o obj-$(CONFIG_MACH_EDB9315) += edb9315.o diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c new file mode 100644 index 0000000..ac5d581 --- /dev/null +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -0,0 +1,91 @@ +/* + * arch/arm/mach-ep93xx/adssphere.c + * ADS Sphere support. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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 + +static struct physmap_flash_data adssphere_flash_data = { + .width = 4, +}; + +static struct resource adssphere_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device adssphere_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &adssphere_flash_data, + }, + .num_resources = 1, + .resource = &adssphere_flash_resource, +}; + +static struct ep93xx_eth_data adssphere_eth_data = { + .phy_id = 1, +}; + +static struct resource adssphere_eth_resource[] = { + { + .start = EP93XX_ETHERNET_PHYS_BASE, + .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_EP93XX_ETHERNET, + .end = IRQ_EP93XX_ETHERNET, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device adssphere_eth_device = { + .name = "ep93xx-eth", + .id = -1, + .dev = { + .platform_data = &adssphere_eth_data, + }, + .num_resources = 2, + .resource = adssphere_eth_resource, +}; + +static void __init adssphere_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&adssphere_flash); + + memcpy(adssphere_eth_data.dev_addr, + (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); + platform_device_register(&adssphere_eth_device); +} + +MACHINE_START(ADSSPHERE, "ADS Sphere board") + /* Maintainer: Lennert Buytenhek */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = adssphere_init_machine, +MACHINE_END -- cgit v0.10.2 From 2024c39dbba4d036f0b16daf530ad5f4416fb344 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 1 Dec 2006 16:02:40 +0100 Subject: [ARM] 3965/1: ixp2000: fix handling of pci master aborts The master abort check in ixp2000_pci_read_config() recently started failing due to the compiler optimising out the read access following the clearing of pci_master_aborts. Mark pci_master_aborts volatile to force the compiler to reload it on every use. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c index d4bf1e1..5a09a90 100644 --- a/arch/arm/mach-ixp2000/pci.c +++ b/arch/arm/mach-ixp2000/pci.c @@ -32,7 +32,7 @@ #include -static int pci_master_aborts = 0; +static volatile int pci_master_aborts = 0; static int clear_master_aborts(void); -- cgit v0.10.2 From b85a8914033d81077e8276df1956bf3307bb31bd Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 14:37:56 +0100 Subject: [ARM] 3962/1: AT91: Support for Atmel AT91SAM9260-EK board This patch adds support for the Atmel AT91SAM9260-EK board. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig new file mode 100644 index 0000000..7904920 --- /dev/null +++ b/arch/arm/configs/at91sam9260ek_defconfig @@ -0,0 +1,950 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc6 +# Fri Nov 17 18:42:21 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_AT91SAM9260=y +# CONFIG_ARCH_AT91SAM9261 is not set + +# +# AT91SAM9260 Board Type +# +CONFIG_MACH_AT91SAM9260EK=y + +# +# AT91 Board Options +# +# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ETH is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 564ad6e..cd83c9f 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o obj-$(CONFIG_MACH_KAFA) += board-kafa.o # AT91SAM9260 board-specific support +obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o # AT91SAM9261 board-specific support diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c new file mode 100644 index 0000000..ffca9bd --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-sam9260ek.c @@ -0,0 +1,201 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * 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 +#include + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 5 = USART0 .. USART5 + * 6 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 6, 0, 1, -1, -1, -1, -1 } /* ttyS0, ..., ttyS6 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PC5, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * SPI devices. + */ +static struct spi_board_info ek_spi_devices[] = { +#if !defined(CONFIG_MMC_AT91) + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 1, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#endif +#endif +#if defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 1, + }, +#endif +}; + + +/* + * MACB Ethernet device + */ +static struct __initdata eth_platform_data ek_macb_data = { + .is_rmii = 1, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 21, + .cle = 22, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .slot_b = 1, + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* Ethernet */ + at91_add_device_eth(&ek_macb_data); + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +} + +MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END -- cgit v0.10.2 From 022cbd7376fcdf030fe821636f1c910c45a9356a Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 14:38:59 +0100 Subject: [ARM] 3961/2: AT91: Support for Atmel AT91SAM9261-EK board This patch adds support for the Atmel AT91SAM9261-EK board. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig new file mode 100644 index 0000000..784ad7c --- /dev/null +++ b/arch/arm/configs/at91sam9261ek_defconfig @@ -0,0 +1,1106 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc6 +# Fri Nov 17 18:00:38 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +CONFIG_ARCH_AT91SAM9261=y + +# +# AT91SAM9261 Board Type +# +CONFIG_MACH_AT91SAM9261EK=y + +# +# AT91 Board Options +# +# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_AT91=y +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_DM9000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ETH is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_AT91=m +# CONFIG_MMC_TIFM_SD is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index cd83c9f..cf77700 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_MACH_KAFA) += board-kafa.o obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o # AT91SAM9261 board-specific support +obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91rm9200/board-sam9261ek.c new file mode 100644 index 0000000..30b490d --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-sam9261ek.c @@ -0,0 +1,259 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * 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 +#include +#include + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 2 = USART0 .. USART2 + * 3 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 1, + .tty_map = { 3, -1, -1, -1 } /* ttyS0, ..., ttyS3 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9261_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9261_init_interrupts(NULL); +} + + +/* + * DM9000 ethernet device + */ +#if defined(CONFIG_DM9000) +static struct resource at91sam9261_dm9000_resource[] = { + [0] = { + .start = AT91_CHIPSELECT_2, + .end = AT91_CHIPSELECT_2 + 3, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = AT91_CHIPSELECT_2 + 0x44, + .end = AT91_CHIPSELECT_2 + 0xFF, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = AT91_PIN_PC11, + .end = AT91_PIN_PC11, + .flags = IORESOURCE_IRQ + } +}; + +static struct dm9000_plat_data dm9000_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +static struct platform_device at91sam9261_dm9000_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(at91sam9261_dm9000_resource), + .resource = at91sam9261_dm9000_resource, + .dev = { + .platform_data = &dm9000_platdata, + } +}; + +static void __init ek_add_device_dm9000(void) +{ + /* + * Configure Chip-Select 2 on SMC for the DM9000. + * Note: These timings were calculated for MASTER_CLOCK = 100000000 + * according to the DM9000 timings. + */ + at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8)); + at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16)); + at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1)); + + /* Configure Reset signal as output */ + at91_set_gpio_output(AT91_PIN_PC10, 0); + + /* Configure Interrupt pin as input, no pull-up */ + at91_set_gpio_input(AT91_PIN_PC11, 0); + + platform_device_register(&at91sam9261_dm9000_device); +} +#else +static void __init ek_add_device_dm9000(void) {} +#endif /* CONFIG_DM9000 */ + + +/* + * USB Host Port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + + +/* + * USB Device Port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024 , + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 22, + .cle = 21, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC15, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + +/* + * SPI devices + */ +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#elif defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 0, + }, +#endif +}; + + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* DM9000 ethernet */ + ek_add_device_dm9000(); + + /* spi0 and mmc/sd share the same PIO pins */ +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); +#else + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +#endif +} + +MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END -- cgit v0.10.2 From 58a0cd7887cd689ae42540dd12b3b3131abfbe6c Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 14:51:13 +0100 Subject: [ARM] 3963/1: AT91: Update configuration files A number of configuration file changes. These are mainly to replace references to ARCH_AT91RM9200 and ARCH_AT91SAM9261 with the common/generic ARCH_AT91. That way we don't need to mention every specific AT91 processor explicitly. Also adds the configuration option for AT91SAM9260-EK and AT91SAM9261-EK boards. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ce00c57..43bd17b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -583,7 +583,7 @@ config LEDS ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ - ARCH_AT91RM9200 || MACH_TRIZEPS4 + ARCH_AT91 || MACH_TRIZEPS4 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index df8595a..abf3352 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -623,7 +623,7 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig index b4cd4b4..9ab0e0a 100644 --- a/arch/arm/configs/kb9202_defconfig +++ b/arch/arm/configs/kb9202_defconfig @@ -437,7 +437,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 8d44326..9f11db8 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -92,6 +92,13 @@ if ARCH_AT91SAM9260 comment "AT91SAM9260 Board Type" +config MACH_AT91SAM9260EK + bool "Atmel AT91SAM9260-EK Evaluation Kit" + depends on ARCH_AT91SAM9260 + help + Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. + + endif # ---------------------------------------------------------- @@ -100,8 +107,31 @@ if ARCH_AT91SAM9261 comment "AT91SAM9261 Board Type" +config MACH_AT91SAM9261EK + bool "Atmel AT91SAM9261-EK Evaluation Kit" + depends on ARCH_AT91SAM9261 + help + Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit. + + endif +# ---------------------------------------------------------- + +comment "AT91 Board Options" + +config MTD_AT91_DATAFLASH_CARD + bool "Enable DataFlash Card support" + depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) + help + Enable support for the DataFlash card. + +config MTD_NAND_AT91_BUSWIDTH_16 + bool "Enable 16-bit data bus interface to NAND flash" + depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) + help + On AT91SAM926x boards both types of NAND flash can be present + (8 and 16 bit data bus width). # ---------------------------------------------------------- diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index ea41852..fbef8da 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -91,11 +91,11 @@ config MMC_AU1X If unsure, say N. -config MMC_AT91RM9200 - tristate "AT91RM9200 SD/MMC Card Interface support" - depends on ARCH_AT91RM9200 && MMC +config MMC_AT91 + tristate "AT91 SD/MMC Card Interface support" + depends on ARCH_AT91 && MMC help - This selects the AT91RM9200 MCI controller. + This selects the AT91 MCI controller. If unsure, say N. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index acfd4de..83ffb93 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o -obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o +obj-$(CONFIG_MMC_AT91) += at91_mci.o obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o mmc_core-y := mmc.o mmc_sysfs.o diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index f9b1719..9980a4d 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_S3C2410 default y if PXA27x default y if ARCH_EP93XX - default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) + default y if ARCH_AT91 default y if ARCH_PNX4008 # PPC: default y if STB03xxx diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index bbbc82a..4097a86 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -189,7 +189,7 @@ config USB_OTG config USB_GADGET_AT91 boolean "AT91 USB Device Port" - depends on ARCH_AT91RM9200 + depends on ARCH_AT91 select USB_GADGET_SELECTED help Many Atmel AT91 processors (such as the AT91RM2000) have a diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ea4714e..4776b3b 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -935,7 +935,7 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif -#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) +#ifdef CONFIG_ARCH_AT91 #include "ohci-at91.c" #endif @@ -952,8 +952,7 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_ARCH_EP93XX) \ || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ - || defined (CONFIG_ARCH_AT91RM9200) \ - || defined (CONFIG_ARCH_AT91SAM9261) \ + || defined (CONFIG_ARCH_AT91) \ || defined (CONFIG_ARCH_PNX4008) \ ) #error "missing bus glue for ohci-hcd" -- cgit v0.10.2 From 69c5eccd164200a17b5a24e594b37958d39d2933 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 1 Dec 2006 15:53:20 +0100 Subject: [ARM] 3966/1: AT91: RM9200 device data update This patch contains various updates the at91rm9200_devices.c file: * Consistent naming of resources and platform_devices. * PCMCIA/Compact Flash: Configuration of the memory controller moved out of the driver and into this file. * MMC: Enable the VCC pin (if one is configured) * MMC: Enable the internal pullups on the I/O pins. * NAND: Configuration of the memory controller moved out of the driver and into this file. * Added TWI/I2C resources. * The names of some of the CONFIG_ variables were changed. Signed-off-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c index 2b3a236..4641b99 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c @@ -15,9 +15,10 @@ #include -#include #include #include +#include +#include #include "generic.h" @@ -33,7 +34,7 @@ static u64 ohci_dmamask = 0xffffffffUL; static struct at91_usbh_data usbh_data; -static struct resource at91_usbh_resources[] = { +static struct resource usbh_resources[] = { [0] = { .start = AT91RM9200_UHP_BASE, .end = AT91RM9200_UHP_BASE + SZ_1M - 1, @@ -54,8 +55,8 @@ static struct platform_device at91rm9200_usbh_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &usbh_data, }, - .resource = at91_usbh_resources, - .num_resources = ARRAY_SIZE(at91_usbh_resources), + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), }; void __init at91_add_device_usbh(struct at91_usbh_data *data) @@ -78,7 +79,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} #ifdef CONFIG_USB_GADGET_AT91 static struct at91_udc_data udc_data; -static struct resource at91_udc_resources[] = { +static struct resource udc_resources[] = { [0] = { .start = AT91RM9200_BASE_UDP, .end = AT91RM9200_BASE_UDP + SZ_16K - 1, @@ -97,8 +98,8 @@ static struct platform_device at91rm9200_udc_device = { .dev = { .platform_data = &udc_data, }, - .resource = at91_udc_resources, - .num_resources = ARRAY_SIZE(at91_udc_resources), + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), }; void __init at91_add_device_udc(struct at91_udc_data *data) @@ -129,7 +130,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} static u64 eth_dmamask = 0xffffffffUL; static struct at91_eth_data eth_data; -static struct resource at91_eth_resources[] = { +static struct resource eth_resources[] = { [0] = { .start = AT91_VA_BASE_EMAC, .end = AT91_VA_BASE_EMAC + SZ_16K - 1, @@ -150,8 +151,8 @@ static struct platform_device at91rm9200_eth_device = { .coherent_dma_mask = 0xffffffff, .platform_data = ð_data, }, - .resource = at91_eth_resources, - .num_resources = ARRAY_SIZE(at91_eth_resources), + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), }; void __init at91_add_device_eth(struct at91_eth_data *data) @@ -202,11 +203,13 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) static struct at91_cf_data cf_data; -static struct resource at91_cf_resources[] = { +#define CF_BASE AT91_CHIPSELECT_4 + +static struct resource cf_resources[] = { [0] = { - .start = AT91_CF_BASE, + .start = CF_BASE, /* ties up CS4, CS5 and CS6 */ - .end = AT91_CF_BASE + (0x30000000 - 1), + .end = CF_BASE + (0x30000000 - 1), .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, }, }; @@ -217,15 +220,38 @@ static struct platform_device at91rm9200_cf_device = { .dev = { .platform_data = &cf_data, }, - .resource = at91_cf_resources, - .num_resources = ARRAY_SIZE(at91_cf_resources), + .resource = cf_resources, + .num_resources = ARRAY_SIZE(cf_resources), }; void __init at91_add_device_cf(struct at91_cf_data *data) { + unsigned int csa; + if (!data) return; + data->chipselect = 4; /* can only use EBI ChipSelect 4 */ + + /* CF takes over CS4, CS5, CS6 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); + + /* + * Static memory controller timing adjustments. + * REVISIT: these timings are in terms of MCK cycles, so + * when MCK changes (cpufreq etc) so must these values... + */ + at91_sys_write(AT91_SMC_CSR(4), + AT91_SMC_ACSS_STD + | AT91_SMC_DBW_16 + | AT91_SMC_BAT + | AT91_SMC_WSEN + | AT91_SMC_NWS_(32) /* wait states */ + | AT91_SMC_RWSETUP_(6) /* setup time */ + | AT91_SMC_RWHOLD_(4) /* hold time */ + ); + /* input/irq */ if (data->irq_pin) { at91_set_gpio_input(data->irq_pin, 1); @@ -245,6 +271,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + /* nWAIT is _not_ a default setting */ + at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ + cf_data = *data; platform_device_register(&at91rm9200_cf_device); } @@ -257,11 +286,11 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {} * MMC / SD * -------------------------------------------------------------------- */ -#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) static u64 mmc_dmamask = 0xffffffffUL; static struct at91_mmc_data mmc_data; -static struct resource at91_mmc_resources[] = { +static struct resource mmc_resources[] = { [0] = { .start = AT91RM9200_BASE_MCI, .end = AT91RM9200_BASE_MCI + SZ_16K - 1, @@ -282,8 +311,8 @@ static struct platform_device at91rm9200_mmc_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &mmc_data, }, - .resource = at91_mmc_resources, - .num_resources = ARRAY_SIZE(at91_mmc_resources), + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), }; void __init at91_add_device_mmc(struct at91_mmc_data *data) @@ -298,31 +327,33 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) } if (data->wp_pin) at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); /* CLK */ at91_set_A_periph(AT91_PIN_PA27, 0); - if (data->is_b) { + if (data->slot_b) { /* CMD */ - at91_set_B_periph(AT91_PIN_PA8, 0); + at91_set_B_periph(AT91_PIN_PA8, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_B_periph(AT91_PIN_PA9, 0); + at91_set_B_periph(AT91_PIN_PA9, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PA10, 0); - at91_set_B_periph(AT91_PIN_PA11, 0); - at91_set_B_periph(AT91_PIN_PA12, 0); + at91_set_B_periph(AT91_PIN_PA10, 1); + at91_set_B_periph(AT91_PIN_PA11, 1); + at91_set_B_periph(AT91_PIN_PA12, 1); } } else { /* CMD */ - at91_set_A_periph(AT91_PIN_PA28, 0); + at91_set_A_periph(AT91_PIN_PA28, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA29, 0); + at91_set_A_periph(AT91_PIN_PA29, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PB3, 0); - at91_set_B_periph(AT91_PIN_PB4, 0); - at91_set_B_periph(AT91_PIN_PB5, 0); + at91_set_B_periph(AT91_PIN_PB3, 1); + at91_set_B_periph(AT91_PIN_PB4, 1); + at91_set_B_periph(AT91_PIN_PB5, 1); } } @@ -341,29 +372,45 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) {} #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) static struct at91_nand_data nand_data; -static struct resource at91_nand_resources[] = { +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { { - .start = AT91_SMARTMEDIA_BASE, - .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, .flags = IORESOURCE_MEM, } }; -static struct platform_device at91_nand_device = { +static struct platform_device at91rm9200_nand_device = { .name = "at91_nand", .id = -1, .dev = { .platform_data = &nand_data, }, - .resource = at91_nand_resources, - .num_resources = ARRAY_SIZE(at91_nand_resources), + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), }; void __init at91_add_device_nand(struct at91_nand_data *data) { + unsigned int csa; + if (!data) return; + /* enable the address range of CS3 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN + | AT91_SMC_NWS_(5) + | AT91_SMC_TDF_(1) + | AT91_SMC_RWSETUP_(0) /* tDS Data Set up Time 30 - ns */ + | AT91_SMC_RWHOLD_(1) /* tDH Data Hold Time 20 - ns */ + ); + /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); @@ -380,7 +427,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&at91rm9200_nand_device); } #else void __init at91_add_device_nand(struct at91_nand_data *data) {} @@ -392,10 +439,25 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91RM9200_BASE_TWI, + .end = AT91RM9200_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_TWI, + .end = AT91RM9200_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device at91rm9200_twi_device = { .name = "at91_i2c", .id = -1, - .num_resources = 0, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), }; void __init at91_add_device_i2c(void) @@ -421,7 +483,7 @@ void __init at91_add_device_i2c(void) {} #if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) static u64 spi_dmamask = 0xffffffffUL; -static struct resource at91_spi_resources[] = { +static struct resource spi_resources[] = { [0] = { .start = AT91RM9200_BASE_SPI, .end = AT91RM9200_BASE_SPI + SZ_16K - 1, @@ -438,14 +500,14 @@ static struct platform_device at91rm9200_spi_device = { .name = "at91_spi", .id = 0, .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, }, - .resource = at91_spi_resources, - .num_resources = ARRAY_SIZE(at91_spi_resources), + .resource = spi_resources, + .num_resources = ARRAY_SIZE(spi_resources), }; -static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; +static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) { @@ -461,7 +523,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) if (devices[i].controller_data) cs_pin = (unsigned long) devices[i].controller_data; else - cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + cs_pin = spi_standard_cs[devices[i].chip_select]; #ifdef CONFIG_SPI_AT91_MANUAL_CS at91_set_gpio_output(cs_pin, 1); @@ -474,7 +536,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) } spi_register_board_info(devices, nr_devices); - at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi"); platform_device_register(&at91rm9200_spi_device); } #else @@ -486,7 +548,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) * RTC * -------------------------------------------------------------------- */ -#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) +#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE) static struct platform_device at91rm9200_rtc_device = { .name = "at91_rtc", .id = -1, @@ -506,7 +568,7 @@ static void __init at91_add_device_rtc(void) {} * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE) static struct platform_device at91rm9200_wdt_device = { .name = "at91_wdt", .id = -1, -- cgit v0.10.2 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 diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 4ccdd82..4e6a534 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 7182d2f..c9f139e 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 v0.10.2 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 diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 494b23f..6495cd8 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 53ffcbb..447fba5 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 659d4a8..06e7fcd 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 828503c..e9b80e9 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 762fa28..895d487 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 a526698..471e9f4 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 9a7d39b..54990ed 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 ced309b..7e040eb 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 895d487..4bf7df8 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 4bf7df8..efd14cf 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 c954d35..11bf2ee 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index efd14cf..827753c 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 11bf2ee..0000000 --- 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 827753c..d46fd02 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index d46fd02..4e46750 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 v0.10.2 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 diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 4e46750..f8830c5 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 v0.10.2 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 diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index ea41852..f4f8cca 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 v0.10.2 From e520a36de2f7985df5ef2e84a9f6d2608ecc6f25 Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Fri, 1 Dec 2006 11:36:41 +0100 Subject: [ARM] 3958/1: add platform device (pxa2xx-udc)to ixp4xx Create include/asm-arm/arch-ixp4xx/udc.h and add platfrom device ixp4xx_udc_device into arch/arm/mach-ixp4xx/common.c. This allows us to use pxa2xx-udc on the ixp4xx platfrom. Both pxa2xx and ixp4xx use the same device controller. Signed-off-by:Milan Svoboda Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 074c965..1cf3bde 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -286,6 +287,44 @@ struct sys_timer ixp4xx_timer = { .init = ixp4xx_timer_init, }; +static struct pxa2xx_udc_mach_info ixp4xx_udc_info; + +void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) +{ + memcpy(&ixp4xx_udc_info, info, sizeof *info); +} + +static struct resource ixp4xx_udc_resources[] = { + [0] = { + .start = 0xc800b000, + .end = 0xc800bfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IXP4XX_USB, + .end = IRQ_IXP4XX_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +/* + * USB device controller. The IXP4xx uses the same controller as PXA2XX, + * so we just use the same device. + */ +static struct platform_device ixp4xx_udc_device = { + .name = "pxa2xx-udc", + .id = -1, + .num_resources = 2, + .resource = ixp4xx_udc_resources, + .dev = { + .platform_data = &ixp4xx_udc_info, + }, +}; + +static struct platform_device *ixp4xx_devices[] __initdata = { + &ixp4xx_udc_device, +}; + static struct resource ixp46x_i2c_resources[] = { [0] = { .start = 0xc8011000, @@ -321,6 +360,8 @@ void __init ixp4xx_sys_init(void) { ixp4xx_exp_bus_size = SZ_16M; + platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); + if (cpu_is_ixp46x()) { int region; diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h new file mode 100644 index 0000000..dbdec36f --- /dev/null +++ b/include/asm-arm/arch-ixp4xx/udc.h @@ -0,0 +1,8 @@ +/* + * linux/include/asm-arm/arch-ixp4xx/udc.h + * + */ +#include + +extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info); + -- cgit v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 766bc544..2d5b930 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 991a373..ce25256 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 08dec8d..311b654 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 */ @@ -88,6 +90,17 @@ #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 e : error bit @@ -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 v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2d5b930..1593a6a 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 311b654..45c51fd8 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 v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1593a6a..82b7643 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 v0.10.2 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 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 82b7643..9d19002 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 ce25256..d0e6a54 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 45c51fd8..2dce60c 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 */ @@ -101,6 +102,19 @@ */ /* + * 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 e : error bit @@ -285,6 +299,14 @@ struct _mmc_csd { #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 */ #define SD_BUS_WIDTH_1 0 -- cgit v0.10.2 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 diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 54990ed..cd98117 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 72a6793..f9d1a0a 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 v0.10.2 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 diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f9027c8..5025abe 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 4e6a534..5fa72cc 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 v0.10.2 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 diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 5025abe..8771357 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 v0.10.2 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 diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 0f8e82a..1b05994 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 5482bfb..e5cb169 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 v0.10.2 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 diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index afa2dd2..10064af 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 ba165af..c91745d 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6d08a3b..5de931c 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 0e76e6d..2a9bf07 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 113e484..401d76f 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 v0.10.2 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 diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 6995ea3..99357b9 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 v0.10.2 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 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ea4714e..a95275a 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 99357b9..1e5ed3b 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 v0.10.2 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 diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index f6b9f7e..c137c04 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 1fd9cb8..5c0a26c 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 fe35137..23153ea 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 5169c2d..97ee718 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 2a4bb66..d3b9a35 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 v0.10.2 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 diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 1e5ed3b..dcf9eb6 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 v0.10.2 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 diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 8122755..8554c1a7 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 v0.10.2 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 diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 6b23a1d..ba30ca6 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 v0.10.2 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 diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index f6971b8..44a9154 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 v0.10.2 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 diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9a9012f..ec3438d 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 v0.10.2 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 diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 3538c2f..ea398e5 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 v0.10.2 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 diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 9b591b8..0e8ee2d 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5de931c..2c12b04 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 v0.10.2 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 diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 8e6e195..c5fee00 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 v0.10.2 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 diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index ff03331..8dd2afa 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 v0.10.2 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 diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 2708949..f861199 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 v0.10.2 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 diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 3baf448..3a158d5 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 v0.10.2 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 diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index abb4dcd..0dc0d03 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 v0.10.2 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 diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 5c780ca..7702a4f 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 v0.10.2 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 diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c870c80..a823486 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 v0.10.2 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 diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index c73285c..b6c2ba7 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 v0.10.2 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 diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index cbbbea3..68a5564 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 v0.10.2 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 diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 760b532..7672e11 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 v0.10.2 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 diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 7c2cbdf..194065d 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 v0.10.2 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 diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index b8d6031..b401084 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 v0.10.2 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 diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 905bf63..2268ca3 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 v0.10.2 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 diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 467cb02..a83c2d5 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 e5cb169..e732e02 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 401d76f..ca0e40e 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ca0e40e..204495f 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 e732e02..864c6c21 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 v0.10.2 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 diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index ce00de8..a774105 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 v0.10.2 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 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c91745d..c961a32 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 1b05994..cf9559c 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 v0.10.2 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 diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 1c17d26..3bd1dfe 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 204495f..44dd610 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 v0.10.2 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 diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h index 1cf08f0..d85abfc 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 3498b89..e7cc20a 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 v0.10.2 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 diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 7f5d546..96c7372 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 v0.10.2 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 diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 07400c0..bbbb993 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 02c1aeb..b5541bf 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 v0.10.2 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 diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 46c1148..83739b2 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 v0.10.2 From 3c8961ee6d93c5a2ddf34d8d8171dd685538722b Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:33:38 +0100 Subject: usb: writing_usb_driver free urb cleanup Allright. As Greg KH suggested I split this big patch into smaller ones to make the changes easier to review. Having no better idea how to split that I split it on a 'patch per file' basis. All those patches clean redundant 'if' before usb_unlink/free/kill_urb(): if (urb) usb_free_urb(urb); /* unlink / free / kill */ I decided not to touch bigger 'if's like if (urb) { usb_kill_urb(urb); usb_free_urb(urb); urb = NULL; } as that would be probably too intrusive. One of patches also fixes drivers/usb/misc/auerswald.c memleak I found when digging the code. All those patches are against 2.6.19-rc4. Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl index 07cd34c..d4188d4 100644 --- a/Documentation/DocBook/writing_usb_driver.tmpl +++ b/Documentation/DocBook/writing_usb_driver.tmpl @@ -345,8 +345,7 @@ static inline void skel_delete (struct usb_skel *dev) usb_buffer_free (dev->udev, dev->bulk_out_size, dev->bulk_out_buffer, dev->write_urb->transfer_dma); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); + usb_free_urb (dev->write_urb); kfree (dev); } -- cgit v0.10.2 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 diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index bda4533..e275dd4 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 v0.10.2 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 diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 105112f..80cdebc 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 v0.10.2 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 diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4ffa9eb..5ebf49ac9 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 v0.10.2 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 diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index ff7d4f56..55bc891 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 v0.10.2 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 diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index a1c9fa9..8135f3e 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 v0.10.2 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 diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f920e0c..1f78733 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 v0.10.2 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 diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c index 70aa63e..57fb320 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 v0.10.2 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 diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 83739b2..62070b9 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 v0.10.2 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 diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 42fb60d..18458d4 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 v0.10.2 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 diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 9a26b94..bbf2bee 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 v0.10.2 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 diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 5b55634..52d0f75 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 v0.10.2 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 diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 14bda76..6e95645 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 v0.10.2 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 diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 36b29ff..6cb66a3 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 v0.10.2 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 diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 787b847..ff23318 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 v0.10.2 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 diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index f982a2b..83f1f79 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2c12b04..f7a67c4 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 v0.10.2 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 diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index b6c2ba7..dac8864 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 v0.10.2 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 diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index e4971d6..c703f73 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 v0.10.2 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 diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index f861199..5dce797 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 v0.10.2 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 diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 0dc0d03..9110793 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 v0.10.2 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 diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 7702a4f..c3469b0 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 v0.10.2 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 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c186b4e..89ce277 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 v0.10.2 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 diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index f740325..907b820 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 v0.10.2 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 diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 91bd301..d06547a 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 v0.10.2 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 diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 53be824..7639652 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 v0.10.2 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 diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 8dd2afa..2372899 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 v0.10.2 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 diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index b7582cc..a906e50 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 v0.10.2 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 diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 0610409..054abee 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 v0.10.2 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 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8006e51..c1257d5 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 v0.10.2 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 diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index befe2e1..eef5eaa 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 v0.10.2 From f5e135af8737bdc57168cddb3fd83028b25c26cd Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:37:00 +0100 Subject: usb: usbmidi kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index b7c5e59..24f5a26 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -981,7 +981,7 @@ void snd_usbmidi_disconnect(struct list_head* p) if (umidi->usb_protocol_ops->finish_out_endpoint) umidi->usb_protocol_ops->finish_out_endpoint(ep->out); } - if (ep->in && ep->in->urb) + if (ep->in) usb_kill_urb(ep->in->urb); } } -- cgit v0.10.2 From 68df9de1d0e95034355283dc12056f93de8e0a79 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:37:04 +0100 Subject: usb: usbmixer free kill urb cleanup - usb_free_urb() cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 1024c17..e74eb1b 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -1620,8 +1620,7 @@ static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) kfree(mixer->urb->transfer_buffer); usb_free_urb(mixer->urb); } - if (mixer->rc_urb) - usb_free_urb(mixer->rc_urb); + usb_free_urb(mixer->rc_urb); kfree(mixer->rc_setup_packet); kfree(mixer); } @@ -2056,8 +2055,6 @@ void snd_usb_mixer_disconnect(struct list_head *p) struct usb_mixer_interface *mixer; mixer = list_entry(p, struct usb_mixer_interface, list); - if (mixer->urb) - usb_kill_urb(mixer->urb); - if (mixer->rc_urb) - usb_kill_urb(mixer->rc_urb); + usb_kill_urb(mixer->urb); + usb_kill_urb(mixer->rc_urb); } -- cgit v0.10.2 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 diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index dcf9eb6..4c94927 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 v0.10.2 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 diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 8554c1a7..b1b5707 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 v0.10.2 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 diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a83c2d5..81cb525 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 v0.10.2 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 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index efb047f..db8b260 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 diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 3038ed0..8ccddf7 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 v0.10.2 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 diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3acc896..0b59083 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 957d6df..44ca139 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 v0.10.2 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 diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 1b20722..7c170a2 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 v0.10.2 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 diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9030994..f2ceb5f 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 7c170a2..0a56dfa 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 v0.10.2 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 diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index f2e89a0..093f303 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 v0.10.2 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 diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 32c635e..5b06e2e 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 v0.10.2 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 diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5b06e2e..8710608 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 0e8ee2d..cb0ba31 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 551ba89..fbb52b2 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 v0.10.2 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 diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 20db364..661af7a 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 933cedd..49704d4 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 + {} }; @@ -313,6 +321,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 */ static struct usbtouch_device_info usbtouch_dev_info[] = { @@ -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 v0.10.2 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 diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 671c24b..1ed506e 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 v0.10.2 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 diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 1792596..4a99156 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 44dd610..40c1bf0 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 v0.10.2 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 diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index c5fee00..c941853 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 v0.10.2 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 diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index f7a67c4..a49644b 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 v0.10.2 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 diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index ca52f12..863966c 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 3a9073d..7167728 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 4543152..6530d39 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 5b71962..02c89e1 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 bbbb993..ae98d8c 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 v0.10.2 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 diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 11dc595..2cba07d 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 v0.10.2 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 diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 881841e..95e682e 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 v0.10.2 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 diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 33abbd2..69eb0db 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 v0.10.2 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 diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 3b2d137..c505b76 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 v0.10.2 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 diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 2a8dd4c..2f4d303 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 a5047dc..61166ad 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 0000000..257a5e4 --- /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 v0.10.2 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 diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 6e3b535..f8324d8 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 c961a32..f6e6921 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 v0.10.2 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 diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f2ceb5f..025d333 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 0a56dfa..bfe5f30 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 e51c1ed8..4bc7970 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 bbc3082..74dbc6c 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 v0.10.2 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 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f6e6921..55812a5 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 v0.10.2 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 diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 4c94927..2441642 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 v0.10.2 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 diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7729c07..5684d87 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 864c6c21..5634a2d 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 v0.10.2 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 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 55812a5..46df5e6 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 v0.10.2 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 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 40c1bf0..0fa15bd 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 46df5e6..e46d38b 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 5634a2d..0cd73ed 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 v0.10.2 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 diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fed92be..3ed4cb2 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 0fa15bd..d6eb5ce 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 e46d38b..0ce393e 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 5684d87..29b0fa9 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 13322e3..17830a8 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 v0.10.2 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 diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5f1b9f5..ecc50db 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 v0.10.2 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 diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index f0cca17..3898f52 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 c321316..064b1dc 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 v0.10.2 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 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a544997..0eaf381 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 v0.10.2 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 diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index c1949ff..cde1170 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 e159d66..0eeac60 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 5b44838..9ca9b9b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -797,56 +797,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 * hence the presence of a Linux check @@ -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 v0.10.2 From 3efe2d84c8d909567c7976a7106114127b8c3470 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 10 Oct 2006 08:01:19 -0600 Subject: PCI: Use pci_generic_prep_mwi on ia64 The pci_generic_prep_mwi() code does everything that pcibios_prep_mwi() does on ia64. All we need to do is be sure that pci_cache_line_size is set appropriately, and we can delete pcibios_prep_mwi(). Using SMP_CACHE_BYTES as the default was wrong on uniprocessor machines as it is only 8 bytes. The default in the generic code of L1_CACHE_BYTES is at least as good. Signed-off-by: Matthew Wilcox Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index b30be7c..4f77472 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -738,75 +738,44 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) return ret; } +/* It's defined in drivers/pci/pci.c */ +extern u8 pci_cache_line_size; + /** - * pci_cacheline_size - determine cacheline size for PCI devices - * @dev: void + * set_pci_cacheline_size - determine cacheline size for PCI devices * * We want to use the line-size of the outer-most cache. We assume * that this line-size is the same for all CPUs. * * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). - * - * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. */ -static unsigned long -pci_cacheline_size (void) +static void __init set_pci_cacheline_size(void) { u64 levels, unique_caches; s64 status; pal_cache_config_info_t cci; - static u8 cacheline_size; - - if (cacheline_size) - return cacheline_size; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", - __FUNCTION__, status); - return SMP_CACHE_BYTES; + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed " + "(status=%ld)\n", __FUNCTION__, status); + return; } - status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, - &cci); + status = ia64_pal_cache_config_info(levels - 1, + /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { - printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", - __FUNCTION__, status); - return SMP_CACHE_BYTES; + printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed " + "(status=%ld)\n", __FUNCTION__, status); + return; } - cacheline_size = 1 << cci.pcci_line_size; - return cacheline_size; + pci_cache_line_size = (1 << cci.pcci_line_size) / 4; } -/** - * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi() - * @dev: the PCI device for which MWI is enabled - * - * For ia64, we can get the cacheline sizes from PAL. - * - * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. - */ -int -pcibios_prep_mwi (struct pci_dev *dev) -{ - unsigned long desired_linesize, current_linesize; - int rc = 0; - u8 pci_linesize; - - desired_linesize = pci_cacheline_size(); - - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize); - current_linesize = 4 * pci_linesize; - if (desired_linesize != current_linesize) { - printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,", - pci_name(dev), current_linesize); - if (current_linesize > desired_linesize) { - printk(" expected %lu bytes instead\n", desired_linesize); - rc = -EINVAL; - } else { - printk(" correcting to %lu\n", desired_linesize); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4); - } - } - return rc; +static int __init pcibios_init(void) +{ + set_pci_cacheline_size(); + return 0; } + +subsys_initcall(pcibios_init); diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h index ef616fd..825eb7d 100644 --- a/include/asm-ia64/pci.h +++ b/include/asm-ia64/pci.h @@ -26,16 +26,18 @@ void pcibios_config_init(void); struct pci_dev; /* - * PCI_DMA_BUS_IS_PHYS should be set to 1 if there is _necessarily_ a direct correspondence - * between device bus addresses and CPU physical addresses. Platforms with a hardware I/O - * MMU _must_ turn this off to suppress the bounce buffer handling code in the block and - * network device layers. Platforms with separate bus address spaces _must_ turn this off - * and provide a device DMA mapping implementation that takes care of the necessary + * PCI_DMA_BUS_IS_PHYS should be set to 1 if there is _necessarily_ a direct + * correspondence between device bus addresses and CPU physical addresses. + * Platforms with a hardware I/O MMU _must_ turn this off to suppress the + * bounce buffer handling code in the block and network device layers. + * Platforms with separate bus address spaces _must_ turn this off and provide + * a device DMA mapping implementation that takes care of the necessary * address translation. * - * For now, the ia64 platforms which may have separate/multiple bus address spaces all - * have I/O MMUs which support the merging of physically discontiguous buffers, so we can - * use that as the sole factor to determine the setting of PCI_DMA_BUS_IS_PHYS. + * For now, the ia64 platforms which may have separate/multiple bus address + * spaces all have I/O MMUs which support the merging of physically + * discontiguous buffers, so we can use that as the sole factor to determine + * the setting of PCI_DMA_BUS_IS_PHYS. */ extern unsigned long ia64_max_iommu_merge_mask; #define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL) @@ -52,9 +54,6 @@ pcibios_penalize_isa_irq (int irq, int active) /* We don't do dynamic PCI IRQ allocation */ } -#define HAVE_ARCH_PCI_MWI 1 -extern int pcibios_prep_mwi (struct pci_dev *); - #include /* pci_unmap_{single,page} is not a nop, thus... */ -- cgit v0.10.2 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 diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index e02f01b..dfc41cd 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 0eaf381..bc88c30 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 e1ea67b..ca65602 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 v0.10.2 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 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bc88c30..4279917 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 46afd29..721c97f0 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 v0.10.2 From e08cf02f32dff732b2be0c9755cf5eb676f88e48 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 10 Oct 2006 08:01:22 -0600 Subject: PCI: Delete unused extern in powermac/pci.c This file no longer uses pci_cache_line_size, so delete the declaration Signed-off-by: Matthew Wilcox Cc: Benjamin Herrenschmidt Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 9923adc..257dc90 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -48,7 +48,6 @@ static struct pci_controller *u3_ht; static int has_second_ohare; #endif /* CONFIG_PPC64 */ -extern u8 pci_cache_line_size; extern int pcibios_assign_bus_offset; struct device_node *k2_skiplist[2]; -- cgit v0.10.2 From 8ea6091f500162e97687d7acf925f84202066b8d Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 4 Oct 2006 16:49:25 -0500 Subject: Altix: Add initial ACPI IO support First phase in introducing ACPI support to SN. In this phase, when running with an ACPI capable PROM, the DSDT will define the root busses and all SN nodes (SGIHUB, SGITIO). An ACPI bus driver will be registered for the node devices, with the acpi_pci_root_driver being used for the root busses. An ACPI vendor descriptor is now used to pass platform specific information for both nodes and busses, eliminating the need for the current SAL calls. Also, with ACPI support, SN fixup code is no longer needed to initiate the PCI bus scans, as the acpi_pci_root_driver does that. However, to maintain backward compatibility with non-ACPI capable PROMs, none of the current 'fixup' code can been deleted, though much restructuring has been done. For example, the bulk of the code in io_common.c is relocated code that is now common regardless of what PROM is running, while io_acpi_init.c and io_init.c contain routines specific to an ACPI or non ACPI capable PROM respectively. A new pci bus fixup platform vector has been created to provide a hook for invoking platform specific bus fixup from pcibios_fixup_bus(). The size of io_space[] has been increased to support systems with large IO configurations. Signed-off-by: John Keller Signed-off-by: Greg Kroah-Hartman diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 4f77472..f4edfbf 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -469,10 +469,11 @@ pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) } } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) { pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); } +EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources); static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev) { @@ -493,6 +494,7 @@ pcibios_fixup_bus (struct pci_bus *b) } list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); + platform_pci_fixup_bus(b); return; } diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 2d78f34..0a59371 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -4,13 +4,14 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved. # CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ - huberror.o io_init.o iomv.o klconflib.o pio_phys.o \ + huberror.o io_acpi_init.o io_common.o \ + io_init.o iomv.o klconflib.o pio_phys.o \ sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_SGI_TIOCX) += tiocx.o diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c new file mode 100644 index 0000000..a9dc369 --- /dev/null +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -0,0 +1,198 @@ +/* + * 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) 2006 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include "xtalk/hubdev.h" +#include + + +/* + * The code in this file will only be executed when running with + * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1) + */ + + +/* + * This value must match the UUID the PROM uses + * (io/acpi/defblk.c) when building a vendor descriptor. + */ +struct acpi_vendor_uuid sn_uuid = { + .subtype = 0, + .data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11, + 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 }, +}; + +/* + * Perform the early IO init in PROM. + */ +static s64 +sal_ioif_init(u64 *result) +{ + struct ia64_sal_retval isrv = {0,0,0,0}; + + SAL_CALL_NOLOCK(isrv, + SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0); + *result = isrv.v0; + return isrv.status; +} + +/* + * sn_hubdev_add - The 'add' function of the acpi_sn_hubdev_driver. + * Called for every "SGIHUB" or "SGITIO" device defined + * in the ACPI namespace. + */ +static int __init +sn_hubdev_add(struct acpi_device *device) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + u64 addr; + struct hubdev_info *hubdev; + struct hubdev_info *hubdev_ptr; + int i; + u64 nasid; + struct acpi_resource *resource; + int ret = 0; + acpi_status status; + struct acpi_resource_vendor_typed *vendor; + extern void sn_common_hubdev_init(struct hubdev_info *); + + status = acpi_get_vendor_resource(device->handle, METHOD_NAME__CRS, + &sn_uuid, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR + "sn_hubdev_add: acpi_get_vendor_resource() failed: %d\n", + status); + return 1; + } + + resource = buffer.pointer; + vendor = &resource->data.vendor_typed; + if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != + sizeof(struct hubdev_info *)) { + printk(KERN_ERR + "sn_hubdev_add: Invalid vendor data length: %d\n", + vendor->byte_length); + ret = 1; + goto exit; + } + + memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *)); + hubdev_ptr = __va((struct hubdev_info *) addr); + + nasid = hubdev_ptr->hdi_nasid; + i = nasid_to_cnodeid(nasid); + hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo); + *hubdev = *hubdev_ptr; + sn_common_hubdev_init(hubdev); + +exit: + kfree(buffer.pointer); + return ret; +} + +/* + * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in + * the ACPI Vendor resource for this bus. + */ +static struct pcibus_bussoft * +sn_get_bussoft_ptr(struct pci_bus *bus) +{ + u64 addr; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle handle; + struct pcibus_bussoft *prom_bussoft_ptr; + struct acpi_resource *resource; + acpi_status status; + struct acpi_resource_vendor_typed *vendor; + + + handle = PCI_CONTROLLER(bus)->acpi_handle; + status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, + &sn_uuid, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR "get_acpi_pcibus_ptr: " + "get_acpi_bussoft_info() failed: %d\n", + status); + return NULL; + } + resource = buffer.pointer; + vendor = &resource->data.vendor_typed; + + if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != + sizeof(struct pcibus_bussoft *)) { + printk(KERN_ERR + "get_acpi_bussoft_ptr: Invalid vendor data " + "length %d\n", vendor->byte_length); + kfree(buffer.pointer); + return NULL; + } + memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *)); + prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr); + kfree(buffer.pointer); + + return prom_bussoft_ptr; +} + +/* + * sn_acpi_bus_fixup + */ +void +sn_acpi_bus_fixup(struct pci_bus *bus) +{ + struct pci_dev *pci_dev = NULL; + struct pcibus_bussoft *prom_bussoft_ptr; + extern void sn_common_bus_fixup(struct pci_bus *, + struct pcibus_bussoft *); + + if (!bus->parent) { /* If root bus */ + prom_bussoft_ptr = sn_get_bussoft_ptr(bus); + if (prom_bussoft_ptr == NULL) { + printk(KERN_ERR + "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to " + "obtain prom_bussoft_ptr\n", + pci_domain_nr(bus), bus->number); + return; + } + sn_common_bus_fixup(bus, prom_bussoft_ptr); + } + list_for_each_entry(pci_dev, &bus->devices, bus_list) { + sn_pci_fixup_slot(pci_dev); + } +} + +static struct acpi_driver acpi_sn_hubdev_driver = { + .name = "SGI HUBDEV Driver", + .ids = "SGIHUB,SGITIO", + .ops = { + .add = sn_hubdev_add, + }, +}; + + +/* + * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the + * nodes and root buses in the DSDT. As a result, bus scanning + * will be initiated by the Linux ACPI code. + */ + +void __init +sn_io_acpi_init(void) +{ + u64 result; + s64 status; + + acpi_bus_register_driver(&acpi_sn_hubdev_driver); + status = sal_ioif_init(&result); + if (status || result) + panic("sal_ioif_init failed: [%lx] %s\n", + status, ia64_sal_strerror(status)); +} diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c new file mode 100644 index 0000000..12531de --- /dev/null +++ b/arch/ia64/sn/kernel/io_common.c @@ -0,0 +1,612 @@ +/* + * 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) 2006 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xtalk/hubdev.h" +#include "xtalk/xwidgetdev.h" +#include +#include +#include + +extern void sn_init_cpei_timer(void); +extern void register_sn_procfs(void); +extern void sn_acpi_bus_fixup(struct pci_bus *); +extern void sn_bus_fixup(struct pci_bus *); +extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *); +extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *); +extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64); +extern void sn_io_acpi_init(void); +extern void sn_io_init(void); + + +static struct list_head sn_sysdata_list; + +/* sysdata list struct */ +struct sysdata_el { + struct list_head entry; + void *sysdata; +}; + +int sn_ioif_inited; /* SN I/O infrastructure initialized? */ + +struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ + +/* + * Hooks and struct for unsupported pci providers + */ + +static dma_addr_t +sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type) +{ + return 0; +} + +static void +sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) +{ + return; +} + +static void * +sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller) +{ + return NULL; +} + +static struct sn_pcibus_provider sn_pci_default_provider = { + .dma_map = sn_default_pci_map, + .dma_map_consistent = sn_default_pci_map, + .dma_unmap = sn_default_pci_unmap, + .bus_fixup = sn_default_pci_bus_fixup, +}; + +/* + * Retrieve the DMA Flush List given nasid, widget, and device. + * This list is needed to implement the WAR - Flush DMA data on PIO Reads. + */ +static inline u64 +sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, + u64 address) +{ + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, + (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST, + (u64) nasid, (u64) widget_num, + (u64) device_num, (u64) address, 0, 0, 0); + return ret_stuff.status; +} + +/* + * Retrieve the pci device information given the bus and device|function number. + */ +static inline u64 +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, + u64 sn_irq_info) +{ + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, + (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, + (u64) segment, (u64) bus_number, (u64) devfn, + (u64) pci_dev, + sn_irq_info, 0, 0); + return ret_stuff.v0; +} + +/* + * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified + * device. + */ +inline struct pcidev_info * +sn_pcidev_info_get(struct pci_dev *dev) +{ + struct pcidev_info *pcidev; + + list_for_each_entry(pcidev, + &(SN_PLATFORM_DATA(dev)->pcidev_info), pdi_list) { + if (pcidev->pdi_linux_pcidev == dev) + return pcidev; + } + return NULL; +} + +/* Older PROM flush WAR + * + * 01/16/06 -- This war will be in place until a new official PROM is released. + * Additionally note that the struct sn_flush_device_war also has to be + * removed from arch/ia64/sn/include/xtalk/hubdev.h + */ +static u8 war_implemented = 0; + +static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, + struct sn_flush_device_common *common) +{ + struct sn_flush_device_war *war_list; + struct sn_flush_device_war *dev_entry; + struct ia64_sal_retval isrv = {0,0,0,0}; + + if (!war_implemented) { + printk(KERN_WARNING "PROM version < 4.50 -- implementing old " + "PROM flush WAR\n"); + war_implemented = 1; + } + + war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); + if (!war_list) + BUG(); + + SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, + nasid, widget, __pa(war_list), 0, 0, 0 ,0); + if (isrv.status) + panic("sn_device_fixup_war failed: %s\n", + ia64_sal_strerror(isrv.status)); + + dev_entry = war_list + device; + memcpy(common,dev_entry, sizeof(*common)); + kfree(war_list); + + return isrv.status; +} + +/* + * sn_common_hubdev_init() - This routine is called to initialize the HUB data + * structure for each node in the system. + */ +void __init +sn_common_hubdev_init(struct hubdev_info *hubdev) +{ + + struct sn_flush_device_kernel *sn_flush_device_kernel; + struct sn_flush_device_kernel *dev_entry; + s64 status; + int widget, device, size; + + /* Attach the error interrupt handlers */ + if (hubdev->hdi_nasid & 1) /* If TIO */ + ice_error_init(hubdev); + else + hub_error_init(hubdev); + + for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) + hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev; + + if (!hubdev->hdi_flush_nasid_list.widget_p) + return; + + size = (HUB_WIDGET_ID_MAX + 1) * + sizeof(struct sn_flush_device_kernel *); + hubdev->hdi_flush_nasid_list.widget_p = + kzalloc(size, GFP_KERNEL); + if (!hubdev->hdi_flush_nasid_list.widget_p) + BUG(); + + for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { + size = DEV_PER_WIDGET * + sizeof(struct sn_flush_device_kernel); + sn_flush_device_kernel = kzalloc(size, GFP_KERNEL); + if (!sn_flush_device_kernel) + BUG(); + + dev_entry = sn_flush_device_kernel; + for (device = 0; device < DEV_PER_WIDGET; + device++, dev_entry++) { + size = sizeof(struct sn_flush_device_common); + dev_entry->common = kzalloc(size, GFP_KERNEL); + if (!dev_entry->common) + BUG(); + if (sn_prom_feature_available(PRF_DEVICE_FLUSH_LIST)) + status = sal_get_device_dmaflush_list( + hubdev->hdi_nasid, widget, device, + (u64)(dev_entry->common)); + else + status = sn_device_fixup_war(hubdev->hdi_nasid, + widget, device, + dev_entry->common); + if (status != SALRET_OK) + panic("SAL call failed: %s\n", + ia64_sal_strerror(status)); + + spin_lock_init(&dev_entry->sfdl_flush_lock); + } + + if (sn_flush_device_kernel) + hubdev->hdi_flush_nasid_list.widget_p[widget] = + sn_flush_device_kernel; + } +} + +void sn_pci_unfixup_slot(struct pci_dev *dev) +{ + struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev; + + sn_irq_unfixup(dev); + pci_dev_put(host_pci_dev); + pci_dev_put(dev); +} + +/* + * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent + * with the Linux PCI abstraction layer. Resources + * acquired from our PCI provider include PIO maps + * to BAR space and interrupt objects. + */ +void sn_pci_fixup_slot(struct pci_dev *dev) +{ + int segment = pci_domain_nr(dev->bus); + int status = 0; + struct pcibus_bussoft *bs; + struct pci_bus *host_pci_bus; + struct pci_dev *host_pci_dev; + struct pcidev_info *pcidev_info; + struct sn_irq_info *sn_irq_info; + unsigned int bus_no, devfn; + + pci_dev_get(dev); /* for the sysdata pointer */ + pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); + if (!pcidev_info) + BUG(); /* Cannot afford to run out of memory */ + + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (!sn_irq_info) + BUG(); /* Cannot afford to run out of memory */ + + /* Call to retrieve pci device information needed by kernel. */ + status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, + dev->devfn, + (u64) __pa(pcidev_info), + (u64) __pa(sn_irq_info)); + if (status) + BUG(); /* Cannot get platform pci device information */ + + /* Add pcidev_info to list in pci_controller.platform_data */ + list_add_tail(&pcidev_info->pdi_list, + &(SN_PLATFORM_DATA(dev->bus)->pcidev_info)); + + if (!SN_ACPI_BASE_SUPPORT()) + 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 + */ + + bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; + devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; + host_pci_bus = pci_find_bus(segment, bus_no); + host_pci_dev = pci_get_slot(host_pci_bus, devfn); + + pcidev_info->host_pci_dev = host_pci_dev; + pcidev_info->pdi_linux_pcidev = dev; + pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); + bs = SN_PCIBUS_BUSSOFT(dev->bus); + pcidev_info->pdi_pcibus_info = bs; + + if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { + SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; + } else { + SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; + } + + /* Only set up IRQ stuff if this device has a host bus context */ + if (bs && sn_irq_info->irq_irq) { + pcidev_info->pdi_sn_irq_info = sn_irq_info; + dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq; + sn_irq_fixup(dev, sn_irq_info); + } else { + pcidev_info->pdi_sn_irq_info = NULL; + kfree(sn_irq_info); + } +} + +/* + * sn_common_bus_fixup - Perform platform specific bus fixup. + * Execute the ASIC specific fixup routine + * for this bus. + */ +void +sn_common_bus_fixup(struct pci_bus *bus, + struct pcibus_bussoft *prom_bussoft_ptr) +{ + int cnode; + struct pci_controller *controller; + struct hubdev_info *hubdev_info; + int nasid; + void *provider_soft; + struct sn_pcibus_provider *provider; + struct sn_platform_data *sn_platform_data; + + controller = PCI_CONTROLLER(bus); + /* + * Per-provider fixup. Copies the bus soft structure from prom + * to local area and links SN_PCIBUS_BUSSOFT(). + */ + + if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) { + printk(KERN_WARNING "sn_common_bus_fixup: Unsupported asic type, %d", + prom_bussoft_ptr->bs_asic_type); + return; + } + + if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) + return; /* no further fixup necessary */ + + provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; + if (provider == NULL) + panic("sn_common_bus_fixup: No provider registered for this asic type, %d", + prom_bussoft_ptr->bs_asic_type); + + if (provider->bus_fixup) + provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, + controller); + else + provider_soft = NULL; + + /* + * Generic bus fixup goes here. Don't reference prom_bussoft_ptr + * after this point. + */ + controller->platform_data = kzalloc(sizeof(struct sn_platform_data), + GFP_KERNEL); + if (controller->platform_data == NULL) + BUG(); + sn_platform_data = + (struct sn_platform_data *) controller->platform_data; + sn_platform_data->provider_soft = provider_soft; + INIT_LIST_HEAD(&((struct sn_platform_data *) + controller->platform_data)->pcidev_info); + nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base); + cnode = nasid_to_cnodeid(nasid); + hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); + SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = + &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); + + /* + * If the node information we obtained during the fixup phase is + * invalid then set controller->node to -1 (undetermined) + */ + if (controller->node >= num_online_nodes()) { + struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); + + printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u" + "L_IO=%lx L_MEM=%lx BASE=%lx\n", + b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, + b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); + printk(KERN_WARNING "on node %d but only %d nodes online." + "Association set to undetermined.\n", + controller->node, num_online_nodes()); + controller->node = -1; + } +} + +void sn_bus_store_sysdata(struct pci_dev *dev) +{ + struct sysdata_el *element; + + element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL); + if (!element) { + dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); + return; + } + element->sysdata = SN_PCIDEV_INFO(dev); + list_add(&element->entry, &sn_sysdata_list); +} + +void sn_bus_free_sysdata(void) +{ + struct sysdata_el *element; + struct list_head *list, *safe; + + list_for_each_safe(list, safe, &sn_sysdata_list) { + element = list_entry(list, struct sysdata_el, entry); + list_del(&element->entry); + list_del(&(((struct pcidev_info *) + (element->sysdata))->pdi_list)); + kfree(element->sysdata); + kfree(element); + } + return; +} + +/* + * hubdev_init_node() - Creates the HUB data structure and link them to it's + * own NODE specific data area. + */ +void hubdev_init_node(nodepda_t * npda, cnodeid_t node) +{ + struct hubdev_info *hubdev_info; + int size; + pg_data_t *pg; + + size = sizeof(struct hubdev_info); + + if (node >= num_online_nodes()) /* Headless/memless IO nodes */ + pg = NODE_DATA(0); + else + pg = NODE_DATA(node); + + hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); + + npda->pdinfo = (void *)hubdev_info; +} + +geoid_t +cnodeid_get_geoid(cnodeid_t cnode) +{ + struct hubdev_info *hubdev; + + hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); + return hubdev->hdi_geoid; +} + +void sn_generate_path(struct pci_bus *pci_bus, char *address) +{ + nasid_t nasid; + cnodeid_t cnode; + geoid_t geoid; + moduleid_t moduleid; + u16 bricktype; + + nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); + cnode = nasid_to_cnodeid(nasid); + geoid = cnodeid_get_geoid(cnode); + moduleid = geo_module(geoid); + + sprintf(address, "module_%c%c%c%c%.2d", + '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)), + '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)), + '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)), + MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid)); + + /* Tollhouse requires slot id to be displayed */ + bricktype = MODULE_GET_BTYPE(moduleid); + if ((bricktype == L1_BRICKTYPE_191010) || + (bricktype == L1_BRICKTYPE_1932)) + sprintf(address, "%s^%d", address, geo_slot(geoid)); +} + +/* + * sn_pci_fixup_bus() - Perform SN specific setup of software structs + * (pcibus_bussoft, pcidev_info) and hardware + * registers, for the specified bus and devices under it. + */ +void __devinit +sn_pci_fixup_bus(struct pci_bus *bus) +{ + + if (SN_ACPI_BASE_SUPPORT()) + sn_acpi_bus_fixup(bus); + else + sn_bus_fixup(bus); +} + +/* + * sn_io_early_init - Perform early IO (and some non-IO) initialization. + * In particular, setup the sn_pci_provider[] array. + * This needs to be done prior to any bus scanning + * (acpi_scan_init()) in the ACPI case, as the SN + * bus fixup code will reference the array. + */ +static int __init +sn_io_early_init(void) +{ + int i; + + if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) + return 0; + + /* + * prime sn_pci_provider[]. Individial provider init routines will + * override their respective default entries. + */ + + for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) + sn_pci_provider[i] = &sn_pci_default_provider; + + pcibr_init_provider(); + tioca_init_provider(); + tioce_init_provider(); + + /* + * This is needed to avoid bounce limit checks in the blk layer + */ + ia64_max_iommu_merge_mask = ~PAGE_MASK; + + sn_irq_lh_init(); + INIT_LIST_HEAD(&sn_sysdata_list); + sn_init_cpei_timer(); + +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif + + printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n", + acpi_gbl_DSDT->oem_revision); + if (SN_ACPI_BASE_SUPPORT()) + sn_io_acpi_init(); + else + sn_io_init(); + return 0; +} + +arch_initcall(sn_io_early_init); + +/* + * sn_io_late_init() - Perform any final platform specific IO initialization. + */ + +int __init +sn_io_late_init(void) +{ + struct pci_bus *bus; + struct pcibus_bussoft *bussoft; + cnodeid_t cnode; + nasid_t nasid; + cnodeid_t near_cnode; + + if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) + return 0; + + /* + * Setup closest node in pci_controller->node for + * PIC, TIOCP, TIOCE (TIOCA does it during bus fixup using + * info from the PROM). + */ + bus = NULL; + while ((bus = pci_find_next_bus(bus)) != NULL) { + bussoft = SN_PCIBUS_BUSSOFT(bus); + nasid = NASID_GET(bussoft->bs_base); + cnode = nasid_to_cnodeid(nasid); + if ((bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) || + (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE)) { + /* TIO PCI Bridge: find nearest node with CPUs */ + int e = sn_hwperf_get_nearest_node(cnode, NULL, + &near_cnode); + if (e < 0) { + near_cnode = (cnodeid_t)-1; /* use any node */ + printk(KERN_WARNING "pcibr_bus_fixup: failed " + "to find near node with CPUs to TIO " + "node %d, err=%d\n", cnode, e); + } + PCI_CONTROLLER(bus)->node = near_cnode; + } else if (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC) { + PCI_CONTROLLER(bus)->node = cnode; + } + } + + sn_ioif_inited = 1; /* SN I/O infrastructure now initialized */ + + return 0; +} + +fs_initcall(sn_io_late_init); + +EXPORT_SYMBOL(sn_pci_fixup_slot); +EXPORT_SYMBOL(sn_pci_unfixup_slot); +EXPORT_SYMBOL(sn_bus_store_sysdata); +EXPORT_SYMBOL(sn_bus_free_sysdata); +EXPORT_SYMBOL(sn_generate_path); + diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index dc09a6a..990224a 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -3,103 +3,28 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved. */ -#include -#include #include #include -#include -#include #include -#include #include -#include +#include #include #include -#include #include -#include -#include #include "xtalk/hubdev.h" -#include "xtalk/xwidgetdev.h" - - -extern void sn_init_cpei_timer(void); -extern void register_sn_procfs(void); - -static struct list_head sn_sysdata_list; - -/* sysdata list struct */ -struct sysdata_el { - struct list_head entry; - void *sysdata; -}; - -struct slab_info { - struct hubdev_info hubdev; -}; - -struct brick { - moduleid_t id; /* Module ID of this module */ - struct slab_info slab_info[MAX_SLABS + 1]; -}; - -int sn_ioif_inited; /* SN I/O infrastructure initialized? */ - -struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ - -static int max_segment_number; /* Default highest segment number */ -static int max_pcibus_number = 255; /* Default highest pci bus number */ /* - * Hooks and struct for unsupported pci providers + * The code in this file will only be executed when running with + * a PROM that does _not_ have base ACPI IO support. + * (i.e., SN_ACPI_BASE_SUPPORT() == 0) */ -static dma_addr_t -sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type) -{ - return 0; -} - -static void -sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) -{ - return; -} - -static void * -sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller) -{ - return NULL; -} - -static struct sn_pcibus_provider sn_pci_default_provider = { - .dma_map = sn_default_pci_map, - .dma_map_consistent = sn_default_pci_map, - .dma_unmap = sn_default_pci_unmap, - .bus_fixup = sn_default_pci_bus_fixup, -}; - -/* - * Retrieve the DMA Flush List given nasid, widget, and device. - * This list is needed to implement the WAR - Flush DMA data on PIO Reads. - */ -static inline u64 -sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, - u64 address) -{ - struct ia64_sal_retval ret_stuff; - ret_stuff.status = 0; - ret_stuff.v0 = 0; +static int max_segment_number; /* Default highest segment number */ +static int max_pcibus_number = 255; /* Default highest pci bus number */ - SAL_CALL_NOLOCK(ret_stuff, - (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST, - (u64) nasid, (u64) widget_num, - (u64) device_num, (u64) address, 0, 0, 0); - return ret_stuff.status; -} /* * Retrieve the hub device info structure for the given nasid. @@ -131,93 +56,20 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) return ret_stuff.v0; } -/* - * Retrieve the pci device information given the bus and device|function number. - */ -static inline u64 -sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, - u64 sn_irq_info) -{ - struct ia64_sal_retval ret_stuff; - ret_stuff.status = 0; - ret_stuff.v0 = 0; - - SAL_CALL_NOLOCK(ret_stuff, - (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, - (u64) segment, (u64) bus_number, (u64) devfn, - (u64) pci_dev, - sn_irq_info, 0, 0); - return ret_stuff.v0; -} - -/* - * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified - * device. - */ -inline struct pcidev_info * -sn_pcidev_info_get(struct pci_dev *dev) -{ - struct pcidev_info *pcidev; - - list_for_each_entry(pcidev, - &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) { - if (pcidev->pdi_linux_pcidev == dev) { - return pcidev; - } - } - return NULL; -} - -/* Older PROM flush WAR - * - * 01/16/06 -- This war will be in place until a new official PROM is released. - * Additionally note that the struct sn_flush_device_war also has to be - * removed from arch/ia64/sn/include/xtalk/hubdev.h - */ -static u8 war_implemented = 0; - -static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, - struct sn_flush_device_common *common) -{ - struct sn_flush_device_war *war_list; - struct sn_flush_device_war *dev_entry; - struct ia64_sal_retval isrv = {0,0,0,0}; - - if (!war_implemented) { - printk(KERN_WARNING "PROM version < 4.50 -- implementing old " - "PROM flush WAR\n"); - war_implemented = 1; - } - - war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); - if (!war_list) - BUG(); - - SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, - nasid, widget, __pa(war_list), 0, 0, 0 ,0); - if (isrv.status) - panic("sn_device_fixup_war failed: %s\n", - ia64_sal_strerror(isrv.status)); - - dev_entry = war_list + device; - memcpy(common,dev_entry, sizeof(*common)); - kfree(war_list); - - return isrv.status; -} /* - * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for - * each node in the system. + * sn_fixup_ionodes() - This routine initializes the HUB data structure for + * each node in the system. This function is only + * executed when running with a non-ACPI capable PROM. */ static void __init sn_fixup_ionodes(void) { - struct sn_flush_device_kernel *sn_flush_device_kernel; - struct sn_flush_device_kernel *dev_entry; + struct hubdev_info *hubdev; u64 status; u64 nasid; - int i, widget, device, size; + int i; + extern void sn_common_hubdev_init(struct hubdev_info *); /* * Get SGI Specific HUB chipset information. @@ -240,70 +92,47 @@ static void __init sn_fixup_ionodes(void) max_segment_number = hubdev->max_segment_number; max_pcibus_number = hubdev->max_pcibus_number; } + sn_common_hubdev_init(hubdev); + } +} - /* Attach the error interrupt handlers */ - if (nasid & 1) - ice_error_init(hubdev); - else - hub_error_init(hubdev); - - for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) - hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev; - - if (!hubdev->hdi_flush_nasid_list.widget_p) - continue; - - size = (HUB_WIDGET_ID_MAX + 1) * - sizeof(struct sn_flush_device_kernel *); - hubdev->hdi_flush_nasid_list.widget_p = - kzalloc(size, GFP_KERNEL); - if (!hubdev->hdi_flush_nasid_list.widget_p) +/* + * sn_pci_legacy_window_fixup - Create PCI controller windows for + * legacy IO and MEM space. This needs to + * be done here, as the PROM does not have + * ACPI support defining the root buses + * and their resources (_CRS), + */ +static void +sn_legacy_pci_window_fixup(struct pci_controller *controller, + u64 legacy_io, u64 legacy_mem) +{ + controller->window = kcalloc(2, sizeof(struct pci_window), + GFP_KERNEL); + if (controller->window == NULL) BUG(); - - for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { - size = DEV_PER_WIDGET * - sizeof(struct sn_flush_device_kernel); - sn_flush_device_kernel = kzalloc(size, GFP_KERNEL); - if (!sn_flush_device_kernel) - BUG(); - - dev_entry = sn_flush_device_kernel; - for (device = 0; device < DEV_PER_WIDGET; - device++,dev_entry++) { - size = sizeof(struct sn_flush_device_common); - dev_entry->common = kzalloc(size, GFP_KERNEL); - if (!dev_entry->common) - BUG(); - - if (sn_prom_feature_available( - PRF_DEVICE_FLUSH_LIST)) - status = sal_get_device_dmaflush_list( - nasid, widget, device, - (u64)(dev_entry->common)); - else - status = sn_device_fixup_war(nasid, - widget, device, - dev_entry->common); - if (status != SALRET_OK) - panic("SAL call failed: %s\n", - ia64_sal_strerror(status)); - - spin_lock_init(&dev_entry->sfdl_flush_lock); - } - - if (sn_flush_device_kernel) - hubdev->hdi_flush_nasid_list.widget_p[widget] = - sn_flush_device_kernel; - } - } + controller->window[0].offset = legacy_io; + controller->window[0].resource.name = "legacy_io"; + controller->window[0].resource.flags = IORESOURCE_IO; + controller->window[0].resource.start = legacy_io; + controller->window[0].resource.end = + controller->window[0].resource.start + 0xffff; + controller->window[0].resource.parent = &ioport_resource; + controller->window[1].offset = legacy_mem; + controller->window[1].resource.name = "legacy_mem"; + controller->window[1].resource.flags = IORESOURCE_MEM; + controller->window[1].resource.start = legacy_mem; + controller->window[1].resource.end = + controller->window[1].resource.start + (1024 * 1024) - 1; + controller->window[1].resource.parent = &iomem_resource; + controller->windows = 2; } /* * sn_pci_window_fixup() - Create a pci_window for each device resource. - * Until ACPI support is added, we need this code - * to setup pci_windows for use by - * pcibios_bus_to_resource(), - * pcibios_resource_to_bus(), etc. + * It will setup pci_windows for use by + * pcibios_bus_to_resource(), pcibios_resource_to_bus(), + * etc. */ static void sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, @@ -342,60 +171,22 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, controller->window = new_window; } -void sn_pci_unfixup_slot(struct pci_dev *dev) -{ - struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev; - - sn_irq_unfixup(dev); - pci_dev_put(host_pci_dev); - pci_dev_put(dev); -} - /* - * sn_pci_fixup_slot() - This routine sets up a slot's resources - * consistent with the Linux PCI abstraction layer. Resources acquired - * from our PCI provider include PIO maps to BAR space and interrupt - * objects. + * sn_more_slot_fixup() - We are not running with an ACPI capable PROM, + * and need to convert the pci_dev->resource + * 'start' and 'end' addresses to mapped addresses, + * and setup the pci_controller->window array entries. */ -void sn_pci_fixup_slot(struct pci_dev *dev) +void +sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info) { unsigned int count = 0; int idx; - int segment = pci_domain_nr(dev->bus); - int status = 0; - struct pcibus_bussoft *bs; - struct pci_bus *host_pci_bus; - struct pci_dev *host_pci_dev; - struct pcidev_info *pcidev_info; s64 pci_addrs[PCI_ROM_RESOURCE + 1]; - struct sn_irq_info *sn_irq_info; - unsigned long size; - unsigned int bus_no, devfn; - - pci_dev_get(dev); /* for the sysdata pointer */ - pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); - if (!pcidev_info) - BUG(); /* Cannot afford to run out of memory */ - - sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); - if (!sn_irq_info) - BUG(); /* Cannot afford to run out of memory */ - - /* Call to retrieve pci device information needed by kernel. */ - status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, - dev->devfn, - (u64) __pa(pcidev_info), - (u64) __pa(sn_irq_info)); - if (status) - BUG(); /* Cannot get platform pci device information */ - - /* Add pcidev_info to list in sn_pci_controller struct */ - list_add_tail(&pcidev_info->pdi_list, - &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info)); + unsigned long addr, end, size, start; /* Copy over PIO Mapped Addresses */ for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { - unsigned long start, end, addr; if (!pcidev_info->pdi_pio_mapped_addr[idx]) { pci_addrs[idx] = -1; @@ -425,54 +216,19 @@ void sn_pci_fixup_slot(struct pci_dev *dev) */ if (count > 0) sn_pci_window_fixup(dev, count, pci_addrs); - - /* - * Using the PROMs values for the PCI host bus, get the Linux - * PCI host_pci_dev struct and set up host bus linkages - */ - - bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; - devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; - host_pci_bus = pci_find_bus(segment, bus_no); - host_pci_dev = pci_get_slot(host_pci_bus, devfn); - - pcidev_info->host_pci_dev = host_pci_dev; - pcidev_info->pdi_linux_pcidev = dev; - pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); - bs = SN_PCIBUS_BUSSOFT(dev->bus); - pcidev_info->pdi_pcibus_info = bs; - - if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { - SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; - } else { - SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; - } - - /* Only set up IRQ stuff if this device has a host bus context */ - if (bs && sn_irq_info->irq_irq) { - pcidev_info->pdi_sn_irq_info = sn_irq_info; - dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq; - sn_irq_fixup(dev, sn_irq_info); - } else { - pcidev_info->pdi_sn_irq_info = NULL; - kfree(sn_irq_info); - } } /* * sn_pci_controller_fixup() - This routine sets up a bus's resources - * consistent with the Linux PCI abstraction layer. + * consistent with the Linux PCI abstraction layer. */ -void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) +static void +sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) { - int status; - int nasid, cnode; + s64 status = 0; struct pci_controller *controller; - struct sn_pci_controller *sn_controller; struct pcibus_bussoft *prom_bussoft_ptr; - struct hubdev_info *hubdev_info; - void *provider_soft; - struct sn_pcibus_provider *provider; + status = sal_get_pcibus_info((u64) segment, (u64) busnum, (u64) ia64_tpa(&prom_bussoft_ptr)); @@ -480,261 +236,77 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) return; /*bus # does not exist */ prom_bussoft_ptr = __va(prom_bussoft_ptr); - /* Allocate a sn_pci_controller, which has a pci_controller struct - * as the first member. - */ - sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL); - if (!sn_controller) + controller = kzalloc(sizeof(*controller), GFP_KERNEL); + if (!controller) BUG(); - INIT_LIST_HEAD(&sn_controller->pcidev_info); - controller = &sn_controller->pci_controller; controller->segment = segment; - if (bus == NULL) { - bus = pci_scan_bus(busnum, &pci_root_ops, controller); - if (bus == NULL) - goto error_return; /* error, or bus already scanned */ - bus->sysdata = NULL; - } - - if (bus->sysdata) - goto error_return; /* sysdata already alloc'd */ - /* - * Per-provider fixup. Copies the contents from prom to local - * area and links SN_PCIBUS_BUSSOFT(). + * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup(). + * (platform_data will be overwritten later in sn_common_bus_fixup()) */ + controller->platform_data = prom_bussoft_ptr; - if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) - goto error_return; /* unsupported asic type */ - - if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) - goto error_return; /* no further fixup necessary */ - - provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; - if (provider == NULL) - goto error_return; /* no provider registerd for this asic */ + bus = pci_scan_bus(busnum, &pci_root_ops, controller); + if (bus == NULL) + goto error_return; /* error, or bus already scanned */ bus->sysdata = controller; - if (provider->bus_fixup) - provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); - else - provider_soft = NULL; - - if (provider_soft == NULL) { - /* fixup failed or not applicable */ - bus->sysdata = NULL; - goto error_return; - } - - /* - * Setup pci_windows for legacy IO and MEM space. - * (Temporary until ACPI support is in place.) - */ - controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL); - if (controller->window == NULL) - BUG(); - controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io; - controller->window[0].resource.name = "legacy_io"; - controller->window[0].resource.flags = IORESOURCE_IO; - controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io; - controller->window[0].resource.end = - controller->window[0].resource.start + 0xffff; - controller->window[0].resource.parent = &ioport_resource; - controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem; - controller->window[1].resource.name = "legacy_mem"; - controller->window[1].resource.flags = IORESOURCE_MEM; - controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem; - controller->window[1].resource.end = - controller->window[1].resource.start + (1024 * 1024) - 1; - controller->window[1].resource.parent = &iomem_resource; - controller->windows = 2; - - /* - * Generic bus fixup goes here. Don't reference prom_bussoft_ptr - * after this point. - */ - - PCI_CONTROLLER(bus)->platform_data = provider_soft; - nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base); - cnode = nasid_to_cnodeid(nasid); - hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); - SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = - &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); - /* - * If the node information we obtained during the fixup phase is invalid - * then set controller->node to -1 (undetermined) - */ - if (controller->node >= num_online_nodes()) { - struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); - - printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u" - "L_IO=%lx L_MEM=%lx BASE=%lx\n", - b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, - b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); - printk(KERN_WARNING "on node %d but only %d nodes online." - "Association set to undetermined.\n", - controller->node, num_online_nodes()); - controller->node = -1; - } return; error_return: - kfree(sn_controller); + kfree(controller); return; } -void sn_bus_store_sysdata(struct pci_dev *dev) +/* + * sn_bus_fixup + */ +void +sn_bus_fixup(struct pci_bus *bus) { - struct sysdata_el *element; - - element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL); - if (!element) { - dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); - return; - } - element->sysdata = SN_PCIDEV_INFO(dev); - list_add(&element->entry, &sn_sysdata_list); -} + struct pci_dev *pci_dev = NULL; + struct pcibus_bussoft *prom_bussoft_ptr; + extern void sn_common_bus_fixup(struct pci_bus *, + struct pcibus_bussoft *); + + + if (!bus->parent) { /* If root bus */ + prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data; + if (prom_bussoft_ptr == NULL) { + printk(KERN_ERR + "sn_bus_fixup: 0x%04x:0x%02x Unable to " + "obtain prom_bussoft_ptr\n", + pci_domain_nr(bus), bus->number); + return; + } + sn_common_bus_fixup(bus, prom_bussoft_ptr); + sn_legacy_pci_window_fixup(PCI_CONTROLLER(bus), + prom_bussoft_ptr->bs_legacy_io, + prom_bussoft_ptr->bs_legacy_mem); + } + list_for_each_entry(pci_dev, &bus->devices, bus_list) { + sn_pci_fixup_slot(pci_dev); + } -void sn_bus_free_sysdata(void) -{ - struct sysdata_el *element; - struct list_head *list, *safe; - - list_for_each_safe(list, safe, &sn_sysdata_list) { - element = list_entry(list, struct sysdata_el, entry); - list_del(&element->entry); - list_del(&(((struct pcidev_info *) - (element->sysdata))->pdi_list)); - kfree(element->sysdata); - kfree(element); - } - return; } /* - * Ugly hack to get PCI setup until we have a proper ACPI namespace. + * sn_io_init - PROM does not have ACPI support to define nodes or root buses, + * so we need to do things the hard way, including initiating the + * bus scanning ourselves. */ -#define PCI_BUSES_TO_SCAN 256 - -static int __init sn_pci_init(void) +void __init sn_io_init(void) { int i, j; - struct pci_dev *pci_dev = NULL; - - if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) - return 0; - - /* - * prime sn_pci_provider[]. Individial provider init routines will - * override their respective default entries. - */ - - for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) - sn_pci_provider[i] = &sn_pci_default_provider; - pcibr_init_provider(); - tioca_init_provider(); - tioce_init_provider(); - - /* - * This is needed to avoid bounce limit checks in the blk layer - */ - ia64_max_iommu_merge_mask = ~PAGE_MASK; sn_fixup_ionodes(); - sn_irq_lh_init(); - INIT_LIST_HEAD(&sn_sysdata_list); - sn_init_cpei_timer(); - -#ifdef CONFIG_PROC_FS - register_sn_procfs(); -#endif /* busses are not known yet ... */ for (i = 0; i <= max_segment_number; i++) for (j = 0; j <= max_pcibus_number; j++) sn_pci_controller_fixup(i, j, NULL); - - /* - * Generic Linux PCI Layer has created the pci_bus and pci_dev - * structures - time for us to add our SN PLatform specific - * information. - */ - - while ((pci_dev = - pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) - sn_pci_fixup_slot(pci_dev); - - sn_ioif_inited = 1; /* sn I/O infrastructure now initialized */ - - return 0; -} - -/* - * hubdev_init_node() - Creates the HUB data structure and link them to it's - * own NODE specific data area. - */ -void hubdev_init_node(nodepda_t * npda, cnodeid_t node) -{ - struct hubdev_info *hubdev_info; - int size; - pg_data_t *pg; - - size = sizeof(struct hubdev_info); - - if (node >= num_online_nodes()) /* Headless/memless IO nodes */ - pg = NODE_DATA(0); - else - pg = NODE_DATA(node); - - hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); - - npda->pdinfo = (void *)hubdev_info; } - -geoid_t -cnodeid_get_geoid(cnodeid_t cnode) -{ - struct hubdev_info *hubdev; - - hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); - return hubdev->hdi_geoid; -} - -void sn_generate_path(struct pci_bus *pci_bus, char *address) -{ - nasid_t nasid; - cnodeid_t cnode; - geoid_t geoid; - moduleid_t moduleid; - u16 bricktype; - - nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); - cnode = nasid_to_cnodeid(nasid); - geoid = cnodeid_get_geoid(cnode); - moduleid = geo_module(geoid); - - sprintf(address, "module_%c%c%c%c%.2d", - '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)), - '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)), - '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)), - MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid)); - - /* Tollhouse requires slot id to be displayed */ - bricktype = MODULE_GET_BTYPE(moduleid); - if ((bricktype == L1_BRICKTYPE_191010) || - (bricktype == L1_BRICKTYPE_1932)) - sprintf(address, "%s^%d", address, geo_slot(geoid)); -} - -subsys_initcall(sn_pci_init); -EXPORT_SYMBOL(sn_pci_fixup_slot); -EXPORT_SYMBOL(sn_pci_unfixup_slot); -EXPORT_SYMBOL(sn_pci_controller_fixup); -EXPORT_SYMBOL(sn_bus_store_sysdata); -EXPORT_SYMBOL(sn_bus_free_sysdata); -EXPORT_SYMBOL(sn_generate_path); diff --git a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c index 7ce3cda..4aa4f30 100644 --- a/arch/ia64/sn/kernel/iomv.c +++ b/arch/ia64/sn/kernel/iomv.c @@ -3,10 +3,11 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2003, 2006 Silicon Graphics, Inc. All rights reserved. */ #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #define IS_LEGACY_VGA_IOPORT(p) \ (((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df)) @@ -31,11 +33,14 @@ void *sn_io_addr(unsigned long port) { if (!IS_RUNNING_ON_SIMULATOR()) { if (IS_LEGACY_VGA_IOPORT(port)) - port += vga_console_iobase; + return (__ia64_mk_io_addr(port)); /* On sn2, legacy I/O ports don't point at anything */ if (port < (64 * 1024)) return NULL; - return ((void *)(port | __IA64_UNCACHED_OFFSET)); + if (SN_ACPI_BASE_SUPPORT()) + return (__ia64_mk_io_addr(port)); + else + return ((void *)(port | __IA64_UNCACHED_OFFSET)); } else { /* but the simulator uses them... */ unsigned long addr; diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 7a2d824..1d009f9 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -388,6 +388,14 @@ void __init sn_setup(char **cmdline_p) ia64_sn_plat_set_error_handling_features(); // obsolete ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV); ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES); + /* + * Note: The calls to notify the PROM of ACPI and PCI Segment + * support must be done prior to acpi_load_tables(), as + * an ACPI capable PROM will rebuild the DSDT as result + * of the call. + */ + ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE); + ia64_sn_set_os_feature(OSF_ACPI_ENABLE); #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) @@ -413,6 +421,16 @@ void __init sn_setup(char **cmdline_p) if (! vga_console_membase) sn_scan_pcdp(); + /* + * Setup legacy IO space. + * vga_console_iobase maps to PCI IO Space address 0 on the + * bus containing the VGA console. + */ + if (vga_console_iobase) { + io_space[0].mmio_base = vga_console_iobase; + io_space[0].sparse = 0; + } + if (vga_console_membase) { /* usable vga ... make tty0 the preferred default console */ if (!strstr(*cmdline_p, "console=")) diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index feaf1a6..493380b 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -552,7 +552,7 @@ static void __exit tiocx_exit(void) bus_unregister(&tiocx_bus_type); } -subsys_initcall(tiocx_init); +fs_initcall(tiocx_init); module_exit(tiocx_exit); /************************************************************************ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 27dd7df..6846dc9 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2004, 2006 Silicon Graphics, Inc. All rights reserved. */ #include @@ -109,7 +109,6 @@ void * pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; - cnodeid_t near_cnode; struct hubdev_info *hubdev_info; struct pcibus_info *soft; struct sn_flush_device_kernel *sn_flush_device_kernel; @@ -186,20 +185,6 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont return NULL; } - if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { - /* TIO PCI Bridge: find nearest node with CPUs */ - int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode); - - if (e < 0) { - near_cnode = (cnodeid_t)-1; /* use any node */ - printk(KERN_WARNING "pcibr_bus_fixup: failed to find " - "near node with CPUs to TIO node %d, err=%d\n", - cnode, e); - } - controller->node = near_cnode; - } - else - controller->node = cnode; return soft; } diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 46e16dc..35f854f 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -15,7 +15,6 @@ #include #include #include -#include /* * 1/26/2006 @@ -990,8 +989,6 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) static void * tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { - int my_nasid; - cnodeid_t my_cnode, mem_cnode; struct tioce_common *tioce_common; struct tioce_kernel *tioce_kern; struct tioce __iomem *tioce_mmr; @@ -1035,21 +1032,6 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont tioce_common->ce_pcibus.bs_persist_segment, tioce_common->ce_pcibus.bs_persist_busnum); - /* - * identify closest nasid for memory allocations - */ - - my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base); - my_cnode = nasid_to_cnodeid(my_nasid); - - if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) { - printk(KERN_WARNING "tioce_bus_fixup: failed to find " - "closest node with MEM to TIO node %d\n", my_cnode); - mem_cnode = (cnodeid_t)-1; /* use any node */ - } - - controller->node = mem_cnode; - return tioce_common; } diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index 855c30a..6311e16 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h @@ -32,7 +32,7 @@ */ #define IO_SPACE_LIMIT 0xffffffffffffffffUL -#define MAX_IO_SPACES_BITS 4 +#define MAX_IO_SPACES_BITS 8 #define MAX_IO_SPACES (1UL << MAX_IO_SPACES_BITS) #define IO_SPACE_BITS 24 #define IO_SPACE_SIZE (1UL << IO_SPACE_BITS) diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index 7ffbddf..8f784f8 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -36,6 +36,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val, typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val, u8 size); typedef void ia64_mv_migrate_t(struct task_struct * task); +typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *); /* DMA-mapping interface: */ typedef void ia64_mv_dma_init (void); @@ -95,6 +96,11 @@ machvec_noop_task (struct task_struct *task) { } +static inline void +machvec_noop_bus (struct pci_bus *bus) +{ +} + extern void machvec_setup (char **); extern void machvec_timer_interrupt (int, void *); extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int); @@ -159,6 +165,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # define platform_migrate ia64_mv.migrate # define platform_setup_msi_irq ia64_mv.setup_msi_irq # define platform_teardown_msi_irq ia64_mv.teardown_msi_irq +# define platform_pci_fixup_bus ia64_mv.pci_fixup_bus # endif /* __attribute__((__aligned__(16))) is required to make size of the @@ -210,6 +217,7 @@ struct ia64_machine_vector { ia64_mv_migrate_t *migrate; ia64_mv_setup_msi_irq_t *setup_msi_irq; ia64_mv_teardown_msi_irq_t *teardown_msi_irq; + ia64_mv_pci_fixup_bus_t *pci_fixup_bus; } __attribute__((__aligned__(16))); /* align attrib? see above comment */ #define MACHVEC_INIT(name) \ @@ -257,6 +265,7 @@ struct ia64_machine_vector { platform_migrate, \ platform_setup_msi_irq, \ platform_teardown_msi_irq, \ + platform_pci_fixup_bus, \ } extern struct ia64_machine_vector ia64_mv; @@ -416,5 +425,8 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size #ifndef platform_teardown_msi_irq # define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL) #endif +#ifndef platform_pci_fixup_bus +# define platform_pci_fixup_bus machvec_noop_bus +#endif #endif /* _ASM_IA64_MACHVEC_H */ diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index c54b165..83325f6 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h @@ -69,6 +69,7 @@ extern ia64_mv_dma_supported sn_dma_supported; extern ia64_mv_migrate_t sn_migrate; extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq; extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq; +extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus; /* @@ -127,6 +128,7 @@ extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq; #define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL) #define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL) #endif +#define platform_pci_fixup_bus sn_pci_fixup_bus #include diff --git a/include/asm-ia64/sn/acpi.h b/include/asm-ia64/sn/acpi.h new file mode 100644 index 0000000..2850a7e --- /dev/null +++ b/include/asm-ia64/sn/acpi.h @@ -0,0 +1,16 @@ +/* + * 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) 2006 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef _ASM_IA64_SN_ACPI_H +#define _ASM_IA64_SN_ACPI_H + +#include "acpi/acglobal.h" + +#define SN_ACPI_BASE_SUPPORT() (acpi_gbl_DSDT->oem_revision >= 0x20101) + +#endif /* _ASM_IA64_SN_ACPI_H */ diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h index eac3561..9fe89a9 100644 --- a/include/asm-ia64/sn/pcidev.h +++ b/include/asm-ia64/sn/pcidev.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_PCI_PCIDEV_H #define _ASM_IA64_SN_PCI_PCIDEV_H @@ -12,31 +12,29 @@ /* * In ia64, pci_dev->sysdata must be a *pci_controller. To provide access to - * the pcidev_info structs for all devices under a controller, we extend the - * definition of pci_controller, via sn_pci_controller, to include a list - * of pcidev_info. + * the pcidev_info structs for all devices under a controller, we keep a + * list of pcidev_info under pci_controller->platform_data. */ -struct sn_pci_controller { - struct pci_controller pci_controller; +struct sn_platform_data { + void *provider_soft; struct list_head pcidev_info; }; -#define SN_PCI_CONTROLLER(dev) ((struct sn_pci_controller *) dev->sysdata) +#define SN_PLATFORM_DATA(busdev) \ + ((struct sn_platform_data *)(PCI_CONTROLLER(busdev)->platform_data)) #define SN_PCIDEV_INFO(dev) sn_pcidev_info_get(dev) -#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \ - (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data)) /* * Given a pci_bus, return the sn pcibus_bussoft struct. Note that * this only works for root busses, not for busses represented by PPB's. */ #define SN_PCIBUS_BUSSOFT(pci_bus) \ - ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data)) + ((struct pcibus_bussoft *)(SN_PLATFORM_DATA(pci_bus)->provider_soft)) #define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \ - (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data)) + ((struct pcibus_info *)(SN_PLATFORM_DATA(pci_bus)->provider_soft)) /* * Given a struct pci_dev, return the sn pcibus_bussoft struct. Note * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due @@ -72,8 +70,6 @@ extern void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info); extern void sn_irq_unfixup(struct pci_dev *pci_dev); extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *); -extern void sn_pci_controller_fixup(int segment, int busnum, - struct pci_bus *bus); extern void sn_bus_store_sysdata(struct pci_dev *dev); extern void sn_bus_free_sysdata(void); extern void sn_generate_path(struct pci_bus *pci_bus, char *address); diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h index 30dcfa4..bfdc362 100644 --- a/include/asm-ia64/sn/sn_feature_sets.h +++ b/include/asm-ia64/sn/sn_feature_sets.h @@ -44,8 +44,14 @@ extern int sn_prom_feature_available(int id); * Once enabled, a feature cannot be disabled. * * By default, features are disabled unless explicitly enabled. + * + * These defines must be kept in sync with the corresponding + * PROM definitions in feature_sets.h. */ #define OSF_MCA_SLV_TO_OS_INIT_SLV 0 #define OSF_FEAT_LOG_SBES 1 +#define OSF_ACPI_ENABLE 2 +#define OSF_PCISEGMENT_ENABLE 3 + #endif /* _ASM_IA64_SN_FEATURE_SETS_H */ diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index ba826b3..be5d83a 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -77,6 +77,7 @@ #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated #define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a +#define SN_SAL_IOIF_INIT 0x0200005f #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 #define SN_SAL_BTE_RECOVER 0x02000061 #define SN_SAL_RESERVED_DO_NOT_USE 0x02000062 -- cgit v0.10.2 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 diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index b62ad31..5d188c5 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 v0.10.2 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 diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index a9dc369..99d7f27 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 12531de..d4dd8f4 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 990224a..9ad843e 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 e1dcefc..d087e08 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 d42c833..cf8696d 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 16167b0..0b9d0db 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index c57d9d5c..c8b6907 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 v0.10.2 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 diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index bb7456c..a064f36 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 v0.10.2 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 diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 194f1d2..84ec9c8 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 v0.10.2 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 diff --git a/drivers/pci/access.c b/drivers/pci/access.c index ea16805..73a58c7 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 v0.10.2 From 7edab2f0876ff6a38e10a88c9aca20180aad307c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 17 Oct 2006 10:17:58 -0700 Subject: pci/i386: style cleanups Mostly CodingStyle cleanups for arch/i386/pci/i386.c: - fit in 80 columns; - use a #defined value instead of an inline constant; Also change one resource_size_t (DBG) printk from %08lx to %lx since it can be more than 32 bits (more than 8 hexits). Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 9858029..43005f0 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -104,16 +104,24 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) /* Depth-First Search on bus tree */ list_for_each_entry(bus, bus_list, node) { if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + for (idx = PCI_BRIDGE_RESOURCES; + idx < PCI_NUM_RESOURCES; idx++) { r = &dev->resource[idx]; if (!r->flags) continue; pr = pci_find_parent_resource(dev, r); - if (!r->start || !pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); - /* Something is wrong with the region. - Invalidate the resource to prevent child - resource allocations in this range. */ + if (!r->start || !pr || + request_resource(pr, r) < 0) { + printk(KERN_ERR "PCI: Cannot allocate " + "resource region %d " + "of bridge %s\n", + idx, pci_name(dev)); + /* + * Something is wrong with the region. + * Invalidate the resource to prevent + * child resource allocations in this + * range. + */ r->flags = 0; } } @@ -131,7 +139,7 @@ static void __init pcibios_allocate_resources(int pass) for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { r = &dev->resource[idx]; if (r->parent) /* Already allocated */ continue; @@ -142,11 +150,15 @@ static void __init pcibios_allocate_resources(int pass) else disabled = !(command & PCI_COMMAND_MEMORY); if (pass == disabled) { - DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", + DBG("PCI: Resource %08lx-%08lx " + "(f=%lx, d=%d, p=%d)\n", r->start, r->end, r->flags, disabled, pass); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev)); + printk(KERN_ERR "PCI: Cannot allocate " + "resource region %d " + "of device %s\n", + idx, pci_name(dev)); /* We'll assign a new address later */ r->end -= r->start; r->start = 0; @@ -156,12 +168,16 @@ static void __init pcibios_allocate_resources(int pass) if (!pass) { r = &dev->resource[PCI_ROM_RESOURCE]; if (r->flags & IORESOURCE_ROM_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ + /* Turn the ROM off, leave the resource region, + * but keep it unregistered. */ u32 reg; - DBG("PCI: Switching off ROM of %s\n", pci_name(dev)); + DBG("PCI: Switching off ROM of %s\n", + pci_name(dev)); r->flags &= ~IORESOURCE_ROM_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); + pci_read_config_dword(dev, + dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, + reg & ~PCI_ROM_ADDRESS_ENABLE); } } } @@ -173,9 +189,11 @@ static int __init pcibios_assign_resources(void) struct resource *r, *pr; if (!(pci_probe & PCI_ASSIGN_ROMS)) { - /* Try to use BIOS settings for ROMs, otherwise let - pci_assign_unassigned_resources() allocate the new - addresses. */ + /* + * Try to use BIOS settings for ROMs, otherwise let + * pci_assign_unassigned_resources() allocate the new + * addresses. + */ for_each_pci_dev(dev) { r = &dev->resource[PCI_ROM_RESOURCE]; if (!r->flags || !r->start) @@ -215,9 +233,9 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; - for(idx = 0; idx < PCI_NUM_RESOURCES; idx++) { + for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { /* Only set up the requested stuff */ - if (!(mask & (1<resource[idx]; @@ -227,7 +245,9 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) (!(r->flags & IORESOURCE_ROM_ENABLE))) continue; if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + printk(KERN_ERR "PCI: Device %s not available " + "because of resource collisions\n", + pci_name(dev)); return -EINVAL; } if (r->flags & IORESOURCE_IO) @@ -236,7 +256,8 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) cmd |= PCI_COMMAND_MEMORY; } if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + printk("PCI: Enabling device %s (%04x -> %04x)\n", + pci_name(dev), old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; @@ -258,7 +279,8 @@ void pcibios_set_master(struct pci_dev *dev) lat = pcibios_max_latency; else return; - printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); + printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", + pci_name(dev), lat); pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } -- cgit v0.10.2 From 039d09a845209122c5193e650ab2d8b3c849ca7c Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Tue, 17 Oct 2006 10:02:50 +0530 Subject: PCI: arch/i386/kernel/pci-dma.c: ioremap balanced with iounmap ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. Tested (compilation only): - using allmodconfig - making sure the files are compiling without any warning/error due to new changes Signed-off-by: Amol Lad Signed-off-by: Greg Kroah-Hartman diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c index 25fe668..5c8c6ef 100644 --- a/arch/i386/kernel/pci-dma.c +++ b/arch/i386/kernel/pci-dma.c @@ -75,7 +75,7 @@ EXPORT_SYMBOL(dma_free_coherent); int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, dma_addr_t device_addr, size_t size, int flags) { - void __iomem *mem_base; + void __iomem *mem_base = NULL; int pages = size >> PAGE_SHIFT; int bitmap_size = (pages + 31)/32; @@ -114,6 +114,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, free1_out: kfree(dev->dma_mem->bitmap); out: + if (mem_base) + iounmap(mem_base); return 0; } EXPORT_SYMBOL(dma_declare_coherent_memory); -- cgit v0.10.2 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 diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 84ec9c8..e5ae3a0 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 f952bfe..7a94076 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 4279917..5a14b73 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -612,30 +612,51 @@ 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 6bf327d..398852f 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 09be0f8..01c7072 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 v0.10.2 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 diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 62f1ac0..8287f95 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 v0.10.2 From 3b59d52d8c7925e7a9a396f2e31a66eb060c6c37 Mon Sep 17 00:00:00 2001 From: Jason Gaston Date: Wed, 22 Nov 2006 15:15:08 -0800 Subject: PCI: irq: irq and pci_ids patch for Intel ICH9 This updated patch adds the Intel ICH9 LPC and SMBus Controller DID's. Signed-off-by: Jason Gaston Signed-off-by: Greg Kroah-Hartman diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 6916399..e65551c 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -543,6 +543,12 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH8_2: case PCI_DEVICE_ID_INTEL_ICH8_3: case PCI_DEVICE_ID_INTEL_ICH8_4: + case PCI_DEVICE_ID_INTEL_ICH9_0: + case PCI_DEVICE_ID_INTEL_ICH9_1: + case PCI_DEVICE_ID_INTEL_ICH9_2: + case PCI_DEVICE_ID_INTEL_ICH9_3: + case PCI_DEVICE_ID_INTEL_ICH9_4: + case PCI_DEVICE_ID_INTEL_ICH9_5: r->name = "PIIX/ICH"; r->get = pirq_piix_get; r->set = pirq_piix_set; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fa4e1d7..e060a76 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2211,6 +2211,13 @@ #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 +#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 +#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2911 +#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 +#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913 +#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914 +#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2915 +#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 -- cgit v0.10.2 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 diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 510816c..04bee52 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 bbb2fbe..c7be2fd 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 59c5b24..ddbadd95 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 c8b6907..40c79b0 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 46825fe..7238346 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 141486d..71a2cb8 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index f93e81e..f13f313 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1c551c6..6d3f580 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 v0.10.2 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 diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index d87a9e3..d8f05d7 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 v0.10.2 From 2b290da053608692ea206507d993b70c39d2cdea Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 16 Nov 2006 13:16:23 +0100 Subject: PCI: make arch/i386/pci/common.c:pci_bf_sort static This patch makes the needlessly global pci_bf_sort static. Signed-off-by: Adrian Bunk Acked-by: Matt Domsch Signed-off-by: Greg Kroah-Hartman diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index cdfcf97..53ca6e8 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -20,7 +20,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; -int pci_bf_sort; +static int pci_bf_sort; int pci_routeirq; int pcibios_last_bus = -1; unsigned long pirq_table_addr; -- cgit v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 7d8a7ce..ed3e8a2 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 002fde4..d4f35d8 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 c5d6bb4..9c88b1e 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 9d4f6a9..b00e027 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 v0.10.2 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 diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9c88b1e..510e788 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 v0.10.2 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 diff --git a/drivers/base/class.c b/drivers/base/class.c index 0ff267a..2e705f6 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 d4f35d8..dbcd40b 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 b00e027..00b29e0 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 v0.10.2 From 88a22c985e3545c55c9779971007f0f29f912519 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Sep 2006 11:23:28 +0200 Subject: CONFIG_SYSFS_DEPRECATED Provide a way to support older versions of udev that are shipped in older distros. If this option is disabled, it will also turn off the compatible symlinks in sysfs that older programs might rely on. When in doubt, or if running a distro older than 2006, say Yes here. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/init/Kconfig b/init/Kconfig index 176f7e5..14d4846 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -249,6 +249,26 @@ config CPUSETS Say N if unsure. +config SYSFS_DEPRECATED + bool "Create deprecated sysfs files" + default y + help + This option creates deprecated symlinks such as the + "device"-link, the :-link, and the + "bus"-link. It may also add deprecated key in the + uevent environment. + None of these features or values should be used today, as + they export driver core implementation details to userspace + or export properties which can't be kept stable across kernel + releases. + + If enabled, this option will also move any device structures + that belong to a class, back into the /sys/class heirachy, in + order to support older versions of udev. + + If you are using a distro that was released in 2006 or later, + it should be safe to say N here. + config RELAY bool "Kernel->user space relay support (formerly relayfs)" help -- cgit v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index dbcd40b..8f8347b 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 v0.10.2 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 diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ed3e8a2..472810f 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index 8f8347b..b565b7e 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index b565b7e..f544adc 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 v0.10.2 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 diff --git a/drivers/base/class.c b/drivers/base/class.c index 2e705f6..f098881 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,20 +650,18 @@ 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; kobject_uevent(&class_dev->kobj, KOBJ_ADD); @@ -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 v0.10.2 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 diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 8e4413f..87587b4 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 v0.10.2 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 diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index bd7a98c..f442b57 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 v0.10.2 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 diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 154a81d..ebace20 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 62ebe09..7a484fc 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 6ad2d3b..6e1329d 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 ba2a203..7c8d039 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 b03cfb9..326da7d 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 v0.10.2 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 diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e90ea39..50dc492 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 5800bee..defd5743 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 884bd72..06298cc 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 596f3ae..7edea01 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 9ad840e..e767afa 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 44091c0..65321f9 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 v0.10.2 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 diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 89b718e..3b32313 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 v0.10.2 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 diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 3f86903..94a4e9a 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 v0.10.2 From a271aaf15f492d202def1b34e447107b60fe4ece Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert msr 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 diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index d535cdb..a773f77 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -239,14 +239,14 @@ static struct file_operations msr_fops = { .open = msr_open, }; -static int msr_class_device_create(int i) +static int msr_device_create(int i) { int err = 0; - struct class_device *class_err; + struct device *dev; - class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i); - if (IS_ERR(class_err)) - err = PTR_ERR(class_err); + dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i); + if (IS_ERR(dev)) + err = PTR_ERR(dev); return err; } @@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - msr_class_device_create(cpu); + msr_device_create(cpu); break; case CPU_DEAD: - class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); + device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); break; } return NOTIFY_OK; @@ -290,7 +290,7 @@ static int __init msr_init(void) goto out_chrdev; } for_each_online_cpu(i) { - err = msr_class_device_create(i); + err = msr_device_create(i); if (err != 0) goto out_class; } @@ -302,7 +302,7 @@ static int __init msr_init(void) out_class: i = 0; for_each_online_cpu(i) - class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i)); + device_destroy(msr_class, MKDEV(MSR_MAJOR, i)); class_destroy(msr_class); out_chrdev: unregister_chrdev(MSR_MAJOR, "cpu/msr"); @@ -314,7 +314,7 @@ static void __exit msr_exit(void) { int cpu = 0; for_each_online_cpu(cpu) - class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); + device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); class_destroy(msr_class); unregister_chrdev(MSR_MAJOR, "cpu/msr"); unregister_hotcpu_notifier(&msr_class_cpu_notifier); -- cgit v0.10.2 From 07accdc18e014cad945013886ee34e09f859f88a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert cpuid 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 diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index fde8bea..ab0c327 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = { .open = cpuid_open, }; -static int cpuid_class_device_create(int i) +static int cpuid_device_create(int i) { int err = 0; - struct class_device *class_err; + struct device *dev; - class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i); - if (IS_ERR(class_err)) - err = PTR_ERR(class_err); + dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i); + if (IS_ERR(dev)) + err = PTR_ERR(dev); return err; } @@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac switch (action) { case CPU_ONLINE: - cpuid_class_device_create(cpu); + cpuid_device_create(cpu); break; case CPU_DEAD: - class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); + device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); break; } return NOTIFY_OK; @@ -206,7 +206,7 @@ static int __init cpuid_init(void) goto out_chrdev; } for_each_online_cpu(i) { - err = cpuid_class_device_create(i); + err = cpuid_device_create(i); if (err != 0) goto out_class; } @@ -218,7 +218,7 @@ static int __init cpuid_init(void) out_class: i = 0; for_each_online_cpu(i) { - class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i)); + device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i)); } class_destroy(cpuid_class); out_chrdev: @@ -232,7 +232,7 @@ static void __exit cpuid_exit(void) int cpu = 0; for_each_online_cpu(cpu) - class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); + device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); class_destroy(cpuid_class); unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); -- cgit v0.10.2 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 diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index f5802e7..c6de566 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 v0.10.2 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 diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index efc485e..c1e3dd8 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 v0.10.2 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 diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 4ccdd82..61a1de8 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 10cc973..ac53296 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 ced309b..682e62b 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 587264a..528e7d3 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 v0.10.2 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 diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 1461569..4bad287 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 v0.10.2 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 diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 93ffcdd..e973a87 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 d3a5041..323bdf6 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 3e69241..fa23e06 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 v0.10.2 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 diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5547337..e67eef4 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 v0.10.2 From d80f19fab89cba8a6d16193154c8ff3edab00942 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert sound 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. It also makes the struct sound_card to show up as a "real" device where all the different sound class devices are placed as childs and different card attribute files can hang off of. /sys/class/sound is still a flat directory, but the symlink targets of all devices belonging to the same card, point the the /sys/devices tree below the new card device object. Thanks to Kay for the updates to this patch. Signed-off-by: Kay Sievers Acked-by: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman diff --git a/include/sound/core.h b/include/sound/core.h index fa1ca01..a994bea 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + struct device *parent; struct device *dev; #ifdef CONFIG_PM @@ -187,13 +188,14 @@ struct snd_minor { int device; /* device number */ const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ - struct class_device *class_dev; /* class device for sysfs */ + struct device *dev; /* device for sysfs */ }; /* sound.c */ extern int snd_major; extern int snd_ecards_limit; +extern struct class *sound_class; void snd_request_card(int card); @@ -203,7 +205,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, int snd_unregister_device(int type, struct snd_card *card, int dev); void *snd_lookup_minor_data(unsigned int minor, int type); int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - const struct class_device_attribute *attr); + struct device_attribute *attr); #ifdef CONFIG_SND_OSSEMUL int snd_register_oss_device(int type, struct snd_card *card, int dev, @@ -255,7 +257,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); #ifndef snd_card_set_dev -#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr)) +#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr)) #endif /* device.c */ diff --git a/sound/core/init.c b/sound/core/init.c index 3058d62..6152a75 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card) snd_printk(KERN_WARNING "unable to free card info\n"); /* Not fatal error */ } + if (card->dev) + device_unregister(card->dev); kfree(card); return 0; } @@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card) int err; snd_assert(card != NULL, return -EINVAL); + if (!card->dev) { + card->dev = device_create(sound_class, card->parent, 0, + "card%i", card->number); + if (IS_ERR(card->dev)) + card->dev = NULL; + } if ((err = snd_device_register_all(card)) < 0) return err; mutex_lock(&snd_card_mutex); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index fbbbcd2..5ac6e19 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) substream->pstr->substream_opened--; } -static ssize_t show_pcm_class(struct class_device *class_device, char *buf) +static ssize_t show_pcm_class(struct device *dev, + struct device_attribute *attr, char *buf) { struct snd_pcm *pcm; const char *str; @@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf) [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", }; - if (! (pcm = class_get_devdata(class_device)) || + if (! (pcm = dev_get_drvdata(dev)) || pcm->dev_class > SNDRV_PCM_CLASS_LAST) str = "none"; else @@ -929,7 +930,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf) return snprintf(buf, PAGE_SIZE, "%s\n", str); } -static struct class_device_attribute pcm_attrs = +static struct device_attribute pcm_attrs = __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); static int snd_pcm_dev_register(struct snd_device *device) diff --git a/sound/core/sound.c b/sound/core/sound.c index efa476c..2827420 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit); static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static DEFINE_MUTEX(sound_mutex); -extern struct class *sound_class; - - #ifdef CONFIG_KMOD /** @@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev, snd_minors[minor] = preg; if (card) device = card->dev; - preg->class_dev = class_device_create(sound_class, NULL, - MKDEV(major, minor), - device, "%s", name); - if (preg->class_dev) - class_set_devdata(preg->class_dev, private_data); + preg->dev = device_create(sound_class, device, MKDEV(major, minor), + "%s", name); + if (preg->dev) + dev_set_drvdata(preg->dev, private_data); mutex_unlock(&sound_mutex); return 0; @@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) return -EINVAL; } - class_device_destroy(sound_class, MKDEV(major, minor)); + device_destroy(sound_class, MKDEV(major, minor)); kfree(snd_minors[minor]); snd_minors[minor] = NULL; @@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) EXPORT_SYMBOL(snd_unregister_device); int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - const struct class_device_attribute *attr) + struct device_attribute *attr) { int minor, ret = -EINVAL; - struct class_device *cdev; + struct device *d; mutex_lock(&sound_mutex); minor = find_snd_minor(type, card, dev); - if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL) - ret = class_device_create_file(cdev, attr); + if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL) + ret = device_create_file(d, attr); mutex_unlock(&sound_mutex); return ret; diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 2344d09..75c5e74 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -557,17 +557,17 @@ static int __init oss_init(void) sound_dmap_flag = (dmabuf > 0 ? 1 : 0); for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { - class_device_create(sound_class, NULL, - MKDEV(SOUND_MAJOR, dev_list[i].minor), - NULL, "%s", dev_list[i].name); + device_create(sound_class, NULL, + MKDEV(SOUND_MAJOR, dev_list[i].minor), + "%s", dev_list[i].name); if (!dev_list[i].num) continue; for (j = 1; j < *dev_list[i].num; j++) - class_device_create(sound_class, NULL, - MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), - NULL, "%s%d", dev_list[i].name, j); + device_create(sound_class, NULL, + MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), + "%s%d", dev_list[i].name, j); } if (sound_nblocks >= 1024) @@ -581,11 +581,11 @@ static void __exit oss_cleanup(void) int i, j; for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { - class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); + device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); if (!dev_list[i].num) continue; for (j = 1; j < *dev_list[i].num; j++) - class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); + device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); } unregister_sound_special(1); diff --git a/sound/sound_core.c b/sound/sound_core.c index 5322c50..8f1ced4 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); - class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor), - dev, s->name+6); + device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), + s->name+6); return r; fail: @@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) p = __sound_remove_unit(list, unit); spin_unlock(&sound_loader_lock); if (p) { - class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); + device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); kfree(p); } } -- cgit v0.10.2 From c6dbaef22a2f78700e242915a13218dd780c89ff Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:18:39 +1100 Subject: Driver core: add dev_archdata to struct device Add arch specific dev_archdata to struct device Adds an arch specific struct dev_arch to struct device. This enables architecture to add specific fields to every device in the system, like DMA operation pointers, NUMA node ID, firmware specific data, etc... Signed-off-by: Benjamin Herrenschmidt Acked-by: Andi Kleen Acked-By: David Howells Signed-off-by: Greg Kroah-Hartman diff --git a/include/asm-alpha/device.h b/include/asm-alpha/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-alpha/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-arm/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-arm26/device.h b/include/asm-arm26/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-arm26/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-avr32/device.h b/include/asm-avr32/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-avr32/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-cris/device.h b/include/asm-cris/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-cris/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-frv/device.h b/include/asm-frv/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-frv/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-generic/device.h b/include/asm-generic/device.h new file mode 100644 index 0000000..c17c960 --- /dev/null +++ b/include/asm-generic/device.h @@ -0,0 +1,12 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#ifndef _ASM_GENERIC_DEVICE_H +#define _ASM_GENERIC_DEVICE_H + +struct dev_archdata { +}; + +#endif /* _ASM_GENERIC_DEVICE_H */ diff --git a/include/asm-h8300/device.h b/include/asm-h8300/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-h8300/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-i386/device.h b/include/asm-i386/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-i386/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-ia64/device.h b/include/asm-ia64/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-ia64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m32r/device.h b/include/asm-m32r/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-m32r/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m68k/device.h b/include/asm-m68k/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-m68k/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m68knommu/device.h b/include/asm-m68knommu/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-m68knommu/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-mips/device.h b/include/asm-mips/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-mips/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-parisc/device.h b/include/asm-parisc/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-parisc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-powerpc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-ppc/device.h b/include/asm-ppc/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-ppc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-s390/device.h b/include/asm-s390/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-s390/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sh/device.h b/include/asm-sh/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-sh/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sh64/device.h b/include/asm-sh64/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-sh64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-sparc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-sparc64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-um/device.h b/include/asm-um/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-um/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-v850/device.h b/include/asm-v850/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-v850/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-x86_64/device.h b/include/asm-x86_64/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-x86_64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-xtensa/device.h b/include/asm-xtensa/device.h new file mode 100644 index 0000000..d8f9872 --- /dev/null +++ b/include/asm-xtensa/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/linux/device.h b/include/linux/device.h index 00b29e0..5b54d75 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -21,6 +21,7 @@ #include #include #include +#include #define DEVICE_NAME_SIZE 50 #define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */ @@ -383,6 +384,8 @@ struct device { struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ + /* arch specific additions */ + struct dev_archdata archdata; /* class_device migration path */ struct list_head node; -- cgit v0.10.2 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 diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 10f160d..a2f46d5 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 f338e40..fdd1095 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 d8f9872..849604c 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 d8f9872..3db6daf 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 d8f9872..3afa03f 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 5b54d75..2d9dc35 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index f544adc..5d11bbd 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 v0.10.2 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 diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 28dccb7..3d12b85 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 v0.10.2 From 035ed7a49447bc8e15d4d9316fc6a359b2d94333 Mon Sep 17 00:00:00 2001 From: Thomas Maier Date: Sun, 22 Oct 2006 19:17:47 +0200 Subject: sysfs: sysfs_write_file() writes zero terminated data since most of the files in sysfs are text files, it would be nice, if the "store" function called during sysfs_write_file() gets a zero terminated string / data. The current implementation seems not to ensure this. (But only if it is the first time the zeroed buffer page is allocated.) So the buffer can be scanned by sscanf() easily, for example. This patch simply sets a \0 char behind the data in buffer->page. Signed-off-by: Thomas Maier Signed-off-by: Greg Kroah-Hartman diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 298303b..95c1651 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count = PAGE_SIZE - 1; error = copy_from_user(buffer->page,buf,count); buffer->needs_read_fill = 1; + /* if buf is assumed to contain a string, terminate it by \0, + so e.g. sscanf() can scan the string easily */ + buffer->page[count] = 0; return error ? -EFAULT : count; } -- cgit v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index 5d11bbd..a29e685 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 2d9dc35..0a0370c 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index a29e685..75b45a1 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index 75b45a1..e4eaf46 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 3aa3434..a5782e8 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 0a0370c..583a341 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 bcd9cd1..d1c8d28 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 6d5c43d..2129d1b 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -97,6 +97,9 @@ 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 *); extern int __must_check @@ -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 7dd5c0e..744a4b1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -311,6 +311,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name) } /** + * 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 7f20e7b..a192276 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 v0.10.2 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 diff --git a/drivers/base/core.c b/drivers/base/core.c index e4eaf46..e4b530e 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 v0.10.2 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 diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 940ce41..d1df4a0 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 29cd6de..20f47b8 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 v0.10.2 From c957b32406b73ed66d0f20ebab0cab25c848105d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:30:14 -0800 Subject: Documentation/driver-model/platform.txt update/rewrite This is almost a rewrite of the driver-model/platform.txt documentation; the previous text was obsolete (for several years), evidently it never got updated to match the change from being a PC "legacy_bus" to the more widely used core bus for most embedded systems. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt index 5eee3e0..9f0bc3b 100644 --- a/Documentation/driver-model/platform.txt +++ b/Documentation/driver-model/platform.txt @@ -1,99 +1,131 @@ Platform Devices and Drivers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See for the driver model interface to the +platform bus: platform_device, and platform_driver. This pseudo-bus +is used to connect devices on busses with minimal infrastructure, +like those used to integrate peripherals on many system-on-chip +processors, or some "legacy" PC interconnects; as opposed to large +formally specified ones like PCI or USB. + Platform devices ~~~~~~~~~~~~~~~~ Platform devices are devices that typically appear as autonomous entities in the system. This includes legacy port-based devices and -host bridges to peripheral buses. - - -Platform drivers -~~~~~~~~~~~~~~~~ -Drivers for platform devices are typically very simple and -unstructured. Either the device was present at a particular I/O port -and the driver was loaded, or it was not. There was no possibility -of hotplugging or alternative discovery besides probing at a specific -I/O address and expecting a specific response. +host bridges to peripheral buses, and most controllers integrated +into system-on-chip platforms. What they usually have in common +is direct addressing from a CPU bus. Rarely, a platform_device will +be connected through a segment of some other kind of bus; but its +registers will still be directly addressible. +Platform devices are given a name, used in driver binding, and a +list of resources such as addresses and IRQs. -Other Architectures, Modern Firmware, and new Platforms -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -These devices are not always at the legacy I/O ports. This is true on -other architectures and on some modern architectures. In most cases, -the drivers are modified to discover the devices at other well-known -ports for the given platform. However, the firmware in these systems -does usually know where exactly these devices reside, and in some -cases, it's the only way of discovering them. +struct platform_device { + const char *name; + u32 id; + struct device dev; + u32 num_resources; + struct resource *resource; +}; -The Platform Bus -~~~~~~~~~~~~~~~~ -A platform bus has been created to deal with these issues. First and -foremost, it groups all the legacy devices under a common bus, and -gives them a common parent if they don't already have one. - -But, besides the organizational benefits, the platform bus can also -accommodate firmware-based enumeration. - - -Device Discovery +Platform drivers ~~~~~~~~~~~~~~~~ -The platform bus has no concept of probing for devices. Devices -discovery is left up to either the legacy drivers or the -firmware. These entities are expected to notify the platform of -devices that it discovers via the bus's add() callback: - - platform_bus.add(parent,bus_id). - - -Bus IDs -~~~~~~~ -Bus IDs are the canonical names for the devices. There is no globally -standard addressing mechanism for legacy devices. In the IA-32 world, -we have Pnp IDs to use, as well as the legacy I/O ports. However, -neither tell what the device really is or have any meaning on other -platforms. - -Since both PnP IDs and the legacy I/O ports (and other standard I/O -ports for specific devices) have a 1:1 mapping, we map the -platform-specific name or identifier to a generic name (at least -within the scope of the kernel). - -For example, a serial driver might find a device at I/O 0x3f8. The -ACPI firmware might also discover a device with PnP ID (_HID) -PNP0501. Both correspond to the same device and should be mapped to the -canonical name 'serial'. - -The bus_id field should be a concatenation of the canonical name and -the instance of that type of device. For example, the device at I/O -port 0x3f8 should have a bus_id of "serial0". This places the -responsibility of enumerating devices of a particular type up to the -discovery mechanism. But, they are the entity that should know best -(as opposed to the platform bus driver). - - -Drivers -~~~~~~~ -Drivers for platform devices should have a name that is the same as -the canonical name of the devices they support. This allows the -platform bus driver to do simple matching with the basic data -structures to determine if a driver supports a certain device. - -For example, a legacy serial driver should have a name of 'serial' and -register itself with the platform bus. - - -Driver Binding -~~~~~~~~~~~~~~ -Legacy drivers assume they are bound to the device once they start up -and probe an I/O port. Divorcing them from this will be a difficult -process. However, that shouldn't prevent us from implementing -firmware-based enumeration. - -The firmware should notify the platform bus about devices before the -legacy drivers have had a chance to load. Once the drivers are loaded, -they driver model core will attempt to bind the driver to any -previously-discovered devices. Once that has happened, it will be free -to discover any other devices it pleases. +Platform drivers follow the standard driver model convention, where +discovery/enumeration is handled outside the drivers, and drivers +provide probe() and remove() methods. They support power management +and shutdown notifications using the standard conventions. + +struct platform_driver { + int (*probe)(struct platform_device *); + int (*remove)(struct platform_device *); + void (*shutdown)(struct platform_device *); + int (*suspend)(struct platform_device *, pm_message_t state); + int (*suspend_late)(struct platform_device *, pm_message_t state); + int (*resume_early)(struct platform_device *); + int (*resume)(struct platform_device *); + struct device_driver driver; +}; + +Note that probe() should general verify that the specified device hardware +actually exists; sometimes platform setup code can't be sure. The probing +can use device resources, including clocks, and device platform_data. + +Platform drivers register themselves the normal way: + + int platform_driver_register(struct platform_driver *drv); + +Or, in common situations where the device is known not to be hot-pluggable, +the probe() routine can live in an init section to reduce the driver's +runtime memory footprint: + + int platform_driver_probe(struct platform_driver *drv, + int (*probe)(struct platform_device *)) + + +Device Enumeration +~~~~~~~~~~~~~~~~~~ +As a rule, platform specific (and often board-specific) setup code wil +register platform devices: + + int platform_device_register(struct platform_device *pdev); + + int platform_add_devices(struct platform_device **pdevs, int ndev); + +The general rule is to register only those devices that actually exist, +but in some cases extra devices might be registered. For example, a kernel +might be configured to work with an external network adapter that might not +be populated on all boards, or likewise to work with an integrated controller +that some boards might not hook up to any peripherals. + +In some cases, boot firmware will export tables describing the devices +that are populated on a given board. Without such tables, often the +only way for system setup code to set up the correct devices is to build +a kernel for a specific target board. Such board-specific kernels are +common with embedded and custom systems development. + +In many cases, the memory and IRQ resources associated with the platform +device are not enough to let the device's driver work. Board setup code +will often provide additional information using the device's platform_data +field to hold additional information. + +Embedded systems frequently need one or more clocks for platform devices, +which are normally kept off until they're actively needed (to save power). +System setup also associates those clocks with the device, so that that +calls to clk_get(&pdev->dev, clock_name) return them as needed. + + +Device Naming and Driver Binding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The platform_device.dev.bus_id is the canonical name for the devices. +It's built from two components: + + * platform_device.name ... which is also used to for driver matching. + + * platform_device.id ... the device instance number, or else "-1" + to indicate there's only one. + +These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and +"serial/3" indicates bus_id "serial.3"; both would use the platform_driver +named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id) +and use the platform_driver called "my_rtc". + +Driver binding is performed automatically by the driver core, invoking +driver probe() after finding a match between device and driver. If the +probe() succeeds, the driver and device are bound as usual. There are +three different ways to find such a match: + + - Whenever a device is registered, the drivers for that bus are + checked for matches. Platform devices should be registered very + early during system boot. + + - When a driver is registered using platform_driver_register(), all + unbound devices on that bus are checked for matches. Drivers + usually register later during booting, or by module loading. + + - Registering a driver using platform_driver_probe() works just like + using platform_driver_register(), except that the the driver won't + be probed later if another device registers. (Which is OK, since + this interface is only for use with non-hotpluggable devices.) -- cgit v0.10.2 From e17e0f51aeea4e59c7e450a1c0f26605b91c1260 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 24 Nov 2006 12:15:25 +0100 Subject: Driver core: show drivers in /sys/module/ Show the drivers, which belong to the module: $ ls -l /sys/module/usbcore/drivers/ hub -> ../../../bus/usb/drivers/hub usb -> ../../../bus/usb/drivers/usb usbfs -> ../../../bus/usb/drivers/usbfs Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/module.h b/include/linux/module.h index d1d00ce..9258ffd 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -264,6 +264,7 @@ struct module struct module_attribute *modinfo_attrs; const char *version; const char *srcversion; + struct kobject *drivers_dir; /* Exported symbols */ const struct kernel_symbol *syms; diff --git a/kernel/module.c b/kernel/module.c index f016656..45e01cb 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod, goto out; kobj_set_kset_s(&mod->mkobj, module_subsys); mod->mkobj.mod = mod; - err = kobject_register(&mod->mkobj.kobj); + + /* delay uevent until full sysfs population */ + kobject_init(&mod->mkobj.kobj); + err = kobject_add(&mod->mkobj.kobj); if (err) goto out; + mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers"); + if (!mod->drivers_dir) + goto out_unreg; + err = module_param_sysfs_setup(mod, kparam, num_params); if (err) - goto out_unreg; + goto out_unreg_drivers; err = module_add_modinfo_attrs(mod); if (err) - goto out_unreg; + goto out_unreg_param; + kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); return 0; +out_unreg_drivers: + kobject_unregister(mod->drivers_dir); +out_unreg_param: + module_param_sysfs_remove(mod); out_unreg: - kobject_unregister(&mod->mkobj.kobj); + kobject_del(&mod->mkobj.kobj); + kobject_put(&mod->mkobj.kobj); out: return err; } @@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod) { module_remove_modinfo_attrs(mod); module_param_sysfs_remove(mod); + kobject_unregister(mod->drivers_dir); kobject_unregister(&mod->mkobj.kobj); } @@ -2275,11 +2289,14 @@ void print_modules(void) void module_add_driver(struct module *mod, struct device_driver *drv) { + int no_warn; + if (!mod || !drv) return; - /* Don't check return code; this call is idempotent */ - sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); + /* Don't check return codes; these calls are idempotent */ + no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); + no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name); } EXPORT_SYMBOL(module_add_driver); @@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv) if (!drv) return; sysfs_remove_link(&drv->kobj, "module"); + if (drv->owner && drv->owner->drivers_dir) + sysfs_remove_link(drv->owner->drivers_dir, drv->name); } EXPORT_SYMBOL(module_remove_driver); -- cgit v0.10.2 From 0e5fdca7622eb950f42f97a1970670e00a739175 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 2 Dec 2006 00:03:47 +0100 Subject: [ARM] 3971/1: xsc3: get rid of L_PTE_COHERENT Merge L_PTE_COHERENT with L_PTE_SHARED and free up a L_PTE_* bit. Signed-off-by: Lennert Buytenhek Signed-off-by: Dan Williams Signed-off-by: Russell King diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index f866bf6..445bc3b 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -265,7 +265,7 @@ static void __init build_mem_type_table(void) if (arch_is_coherent()) { if (cpu_is_xsc3()) { mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT; + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; } } diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index c4d778a..85c3523 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -371,8 +371,10 @@ ENTRY(cpu_xsc3_switch_mm) ENTRY(cpu_xsc3_set_pte) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0xdf0 @ Keep C, B, coherency bits + bic r2, r1, #0xff0 @ Keep C, B bits orr r2, r2, #PTE_TYPE_EXT @ extended page + tst r1, #L_PTE_SHARED @ Shared? + orrne r2, r2, #0x200 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index ed8cb59..88cd5c7 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -169,8 +169,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define L_PTE_WRITE (1 << 5) #define L_PTE_EXEC (1 << 6) #define L_PTE_DIRTY (1 << 7) -#define L_PTE_COHERENT (1 << 9) /* I/O coherent (xsc3) */ -#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */ +#define L_PTE_SHARED (1 << 10) /* shared(v6), coherent(xsc3) */ #define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */ #ifndef __ASSEMBLY__ -- cgit v0.10.2 From f5236225a3858b505221a59233af1f1158be9139 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Dec 2006 19:31:42 +0100 Subject: [ARM] 3967/1: xsc3: make branch predication configurable on xsc3 Remove BTB_ENABLE from proc-xsc3.S On some early revisions of xsc3 enabling the branch target buffer can cause crashes, see erratum #42. Cc: Lennert Buytenhek Signed-off-by: Dan Williams Signed-off-by: Russell King diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c0bfb82..efebd60 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -580,7 +580,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 + depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 85c3523..1ef564d 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -57,11 +57,6 @@ #define L2_CACHE_ENABLE 1 /* - * Enable the Branch Target Buffer (can cause crashes, see erratum #42.) - */ -#define BTB_ENABLE 0 - -/* * This macro is used to wait for a CP15 write and is needed * when we have to ensure that the last operation to the co-pro * was completed before continuing with operation. @@ -434,9 +429,7 @@ __xsc3_setup: mrc p15, 0, r0, c1, c0, 0 @ get control register bic r0, r0, r5 @ .... .... .... ..A. orr r0, r0, r6 @ .... .... .... .C.M -#if BTB_ENABLE orr r0, r0, #0x00000800 @ ..VI Z..S .... .... -#endif #if L2_CACHE_ENABLE orr r0, r0, #0x04000000 @ L2 enable #endif -- cgit v0.10.2 From da66116eef7da8557762c9b5efdc435bc0afecfa Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:24:28 +0100 Subject: [2.6 patch] make ocfs2_create_new_lock() static This patch makes the needlessly global ocfs2_create_new_lock() static. Signed-off-by: Adrian Bunk Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 8801e41..ff8d3db 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1063,10 +1063,10 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb, mlog_exit_void(); } -int ocfs2_create_new_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int ex, - int local) +static int ocfs2_create_new_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int ex, + int local) { int level = ex ? LKM_EXMODE : LKM_PRMODE; unsigned long flags; diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 4a27693..75c49ce 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h @@ -68,8 +68,6 @@ void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl, u64 parent, struct inode *inode); void ocfs2_lock_res_free(struct ocfs2_lock_res *res); int ocfs2_create_new_inode_locks(struct inode *inode); -int ocfs2_create_new_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, int ex, int local); int ocfs2_drop_inode_locks(struct inode *inode); int ocfs2_data_lock_full(struct inode *inode, int write, -- cgit v0.10.2 From f5a923d1ba648bfb3cc922c66981fc8e3280f57f Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 28 Nov 2006 15:13:18 -0800 Subject: ocfs2: fix format warnings in dlm_alloc_pagevec() Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 8d1065f..f6cdab3 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -68,7 +68,8 @@ static void **dlm_alloc_pagevec(int pages) goto out_free; mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n", - pages, DLM_HASH_PAGES, (unsigned long)DLM_BUCKETS_PER_PAGE); + pages, (unsigned long)DLM_HASH_PAGES, + (unsigned long)DLM_BUCKETS_PER_PAGE); return vec; out_free: dlm_free_pagevec(vec, i); -- cgit v0.10.2 From 01ddf1e186b3b12b38c9e44912e0fd6a1cbc882b Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 13:54:39 -0700 Subject: ocfs2: remove unused ocfs2_journal_handle field max_buffs was just being set and not actually used. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index fd9734d..e26cd0c 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -124,7 +124,6 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) return NULL; } - retval->max_buffs = 0; retval->num_locks = 0; retval->k_handle = NULL; @@ -172,8 +171,6 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, goto done_free; } - handle->max_buffs = max_buffs; - down_read(&osb->journal->j_trans_barrier); /* actually start the transaction now */ @@ -353,9 +350,7 @@ int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, mlog_errno(status); goto bail; } - handle->max_buffs = nblocks; - } else - handle->max_buffs += nblocks; + } status = 0; bail: diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 2f3a6ac..35ae835 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -144,7 +144,6 @@ struct ocfs2_journal_handle { handle_t *k_handle; /* kernel handle. */ struct ocfs2_journal *journal; u32 flags; /* see flags below. */ - int max_buffs; /* Buffs reserved by this handle */ /* The following two fields are for ocfs2_handle_add_lock */ int num_locks; -- cgit v0.10.2 From 1fc581467e52546195c7ee8233a34d63c1cc1322 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 14:15:36 -0700 Subject: ocfs2: have ocfs2_extend_trans() take handle_t No reason to use our wrapper struct in this function, so take the handle_t directly. Also fixes a bug where we were incorrectly setting the handle to NULL in case of a failure from journal_restart() Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f43bc5f..74b93f9 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1074,7 +1074,7 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, /* TODO: Perhaps we can calculate the bulk of the * credits up front rather than extending like * this. */ - status = ocfs2_extend_trans(handle, + status = ocfs2_extend_trans(handle->k_handle, OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC); if (status < 0) { mlog_errno(status); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 1be74c4..d8bd2c3 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -566,7 +566,7 @@ restarted_transaction: credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add); - status = ocfs2_extend_trans(handle, credits); + status = ocfs2_extend_trans(handle->k_handle, credits); if (status < 0) { /* handle still has to be committed at * this point. */ diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index e26cd0c..7c0c57a 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -323,20 +323,18 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) * good because transaction ids haven't yet been recorded on the * cluster locks associated with this handle. */ -int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, - int nblocks) +int ocfs2_extend_trans(handle_t *handle, int nblocks) { int status; BUG_ON(!handle); - BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); BUG_ON(!nblocks); mlog_entry_void(); mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); - status = journal_extend(handle->k_handle, nblocks); + status = journal_extend(handle, nblocks); if (status < 0) { mlog_errno(status); goto bail; @@ -344,9 +342,8 @@ int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, if (status > 0) { mlog(0, "journal_extend failed, trying journal_restart\n"); - status = journal_restart(handle->k_handle, nblocks); + status = journal_restart(handle, nblocks); if (status < 0) { - handle->k_handle = NULL; mlog_errno(status); goto bail; } diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 35ae835..9f3d79d 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -264,8 +264,7 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, int max_buffs); void ocfs2_commit_trans(struct ocfs2_journal_handle *handle); -int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, - int nblocks); +int ocfs2_extend_trans(handle_t *handle, int nblocks); /* * Create access is for when we get a newly created buffer and we're -- cgit v0.10.2 From c161f89be7d57af863e434e9b15afaa863343a7a Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 15:11:36 -0700 Subject: ocfs2: remove ocfs2_journal_handle flags field Callers can set h_sync directly on the handle_t, whether a transaction has been started or not can be determined via the existence of the handle_t on the struct ocfs2_journal_handle. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 7c0c57a..ca6f209 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -190,7 +190,6 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, } atomic_inc(&(osb->journal->j_num_trans)); - handle->flags |= OCFS2_HANDLE_STARTED; mlog_exit_ptr(handle); return handle; @@ -247,8 +246,6 @@ static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle) { mlog_entry_void(); - BUG_ON(handle->flags & OCFS2_HANDLE_STARTED); - ocfs2_handle_unlock_inodes(handle); /* You are allowed to add journal locks before the transaction * has started. */ @@ -269,7 +266,7 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) BUG_ON(!handle); - if (!(handle->flags & OCFS2_HANDLE_STARTED)) { + if (!handle->k_handle) { ocfs2_commit_unstarted_handle(handle); mlog_exit_void(); return; @@ -285,11 +282,6 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) if (handle->k_handle) { jbd_handle = handle->k_handle; - if (handle->flags & OCFS2_HANDLE_SYNC) - jbd_handle->h_sync = 1; - else - jbd_handle->h_sync = 0; - /* actually stop the transaction. if we've set h_sync, * it'll have been committed when we return */ retval = journal_stop(jbd_handle); @@ -366,7 +358,6 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, BUG_ON(!inode); BUG_ON(!handle); BUG_ON(!bh); - BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", (unsigned long long)bh->b_blocknr, type, @@ -421,8 +412,6 @@ int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, { int status; - BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); - mlog_entry("(bh->b_blocknr=%llu)\n", (unsigned long long)bh->b_blocknr); diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 9f3d79d..6b5d548 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -143,7 +143,6 @@ struct ocfs2_journal_lock { struct ocfs2_journal_handle { handle_t *k_handle; /* kernel handle. */ struct ocfs2_journal *journal; - u32 flags; /* see flags below. */ /* The following two fields are for ocfs2_handle_add_lock */ int num_locks; @@ -154,22 +153,6 @@ struct ocfs2_journal_handle { struct list_head inode_list; }; -#define OCFS2_HANDLE_STARTED 1 -/* should we sync-commit this handle? */ -#define OCFS2_HANDLE_SYNC 2 -static inline int ocfs2_handle_started(struct ocfs2_journal_handle *handle) -{ - return handle->flags & OCFS2_HANDLE_STARTED; -} - -static inline void ocfs2_handle_set_sync(struct ocfs2_journal_handle *handle, int sync) -{ - if (sync) - handle->flags |= OCFS2_HANDLE_SYNC; - else - handle->flags &= ~OCFS2_HANDLE_SYNC; -} - /* Exported only for the journal struct init code in super.c. Do not call. */ void ocfs2_complete_recovery(void *data); diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 1f17a4d..f2f384d 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -423,7 +423,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, } /* we want the bitmap change to be recorded on disk asap */ - ocfs2_handle_set_sync(handle, 1); + handle->k_handle->h_sync = 1; status = ocfs2_sync_local_to_main(osb, handle, alloc, main_bm_inode, main_bm_bh); @@ -465,7 +465,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, BUG_ON(!passed_handle); BUG_ON(!ac); - BUG_ON(passed_handle->flags & OCFS2_HANDLE_STARTED); + BUG_ON(passed_handle->k_handle); local_alloc_inode = ocfs2_get_system_file_inode(osb, diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 9d91e66..3209340 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -414,7 +414,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, mlog_entry_void(); - BUG_ON(handle->flags & OCFS2_HANDLE_STARTED); + BUG_ON(handle->k_handle); ocfs2_handle_add_inode(handle, alloc_inode); status = ocfs2_meta_lock(alloc_inode, handle, &bh, 1); -- cgit v0.10.2 From 8898a5a58fb2a2f78a15b046588b5b3adccb82c4 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 15:42:08 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock() in localalloc.c Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index f2f384d..75f09f1 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -196,7 +196,7 @@ bail: void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) { int status; - struct ocfs2_journal_handle *handle = NULL; + struct ocfs2_journal_handle *handle; struct inode *local_alloc_inode = NULL; struct buffer_head *bh = NULL; struct buffer_head *main_bm_bh = NULL; @@ -207,7 +207,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) mlog_entry_void(); if (osb->local_alloc_state == OCFS2_LA_UNUSED) - goto bail; + goto out; local_alloc_inode = ocfs2_get_system_file_inode(osb, @@ -216,40 +216,34 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) if (!local_alloc_inode) { status = -ENOENT; mlog_errno(status); - goto bail; + goto out; } osb->local_alloc_state = OCFS2_LA_DISABLED; - handle = ocfs2_alloc_handle(osb); - if (!handle) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - main_bm_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); if (!main_bm_inode) { status = -EINVAL; mlog_errno(status); - goto bail; + goto out; } - ocfs2_handle_add_inode(handle, main_bm_inode); - status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1); + mutex_lock(&main_bm_inode->i_mutex); + + status = ocfs2_meta_lock(main_bm_inode, NULL, &main_bm_bh, 1); if (status < 0) { mlog_errno(status); - goto bail; + goto out_mutex; } /* WINDOW_MOVE_CREDITS is a bit heavy... */ - handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { mlog_errno(PTR_ERR(handle)); handle = NULL; - goto bail; + goto out_unlock; } bh = osb->local_alloc_bh; @@ -258,7 +252,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) alloc_copy = kmalloc(bh->b_size, GFP_KERNEL); if (!alloc_copy) { status = -ENOMEM; - goto bail; + goto out_commit; } memcpy(alloc_copy, alloc, bh->b_size); @@ -266,7 +260,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); - goto bail; + goto out_commit; } ocfs2_clear_local_alloc(alloc); @@ -274,7 +268,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) status = ocfs2_journal_dirty(handle, bh); if (status < 0) { mlog_errno(status); - goto bail; + goto out_commit; } brelse(bh); @@ -286,16 +280,20 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) if (status < 0) mlog_errno(status); -bail: - if (handle) - ocfs2_commit_trans(handle); +out_commit: + ocfs2_commit_trans(handle); +out_unlock: if (main_bm_bh) brelse(main_bm_bh); - if (main_bm_inode) - iput(main_bm_inode); + ocfs2_meta_unlock(main_bm_inode, 1); +out_mutex: + mutex_unlock(&main_bm_inode->i_mutex); + iput(main_bm_inode); + +out: if (local_alloc_inode) iput(local_alloc_inode); @@ -385,41 +383,35 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, struct ocfs2_dinode *alloc) { int status; - struct ocfs2_journal_handle *handle = NULL; + struct ocfs2_journal_handle *handle; struct buffer_head *main_bm_bh = NULL; - struct inode *main_bm_inode = NULL; + struct inode *main_bm_inode; mlog_entry_void(); - handle = ocfs2_alloc_handle(osb); - if (!handle) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - main_bm_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); if (!main_bm_inode) { status = -EINVAL; mlog_errno(status); - goto bail; + goto out; } - ocfs2_handle_add_inode(handle, main_bm_inode); - status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1); + mutex_lock(&main_bm_inode->i_mutex); + + status = ocfs2_meta_lock(main_bm_inode, NULL, &main_bm_bh, 1); if (status < 0) { mlog_errno(status); - goto bail; + goto out_mutex; } - handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); - goto bail; + goto out_unlock; } /* we want the bitmap change to be recorded on disk asap */ @@ -430,16 +422,20 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, if (status < 0) mlog_errno(status); -bail: - if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(handle); + +out_unlock: + ocfs2_meta_unlock(main_bm_inode, 1); + +out_mutex: + mutex_unlock(&main_bm_inode->i_mutex); if (main_bm_bh) brelse(main_bm_bh); - if (main_bm_inode) - iput(main_bm_inode); + iput(main_bm_inode); +out: mlog_exit(status); return status; } -- cgit v0.10.2 From e08dc8b9808f06d412904db4d67434bf19984752 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 15:58:48 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock() in __ocfs2_flush_truncate_log() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 74b93f9..c8a4727 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1113,7 +1113,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) { int status; unsigned int num_to_flush; - struct ocfs2_journal_handle *handle = NULL; + struct ocfs2_journal_handle *handle; struct inode *tl_inode = osb->osb_tl_inode; struct inode *data_alloc_inode = NULL; struct buffer_head *tl_bh = osb->osb_tl_bh; @@ -1130,7 +1130,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) if (!OCFS2_IS_VALID_DINODE(di)) { OCFS2_RO_ON_INVALID_DINODE(osb->sb, di); status = -EIO; - goto bail; + goto out; } num_to_flush = le16_to_cpu(tl->tl_used); @@ -1138,14 +1138,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno); if (!num_to_flush) { status = 0; - goto bail; - } - - handle = ocfs2_alloc_handle(osb); - if (!handle) { - status = -ENOMEM; - mlog_errno(status); - goto bail; + goto out; } data_alloc_inode = ocfs2_get_system_file_inode(osb, @@ -1154,41 +1147,40 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) if (!data_alloc_inode) { status = -EINVAL; mlog(ML_ERROR, "Could not get bitmap inode!\n"); - goto bail; + goto out; } - ocfs2_handle_add_inode(handle, data_alloc_inode); - status = ocfs2_meta_lock(data_alloc_inode, handle, &data_alloc_bh, 1); + mutex_lock(&data_alloc_inode->i_mutex); + + status = ocfs2_meta_lock(data_alloc_inode, NULL, &data_alloc_bh, 1); if (status < 0) { mlog_errno(status); - goto bail; + goto out_mutex; } - handle = ocfs2_start_trans(osb, handle, OCFS2_TRUNCATE_LOG_UPDATE); + handle = ocfs2_start_trans(osb, NULL, OCFS2_TRUNCATE_LOG_UPDATE); if (IS_ERR(handle)) { status = PTR_ERR(handle); - handle = NULL; mlog_errno(status); - goto bail; + goto out_unlock; } status = ocfs2_replay_truncate_records(osb, handle, data_alloc_inode, data_alloc_bh); - if (status < 0) { + if (status < 0) mlog_errno(status); - goto bail; - } -bail: - if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(handle); - if (data_alloc_inode) - iput(data_alloc_inode); +out_unlock: + brelse(data_alloc_bh); + ocfs2_meta_unlock(data_alloc_inode, 1); - if (data_alloc_bh) - brelse(data_alloc_bh); +out_mutex: + mutex_unlock(&data_alloc_inode->i_mutex); + iput(data_alloc_inode); +out: mlog_exit(status); return status; } -- cgit v0.10.2 From e3a821385984e57d5dd1b0e7292761abb0ea4dd9 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 16:04:17 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock() in ocfs2_mknod() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index a57b751..702f0c3 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -333,6 +333,13 @@ static int ocfs2_mknod(struct inode *dir, /* get our super block */ osb = OCFS2_SB(dir->i_sb); + status = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); + if (status < 0) { + if (status != -ENOENT) + mlog_errno(status); + return status; + } + handle = ocfs2_alloc_handle(osb); if (handle == NULL) { status = -ENOMEM; @@ -340,13 +347,6 @@ static int ocfs2_mknod(struct inode *dir, goto leave; } - status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1); - if (status < 0) { - if (status != -ENOENT) - mlog_errno(status); - goto leave; - } - if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { status = -EMLINK; goto leave; @@ -455,6 +455,8 @@ leave: if (handle) ocfs2_commit_trans(handle); + ocfs2_meta_unlock(dir, 1); + if (status == -ENOSPC) mlog(0, "Disk is full\n"); -- cgit v0.10.2 From 123a9643408882620347cc2c82f24e57dab05f44 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 16:48:23 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock() in ocfs2_link() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 702f0c3..79f5130 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -655,7 +655,7 @@ static int ocfs2_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { - struct ocfs2_journal_handle *handle = NULL; + struct ocfs2_journal_handle *handle; struct inode *inode = old_dentry->d_inode; int err; struct buffer_head *fe_bh = NULL; @@ -668,68 +668,60 @@ static int ocfs2_link(struct dentry *old_dentry, old_dentry->d_name.len, old_dentry->d_name.name, dentry->d_name.len, dentry->d_name.name); - if (S_ISDIR(inode->i_mode)) { - err = -EPERM; - goto bail; - } - - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - err = -ENOMEM; - goto bail; - } + if (S_ISDIR(inode->i_mode)) + return -EPERM; - err = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1); + err = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); if (err < 0) { if (err != -ENOENT) mlog_errno(err); - goto bail; + return err; } if (!dir->i_nlink) { err = -ENOENT; - goto bail; + goto out; } err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, dentry->d_name.len); if (err) - goto bail; + goto out; err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, dentry->d_name.name, dentry->d_name.len, &de_bh); if (err < 0) { mlog_errno(err); - goto bail; + goto out; } - err = ocfs2_meta_lock(inode, handle, &fe_bh, 1); + err = ocfs2_meta_lock(inode, NULL, &fe_bh, 1); if (err < 0) { if (err != -ENOENT) mlog_errno(err); - goto bail; + goto out; } fe = (struct ocfs2_dinode *) fe_bh->b_data; if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) { err = -EMLINK; - goto bail; + goto out_unlock_inode; } - handle = ocfs2_start_trans(osb, handle, OCFS2_LINK_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_LINK_CREDITS); if (IS_ERR(handle)) { err = PTR_ERR(handle); handle = NULL; mlog_errno(err); - goto bail; + goto out_unlock_inode; } err = ocfs2_journal_access(handle, inode, fe_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (err < 0) { mlog_errno(err); - goto bail; + goto out_commit; } inc_nlink(inode); @@ -743,7 +735,7 @@ static int ocfs2_link(struct dentry *old_dentry, le16_add_cpu(&fe->i_links_count, -1); drop_nlink(inode); mlog_errno(err); - goto bail; + goto out_commit; } err = ocfs2_add_entry(handle, dentry, inode, @@ -753,21 +745,27 @@ static int ocfs2_link(struct dentry *old_dentry, le16_add_cpu(&fe->i_links_count, -1); drop_nlink(inode); mlog_errno(err); - goto bail; + goto out_commit; } err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); if (err) { mlog_errno(err); - goto bail; + goto out_commit; } atomic_inc(&inode->i_count); dentry->d_op = &ocfs2_dentry_ops; d_instantiate(dentry, inode); -bail: - if (handle) - ocfs2_commit_trans(handle); + +out_commit: + ocfs2_commit_trans(handle); +out_unlock_inode: + ocfs2_meta_unlock(inode, 1); + +out: + ocfs2_meta_unlock(dir, 1); + if (de_bh) brelse(de_bh); if (fe_bh) -- cgit v0.10.2 From 5098c27bb8cd89e30d909ac9d76e305d334dadaf Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 5 Oct 2006 18:12:57 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock() in orphan dir code Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 79f5130..dc2e89a 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -112,7 +112,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, struct inode *inode2); static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + struct inode **ret_orphan_dir, struct inode *inode, char *name, struct buffer_head **de_bh); @@ -122,7 +122,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct inode *inode, struct ocfs2_dinode *fe, char *name, - struct buffer_head *de_bh); + struct buffer_head *de_bh, + struct inode *orphan_dir_inode); static int ocfs2_create_symlink_data(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, @@ -813,6 +814,7 @@ static int ocfs2_unlink(struct inode *dir, { int status; struct inode *inode = dentry->d_inode; + struct inode *orphan_dir = NULL; struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); u64 blkno; struct ocfs2_dinode *fe = NULL; @@ -895,7 +897,7 @@ static int ocfs2_unlink(struct inode *dir, } if (inode_is_unlinkable(inode)) { - status = ocfs2_prepare_orphan_dir(osb, handle, inode, + status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, inode, orphan_name, &orphan_entry_bh); if (status < 0) { @@ -923,7 +925,7 @@ static int ocfs2_unlink(struct inode *dir, if (inode_is_unlinkable(inode)) { status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, - orphan_entry_bh); + orphan_entry_bh, orphan_dir); if (status < 0) { mlog_errno(status); goto leave; @@ -962,6 +964,13 @@ leave: if (handle) ocfs2_commit_trans(handle); + if (orphan_dir) { + /* This was locked for us in ocfs2_prepare_orphan_dir() */ + ocfs2_meta_unlock(orphan_dir, 1); + mutex_unlock(&orphan_dir->i_mutex); + iput(orphan_dir); + } + if (fe_bh) brelse(fe_bh); @@ -1053,6 +1062,7 @@ static int ocfs2_rename(struct inode *old_dir, int status = 0, rename_lock = 0; struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; + struct inode *orphan_dir = NULL; struct ocfs2_dinode *newfe = NULL; char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; struct buffer_head *orphan_entry_bh = NULL; @@ -1252,7 +1262,7 @@ static int ocfs2_rename(struct inode *old_dir, (unsigned long long)newfe_bh->b_blocknr : 0ULL); if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { - status = ocfs2_prepare_orphan_dir(osb, handle, + status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, new_inode, orphan_name, &orphan_entry_bh); @@ -1307,7 +1317,7 @@ static int ocfs2_rename(struct inode *old_dir, (newfe->i_links_count == cpu_to_le16(1))){ status = ocfs2_orphan_add(osb, handle, new_inode, newfe, orphan_name, - orphan_entry_bh); + orphan_entry_bh, orphan_dir); if (status < 0) { mlog_errno(status); goto bail; @@ -1426,6 +1436,13 @@ bail: if (handle) ocfs2_commit_trans(handle); + if (orphan_dir) { + /* This was locked for us in ocfs2_prepare_orphan_dir() */ + ocfs2_meta_unlock(orphan_dir, 1); + mutex_unlock(&orphan_dir->i_mutex); + iput(orphan_dir); + } + if (new_inode) sync_mapping_buffers(old_inode->i_mapping); @@ -2085,19 +2102,19 @@ bail: } static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + struct inode **ret_orphan_dir, struct inode *inode, char *name, struct buffer_head **de_bh) { - struct inode *orphan_dir_inode = NULL; + struct inode *orphan_dir_inode; struct buffer_head *orphan_dir_bh = NULL; int status = 0; status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); if (status < 0) { mlog_errno(status); - goto leave; + return status; } orphan_dir_inode = ocfs2_get_system_file_inode(osb, @@ -2106,11 +2123,12 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, if (!orphan_dir_inode) { status = -ENOENT; mlog_errno(status); - goto leave; + return status; } - ocfs2_handle_add_inode(handle, orphan_dir_inode); - status = ocfs2_meta_lock(orphan_dir_inode, handle, &orphan_dir_bh, 1); + mutex_lock(&orphan_dir_inode->i_mutex); + + status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1); if (status < 0) { mlog_errno(status); goto leave; @@ -2120,13 +2138,19 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, orphan_dir_bh, name, OCFS2_ORPHAN_NAMELEN, de_bh); if (status < 0) { + ocfs2_meta_unlock(orphan_dir_inode, 1); + mlog_errno(status); goto leave; } + *ret_orphan_dir = orphan_dir_inode; + leave: - if (orphan_dir_inode) + if (status) { + mutex_unlock(&orphan_dir_inode->i_mutex); iput(orphan_dir_inode); + } if (orphan_dir_bh) brelse(orphan_dir_bh); @@ -2140,24 +2164,15 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct inode *inode, struct ocfs2_dinode *fe, char *name, - struct buffer_head *de_bh) + struct buffer_head *de_bh, + struct inode *orphan_dir_inode) { - struct inode *orphan_dir_inode = NULL; struct buffer_head *orphan_dir_bh = NULL; int status = 0; struct ocfs2_dinode *orphan_fe; mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); - orphan_dir_inode = ocfs2_get_system_file_inode(osb, - ORPHAN_DIR_SYSTEM_INODE, - osb->slot_num); - if (!orphan_dir_inode) { - status = -ENOENT; - mlog_errno(status); - goto leave; - } - status = ocfs2_read_block(osb, OCFS2_I(orphan_dir_inode)->ip_blkno, &orphan_dir_bh, OCFS2_BH_CACHED, @@ -2209,9 +2224,6 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); leave: - if (orphan_dir_inode) - iput(orphan_dir_inode); - if (orphan_dir_bh) brelse(orphan_dir_bh); -- cgit v0.10.2 From 30a4f5e86bc7bc388ce808117e7722706f739602 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 11:49:45 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_unlink() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index dc2e89a..f64cff0 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -813,6 +813,7 @@ static int ocfs2_unlink(struct inode *dir, struct dentry *dentry) { int status; + int child_locked = 0; struct inode *inode = dentry->d_inode; struct inode *orphan_dir = NULL; struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); @@ -835,22 +836,14 @@ static int ocfs2_unlink(struct inode *dir, if (inode == osb->root_inode) { mlog(0, "Cannot delete the root directory\n"); - status = -EPERM; - goto leave; - } - - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto leave; + return -EPERM; } - status = ocfs2_meta_lock(dir, handle, &parent_node_bh, 1); + status = ocfs2_meta_lock(dir, NULL, &parent_node_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); - goto leave; + return status; } status = ocfs2_find_files_on_disk(dentry->d_name.name, @@ -871,12 +864,13 @@ static int ocfs2_unlink(struct inode *dir, goto leave; } - status = ocfs2_meta_lock(inode, handle, &fe_bh, 1); + status = ocfs2_meta_lock(inode, NULL, &fe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); goto leave; } + child_locked = 1; if (S_ISDIR(inode->i_mode)) { if (!ocfs2_empty_dir(inode)) { @@ -906,7 +900,7 @@ static int ocfs2_unlink(struct inode *dir, } } - handle = ocfs2_start_trans(osb, handle, OCFS2_UNLINK_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_UNLINK_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -964,6 +958,11 @@ leave: if (handle) ocfs2_commit_trans(handle); + if (child_locked) + ocfs2_meta_unlock(inode, 1); + + ocfs2_meta_unlock(dir, 1); + if (orphan_dir) { /* This was locked for us in ocfs2_prepare_orphan_dir() */ ocfs2_meta_unlock(orphan_dir, 1); -- cgit v0.10.2 From 6d8fc40e63401be065b0aa98dfa4246deca04b8c Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 11:54:33 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_symlink() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f64cff0..7e9da94 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -1603,19 +1603,12 @@ static int ocfs2_symlink(struct inode *dir, credits = ocfs2_calc_symlink_credits(sb); - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - /* lock the parent directory */ - status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1); + status = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); - goto bail; + return status; } dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; @@ -1638,6 +1631,13 @@ static int ocfs2_symlink(struct inode *dir, goto bail; } + handle = ocfs2_alloc_handle(osb); + if (handle == NULL) { + status = -ENOMEM; + mlog_errno(status); + goto bail; + } + status = ocfs2_reserve_new_inode(osb, handle, &inode_ac); if (status < 0) { if (status != -ENOSPC) @@ -1734,6 +1734,9 @@ static int ocfs2_symlink(struct inode *dir, bail: if (handle) ocfs2_commit_trans(handle); + + ocfs2_meta_unlock(dir, 1); + if (new_fe_bh) brelse(new_fe_bh); if (parent_fe_bh) -- cgit v0.10.2 From 8d5596c687c49c1d8812c3456946dec15d069139 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 15:04:51 -0700 Subject: ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_rename() Take and drop the locks directly. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 7e9da94..5bd5f99 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -104,13 +104,6 @@ static int ocfs2_fill_new_dir(struct ocfs2_super *osb, struct buffer_head *fe_bh, struct ocfs2_alloc_context *data_ac); -static int ocfs2_double_lock(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, - struct buffer_head **bh1, - struct inode *inode1, - struct buffer_head **bh2, - struct inode *inode2); - static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, struct inode **ret_orphan_dir, struct inode *inode, @@ -992,7 +985,6 @@ leave: * if they have the same id, then the 1st one is the only one locked. */ static int ocfs2_double_lock(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct buffer_head **bh1, struct inode *inode1, struct buffer_head **bh2, @@ -1008,8 +1000,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, (unsigned long long)oi1->ip_blkno, (unsigned long long)oi2->ip_blkno); - BUG_ON(!handle); - if (*bh1) *bh1 = NULL; if (*bh2) @@ -1029,25 +1019,41 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, inode1 = tmpinode; } /* lock id2 */ - status = ocfs2_meta_lock(inode2, handle, bh2, 1); + status = ocfs2_meta_lock(inode2, NULL, bh2, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); goto bail; } } + /* lock id1 */ - status = ocfs2_meta_lock(inode1, handle, bh1, 1); + status = ocfs2_meta_lock(inode1, NULL, bh1, 1); if (status < 0) { + /* + * An error return must mean that no cluster locks + * were held on function exit. + */ + if (oi1->ip_blkno != oi2->ip_blkno) + ocfs2_meta_unlock(inode2, 1); + if (status != -ENOENT) mlog_errno(status); - goto bail; } + bail: mlog_exit(status); return status; } +static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2) +{ + ocfs2_meta_unlock(inode1, 1); + + if (inode1 != inode2) + ocfs2_meta_unlock(inode2, 1); +} + #define PARENT_INO(buffer) \ ((struct ocfs2_dir_entry *) \ ((char *)buffer + \ @@ -1058,7 +1064,8 @@ static int ocfs2_rename(struct inode *old_dir, struct inode *new_dir, struct dentry *new_dentry) { - int status = 0, rename_lock = 0; + int status = 0, rename_lock = 0, parents_locked = 0; + int old_child_locked = 0, new_child_locked = 0; struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct inode *orphan_dir = NULL; @@ -1122,13 +1129,13 @@ static int ocfs2_rename(struct inode *old_dir, } /* if old and new are the same, this'll just do one lock. */ - status = ocfs2_double_lock(osb, handle, - &old_dir_bh, old_dir, - &new_dir_bh, new_dir); + status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, + &new_dir_bh, new_dir); if (status < 0) { mlog_errno(status); goto bail; } + parents_locked = 1; /* make sure both dirs have bhs * get an extra ref on old_dir_bh if old==new */ @@ -1149,12 +1156,13 @@ static int ocfs2_rename(struct inode *old_dir, * the vote thread on other nodes won't have to concurrently * downconvert the inode and the dentry locks. */ - status = ocfs2_meta_lock(old_inode, handle, NULL, 1); + status = ocfs2_meta_lock(old_inode, NULL, NULL, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); goto bail; } + old_child_locked = 1; status = ocfs2_remote_dentry_delete(old_dentry); if (status < 0) { @@ -1240,12 +1248,13 @@ static int ocfs2_rename(struct inode *old_dir, goto bail; } - status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1); + status = ocfs2_meta_lock(new_inode, NULL, &newfe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); goto bail; } + new_child_locked = 1; status = ocfs2_remote_dentry_delete(new_dentry); if (status < 0) { @@ -1435,6 +1444,15 @@ bail: if (handle) ocfs2_commit_trans(handle); + if (parents_locked) + ocfs2_double_unlock(old_dir, new_dir); + + if (old_child_locked) + ocfs2_meta_unlock(old_inode, 1); + + if (new_child_locked) + ocfs2_meta_unlock(new_inode, 1); + if (orphan_dir) { /* This was locked for us in ocfs2_prepare_orphan_dir() */ ocfs2_meta_unlock(orphan_dir, 1); -- cgit v0.10.2 From da5cbf2f9df922cfdafa39351691fa83517f1e25 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 18:34:35 -0700 Subject: ocfs2: don't use handle for locking in allocation functions Instead we record our state on the allocation context structure which all callers already know about and lifetime correctly. This means the reservation functions don't need a handle passed in any more, and we can also take it off the alloc context. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 04e0191..d10ccea 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -409,13 +409,6 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, mlog(0, "extending dir %llu (i_size = %lld)\n", (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - /* dir->i_size is always block aligned. */ spin_lock(&OCFS2_I(dir)->ip_lock); if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) { @@ -428,8 +421,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, } if (!num_free_extents) { - status = ocfs2_reserve_new_metadata(osb, handle, - fe, &meta_ac); + status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -437,7 +429,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, } } - status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac); + status = ocfs2_reserve_clusters(osb, 1, &data_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -450,7 +442,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; } - handle = ocfs2_start_trans(osb, handle, credits); + handle = ocfs2_start_trans(osb, NULL, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d8bd2c3..bd944e8 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -463,13 +463,6 @@ restart_all: (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode), fe->i_clusters, clusters_to_add); - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto leave; - } - num_free_extents = ocfs2_num_free_extents(osb, inode, fe); @@ -480,10 +473,7 @@ restart_all: } if (!num_free_extents) { - status = ocfs2_reserve_new_metadata(osb, - handle, - fe, - &meta_ac); + status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -491,10 +481,7 @@ restart_all: } } - status = ocfs2_reserve_clusters(osb, - handle, - clusters_to_add, - &data_ac); + status = ocfs2_reserve_clusters(osb, clusters_to_add, &data_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -509,7 +496,7 @@ restart_all: drop_alloc_sem = 1; credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add); - handle = ocfs2_start_trans(osb, handle, credits); + handle = ocfs2_start_trans(osb, NULL, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 75f09f1..869383e 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -64,7 +64,6 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, struct buffer_head *main_bm_bh); static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context **ac, struct inode **bitmap_inode, struct buffer_head **bitmap_bh); @@ -448,7 +447,6 @@ out: * our own in order to shift windows. */ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, - struct ocfs2_journal_handle *passed_handle, u32 bits_wanted, struct ocfs2_alloc_context *ac) { @@ -459,9 +457,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, mlog_entry_void(); - BUG_ON(!passed_handle); BUG_ON(!ac); - BUG_ON(passed_handle->k_handle); local_alloc_inode = ocfs2_get_system_file_inode(osb, @@ -472,7 +468,11 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, mlog_errno(status); goto bail; } - ocfs2_handle_add_inode(passed_handle, local_alloc_inode); + + mutex_lock(&local_alloc_inode->i_mutex); + + ac->ac_inode = local_alloc_inode; + ac->ac_which = OCFS2_AC_USE_LOCAL; if (osb->local_alloc_state != OCFS2_LA_ENABLED) { status = -ENOSPC; @@ -511,14 +511,10 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, } } - ac->ac_inode = igrab(local_alloc_inode); get_bh(osb->local_alloc_bh); ac->ac_bh = osb->local_alloc_bh; - ac->ac_which = OCFS2_AC_USE_LOCAL; status = 0; bail: - if (local_alloc_inode) - iput(local_alloc_inode); mlog_exit(status); return status; @@ -774,7 +770,6 @@ bail: } static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context **ac, struct inode **bitmap_inode, struct buffer_head **bitmap_bh) @@ -788,7 +783,6 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb, goto bail; } - (*ac)->ac_handle = handle; (*ac)->ac_bits_wanted = ocfs2_local_alloc_window_bits(osb); status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac); @@ -891,16 +885,8 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, mlog_entry_void(); - handle = ocfs2_alloc_handle(osb); - if (!handle) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - /* This will lock the main bitmap for us. */ status = ocfs2_local_alloc_reserve_for_window(osb, - handle, &ac, &main_bm_inode, &main_bm_bh); @@ -910,7 +896,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, goto bail; } - handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h index 30f88ce..4bd624c 100644 --- a/fs/ocfs2/localalloc.h +++ b/fs/ocfs2/localalloc.h @@ -42,7 +42,6 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, struct ocfs2_alloc_context; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, - struct ocfs2_journal_handle *passed_handle, u32 bits_wanted, struct ocfs2_alloc_context *ac); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 5bd5f99..ca01244 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -334,13 +334,6 @@ static int ocfs2_mknod(struct inode *dir, return status; } - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto leave; - } - if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { status = -EMLINK; goto leave; @@ -368,7 +361,7 @@ static int ocfs2_mknod(struct inode *dir, } /* reserve an inode spot */ - status = ocfs2_reserve_new_inode(osb, handle, &inode_ac); + status = ocfs2_reserve_new_inode(osb, &inode_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -378,7 +371,7 @@ static int ocfs2_mknod(struct inode *dir, /* are we making a directory? If so, reserve a cluster for his * 1st extent. */ if (S_ISDIR(mode)) { - status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac); + status = ocfs2_reserve_clusters(osb, 1, &data_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -386,7 +379,7 @@ static int ocfs2_mknod(struct inode *dir, } } - handle = ocfs2_start_trans(osb, handle, OCFS2_MKNOD_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_MKNOD_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -1649,14 +1642,7 @@ static int ocfs2_symlink(struct inode *dir, goto bail; } - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - - status = ocfs2_reserve_new_inode(osb, handle, &inode_ac); + status = ocfs2_reserve_new_inode(osb, &inode_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -1665,7 +1651,7 @@ static int ocfs2_symlink(struct inode *dir, /* don't reserve bitmap space for fast symlinks. */ if (l > ocfs2_fast_symlink_chars(sb)) { - status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac); + status = ocfs2_reserve_clusters(osb, 1, &data_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -1673,7 +1659,7 @@ static int ocfs2_symlink(struct inode *dir, } } - handle = ocfs2_start_trans(osb, handle, credits); + handle = ocfs2_start_trans(osb, NULL, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 3209340..31bda54 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -59,9 +59,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct inode *alloc_inode, struct buffer_head *bh); -static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, - struct ocfs2_alloc_context *ac); - static int ocfs2_cluster_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, @@ -72,6 +69,7 @@ static int ocfs2_block_group_search(struct inode *inode, u16 *bit_off, u16 *bits_found); static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, + struct ocfs2_journal_handle *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -120,8 +118,16 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) { - if (ac->ac_inode) - iput(ac->ac_inode); + struct inode *inode = ac->ac_inode; + + if (inode) { + if (ac->ac_which != OCFS2_AC_USE_LOCAL) + ocfs2_meta_unlock(inode, 1); + + mutex_unlock(&inode->i_mutex); + + iput(inode); + } if (ac->ac_bh) brelse(ac->ac_bh); kfree(ac); @@ -284,16 +290,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, mlog_entry_void(); - handle = ocfs2_alloc_handle(osb); - if (!handle) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters(osb, - handle, le16_to_cpu(cl->cl_cpg), &ac); if (status < 0) { @@ -402,27 +400,38 @@ bail: } static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, - struct ocfs2_alloc_context *ac) + struct ocfs2_alloc_context *ac, + int type, + u32 slot) { int status; u32 bits_wanted = ac->ac_bits_wanted; - struct inode *alloc_inode = ac->ac_inode; + struct inode *alloc_inode; struct buffer_head *bh = NULL; - struct ocfs2_journal_handle *handle = ac->ac_handle; struct ocfs2_dinode *fe; u32 free_bits; mlog_entry_void(); - BUG_ON(handle->k_handle); + alloc_inode = ocfs2_get_system_file_inode(osb, type, slot); + if (!alloc_inode) { + mlog_errno(-EINVAL); + return -EINVAL; + } - ocfs2_handle_add_inode(handle, alloc_inode); - status = ocfs2_meta_lock(alloc_inode, handle, &bh, 1); + mutex_lock(&alloc_inode->i_mutex); + + status = ocfs2_meta_lock(alloc_inode, NULL, &bh, 1); if (status < 0) { + mutex_unlock(&alloc_inode->i_mutex); + iput(alloc_inode); + mlog_errno(status); - goto bail; + return status; } + ac->ac_inode = alloc_inode; + fe = (struct ocfs2_dinode *) bh->b_data; if (!OCFS2_IS_VALID_DINODE(fe)) { OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe); @@ -473,12 +482,11 @@ bail: } int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_dinode *fe, struct ocfs2_alloc_context **ac) { int status; - struct inode *alloc_inode = NULL; + u32 slot; *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { @@ -488,28 +496,18 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, } (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe); - (*ac)->ac_handle = handle; (*ac)->ac_which = OCFS2_AC_USE_META; #ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS - alloc_inode = ocfs2_get_system_file_inode(osb, - EXTENT_ALLOC_SYSTEM_INODE, - 0); + slot = 0; #else - alloc_inode = ocfs2_get_system_file_inode(osb, - EXTENT_ALLOC_SYSTEM_INODE, - osb->slot_num); + slot = osb->slot_num; #endif - if (!alloc_inode) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - (*ac)->ac_inode = igrab(alloc_inode); (*ac)->ac_group_search = ocfs2_block_group_search; - status = ocfs2_reserve_suballoc_bits(osb, (*ac)); + status = ocfs2_reserve_suballoc_bits(osb, (*ac), + EXTENT_ALLOC_SYSTEM_INODE, slot); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -523,19 +521,14 @@ bail: *ac = NULL; } - if (alloc_inode) - iput(alloc_inode); - mlog_exit(status); return status; } int ocfs2_reserve_new_inode(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context **ac) { int status; - struct inode *alloc_inode = NULL; *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { @@ -545,22 +538,13 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, } (*ac)->ac_bits_wanted = 1; - (*ac)->ac_handle = handle; (*ac)->ac_which = OCFS2_AC_USE_INODE; - alloc_inode = ocfs2_get_system_file_inode(osb, - INODE_ALLOC_SYSTEM_INODE, - osb->slot_num); - if (!alloc_inode) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - - (*ac)->ac_inode = igrab(alloc_inode); (*ac)->ac_group_search = ocfs2_block_group_search; - status = ocfs2_reserve_suballoc_bits(osb, *ac); + status = ocfs2_reserve_suballoc_bits(osb, *ac, + INODE_ALLOC_SYSTEM_INODE, + osb->slot_num); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -574,9 +558,6 @@ bail: *ac = NULL; } - if (alloc_inode) - iput(alloc_inode); - mlog_exit(status); return status; } @@ -588,20 +569,17 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb, { int status; - ac->ac_inode = ocfs2_get_system_file_inode(osb, - GLOBAL_BITMAP_SYSTEM_INODE, - OCFS2_INVALID_SLOT); - if (!ac->ac_inode) { - status = -EINVAL; - mlog(ML_ERROR, "Could not get bitmap inode!\n"); - goto bail; - } ac->ac_which = OCFS2_AC_USE_MAIN; ac->ac_group_search = ocfs2_cluster_group_search; - status = ocfs2_reserve_suballoc_bits(osb, ac); - if (status < 0 && status != -ENOSPC) + status = ocfs2_reserve_suballoc_bits(osb, ac, + GLOBAL_BITMAP_SYSTEM_INODE, + OCFS2_INVALID_SLOT); + if (status < 0 && status != -ENOSPC) { mlog_errno(status); + goto bail; + } + bail: return status; } @@ -610,7 +588,6 @@ bail: * use so we figure it out for them, but unfortunately this clutters * things a bit. */ int ocfs2_reserve_clusters(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, u32 bits_wanted, struct ocfs2_alloc_context **ac) { @@ -618,8 +595,6 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb, mlog_entry_void(); - BUG_ON(!handle); - *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; @@ -628,12 +603,10 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb, } (*ac)->ac_bits_wanted = bits_wanted; - (*ac)->ac_handle = handle; status = -ENOSPC; if (ocfs2_alloc_should_use_local(osb, bits_wanted)) { status = ocfs2_reserve_local_alloc_bits(osb, - handle, bits_wanted, *ac); if ((status < 0) && (status != -ENOSPC)) { @@ -1055,6 +1028,7 @@ out: } static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, + struct ocfs2_journal_handle *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1067,7 +1041,6 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, struct buffer_head *group_bh = NULL; struct ocfs2_group_desc *gd; struct inode *alloc_inode = ac->ac_inode; - struct ocfs2_journal_handle *handle = ac->ac_handle; ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno, &group_bh, OCFS2_BH_CACHED, alloc_inode); @@ -1115,6 +1088,7 @@ out: } static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, + struct ocfs2_journal_handle *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1126,7 +1100,6 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, u16 chain, tmp_bits; u32 tmp_used; u64 next_group; - struct ocfs2_journal_handle *handle = ac->ac_handle; struct inode *alloc_inode = ac->ac_inode; struct buffer_head *group_bh = NULL; struct buffer_head *prev_group_bh = NULL; @@ -1272,6 +1245,7 @@ bail: /* will give out up to bits_wanted contiguous bits. */ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, + struct ocfs2_journal_handle *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1313,8 +1287,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, * by jumping straight to the most recently used * allocation group. This helps us mantain some * contiguousness across allocations. */ - status = ocfs2_search_one_group(ac, bits_wanted, min_bits, - bit_off, num_bits, + status = ocfs2_search_one_group(ac, handle, bits_wanted, + min_bits, bit_off, num_bits, hint_blkno, &bits_left); if (!status) { /* Be careful to update *bg_blkno here as the @@ -1336,7 +1310,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_chain = victim; ac->ac_allow_chain_relink = 1; - status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off, + status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off, num_bits, bg_blkno, &bits_left); if (!status) goto set_hint; @@ -1360,7 +1334,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, continue; ac->ac_chain = i; - status = ocfs2_search_chain(ac, bits_wanted, min_bits, + status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off, num_bits, bg_blkno, &bits_left); if (!status) @@ -1401,10 +1375,10 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb, BUG_ON(!ac); BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted)); BUG_ON(ac->ac_which != OCFS2_AC_USE_META); - BUG_ON(ac->ac_handle != handle); status = ocfs2_claim_suballoc_bits(osb, ac, + handle, bits_wanted, 1, suballoc_bit_start, @@ -1440,10 +1414,10 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb, BUG_ON(ac->ac_bits_given != 0); BUG_ON(ac->ac_bits_wanted != 1); BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE); - BUG_ON(ac->ac_handle != handle); status = ocfs2_claim_suballoc_bits(osb, ac, + handle, 1, 1, suballoc_bit, @@ -1546,7 +1520,6 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL && ac->ac_which != OCFS2_AC_USE_MAIN); - BUG_ON(ac->ac_handle != handle); if (ac->ac_which == OCFS2_AC_USE_LOCAL) { status = ocfs2_claim_local_alloc_bits(osb, @@ -1572,6 +1545,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, status = ocfs2_claim_suballoc_bits(osb, ac, + handle, bits_wanted, min_clusters, &bg_bit_off, diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index c787838..e7c4b27 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h @@ -43,7 +43,6 @@ struct ocfs2_alloc_context { #define OCFS2_AC_USE_INODE 3 #define OCFS2_AC_USE_META 4 u32 ac_which; - struct ocfs2_journal_handle *ac_handle; /* these are used by the chain search */ u16 ac_chain; @@ -60,14 +59,11 @@ static inline int ocfs2_alloc_context_bits_left(struct ocfs2_alloc_context *ac) } int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_dinode *fe, struct ocfs2_alloc_context **ac); int ocfs2_reserve_new_inode(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context **ac); int ocfs2_reserve_clusters(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, u32 bits_wanted, struct ocfs2_alloc_context **ac); -- cgit v0.10.2 From 85b9e783cbc8cf4acc7bfaa76f37ea26b426f514 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 18:40:41 -0700 Subject: ocfs2: Don't allocate handle early in ocfs2_rename() It isn't used until ocfs2_start_trans() anyway. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index ca01244..8d03ef4 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -1114,13 +1114,6 @@ static int ocfs2_rename(struct inode *old_dir, rename_lock = 1; } - handle = ocfs2_alloc_handle(osb); - if (handle == NULL) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - /* if old and new are the same, this'll just do one lock. */ status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, &new_dir_bh, new_dir); @@ -1291,7 +1284,7 @@ static int ocfs2_rename(struct inode *old_dir, } } - handle = ocfs2_start_trans(osb, handle, OCFS2_RENAME_CREDITS); + handle = ocfs2_start_trans(osb, NULL, OCFS2_RENAME_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; -- cgit v0.10.2 From 02928a71ae6da6e3e205d99e1fa1a1f598ddb62d Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 18:51:46 -0700 Subject: ocfs2: remove unused ocfs2_handle_add_inode() We can also delete the unused infrastructure which was once in place to support this functionality. ocfs2_inode_private loses ip_handle and ip_handle_list. ocfs2_journal_handle loses handle_list. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 16e8e74..20e60e4 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -1067,12 +1067,6 @@ void ocfs2_clear_inode(struct inode *inode) mlog_bug_on_msg(oi->ip_open_count, "Clear inode of %llu has open count %d\n", (unsigned long long)oi->ip_blkno, oi->ip_open_count); - mlog_bug_on_msg(!list_empty(&oi->ip_handle_list), - "Clear inode of %llu has non empty handle list\n", - (unsigned long long)oi->ip_blkno); - mlog_bug_on_msg(oi->ip_handle, - "Clear inode of %llu has non empty handle pointer\n", - (unsigned long long)oi->ip_blkno); /* Clear all other flags. */ oi->ip_flags = OCFS2_INODE_CACHE_INLINE; diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 9957810..9b73545 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -48,13 +48,6 @@ struct ocfs2_inode_info struct mutex ip_io_mutex; - /* Used by the journalling code to attach an inode to a - * handle. These are protected by ip_io_mutex in order to lock - * out other I/O to the inode until we either commit or - * abort. */ - struct list_head ip_handle_list; - struct ocfs2_journal_handle *ip_handle; - u32 ip_flags; /* see below */ u32 ip_attr; /* inode attributes */ diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index ca6f209..f02af63 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -128,7 +128,6 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) retval->k_handle = NULL; INIT_LIST_HEAD(&retval->locks); - INIT_LIST_HEAD(&retval->inode_list); retval->journal = osb->journal; return retval; @@ -202,51 +201,12 @@ done_free: return ERR_PTR(ret); } -void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle, - struct inode *inode) -{ - BUG_ON(!handle); - BUG_ON(!inode); - - atomic_inc(&inode->i_count); - - /* we're obviously changing it... */ - mutex_lock(&inode->i_mutex); - - /* sanity check */ - BUG_ON(OCFS2_I(inode)->ip_handle); - BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list)); - - OCFS2_I(inode)->ip_handle = handle; - list_move_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list)); -} - -static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle) -{ - struct list_head *p, *n; - struct inode *inode; - struct ocfs2_inode_info *oi; - - list_for_each_safe(p, n, &handle->inode_list) { - oi = list_entry(p, struct ocfs2_inode_info, - ip_handle_list); - inode = &oi->vfs_inode; - - OCFS2_I(inode)->ip_handle = NULL; - list_del_init(&OCFS2_I(inode)->ip_handle_list); - - mutex_unlock(&inode->i_mutex); - iput(inode); - } -} - /* This is trivial so we do it out of the main commit * paths. Beware, it can be called from start_trans too! */ static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle) { mlog_entry_void(); - ocfs2_handle_unlock_inodes(handle); /* You are allowed to add journal locks before the transaction * has started. */ ocfs2_handle_cleanup_locks(handle->journal, handle); @@ -272,9 +232,6 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) return; } - /* release inode semaphores we took during this transaction */ - ocfs2_handle_unlock_inodes(handle); - /* ocfs2_extend_trans may have had to call journal_restart * which will always commit the transaction, but may return * error for any number of reasons. If this is the case, we diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 6b5d548..3a16d7d 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -149,8 +149,6 @@ struct ocfs2_journal_handle { struct list_head locks; /* A bunch of locks to * release on commit. This * should be a list_head */ - - struct list_head inode_list; }; /* Exported only for the journal struct init code in super.c. Do not call. */ @@ -236,7 +234,6 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) * ocfs2_handle_add_lock to indicate that a lock needs * to be released at the end of that handle. Locks * will be released in the order that they are added. - * ocfs2_handle_add_inode - Add a locked inode to a transaction. */ /* You must always start_trans with a number of buffs > 0, but it's @@ -293,12 +290,6 @@ int ocfs2_journal_dirty_data(handle_t *handle, struct buffer_head *bh); int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle, struct inode *inode); -/* - * Use this to protect from other processes reading buffer state while - * it's in flight. - */ -void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle, - struct inode *inode); /* * Credit Macros: diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 76b46eb..f3027c2f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -914,9 +914,7 @@ static void ocfs2_inode_init_once(void *data, oi->ip_open_count = 0; spin_lock_init(&oi->ip_lock); ocfs2_extent_map_init(&oi->vfs_inode); - INIT_LIST_HEAD(&oi->ip_handle_list); INIT_LIST_HEAD(&oi->ip_io_markers); - oi->ip_handle = NULL; oi->ip_created_trans = 0; oi->ip_last_trans = 0; oi->ip_dir_start_lookup = 0; -- cgit v0.10.2 From daf29e9cdab7219838c6b6e82380aec3466cf379 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 19:05:31 -0700 Subject: ocfs2: remove unused ocfs2_handle_add_lock() This gets us rid of a slab we no longer need, as well as removing the majority of what's left on ocfs2_journal_handle. ocfs2_commit_unstarted_handle() has no more real work to do, so remove that function too. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index ff8d3db..1c29b96 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1668,12 +1668,6 @@ int ocfs2_meta_lock_full(struct inode *inode, } } - if (handle) { - status = ocfs2_handle_add_lock(handle, inode); - if (status < 0) - mlog_errno(status); - } - bail: if (status < 0) { if (ret_bh && (*ret_bh)) { diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index f02af63..3ef1678 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -57,9 +57,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, static int __ocfs2_recovery_thread(void *arg); static int ocfs2_commit_cache(struct ocfs2_super *osb); static int ocfs2_wait_on_mount(struct ocfs2_super *osb); -static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal, - struct ocfs2_journal_handle *handle); -static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle); static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, int dirty); static int ocfs2_trylock_journal(struct ocfs2_super *osb, @@ -123,11 +120,8 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) "handle!\n"); return NULL; } - - retval->num_locks = 0; retval->k_handle = NULL; - INIT_LIST_HEAD(&retval->locks); retval->journal = osb->journal; return retval; @@ -195,27 +189,12 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, done_free: if (handle) - ocfs2_commit_unstarted_handle(handle); /* will kfree handle */ + kfree(handle); mlog_exit(ret); return ERR_PTR(ret); } -/* This is trivial so we do it out of the main commit - * paths. Beware, it can be called from start_trans too! */ -static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle) -{ - mlog_entry_void(); - - /* You are allowed to add journal locks before the transaction - * has started. */ - ocfs2_handle_cleanup_locks(handle->journal, handle); - - kfree(handle); - - mlog_exit_void(); -} - void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) { handle_t *jbd_handle; @@ -227,7 +206,7 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) BUG_ON(!handle); if (!handle->k_handle) { - ocfs2_commit_unstarted_handle(handle); + kfree(handle); mlog_exit_void(); return; } @@ -251,8 +230,6 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) handle->k_handle = NULL; /* it's been free'd in journal_stop */ } - ocfs2_handle_cleanup_locks(journal, handle); - up_read(&journal->j_trans_barrier); kfree(handle); @@ -394,59 +371,6 @@ int ocfs2_journal_dirty_data(handle_t *handle, return err; } -/* We always assume you're adding a metadata lock at level 'ex' */ -int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle, - struct inode *inode) -{ - int status; - struct ocfs2_journal_lock *lock; - - BUG_ON(!inode); - - lock = kmem_cache_alloc(ocfs2_lock_cache, GFP_NOFS); - if (!lock) { - status = -ENOMEM; - mlog_errno(-ENOMEM); - goto bail; - } - - if (!igrab(inode)) - BUG(); - lock->jl_inode = inode; - - list_add_tail(&(lock->jl_lock_list), &(handle->locks)); - handle->num_locks++; - - status = 0; -bail: - mlog_exit(status); - return status; -} - -static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal, - struct ocfs2_journal_handle *handle) -{ - struct list_head *p, *n; - struct ocfs2_journal_lock *lock; - struct inode *inode; - - list_for_each_safe(p, n, &(handle->locks)) { - lock = list_entry(p, struct ocfs2_journal_lock, - jl_lock_list); - list_del(&lock->jl_lock_list); - handle->num_locks--; - - inode = lock->jl_inode; - ocfs2_meta_unlock(inode, 1); - if (atomic_read(&inode->i_count) == 1) - mlog(ML_ERROR, - "Inode %llu, I'm doing a last iput for!", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - iput(inode); - kmem_cache_free(ocfs2_lock_cache, lock); - } -} - #define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * 5) void ocfs2_set_journal_params(struct ocfs2_super *osb) diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 3a16d7d..7e9c130 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -133,22 +133,9 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, spin_unlock(&trans_inc_lock); } -extern kmem_cache_t *ocfs2_lock_cache; - -struct ocfs2_journal_lock { - struct inode *jl_inode; - struct list_head jl_lock_list; -}; - struct ocfs2_journal_handle { handle_t *k_handle; /* kernel handle. */ struct ocfs2_journal *journal; - - /* The following two fields are for ocfs2_handle_add_lock */ - int num_locks; - struct list_head locks; /* A bunch of locks to - * release on commit. This - * should be a list_head */ }; /* Exported only for the journal struct init code in super.c. Do not call. */ @@ -229,11 +216,6 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) * ocfs2_journal_dirty - Mark a journalled buffer as having dirty data. * ocfs2_journal_dirty_data - Indicate that a data buffer should go out before * the current handle commits. - * ocfs2_handle_add_lock - Sometimes we need to delay lock release - * until after a transaction has been completed. Use - * ocfs2_handle_add_lock to indicate that a lock needs - * to be released at the end of that handle. Locks - * will be released in the order that they are added. */ /* You must always start_trans with a number of buffs > 0, but it's @@ -288,8 +270,6 @@ int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, struct buffer_head *bh); int ocfs2_journal_dirty_data(handle_t *handle, struct buffer_head *bh); -int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle, - struct inode *inode); /* * Credit Macros: diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index f3027c2f..290d531 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -70,8 +70,6 @@ static kmem_cache_t *ocfs2_inode_cachep = NULL; -kmem_cache_t *ocfs2_lock_cache = NULL; - /* OCFS2 needs to schedule several differnt types of work which * require cluster locking, disk I/O, recovery waits, etc. Since these * types of work tend to be heavy we avoid using the kernel events @@ -946,14 +944,6 @@ static int ocfs2_initialize_mem_caches(void) if (!ocfs2_inode_cachep) return -ENOMEM; - ocfs2_lock_cache = kmem_cache_create("ocfs2_lock", - sizeof(struct ocfs2_journal_lock), - 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!ocfs2_lock_cache) - return -ENOMEM; - return 0; } @@ -961,11 +951,8 @@ static void ocfs2_free_mem_caches(void) { if (ocfs2_inode_cachep) kmem_cache_destroy(ocfs2_inode_cachep); - if (ocfs2_lock_cache) - kmem_cache_destroy(ocfs2_lock_cache); ocfs2_inode_cachep = NULL; - ocfs2_lock_cache = NULL; } static int ocfs2_get_sector(struct super_block *sb, -- cgit v0.10.2 From a301a27d715276a71827004549bcbb2b64776c11 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 6 Oct 2006 19:07:43 -0700 Subject: ocfs2: make ocfs2_alloc_handle() static This is no longer used outside of journal.c Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 3ef1678..f070487 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -110,7 +110,7 @@ finally: return status; } -struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) +static struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) { struct ocfs2_journal_handle *retval = NULL; diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 7e9c130..3e64e6b 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -198,11 +198,6 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) * Transaction Handling: * Manage the lifetime of a transaction handle. * - * ocfs2_alloc_handle - Only allocate a handle so we can start putting - * cluster locks on it. To actually change blocks, - * call ocfs2_start_trans with the handle returned - * from this function. You may call ocfs2_commit_trans - * at any time in the lifetime of a handle. * ocfs2_start_trans - Begin a transaction. Give it an upper estimate of * the number of blocks that will be changed during * this handle. @@ -221,7 +216,6 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) /* You must always start_trans with a number of buffs > 0, but it's * perfectly legal to go through an entire transaction without having * dirtied any buffers. */ -struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb); struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, int max_buffs); -- cgit v0.10.2 From 4bcec1847ac4f75c2ee6d091b495f34d8d822e6a Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 9 Oct 2006 16:02:40 -0700 Subject: ocfs2: remove unused handle argument from ocfs2_meta_lock_full() Now that this is unused and all callers pass NULL, we can safely remove it. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index c8a4727..22dd608 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1152,7 +1152,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) mutex_lock(&data_alloc_inode->i_mutex); - status = ocfs2_meta_lock(data_alloc_inode, NULL, &data_alloc_bh, 1); + status = ocfs2_meta_lock(data_alloc_inode, &data_alloc_bh, 1); if (status < 0) { mlog_errno(status); goto out_mutex; @@ -2003,10 +2003,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb, mutex_lock(&ext_alloc_inode->i_mutex); (*tc)->tc_ext_alloc_inode = ext_alloc_inode; - status = ocfs2_meta_lock(ext_alloc_inode, - NULL, - &ext_alloc_bh, - 1); + status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1); if (status < 0) { mlog_errno(status); goto bail; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 3d7c082..196a71c 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -200,7 +200,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0)); - ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page); + ret = ocfs2_meta_lock_with_page(inode, NULL, 0, page); if (ret != 0) { if (ret == AOP_TRUNCATED_PAGE) unlock = 0; @@ -305,7 +305,7 @@ static int ocfs2_prepare_write(struct file *file, struct page *page, mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); - ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page); + ret = ocfs2_meta_lock_with_page(inode, NULL, 0, page); if (ret != 0) { mlog_errno(ret); goto out; @@ -412,7 +412,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page, * stale inode allocation image (i_size, i_clusters, etc). */ - ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page); + ret = ocfs2_meta_lock_with_page(inode, &di_bh, 1, page); if (ret != 0) { mlog_errno(ret); goto out; @@ -490,7 +490,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) * accessed concurrently from multiple nodes. */ if (!INODE_JOURNAL(inode)) { - err = ocfs2_meta_lock(inode, NULL, NULL, 0); + err = ocfs2_meta_lock(inode, NULL, 0); if (err) { if (err != -ENOENT) mlog_errno(err); diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index d10ccea..db46ee5 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -89,7 +89,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) stored = 0; bh = NULL; - error = ocfs2_meta_lock(inode, NULL, NULL, 0); + error = ocfs2_meta_lock(inode, NULL, 0); if (error < 0) { if (error != -ENOENT) mlog_errno(error); diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 1c29b96..7a22118 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1579,7 +1579,6 @@ static int ocfs2_assign_bh(struct inode *inode, * the result of the lock will be communicated via the callback. */ int ocfs2_meta_lock_full(struct inode *inode, - struct ocfs2_journal_handle *handle, struct buffer_head **ret_bh, int ex, int arg_flags) @@ -1707,18 +1706,16 @@ bail: * the lock inversion simply. */ int ocfs2_meta_lock_with_page(struct inode *inode, - struct ocfs2_journal_handle *handle, struct buffer_head **ret_bh, int ex, struct page *page) { int ret; - ret = ocfs2_meta_lock_full(inode, handle, ret_bh, ex, - OCFS2_LOCK_NONBLOCK); + ret = ocfs2_meta_lock_full(inode, ret_bh, ex, OCFS2_LOCK_NONBLOCK); if (ret == -EAGAIN) { unlock_page(page); - if (ocfs2_meta_lock(inode, handle, ret_bh, ex) == 0) + if (ocfs2_meta_lock(inode, ret_bh, ex) == 0) ocfs2_meta_unlock(inode, ex); ret = AOP_TRUNCATED_PAGE; } diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 75c49ce..a1165ed 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h @@ -81,18 +81,16 @@ void ocfs2_data_unlock(struct inode *inode, int ocfs2_rw_lock(struct inode *inode, int write); void ocfs2_rw_unlock(struct inode *inode, int write); int ocfs2_meta_lock_full(struct inode *inode, - struct ocfs2_journal_handle *handle, struct buffer_head **ret_bh, int ex, int arg_flags); int ocfs2_meta_lock_with_page(struct inode *inode, - struct ocfs2_journal_handle *handle, struct buffer_head **ret_bh, int ex, struct page *page); /* 99% of the time we don't want to supply any additional flags -- * those are for very specific cases only. */ -#define ocfs2_meta_lock(i, h, b, e) ocfs2_meta_lock_full(i, h, b, e, 0) +#define ocfs2_meta_lock(i, b, e) ocfs2_meta_lock_full(i, b, e, 0) void ocfs2_meta_unlock(struct inode *inode, int ex); int ocfs2_super_lock(struct ocfs2_super *osb, diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index fb91089..06be6e7 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -100,7 +100,7 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) mlog(0, "find parent of directory %llu\n", (unsigned long long)OCFS2_I(dir)->ip_blkno); - status = ocfs2_meta_lock(dir, NULL, NULL, 0); + status = ocfs2_meta_lock(dir, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index bd944e8..bcae269 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -812,7 +812,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) } } - status = ocfs2_meta_lock(inode, NULL, &bh, 1); + status = ocfs2_meta_lock(inode, &bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1006,7 +1006,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, */ meta_level = (filp->f_flags & O_APPEND) ? 1 : 0; for(;;) { - ret = ocfs2_meta_lock(inode, NULL, NULL, meta_level); + ret = ocfs2_meta_lock(inode, NULL, meta_level); if (ret < 0) { meta_level = -1; mlog_errno(ret); @@ -1174,7 +1174,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, * like i_size. This allows the checks down below * generic_file_aio_read() a chance of actually working. */ - ret = ocfs2_meta_lock(inode, NULL, NULL, 0); + ret = ocfs2_meta_lock(inode, NULL, 0); if (ret < 0) { mlog_errno(ret); goto bail; diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 20e60e4..dec0ece 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -441,7 +441,7 @@ static int ocfs2_read_locked_inode(struct inode *inode, generation, inode); if (can_lock) { - status = ocfs2_meta_lock(inode, NULL, NULL, 0); + status = ocfs2_meta_lock(inode, NULL, 0); if (status) { make_bad_inode(inode); mlog_errno(status); @@ -582,7 +582,7 @@ static int ocfs2_remove_inode(struct inode *inode, } mutex_lock(&inode_alloc_inode->i_mutex); - status = ocfs2_meta_lock(inode_alloc_inode, NULL, &inode_alloc_bh, 1); + status = ocfs2_meta_lock(inode_alloc_inode, &inode_alloc_bh, 1); if (status < 0) { mutex_unlock(&inode_alloc_inode->i_mutex); @@ -705,7 +705,7 @@ static int ocfs2_wipe_inode(struct inode *inode, * delete_inode operation. We do this now to avoid races with * recovery completion on other nodes. */ mutex_lock(&orphan_dir_inode->i_mutex); - status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1); + status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1); if (status < 0) { mutex_unlock(&orphan_dir_inode->i_mutex); @@ -933,7 +933,7 @@ void ocfs2_delete_inode(struct inode *inode) * allocation lock here as it won't be needed - nobody will * have the file open. */ - status = ocfs2_meta_lock(inode, NULL, &di_bh, 1); + status = ocfs2_meta_lock(inode, &di_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1180,7 +1180,7 @@ int ocfs2_inode_revalidate(struct dentry *dentry) /* Let ocfs2_meta_lock do the work of updating our struct * inode for us. */ - status = ocfs2_meta_lock(inode, NULL, NULL, 0); + status = ocfs2_meta_lock(inode, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 3663cef..16d8861 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -26,7 +26,7 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) { int status; - status = ocfs2_meta_lock(inode, NULL, NULL, 0); + status = ocfs2_meta_lock(inode, NULL, 0); if (status < 0) { mlog_errno(status); return status; @@ -50,7 +50,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, mutex_lock(&inode->i_mutex); - status = ocfs2_meta_lock(inode, NULL, &bh, 1); + status = ocfs2_meta_lock(inode, &bh, 1); if (status < 0) { mlog_errno(status); goto bail; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index f070487..61db8e7 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -424,8 +424,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) /* Skip recovery waits here - journal inode metadata never * changes in a live cluster so it can be considered an * exception to the rule. */ - status = ocfs2_meta_lock_full(inode, NULL, &bh, 1, - OCFS2_META_LOCK_RECOVERY); + status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); if (status < 0) { if (status != -ERESTARTSYS) mlog(ML_ERROR, "Could not get lock on journal!\n"); @@ -1022,8 +1021,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, } SET_INODE_JOURNAL(inode); - status = ocfs2_meta_lock_full(inode, NULL, &bh, 1, - OCFS2_META_LOCK_RECOVERY); + status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); if (status < 0) { mlog(0, "status returned from ocfs2_meta_lock=%d\n", status); if (status != -ERESTARTSYS) @@ -1212,7 +1210,7 @@ static int ocfs2_trylock_journal(struct ocfs2_super *osb, SET_INODE_JOURNAL(inode); flags = OCFS2_META_LOCK_RECOVERY | OCFS2_META_LOCK_NOQUEUE; - status = ocfs2_meta_lock_full(inode, NULL, NULL, 1, flags); + status = ocfs2_meta_lock_full(inode, NULL, 1, flags); if (status < 0) { if (status != -EAGAIN) mlog_errno(status); @@ -1295,7 +1293,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, } mutex_lock(&orphan_dir_inode->i_mutex); - status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0); + status = ocfs2_meta_lock(orphan_dir_inode, NULL, 0); if (status < 0) { mlog_errno(status); goto out; diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 869383e..4c46c0a 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -231,7 +231,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) mutex_lock(&main_bm_inode->i_mutex); - status = ocfs2_meta_lock(main_bm_inode, NULL, &main_bm_bh, 1); + status = ocfs2_meta_lock(main_bm_inode, &main_bm_bh, 1); if (status < 0) { mlog_errno(status); goto out_mutex; @@ -399,7 +399,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, mutex_lock(&main_bm_inode->i_mutex); - status = ocfs2_meta_lock(main_bm_inode, NULL, &main_bm_bh, 1); + status = ocfs2_meta_lock(main_bm_inode, &main_bm_bh, 1); if (status < 0) { mlog_errno(status); goto out_mutex; diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 8d03ef4..daf7060 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -159,7 +159,7 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len, dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno); - status = ocfs2_meta_lock(dir, NULL, NULL, 0); + status = ocfs2_meta_lock(dir, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -327,7 +327,7 @@ static int ocfs2_mknod(struct inode *dir, /* get our super block */ osb = OCFS2_SB(dir->i_sb); - status = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); + status = ocfs2_meta_lock(dir, &parent_fe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -658,7 +658,7 @@ static int ocfs2_link(struct dentry *old_dentry, if (S_ISDIR(inode->i_mode)) return -EPERM; - err = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); + err = ocfs2_meta_lock(dir, &parent_fe_bh, 1); if (err < 0) { if (err != -ENOENT) mlog_errno(err); @@ -683,7 +683,7 @@ static int ocfs2_link(struct dentry *old_dentry, goto out; } - err = ocfs2_meta_lock(inode, NULL, &fe_bh, 1); + err = ocfs2_meta_lock(inode, &fe_bh, 1); if (err < 0) { if (err != -ENOENT) mlog_errno(err); @@ -825,7 +825,7 @@ static int ocfs2_unlink(struct inode *dir, return -EPERM; } - status = ocfs2_meta_lock(dir, NULL, &parent_node_bh, 1); + status = ocfs2_meta_lock(dir, &parent_node_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -850,7 +850,7 @@ static int ocfs2_unlink(struct inode *dir, goto leave; } - status = ocfs2_meta_lock(inode, NULL, &fe_bh, 1); + status = ocfs2_meta_lock(inode, &fe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1012,7 +1012,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, inode1 = tmpinode; } /* lock id2 */ - status = ocfs2_meta_lock(inode2, NULL, bh2, 1); + status = ocfs2_meta_lock(inode2, bh2, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1021,7 +1021,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, } /* lock id1 */ - status = ocfs2_meta_lock(inode1, NULL, bh1, 1); + status = ocfs2_meta_lock(inode1, bh1, 1); if (status < 0) { /* * An error return must mean that no cluster locks @@ -1142,7 +1142,7 @@ static int ocfs2_rename(struct inode *old_dir, * the vote thread on other nodes won't have to concurrently * downconvert the inode and the dentry locks. */ - status = ocfs2_meta_lock(old_inode, NULL, NULL, 1); + status = ocfs2_meta_lock(old_inode, NULL, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1234,7 +1234,7 @@ static int ocfs2_rename(struct inode *old_dir, goto bail; } - status = ocfs2_meta_lock(new_inode, NULL, &newfe_bh, 1); + status = ocfs2_meta_lock(new_inode, &newfe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -1608,7 +1608,7 @@ static int ocfs2_symlink(struct inode *dir, credits = ocfs2_calc_symlink_credits(sb); /* lock the parent directory */ - status = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1); + status = ocfs2_meta_lock(dir, &parent_fe_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -2127,7 +2127,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, mutex_lock(&orphan_dir_inode->i_mutex); - status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1); + status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1); if (status < 0) { mlog_errno(status); goto leave; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 31bda54..27f8dc4 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -421,7 +421,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, mutex_lock(&alloc_inode->i_mutex); - status = ocfs2_meta_lock(alloc_inode, NULL, &bh, 1); + status = ocfs2_meta_lock(alloc_inode, &bh, 1); if (status < 0) { mutex_unlock(&alloc_inode->i_mutex); iput(alloc_inode); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 290d531..d9b1eb6 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -865,7 +865,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) goto bail; } - status = ocfs2_meta_lock(inode, NULL, &bh, 0); + status = ocfs2_meta_lock(inode, &bh, 0); if (status < 0) { mlog_errno(status); goto bail; -- cgit v0.10.2 From 02dc1af44e9fa4b8801169891b3a1ba4047537ad Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 9 Oct 2006 16:48:10 -0700 Subject: ocfs2: pass ocfs2_super * into ocfs2_commit_trans() This sets us up to remove handle->journal. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 22dd608..f3dbd31 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1170,7 +1170,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) if (status < 0) mlog_errno(status); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out_unlock: brelse(data_alloc_bh); @@ -1379,7 +1379,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, status = ocfs2_truncate_log_append(osb, handle, start_blk, clusters); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (status < 0) { mlog_errno(status); goto bail_up; @@ -1883,7 +1883,7 @@ start: mutex_unlock(&tl_inode->i_mutex); tl_sem = 0; - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); handle = NULL; BUG_ON(le32_to_cpu(fe->i_clusters) < target_i_clusters); @@ -1898,7 +1898,7 @@ bail: mutex_unlock(&tl_inode->i_mutex); if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (last_eb_bh) brelse(last_eb_bh); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 196a71c..c369399 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -382,7 +382,7 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, out: if (ret) { if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); handle = ERR_PTR(ret); } return handle; @@ -464,7 +464,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page, } out_commit: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); out_unlock_data: ocfs2_data_unlock(inode, 1); out_unlock_meta: diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index db46ee5..2bda5f3 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -488,7 +488,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, get_bh(*new_de_bh); bail: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (data_ac) ocfs2_free_alloc_context(data_ac); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index bcae269..9eb60f2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -178,7 +178,7 @@ static int ocfs2_simple_size_update(struct inode *inode, if (ret < 0) mlog_errno(ret); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out: return ret; } @@ -207,7 +207,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, if (status < 0) mlog_errno(status); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out: mlog_exit(status); return status; @@ -576,7 +576,7 @@ leave: drop_alloc_sem = 0; } if (handle) { - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); handle = NULL; } if (data_ac) { @@ -655,7 +655,7 @@ static int ocfs2_write_zero_page(struct inode *inode, ret = 0; if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); out_unlock: unlock_page(page); page_cache_release(page); @@ -850,7 +850,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) mlog_errno(status); bail_commit: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); bail_unlock: ocfs2_meta_unlock(inode, 1); bail_unlock_rw: @@ -938,7 +938,7 @@ static int ocfs2_write_remove_suid(struct inode *inode) out_bh: brelse(bh); out_trans: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out: mlog_exit(ret); return ret; diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index dec0ece..7708c63 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -538,7 +538,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, goto bail; } - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); handle = NULL; status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc); @@ -554,7 +554,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, } bail: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); mlog_exit(status); return status; @@ -629,7 +629,7 @@ static int ocfs2_remove_inode(struct inode *inode, mlog_errno(status); bail_commit: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); bail_unlock: ocfs2_meta_unlock(inode_alloc_inode, 1); mutex_unlock(&inode_alloc_inode->i_mutex); diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 16d8861..e927758 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -96,7 +96,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, if (status < 0) mlog_errno(status); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); bail_unlock: ocfs2_meta_unlock(inode, 1); bail: diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 61db8e7..00402e7 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -195,11 +195,12 @@ done_free: return ERR_PTR(ret); } -void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) +void ocfs2_commit_trans(struct ocfs2_super *osb, + struct ocfs2_journal_handle *handle) { handle_t *jbd_handle; int retval; - struct ocfs2_journal *journal = handle->journal; + struct ocfs2_journal *journal = osb->journal; mlog_entry_void(); diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 3e64e6b..d315179 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -219,7 +219,8 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, int max_buffs); -void ocfs2_commit_trans(struct ocfs2_journal_handle *handle); +void ocfs2_commit_trans(struct ocfs2_super *osb, + struct ocfs2_journal_handle *handle); int ocfs2_extend_trans(handle_t *handle, int nblocks); /* diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 4c46c0a..9dd208d 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -280,7 +280,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) mlog_errno(status); out_commit: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out_unlock: if (main_bm_bh) @@ -421,7 +421,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, if (status < 0) mlog_errno(status); - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out_unlock: ocfs2_meta_unlock(main_bm_inode, 1); @@ -954,7 +954,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, status = 0; bail: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (main_bm_bh) brelse(main_bm_bh); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index daf7060..9a56bfd 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -440,7 +440,7 @@ static int ocfs2_mknod(struct inode *dir, status = 0; leave: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); ocfs2_meta_unlock(dir, 1); @@ -746,7 +746,7 @@ static int ocfs2_link(struct dentry *old_dentry, d_instantiate(dentry, inode); out_commit: - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); out_unlock_inode: ocfs2_meta_unlock(inode, 1); @@ -942,7 +942,7 @@ static int ocfs2_unlink(struct inode *dir, leave: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (child_locked) ocfs2_meta_unlock(inode, 1); @@ -1428,7 +1428,7 @@ bail: ocfs2_rename_unlock(osb); if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (parents_locked) ocfs2_double_unlock(old_dir, new_dir); @@ -1730,7 +1730,7 @@ static int ocfs2_symlink(struct inode *dir, d_instantiate(dentry, inode); bail: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); ocfs2_meta_unlock(dir, 1); diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 27f8dc4..ea63a519 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -387,7 +387,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, status = 0; bail: if (handle) - ocfs2_commit_trans(handle); + ocfs2_commit_trans(osb, handle); if (ac) ocfs2_free_alloc_context(ac); -- cgit v0.10.2 From dae85832ffe2879b57b23aea319a0ec17667898d Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 9 Oct 2006 16:50:32 -0700 Subject: ocfs2: remove ocfs2_journal_handle journal field It is no longer used. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 00402e7..81fb917 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -122,8 +122,6 @@ static struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) } retval->k_handle = NULL; - retval->journal = osb->journal; - return retval; } diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index d315179..d96f61a 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -135,7 +135,6 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, struct ocfs2_journal_handle { handle_t *k_handle; /* kernel handle. */ - struct ocfs2_journal *journal; }; /* Exported only for the journal struct init code in super.c. Do not call. */ -- cgit v0.10.2 From 65eff9ccf86d63eb5c3e9071450a36e4e4fa9564 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 9 Oct 2006 17:26:22 -0700 Subject: ocfs2: remove handle argument to ocfs2_start_trans() All callers either pass in NULL directly, or a local variable that is already set to NULL. The internals of ocfs2_start_trans() get a nice cleanup as a result. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f3dbd31..354817a 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1158,7 +1158,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) goto out_mutex; } - handle = ocfs2_start_trans(osb, NULL, OCFS2_TRUNCATE_LOG_UPDATE); + handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); @@ -1365,8 +1365,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, } } - handle = ocfs2_start_trans(osb, NULL, - OCFS2_TRUNCATE_LOG_UPDATE); + handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); @@ -1860,7 +1859,7 @@ start: credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del, fe, el); - handle = ocfs2_start_trans(osb, NULL, credits); + handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c369399..fcdcdf6 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -364,7 +364,7 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, struct ocfs2_journal_handle *handle = NULL; int ret = 0; - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (!handle) { ret = -ENOMEM; mlog_errno(ret); diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 2bda5f3..036c891 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -442,7 +442,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; } - handle = ocfs2_start_trans(osb, NULL, credits); + handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9eb60f2..100754d 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -165,8 +165,7 @@ static int ocfs2_simple_size_update(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_journal_handle *handle = NULL; - handle = ocfs2_start_trans(osb, NULL, - OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (handle == NULL) { ret = -ENOMEM; mlog_errno(ret); @@ -196,7 +195,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, /* TODO: This needs to actually orphan the inode in this * transaction. */ - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); @@ -496,7 +495,7 @@ restart_all: drop_alloc_sem = 1; credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add); - handle = ocfs2_start_trans(osb, NULL, credits); + handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -832,7 +831,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) } } - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); @@ -905,7 +904,7 @@ static int ocfs2_write_remove_suid(struct inode *inode) mlog_entry("(Inode %llu, mode 0%o)\n", (unsigned long long)oi->ip_blkno, inode->i_mode); - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (handle == NULL) { ret = -ENOMEM; mlog_errno(ret); diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 7708c63..ac78877 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -524,7 +524,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, if (!fe->i_clusters) goto bail; - handle = ocfs2_start_trans(osb, handle, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -590,7 +590,7 @@ static int ocfs2_remove_inode(struct inode *inode, goto bail; } - handle = ocfs2_start_trans(osb, NULL, OCFS2_DELETE_INODE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index e927758..7527358 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -67,7 +67,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, if (!S_ISDIR(inode->i_mode)) flags &= ~OCFS2_DIRSYNC_FL; - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 81fb917..6d9658b 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -129,20 +129,16 @@ static struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) * you pass it a handle however, it may still return error, in which * case it has free'd the passed handle for you. */ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, int max_buffs) { int ret; journal_t *journal = osb->journal->j_journal; - - mlog_entry("(max_buffs = %d)\n", max_buffs); + struct ocfs2_journal_handle *handle; BUG_ON(!osb || !osb->journal->j_journal); - if (ocfs2_is_hard_readonly(osb)) { - ret = -EROFS; - goto done_free; - } + if (ocfs2_is_hard_readonly(osb)) + return ERR_PTR(-EROFS); BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE); BUG_ON(max_buffs <= 0); @@ -153,13 +149,11 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, BUG(); } - if (!handle) - handle = ocfs2_alloc_handle(osb); + handle = ocfs2_alloc_handle(osb); if (!handle) { ret = -ENOMEM; - mlog(ML_ERROR, "Failed to allocate memory for journal " - "handle!\n"); - goto done_free; + mlog_errno(ret); + return ERR_PTR(ret); } down_read(&osb->journal->j_trans_barrier); @@ -168,6 +162,7 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, handle->k_handle = journal_start(journal, max_buffs); if (IS_ERR(handle->k_handle)) { up_read(&osb->journal->j_trans_barrier); + kfree(handle); ret = PTR_ERR(handle->k_handle); handle->k_handle = NULL; @@ -177,20 +172,12 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, ocfs2_abort(osb->sb, "Detected aborted journal"); ret = -EROFS; } - goto done_free; + return ERR_PTR(ret); } atomic_inc(&(osb->journal->j_num_trans)); - mlog_exit_ptr(handle); return handle; - -done_free: - if (handle) - kfree(handle); - - mlog_exit(ret); - return ERR_PTR(ret); } void ocfs2_commit_trans(struct ocfs2_super *osb, diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index d96f61a..3c0d15c 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -216,7 +216,6 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) * perfectly legal to go through an entire transaction without having * dirtied any buffers. */ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, int max_buffs); void ocfs2_commit_trans(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle); diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 9dd208d..2ae567a 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -238,7 +238,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) } /* WINDOW_MOVE_CREDITS is a bit heavy... */ - handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { mlog_errno(PTR_ERR(handle)); handle = NULL; @@ -405,7 +405,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, goto out_mutex; } - handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -896,7 +896,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, goto bail; } - handle = ocfs2_start_trans(osb, NULL, OCFS2_WINDOW_MOVE_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 9a56bfd..d63ab7b 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -379,7 +379,7 @@ static int ocfs2_mknod(struct inode *dir, } } - handle = ocfs2_start_trans(osb, NULL, OCFS2_MKNOD_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -696,7 +696,7 @@ static int ocfs2_link(struct dentry *old_dentry, goto out_unlock_inode; } - handle = ocfs2_start_trans(osb, NULL, OCFS2_LINK_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS); if (IS_ERR(handle)) { err = PTR_ERR(handle); handle = NULL; @@ -886,7 +886,7 @@ static int ocfs2_unlink(struct inode *dir, } } - handle = ocfs2_start_trans(osb, NULL, OCFS2_UNLINK_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -1284,7 +1284,7 @@ static int ocfs2_rename(struct inode *old_dir, } } - handle = ocfs2_start_trans(osb, NULL, OCFS2_RENAME_CREDITS); + handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; @@ -1652,7 +1652,7 @@ static int ocfs2_symlink(struct inode *dir, } } - handle = ocfs2_start_trans(osb, NULL, credits); + handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index ea63a519..186d2c3 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -302,7 +302,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, credits = ocfs2_calc_group_alloc_credits(osb->sb, le16_to_cpu(cl->cl_cpg)); - handle = ocfs2_start_trans(osb, handle, credits); + handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; -- cgit v0.10.2 From 1fabe1481fac9e01bf8bffa60a2307ef379aa5de Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 9 Oct 2006 18:11:45 -0700 Subject: ocfs2: Remove struct ocfs2_journal_handle in favor of handle_t This is mostly a search and replace as ocfs2_journal_handle is now no more than a container for a handle_t pointer. ocfs2_commit_trans() becomes very straight forward, and we remove some out of date comments / code. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 354817a..85a048b 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -52,14 +52,14 @@ static int ocfs2_extent_contig(struct inode *inode, u64 blkno); static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, int wanted, struct ocfs2_alloc_context *meta_ac, struct buffer_head *bhs[]); static int ocfs2_add_branch(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, struct buffer_head *eb_bh, @@ -67,14 +67,14 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, struct ocfs2_alloc_context *meta_ac); static int ocfs2_shift_tree_depth(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, struct ocfs2_alloc_context *meta_ac, struct buffer_head **ret_new_eb_bh); static int ocfs2_do_insert_extent(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 blkno, @@ -152,7 +152,7 @@ bail: * l_count for you */ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, int wanted, struct ocfs2_alloc_context *meta_ac, @@ -253,7 +253,7 @@ bail: * contain a single record with e_clusters == 0. */ static int ocfs2_add_branch(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, struct buffer_head *eb_bh, @@ -418,7 +418,7 @@ bail: * after this call. */ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, struct ocfs2_alloc_context *meta_ac, @@ -520,7 +520,7 @@ bail: * down. */ static int ocfs2_do_insert_extent(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 start_blk, @@ -809,7 +809,7 @@ bail: /* the caller needs to update fe->i_clusters */ int ocfs2_insert_extent(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 start_blk, @@ -951,7 +951,7 @@ static int ocfs2_truncate_log_can_coalesce(struct ocfs2_truncate_log *tl, } static int ocfs2_truncate_log_append(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, u64 start_blk, unsigned int num_clusters) { @@ -1034,7 +1034,7 @@ bail: } static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *data_alloc_inode, struct buffer_head *data_alloc_bh) { @@ -1074,7 +1074,7 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, /* TODO: Perhaps we can calculate the bulk of the * credits up front rather than extending like * this. */ - status = ocfs2_extend_trans(handle->k_handle, + status = ocfs2_extend_trans(handle, OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC); if (status < 0) { mlog_errno(status); @@ -1113,7 +1113,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) { int status; unsigned int num_to_flush; - struct ocfs2_journal_handle *handle; + handle_t *handle; struct inode *tl_inode = osb->osb_tl_inode; struct inode *data_alloc_inode = NULL; struct buffer_head *tl_bh = osb->osb_tl_bh; @@ -1339,7 +1339,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, int i; unsigned int clusters, num_recs, start_cluster; u64 start_blk; - struct ocfs2_journal_handle *handle; + handle_t *handle; struct inode *tl_inode = osb->osb_tl_inode; struct ocfs2_truncate_log *tl; @@ -1534,7 +1534,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, struct inode *inode, struct buffer_head *fe_bh, struct buffer_head *old_last_eb_bh, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_truncate_context *tc) { int status, i, depth; @@ -1773,7 +1773,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, struct ocfs2_extent_block *eb; struct ocfs2_extent_list *el; struct buffer_head *last_eb_bh; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct inode *tl_inode = osb->osb_tl_inode; mlog_entry_void(); diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 12ba897..0b82e80 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h @@ -28,7 +28,7 @@ struct ocfs2_alloc_context; int ocfs2_insert_extent(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 blkno, diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index fcdcdf6..2f7268e 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -355,13 +355,13 @@ static int walk_page_buffers( handle_t *handle, return ret; } -struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, +handle_t *ocfs2_start_walk_page_trans(struct inode *inode, struct page *page, unsigned from, unsigned to) { struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; int ret = 0; handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); @@ -372,7 +372,7 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, } if (ocfs2_should_order_data(inode)) { - ret = walk_page_buffers(handle->k_handle, + ret = walk_page_buffers(handle, page_buffers(page), from, to, NULL, ocfs2_journal_dirty_data); @@ -394,7 +394,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page, int ret; struct buffer_head *di_bh = NULL; struct inode *inode = page->mapping->host; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_dinode *di; mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index e88c3f0..f446a15 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -25,7 +25,7 @@ int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page, unsigned from, unsigned to); -struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, +handle_t *ocfs2_start_walk_page_trans(struct inode *inode, struct page *page, unsigned from, unsigned to); diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 036c891..5efea44 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -340,7 +340,7 @@ int ocfs2_empty_dir(struct inode *inode) /* returns a bh of the 1st new block in the allocation. */ int ocfs2_do_extend_dir(struct super_block *sb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *dir, struct buffer_head *parent_fe_bh, struct ocfs2_alloc_context *data_ac, @@ -398,7 +398,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_alloc_context *meta_ac = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct buffer_head *new_bh = NULL; struct ocfs2_dir_entry * de; struct super_block *sb = osb->sb; diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h index 5f614ec..3f67e14 100644 --- a/fs/ocfs2/dir.h +++ b/fs/ocfs2/dir.h @@ -45,7 +45,7 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, struct buffer_head **ret_de_bh); struct ocfs2_alloc_context; int ocfs2_do_extend_dir(struct super_block *sb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *dir, struct buffer_head *parent_fe_bh, struct ocfs2_alloc_context *data_ac, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 100754d..fe6b795 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -134,7 +134,7 @@ bail: return (err < 0) ? -EIO : 0; } -int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle, +int ocfs2_set_inode_size(handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 new_i_size) @@ -163,7 +163,7 @@ static int ocfs2_simple_size_update(struct inode *inode, { int ret; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (handle == NULL) { @@ -188,7 +188,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, u64 new_i_size) { int status; - struct ocfs2_journal_handle *handle; + handle_t *handle; mlog_entry_void(); @@ -327,7 +327,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, struct inode *inode, u32 clusters_to_add, struct buffer_head *fe_bh, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, enum ocfs2_alloc_restarted *reason_ret) @@ -432,7 +432,7 @@ static int ocfs2_extend_allocation(struct inode *inode, u32 prev_clusters; struct buffer_head *bh = NULL; struct ocfs2_dinode *fe = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_alloc_context *meta_ac = NULL; enum ocfs2_alloc_restarted why; @@ -552,7 +552,7 @@ restarted_transaction: credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add); - status = ocfs2_extend_trans(handle->k_handle, credits); + status = ocfs2_extend_trans(handle, credits); if (status < 0) { /* handle still has to be committed at * this point. */ @@ -610,7 +610,7 @@ static int ocfs2_write_zero_page(struct inode *inode, struct page *page; unsigned long index; unsigned int offset; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; int ret; offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */ @@ -775,7 +775,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct super_block *sb = inode->i_sb; struct ocfs2_super *osb = OCFS2_SB(sb); struct buffer_head *bh = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; mlog_entry("(0x%p, '%.*s')\n", dentry, dentry->d_name.len, dentry->d_name.name); @@ -897,7 +897,7 @@ static int ocfs2_write_remove_suid(struct inode *inode) int ret; struct buffer_head *bh = NULL; struct ocfs2_inode_info *oi = OCFS2_I(inode); - struct ocfs2_journal_handle *handle; + handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 740c9e7..84f8b97 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -41,7 +41,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, struct inode *inode, u32 clusters_to_add, struct buffer_head *fe_bh, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, enum ocfs2_alloc_restarted *reason); @@ -49,7 +49,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); -int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle, +int ocfs2_set_inode_size(handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, u64 new_i_size); diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index ac78877..ad4d4a1 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -512,7 +512,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct buffer_head *fe_bh) { int status = 0; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_truncate_context *tc = NULL; struct ocfs2_dinode *fe; @@ -568,7 +568,7 @@ static int ocfs2_remove_inode(struct inode *inode, int status; struct inode *inode_alloc_inode = NULL; struct buffer_head *inode_alloc_bh = NULL; - struct ocfs2_journal_handle *handle; + handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; @@ -1198,7 +1198,7 @@ bail: * struct inode. * Only takes ip_lock. */ -int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, +int ocfs2_mark_inode_dirty(handle_t *handle, struct inode *inode, struct buffer_head *bh) { diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 9b73545..46a378f 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -136,7 +136,7 @@ ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf, void ocfs2_sync_blockdev(struct super_block *sb); void ocfs2_refresh_inode(struct inode *inode, struct ocfs2_dinode *fe); -int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, +int ocfs2_mark_inode_dirty(handle_t *handle, struct inode *inode, struct buffer_head *bh); int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7527358..4768be5 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -43,7 +43,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, { struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct buffer_head *bh = NULL; unsigned oldflags; int status; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 6d9658b..c0ad7cb 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -110,30 +110,13 @@ finally: return status; } -static struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) -{ - struct ocfs2_journal_handle *retval = NULL; - - retval = kcalloc(1, sizeof(*retval), GFP_NOFS); - if (!retval) { - mlog(ML_ERROR, "Failed to allocate memory for journal " - "handle!\n"); - return NULL; - } - retval->k_handle = NULL; - - return retval; -} - /* pass it NULL and it will allocate a new handle object for you. If * you pass it a handle however, it may still return error, in which * case it has free'd the passed handle for you. */ -struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, - int max_buffs) +handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs) { - int ret; journal_t *journal = osb->journal->j_journal; - struct ocfs2_journal_handle *handle; + handle_t *handle; BUG_ON(!osb || !osb->journal->j_journal); @@ -149,77 +132,39 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, BUG(); } - handle = ocfs2_alloc_handle(osb); - if (!handle) { - ret = -ENOMEM; - mlog_errno(ret); - return ERR_PTR(ret); - } - down_read(&osb->journal->j_trans_barrier); - /* actually start the transaction now */ - handle->k_handle = journal_start(journal, max_buffs); - if (IS_ERR(handle->k_handle)) { + handle = journal_start(journal, max_buffs); + if (IS_ERR(handle)) { up_read(&osb->journal->j_trans_barrier); - kfree(handle); - ret = PTR_ERR(handle->k_handle); - handle->k_handle = NULL; - mlog_errno(ret); + mlog_errno(PTR_ERR(handle)); if (is_journal_aborted(journal)) { ocfs2_abort(osb->sb, "Detected aborted journal"); - ret = -EROFS; + handle = ERR_PTR(-EROFS); } - return ERR_PTR(ret); - } - - atomic_inc(&(osb->journal->j_num_trans)); + } else + atomic_inc(&(osb->journal->j_num_trans)); return handle; } -void ocfs2_commit_trans(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle) +int ocfs2_commit_trans(struct ocfs2_super *osb, + handle_t *handle) { - handle_t *jbd_handle; - int retval; + int ret; struct ocfs2_journal *journal = osb->journal; - mlog_entry_void(); - BUG_ON(!handle); - if (!handle->k_handle) { - kfree(handle); - mlog_exit_void(); - return; - } - - /* ocfs2_extend_trans may have had to call journal_restart - * which will always commit the transaction, but may return - * error for any number of reasons. If this is the case, we - * clear k_handle as it's not valid any more. */ - if (handle->k_handle) { - jbd_handle = handle->k_handle; - - /* actually stop the transaction. if we've set h_sync, - * it'll have been committed when we return */ - retval = journal_stop(jbd_handle); - if (retval < 0) { - mlog_errno(retval); - mlog(ML_ERROR, "Could not commit transaction\n"); - BUG(); - } - - handle->k_handle = NULL; /* it's been free'd in journal_stop */ - } + ret = journal_stop(handle); + if (ret < 0) + mlog_errno(ret); up_read(&journal->j_trans_barrier); - kfree(handle); - mlog_exit_void(); + return ret; } /* @@ -268,7 +213,7 @@ bail: return status; } -int ocfs2_journal_access(struct ocfs2_journal_handle *handle, +int ocfs2_journal_access(handle_t *handle, struct inode *inode, struct buffer_head *bh, int type) @@ -306,11 +251,11 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, switch (type) { case OCFS2_JOURNAL_ACCESS_CREATE: case OCFS2_JOURNAL_ACCESS_WRITE: - status = journal_get_write_access(handle->k_handle, bh); + status = journal_get_write_access(handle, bh); break; case OCFS2_JOURNAL_ACCESS_UNDO: - status = journal_get_undo_access(handle->k_handle, bh); + status = journal_get_undo_access(handle, bh); break; default: @@ -327,7 +272,7 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, return status; } -int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, +int ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) { int status; @@ -335,7 +280,7 @@ int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, mlog_entry("(bh->b_blocknr=%llu)\n", (unsigned long long)bh->b_blocknr); - status = journal_dirty_metadata(handle->k_handle, bh); + status = journal_dirty_metadata(handle, bh); if (status < 0) mlog(ML_ERROR, "Could not dirty metadata buffer. " "(bh->b_blocknr=%llu)\n", diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 3c0d15c..d86cb96 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -37,7 +37,6 @@ enum ocfs2_journal_state { struct ocfs2_super; struct ocfs2_dinode; -struct ocfs2_journal_handle; struct ocfs2_journal { enum ocfs2_journal_state j_state; /* Journals current state */ @@ -133,10 +132,6 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, spin_unlock(&trans_inc_lock); } -struct ocfs2_journal_handle { - handle_t *k_handle; /* kernel handle. */ -}; - /* Exported only for the journal struct init code in super.c. Do not call. */ void ocfs2_complete_recovery(void *data); @@ -200,7 +195,11 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) * ocfs2_start_trans - Begin a transaction. Give it an upper estimate of * the number of blocks that will be changed during * this handle. - * ocfs2_commit_trans - Complete a handle. + * ocfs2_commit_trans - Complete a handle. It might return -EIO if + * the journal was aborted. The majority of paths don't + * check the return value as an error there comes too + * late to do anything (and will be picked up in a + * later transaction). * ocfs2_extend_trans - Extend a handle by nblocks credits. This may * commit the handle to disk in the process, but will * not release any locks taken during the transaction. @@ -215,10 +214,10 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) /* You must always start_trans with a number of buffs > 0, but it's * perfectly legal to go through an entire transaction without having * dirtied any buffers. */ -struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, +handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs); -void ocfs2_commit_trans(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle); +int ocfs2_commit_trans(struct ocfs2_super *osb, + handle_t *handle); int ocfs2_extend_trans(handle_t *handle, int nblocks); /* @@ -236,7 +235,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks); #define OCFS2_JOURNAL_ACCESS_WRITE 1 #define OCFS2_JOURNAL_ACCESS_UNDO 2 -int ocfs2_journal_access(struct ocfs2_journal_handle *handle, +int ocfs2_journal_access(handle_t *handle, struct inode *inode, struct buffer_head *bh, int type); @@ -259,7 +258,7 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, * * ocfs2_journal_dirty(handle, bh); */ -int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, +int ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh); int ocfs2_journal_dirty_data(handle_t *handle, struct buffer_head *bh); diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 2ae567a..698d79a 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -58,7 +58,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc); static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_dinode *alloc, struct inode *main_bm_inode, struct buffer_head *main_bm_bh); @@ -69,7 +69,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb, struct buffer_head **bitmap_bh); static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac); static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, @@ -195,7 +195,7 @@ bail: void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) { int status; - struct ocfs2_journal_handle *handle; + handle_t *handle; struct inode *local_alloc_inode = NULL; struct buffer_head *bh = NULL; struct buffer_head *main_bm_bh = NULL; @@ -382,7 +382,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, struct ocfs2_dinode *alloc) { int status; - struct ocfs2_journal_handle *handle; + handle_t *handle; struct buffer_head *main_bm_bh = NULL; struct inode *main_bm_inode; @@ -414,7 +414,7 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, } /* we want the bitmap change to be recorded on disk asap */ - handle->k_handle->h_sync = 1; + handle->h_sync = 1; status = ocfs2_sync_local_to_main(osb, handle, alloc, main_bm_inode, main_bm_bh); @@ -521,7 +521,7 @@ bail: } int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_bits, u32 *bit_off, @@ -699,7 +699,7 @@ static void ocfs2_verify_zero_bits(unsigned long *bitmap, * passed is used for caching. */ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_dinode *alloc, struct inode *main_bm_inode, struct buffer_head *main_bm_bh) @@ -811,7 +811,7 @@ bail: * pass it the bitmap lock in lock_bh if you have it. */ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac) { int status = 0; @@ -878,7 +878,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, int status = 0; struct buffer_head *main_bm_bh = NULL; struct inode *main_bm_inode = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_dinode *alloc; struct ocfs2_dinode *alloc_copy = NULL; struct ocfs2_alloc_context *ac = NULL; diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h index 4bd624c..385a101 100644 --- a/fs/ocfs2/localalloc.h +++ b/fs/ocfs2/localalloc.h @@ -46,7 +46,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac); int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_bits, u32 *bit_off, diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index d63ab7b..583bffe 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -75,12 +75,12 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, unsigned long offset, struct ocfs2_dir_entry **res_dir); -static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle, +static int ocfs2_delete_entry(handle_t *handle, struct inode *dir, struct ocfs2_dir_entry *de_del, struct buffer_head *bh); -static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle, +static int __ocfs2_add_entry(handle_t *handle, struct inode *dir, const char *name, int namelen, struct inode *inode, u64 blkno, @@ -93,12 +93,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, dev_t dev, struct buffer_head **new_fe_bh, struct buffer_head *parent_fe_bh, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode **ret_inode, struct ocfs2_alloc_context *inode_ac); static int ocfs2_fill_new_dir(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *parent, struct inode *inode, struct buffer_head *fe_bh, @@ -111,7 +111,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, struct buffer_head **de_bh); static int ocfs2_orphan_add(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct ocfs2_dinode *fe, char *name, @@ -119,11 +119,11 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct inode *orphan_dir_inode); static int ocfs2_create_symlink_data(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, const char *symname); -static inline int ocfs2_add_entry(struct ocfs2_journal_handle *handle, +static inline int ocfs2_add_entry(handle_t *handle, struct dentry *dentry, struct inode *inode, u64 blkno, struct buffer_head *parent_fe_bh, @@ -236,7 +236,7 @@ bail: } static int ocfs2_fill_new_dir(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *parent, struct inode *inode, struct buffer_head *fe_bh, @@ -311,7 +311,7 @@ static int ocfs2_mknod(struct inode *dir, { int status = 0; struct buffer_head *parent_fe_bh = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_super *osb; struct ocfs2_dinode *dirfe; struct buffer_head *new_fe_bh = NULL; @@ -476,7 +476,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, dev_t dev, struct buffer_head **new_fe_bh, struct buffer_head *parent_fe_bh, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode **ret_inode, struct ocfs2_alloc_context *inode_ac) { @@ -642,7 +642,7 @@ static int ocfs2_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { - struct ocfs2_journal_handle *handle; + handle_t *handle; struct inode *inode = old_dentry->d_inode; int err; struct buffer_head *fe_bh = NULL; @@ -807,7 +807,7 @@ static int ocfs2_unlink(struct inode *dir, struct ocfs2_dinode *fe = NULL; struct buffer_head *fe_bh = NULL; struct buffer_head *parent_node_bh = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_dir_entry *dirent = NULL; struct buffer_head *dirent_bh = NULL; char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; @@ -1069,7 +1069,7 @@ static int ocfs2_rename(struct inode *old_dir, struct buffer_head *insert_entry_bh = NULL; struct ocfs2_super *osb = NULL; u64 newfe_blkno; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct buffer_head *old_dir_bh = NULL; struct buffer_head *new_dir_bh = NULL; struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry @@ -1478,7 +1478,7 @@ bail: * data, including the null terminator. */ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, const char *symname) { @@ -1593,7 +1593,7 @@ static int ocfs2_symlink(struct inode *dir, struct buffer_head *parent_fe_bh = NULL; struct ocfs2_dinode *fe = NULL; struct ocfs2_dinode *dirfe; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; struct ocfs2_alloc_context *inode_ac = NULL; struct ocfs2_alloc_context *data_ac = NULL; @@ -1784,7 +1784,7 @@ int ocfs2_check_dir_entry(struct inode * dir, * If you pass me insert_bh, I'll skip the search of the other dir * blocks and put the record in there. */ -static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle, +static int __ocfs2_add_entry(handle_t *handle, struct inode *dir, const char *name, int namelen, struct inode *inode, u64 blkno, @@ -1870,7 +1870,7 @@ bail: * ocfs2_delete_entry deletes a directory entry by merging it with the * previous entry */ -static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle, +static int ocfs2_delete_entry(handle_t *handle, struct inode *dir, struct ocfs2_dir_entry *de_del, struct buffer_head *bh) @@ -2159,7 +2159,7 @@ leave: } static int ocfs2_orphan_add(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *inode, struct ocfs2_dinode *fe, char *name, @@ -2232,7 +2232,7 @@ leave: /* unlike orphan_add, we expect the orphan dir to already be locked here. */ int ocfs2_orphan_del(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *orphan_dir_inode, struct inode *inode, struct buffer_head *orphan_dir_bh) diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h index deaaa97..8425944 100644 --- a/fs/ocfs2/namei.h +++ b/fs/ocfs2/namei.h @@ -39,7 +39,7 @@ struct buffer_head *ocfs2_find_entry(const char *name, struct inode *dir, struct ocfs2_dir_entry **res_dir); int ocfs2_orphan_del(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct inode *orphan_dir_inode, struct inode *inode, struct buffer_head *orphan_dir_bh); diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 0462a7f..553e702 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "cluster/nodemanager.h" #include "cluster/heartbeat.h" @@ -181,7 +182,6 @@ enum ocfs2_mount_options #define OCFS2_OSB_ERROR_FS 0x0004 struct ocfs2_journal; -struct ocfs2_journal_handle; struct ocfs2_super { struct task_struct *commit_task; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 186d2c3..000d71c 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -49,7 +49,7 @@ static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl); -static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle, +static int ocfs2_block_group_fill(handle_t *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, u64 group_blkno, @@ -69,7 +69,7 @@ static int ocfs2_block_group_search(struct inode *inode, u16 *bit_off, u16 *bits_found); static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, - struct ocfs2_journal_handle *handle, + handle_t *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -77,20 +77,20 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, u64 *bg_blkno); static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr); -static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle, +static inline int ocfs2_block_group_set_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, unsigned int bit_off, unsigned int num_bits); -static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle, +static inline int ocfs2_block_group_clear_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, unsigned int bit_off, unsigned int num_bits); -static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle, +static int ocfs2_relink_block_group(handle_t *handle, struct inode *alloc_inode, struct buffer_head *fe_bh, struct buffer_head *bg_bh, @@ -98,7 +98,7 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle, u16 chain); static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg, u32 wanted); -static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, +static int ocfs2_free_suballoc_bits(handle_t *handle, struct inode *alloc_inode, struct buffer_head *alloc_bh, unsigned int start_bit, @@ -196,7 +196,7 @@ static int ocfs2_check_group_descriptor(struct super_block *sb, return 0; } -static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle, +static int ocfs2_block_group_fill(handle_t *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, u64 group_blkno, @@ -279,7 +279,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; struct ocfs2_chain_list *cl; struct ocfs2_alloc_context *ac = NULL; - struct ocfs2_journal_handle *handle = NULL; + handle_t *handle = NULL; u32 bit_off, num_bits; u16 alloc_rec; u64 bg_blkno; @@ -747,7 +747,7 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, return status; } -static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle, +static inline int ocfs2_block_group_set_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, @@ -818,7 +818,7 @@ static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl) return best; } -static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle, +static int ocfs2_relink_block_group(handle_t *handle, struct inode *alloc_inode, struct buffer_head *fe_bh, struct buffer_head *bg_bh, @@ -998,7 +998,7 @@ static int ocfs2_block_group_search(struct inode *inode, } static int ocfs2_alloc_dinode_update_counts(struct inode *inode, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct buffer_head *di_bh, u32 num_bits, u16 chain) @@ -1028,7 +1028,7 @@ out: } static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, - struct ocfs2_journal_handle *handle, + handle_t *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1088,7 +1088,7 @@ out: } static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, - struct ocfs2_journal_handle *handle, + handle_t *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1245,7 +1245,7 @@ bail: /* will give out up to bits_wanted contiguous bits. */ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, - struct ocfs2_journal_handle *handle, + handle_t *handle, u32 bits_wanted, u32 min_bits, u16 *bit_off, @@ -1362,7 +1362,7 @@ bail: } int ocfs2_claim_metadata(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 bits_wanted, u16 *suballoc_bit_start, @@ -1399,7 +1399,7 @@ bail: } int ocfs2_claim_new_inode(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u16 *suballoc_bit, u64 *fe_blkno) @@ -1502,7 +1502,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, * of any size. */ int ocfs2_claim_clusters(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 *cluster_start, @@ -1572,7 +1572,7 @@ bail: return status; } -static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle, +static inline int ocfs2_block_group_clear_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, @@ -1627,7 +1627,7 @@ bail: /* * expects the suballoc inode to already be locked. */ -static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, +static int ocfs2_free_suballoc_bits(handle_t *handle, struct inode *alloc_inode, struct buffer_head *alloc_bh, unsigned int start_bit, @@ -1711,7 +1711,7 @@ static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit) return group; } -int ocfs2_free_dinode(struct ocfs2_journal_handle *handle, +int ocfs2_free_dinode(handle_t *handle, struct inode *inode_alloc_inode, struct buffer_head *inode_alloc_bh, struct ocfs2_dinode *di) @@ -1724,7 +1724,7 @@ int ocfs2_free_dinode(struct ocfs2_journal_handle *handle, inode_alloc_bh, bit, bg_blkno, 1); } -int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle, +int ocfs2_free_extent_block(handle_t *handle, struct inode *eb_alloc_inode, struct buffer_head *eb_alloc_bh, struct ocfs2_extent_block *eb) @@ -1737,7 +1737,7 @@ int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle, bit, bg_blkno, 1); } -int ocfs2_free_clusters(struct ocfs2_journal_handle *handle, +int ocfs2_free_clusters(handle_t *handle, struct inode *bitmap_inode, struct buffer_head *bitmap_bh, u64 start_blk, diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index e7c4b27..1a3c94c 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h @@ -68,33 +68,33 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb, struct ocfs2_alloc_context **ac); int ocfs2_claim_metadata(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 bits_wanted, u16 *suballoc_bit_start, u32 *num_bits, u64 *blkno_start); int ocfs2_claim_new_inode(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u16 *suballoc_bit, u64 *fe_blkno); int ocfs2_claim_clusters(struct ocfs2_super *osb, - struct ocfs2_journal_handle *handle, + handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 *cluster_start, u32 *num_clusters); -int ocfs2_free_dinode(struct ocfs2_journal_handle *handle, +int ocfs2_free_dinode(handle_t *handle, struct inode *inode_alloc_inode, struct buffer_head *inode_alloc_bh, struct ocfs2_dinode *di); -int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle, +int ocfs2_free_extent_block(handle_t *handle, struct inode *eb_alloc_inode, struct buffer_head *eb_alloc_bh, struct ocfs2_extent_block *eb); -int ocfs2_free_clusters(struct ocfs2_journal_handle *handle, +int ocfs2_free_clusters(handle_t *handle, struct inode *bitmap_inode, struct buffer_head *bitmap_bh, u64 start_blk, -- cgit v0.10.2 From 55ed16029d597622db8121270e687373b5e31722 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 20 Oct 2006 14:55:54 -0700 Subject: configfs: mutex_lock_nested() fix configfs_unregister_subsystem() nests a pair of inode i_mutex acquisitions, and thus needs annotation via mutex_lock_nested(). Signed-off-by: Mark Fasheh diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8a3b6a1..452cfd1 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1176,8 +1176,9 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) return; } - mutex_lock(&configfs_sb->s_root->d_inode->i_mutex); - mutex_lock(&dentry->d_inode->i_mutex); + mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex, + I_MUTEX_PARENT); + mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); if (configfs_detach_prep(dentry)) { printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n"); } -- cgit v0.10.2 From d23a147bb6e8d467e8df73b6589888717da3b9ce Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 17 Oct 2006 17:05:18 -0700 Subject: [PATCH] Export should_remove_suid() This helps us avoid replicating the same logic within file system drivers. Signed-off-by: Mark Fasheh diff --git a/mm/filemap.c b/mm/filemap.c index 7b84dc8..13df01c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1893,6 +1893,7 @@ int should_remove_suid(struct dentry *dentry) return 0; } +EXPORT_SYMBOL(should_remove_suid); int __remove_suid(struct dentry *dentry, int kill) { -- cgit v0.10.2 From e88d0c9a4180821ad64c1fb421e4c28f8155eb74 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 17 Oct 2006 17:06:53 -0700 Subject: ocfs2: Remove ocfs2_write_should_remove_suid() Use should_remove_suid() instead. Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index fe6b795..39b2f16 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -943,20 +943,6 @@ out: return ret; } -static inline int ocfs2_write_should_remove_suid(struct inode *inode) -{ - mode_t mode = inode->i_mode; - - if (!capable(CAP_FSETID)) { - if (unlikely(mode & S_ISUID)) - return 1; - - if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) - return 1; - } - return 0; -} - static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, @@ -1021,7 +1007,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, * inode. There's also the dinode i_size state which * can be lost via setattr during extending writes (we * set inode->i_size at the end of a write. */ - if (ocfs2_write_should_remove_suid(inode)) { + if (should_remove_suid(filp->f_dentry)) { if (meta_level == 0) { ocfs2_meta_unlock(inode, meta_level); meta_level = 1; -- cgit v0.10.2 From 8659ac25b434fcc61cf7797f4b69edc3eaaffb55 Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Tue, 17 Oct 2006 18:29:52 -0700 Subject: ocfs2: Add splice support Add splice read/write support in ocfs2. ocfs2_file_splice_read/write are very similar to ocfs2_file_aio_read/write. Signed-off-by: Tiger Yang Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 39b2f16..b32cdb3 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -31,6 +31,7 @@ #include #include #include +#include #define MLOG_MASK_PREFIX ML_INODE #include @@ -943,53 +944,21 @@ out: return ret; } -static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, - const struct iovec *iov, - unsigned long nr_segs, - loff_t pos) +static int ocfs2_prepare_inode_for_write(struct dentry *dentry, + loff_t *ppos, + size_t count, + int appending) { - int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0; + int ret = 0, meta_level = appending; + struct inode *inode = dentry->d_inode; u32 clusters; - struct file *filp = iocb->ki_filp; - struct inode *inode = filp->f_dentry->d_inode; loff_t newsize, saved_pos; - mlog_entry("(0x%p, %u, '%.*s')\n", filp, - (unsigned int)nr_segs, - filp->f_dentry->d_name.len, - filp->f_dentry->d_name.name); - - /* happy write of zero bytes */ - if (iocb->ki_left == 0) - return 0; - - if (!inode) { - mlog(0, "bad inode\n"); - return -EIO; - } - - mutex_lock(&inode->i_mutex); - /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ - if (filp->f_flags & O_DIRECT) { - have_alloc_sem = 1; - down_read(&inode->i_alloc_sem); - } - - /* concurrent O_DIRECT writes are allowed */ - rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1; - ret = ocfs2_rw_lock(inode, rw_level); - if (ret < 0) { - rw_level = -1; - mlog_errno(ret); - goto out; - } - /* * We sample i_size under a read level meta lock to see if our write * is extending the file, if it is we back off and get a write level * meta lock. */ - meta_level = (filp->f_flags & O_APPEND) ? 1 : 0; for(;;) { ret = ocfs2_meta_lock(inode, NULL, meta_level); if (ret < 0) { @@ -1007,7 +976,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, * inode. There's also the dinode i_size state which * can be lost via setattr during extending writes (we * set inode->i_size at the end of a write. */ - if (should_remove_suid(filp->f_dentry)) { + if (should_remove_suid(dentry)) { if (meta_level == 0) { ocfs2_meta_unlock(inode, meta_level); meta_level = 1; @@ -1017,19 +986,19 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ret = ocfs2_write_remove_suid(inode); if (ret < 0) { mlog_errno(ret); - goto out; + goto out_unlock; } } /* work on a copy of ppos until we're sure that we won't have * to recalculate it due to relocking. */ - if (filp->f_flags & O_APPEND) { + if (appending) { saved_pos = i_size_read(inode); mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos); } else { - saved_pos = iocb->ki_pos; + saved_pos = *ppos; } - newsize = iocb->ki_left + saved_pos; + newsize = count + saved_pos; mlog(0, "pos=%lld newsize=%lld cursize=%lld\n", (long long) saved_pos, (long long) newsize, @@ -1062,19 +1031,66 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, if (!clusters) break; - ret = ocfs2_extend_file(inode, NULL, newsize, iocb->ki_left); + ret = ocfs2_extend_file(inode, NULL, newsize, count); if (ret < 0) { if (ret != -ENOSPC) mlog_errno(ret); - goto out; + goto out_unlock; } break; } - /* ok, we're done with i_size and alloc work */ - iocb->ki_pos = saved_pos; + if (appending) + *ppos = saved_pos; + +out_unlock: ocfs2_meta_unlock(inode, meta_level); - meta_level = -1; + +out: + return ret; +} + +static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, + const struct iovec *iov, + unsigned long nr_segs, + loff_t pos) +{ + int ret, rw_level, have_alloc_sem = 0; + struct file *filp = iocb->ki_filp; + struct inode *inode = filp->f_dentry->d_inode; + int appending = filp->f_flags & O_APPEND ? 1 : 0; + + mlog_entry("(0x%p, %u, '%.*s')\n", filp, + (unsigned int)nr_segs, + filp->f_dentry->d_name.len, + filp->f_dentry->d_name.name); + + /* happy write of zero bytes */ + if (iocb->ki_left == 0) + return 0; + + mutex_lock(&inode->i_mutex); + /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ + if (filp->f_flags & O_DIRECT) { + have_alloc_sem = 1; + down_read(&inode->i_alloc_sem); + } + + /* concurrent O_DIRECT writes are allowed */ + rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1; + ret = ocfs2_rw_lock(inode, rw_level); + if (ret < 0) { + rw_level = -1; + mlog_errno(ret); + goto out; + } + + ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos, + iocb->ki_left, appending); + if (ret < 0) { + mlog_errno(ret); + goto out; + } /* communicate with ocfs2_dio_end_io */ ocfs2_iocb_set_rw_locked(iocb); @@ -1100,8 +1116,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, } out: - if (meta_level != -1) - ocfs2_meta_unlock(inode, meta_level); if (have_alloc_sem) up_read(&inode->i_alloc_sem); if (rw_level != -1) @@ -1112,6 +1126,77 @@ out: return ret; } +static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + struct file *out, + loff_t *ppos, + size_t len, + unsigned int flags) +{ + int ret; + struct inode *inode = out->f_dentry->d_inode; + + mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, + (unsigned int)len, + out->f_dentry->d_name.len, + out->f_dentry->d_name.name); + + inode_double_lock(inode, pipe->inode); + + ret = ocfs2_rw_lock(inode, 1); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + + ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0); + if (ret < 0) { + mlog_errno(ret); + goto out_unlock; + } + + /* ok, we're done with i_size and alloc work */ + ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags); + +out_unlock: + ocfs2_rw_unlock(inode, 1); +out: + inode_double_unlock(inode, pipe->inode); + + mlog_exit(ret); + return ret; +} + +static ssize_t ocfs2_file_splice_read(struct file *in, + loff_t *ppos, + struct pipe_inode_info *pipe, + size_t len, + unsigned int flags) +{ + int ret = 0; + struct inode *inode = in->f_dentry->d_inode; + + mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, + (unsigned int)len, + in->f_dentry->d_name.len, + in->f_dentry->d_name.name); + + /* + * See the comment in ocfs2_file_aio_read() + */ + ret = ocfs2_meta_lock(inode, NULL, 0); + if (ret < 0) { + mlog_errno(ret); + goto bail; + } + ocfs2_meta_unlock(inode, 0); + + ret = generic_file_splice_read(in, ppos, pipe, len, flags); + +bail: + mlog_exit(ret); + return ret; +} + static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, @@ -1210,6 +1295,8 @@ const struct file_operations ocfs2_fops = { .aio_read = ocfs2_file_aio_read, .aio_write = ocfs2_file_aio_write, .ioctl = ocfs2_ioctl, + .splice_read = ocfs2_file_splice_read, + .splice_write = ocfs2_file_splice_write, }; const struct file_operations ocfs2_dops = { -- cgit v0.10.2 From 7f1a37e31f94b4f1c123d32ce9f69205ab2095bd Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Wed, 15 Nov 2006 15:48:42 +0800 Subject: ocfs2: core atime update functions This patch adds the core routines for updating atime in ocfs2. Signed-off-by: Tiger Yang Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 7a22118..69fba16 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -49,6 +49,7 @@ #include "dcache.h" #include "dlmglue.h" #include "extent_map.h" +#include "file.h" #include "heartbeat.h" #include "inode.h" #include "journal.h" @@ -1723,6 +1724,44 @@ int ocfs2_meta_lock_with_page(struct inode *inode, return ret; } +int ocfs2_meta_lock_atime(struct inode *inode, + struct vfsmount *vfsmnt, + int *level) +{ + int ret; + + mlog_entry_void(); + ret = ocfs2_meta_lock(inode, NULL, 0); + if (ret < 0) { + mlog_errno(ret); + return ret; + } + + /* + * If we should update atime, we will get EX lock, + * otherwise we just get PR lock. + */ + if (ocfs2_should_update_atime(inode, vfsmnt)) { + struct buffer_head *bh = NULL; + + ocfs2_meta_unlock(inode, 0); + ret = ocfs2_meta_lock(inode, &bh, 1); + if (ret < 0) { + mlog_errno(ret); + return ret; + } + *level = 1; + if (ocfs2_should_update_atime(inode, vfsmnt)) + ocfs2_update_inode_atime(inode, bh); + if (bh) + brelse(bh); + } else + *level = 0; + + mlog_exit(ret); + return ret; +} + void ocfs2_meta_unlock(struct inode *inode, int ex) { diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index a1165ed..c343fca 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h @@ -80,6 +80,9 @@ void ocfs2_data_unlock(struct inode *inode, int write); int ocfs2_rw_lock(struct inode *inode, int write); void ocfs2_rw_unlock(struct inode *inode, int write); +int ocfs2_meta_lock_atime(struct inode *inode, + struct vfsmount *vfsmnt, + int *level); int ocfs2_meta_lock_full(struct inode *inode, struct buffer_head **ret_bh, int ex, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b32cdb3..e82288f 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -32,6 +32,7 @@ #include #include #include +#include #define MLOG_MASK_PREFIX ML_INODE #include @@ -135,6 +136,57 @@ bail: return (err < 0) ? -EIO : 0; } +int ocfs2_should_update_atime(struct inode *inode, + struct vfsmount *vfsmnt) +{ + struct timespec now; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + + if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) + return 0; + + if ((inode->i_flags & S_NOATIME) || + ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))) + return 0; + + if ((vfsmnt->mnt_flags & MNT_NOATIME) || + ((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) + return 0; + + now = CURRENT_TIME; + if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum)) + return 0; + else + return 1; +} + +int ocfs2_update_inode_atime(struct inode *inode, + struct buffer_head *bh) +{ + int ret; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + handle_t *handle; + + mlog_entry_void(); + + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); + if (handle == NULL) { + ret = -ENOMEM; + mlog_errno(ret); + goto out; + } + + inode->i_atime = CURRENT_TIME; + ret = ocfs2_mark_inode_dirty(handle, inode, bh); + if (ret < 0) + mlog_errno(ret); + + ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); +out: + mlog_exit(ret); + return ret; +} + int ocfs2_set_inode_size(handle_t *handle, struct inode *inode, struct buffer_head *fe_bh, diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 84f8b97..475ed8a 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -54,4 +54,9 @@ int ocfs2_set_inode_size(handle_t *handle, struct buffer_head *fe_bh, u64 new_i_size); +int ocfs2_should_update_atime(struct inode *inode, + struct vfsmount *vfsmnt); +int ocfs2_update_inode_atime(struct inode *inode, + struct buffer_head *bh); + #endif /* OCFS2_FILE_H */ diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index ad4d4a1..42e361f 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -360,7 +360,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, inode); ocfs2_set_inode_flags(inode); - inode->i_flags |= S_NOATIME; status = 0; bail: diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 553e702..0788837 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -180,6 +180,7 @@ enum ocfs2_mount_options #define OCFS2_OSB_SOFT_RO 0x0001 #define OCFS2_OSB_HARD_RO 0x0002 #define OCFS2_OSB_ERROR_FS 0x0004 +#define OCFS2_DEFAULT_ATIME_QUANTUM 60 struct ocfs2_journal; struct ocfs2_super @@ -218,6 +219,7 @@ struct ocfs2_super unsigned long osb_flags; unsigned long s_mount_opt; + unsigned int s_atime_quantum; u16 max_slots; s16 node_num; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index d9b1eb6..b099257 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -139,6 +139,7 @@ enum { Opt_hb_local, Opt_data_ordered, Opt_data_writeback, + Opt_atime_quantum, Opt_err, }; @@ -152,6 +153,7 @@ static match_table_t tokens = { {Opt_hb_local, OCFS2_HB_LOCAL}, {Opt_data_ordered, "data=ordered"}, {Opt_data_writeback, "data=writeback"}, + {Opt_atime_quantum, "atime_quantum=%u"}, {Opt_err, NULL} }; @@ -705,6 +707,7 @@ static int ocfs2_parse_options(struct super_block *sb, while ((p = strsep(&options, ",")) != NULL) { int token, option; substring_t args[MAX_OPT_ARGS]; + struct ocfs2_super * osb = OCFS2_SB(sb); if (!*p) continue; @@ -745,6 +748,16 @@ static int ocfs2_parse_options(struct super_block *sb, case Opt_data_writeback: *mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK; break; + case Opt_atime_quantum: + if (match_int(&args[0], &option)) { + status = 0; + goto bail; + } + if (option >= 0) + osb->s_atime_quantum = option; + else + osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; + break; default: mlog(ML_ERROR, "Unrecognized mount option \"%s\" " @@ -1265,6 +1278,8 @@ static int ocfs2_initialize_super(struct super_block *sb, init_waitqueue_head(&osb->checkpoint_event); atomic_set(&osb->needs_checkpoint, 0); + osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; + osb->node_num = O2NM_INVALID_NODE_NUM; osb->slot_num = OCFS2_INVALID_SLOT; -- cgit v0.10.2 From 25899deef46c226c49c53b42c00e0f032379c04b Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Wed, 15 Nov 2006 15:49:02 +0800 Subject: ocfs2: update file system paths to set atime Conditionally update atime in ocfs2_file_aio_read(), ocfs2_readdir() and ocfs2_mmap(). Signed-off-by: Tiger Yang Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 5efea44..baad2aa 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -82,6 +82,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct inode *inode = filp->f_dentry->d_inode; struct super_block * sb = inode->i_sb; unsigned int ra_sectors = 16; + int lock_level = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -89,7 +90,15 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) stored = 0; bh = NULL; - error = ocfs2_meta_lock(inode, NULL, 0); + error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); + if (lock_level && error >= 0) { + /* We release EX lock which used to update atime + * and get PR lock again to reduce contention + * on commonly accessed directories. */ + ocfs2_meta_unlock(inode, 1); + lock_level = 0; + error = ocfs2_meta_lock(inode, NULL, 0); + } if (error < 0) { if (error != -ENOENT) mlog_errno(error); @@ -198,7 +207,7 @@ revalidate: stored = 0; bail: - ocfs2_meta_unlock(inode, 0); + ocfs2_meta_unlock(inode, lock_level); bail_nolock: mlog_exit(stored); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index e82288f..b64ef7c6 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1254,7 +1254,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, unsigned long nr_segs, loff_t pos) { - int ret = 0, rw_level = -1, have_alloc_sem = 0; + int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0; struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_dentry->d_inode; @@ -1296,12 +1296,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, * like i_size. This allows the checks down below * generic_file_aio_read() a chance of actually working. */ - ret = ocfs2_meta_lock(inode, NULL, 0); + ret = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); if (ret < 0) { mlog_errno(ret); goto bail; } - ocfs2_meta_unlock(inode, 0); + ocfs2_meta_unlock(inode, lock_level); ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos); if (ret == -EINVAL) diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 83934e3..69f85ae 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -82,6 +82,8 @@ static struct vm_operations_struct ocfs2_file_vm_ops = { int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) { + int ret = 0, lock_level = 0; + /* We don't want to support shared writable mappings yet. */ if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) { @@ -91,7 +93,14 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; } - file_accessed(file); + ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode, + file->f_vfsmnt, &lock_level); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level); +out: vma->vm_ops = &ocfs2_file_vm_ops; return 0; } diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index c0f68aa..957d687 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -126,6 +126,10 @@ static int ocfs2_readlink(struct dentry *dentry, goto out; } + /* + * Without vfsmount we can't update atime now, + * but we will update atime here ultimately. + */ ret = vfs_readlink(dentry, buffer, buflen, link); brelse(bh); -- cgit v0.10.2 From 58d206c2fa5cc0b35bf3ca48324d7633aa7d0412 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:24:00 +0100 Subject: configfs: make configfs_dirent_exists() static This patch makes the needlessly global configfs_dirent_exists() static. Signed-off-by: Adrian Bunk Signed-off-by: Joel Becker Signed-off-by: Mark Fasheh diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 452cfd1..c398861 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -93,8 +93,8 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare * * called with parent inode's i_mutex held */ -int configfs_dirent_exists(struct configfs_dirent *parent_sd, - const unsigned char *new) +static int configfs_dirent_exists(struct configfs_dirent *parent_sd, + const unsigned char *new) { struct configfs_dirent * sd; -- cgit v0.10.2 From d38eb8db6aa359c060dfb72a29cf8d94a96657d8 Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Mon, 27 Nov 2006 09:59:21 +0800 Subject: ocfs2: implement i_op->permission Implement .permission() in ocfs2_file_iops, ocfs2_special_file_iops and ocfs2_dir_iops. This helps us avoid some multi-node races with mode change and vfs operations. Signed-off-by: Tiger Yang Signed-off-by: Mark Fasheh diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b64ef7c6..8786b3c 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -945,6 +945,28 @@ bail: return err; } +int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + int ret; + + mlog_entry_void(); + + ret = ocfs2_meta_lock(inode, NULL, 0); + if (ret) { + mlog_errno(ret); + goto out; + } + + ret = generic_permission(inode, mask, NULL); + if (ret) + mlog_errno(ret); + + ocfs2_meta_unlock(inode, 0); +out: + mlog_exit(ret); + return ret; +} + static int ocfs2_write_remove_suid(struct inode *inode) { int ret; @@ -1329,11 +1351,13 @@ bail: struct inode_operations ocfs2_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, + .permission = ocfs2_permission, }; struct inode_operations ocfs2_special_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, + .permission = ocfs2_permission, }; const struct file_operations ocfs2_fops = { diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 475ed8a..601a453 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -48,6 +48,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); +int ocfs2_permission(struct inode *inode, int mask, + struct nameidata *nd); int ocfs2_set_inode_size(handle_t *handle, struct inode *inode, diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 583bffe..21db45d 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2311,4 +2311,5 @@ struct inode_operations ocfs2_dir_iops = { .rename = ocfs2_rename, .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, + .permission = ocfs2_permission, }; -- cgit v0.10.2 From 7e45b0e5f6f68d04311ba7813f5f5457c9119640 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 29 Sep 2006 18:30:05 +0100 Subject: [PATCH] libata: Winbond support Winbond 83759A support in non-multichip mode (afaik nobody ever used multichip mode anyway). The 83759 is not supported by this driver as it is already handled elsewhere and doens't use the same interfaces. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 03f6338..b38e2c3 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -483,6 +483,13 @@ config PATA_WINBOND If unsure, say N. +config PATA_WINBOND_VLB + tristate "Winbond W83759A VLB PATA support (Experimental)" + depends on ISA && EXPERIMENTAL + help + Support for the Winbond W83759A controller on Vesa Local Bus + systems. + endif endmenu diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 72243a6..ff6c6db 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o obj-$(CONFIG_PATA_SIL680) += pata_sil680.o obj-$(CONFIG_PATA_VIA) += pata_via.o obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o +obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o obj-$(CONFIG_PATA_SIS) += pata_sis.o obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o # Should be last but one libata driver diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c new file mode 100644 index 0000000..48941d0 --- /dev/null +++ b/drivers/ata/pata_winbond.c @@ -0,0 +1,306 @@ +/* + * pata_winbond.c - Winbond VLB ATA controllers + * (C) 2006 Red Hat + * + * Support for the Winbond 83759A when operating in advanced mode. + * Multichip mode is not currently supported. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pata_winbond" +#define DRV_VERSION "0.0.1" + +#define NR_HOST 4 /* Two winbond controllers, two channels each */ + +struct winbond_data { + unsigned long config; + struct platform_device *platform_dev; +}; + +static struct ata_host *winbond_host[NR_HOST]; +static struct winbond_data winbond_data[NR_HOST]; +static int nr_winbond_host; + +#ifdef MODULE +static int probe_winbond = 1; +#else +static int probe_winbond; +#endif + +static spinlock_t winbond_lock = SPIN_LOCK_UNLOCKED; + +static void winbond_writecfg(unsigned long port, u8 reg, u8 val) +{ + unsigned long flags; + spin_lock_irqsave(&winbond_lock, flags); + outb(reg, port + 0x01); + outb(val, port + 0x02); + spin_unlock_irqrestore(&winbond_lock, flags); +} + +static u8 winbond_readcfg(unsigned long port, u8 reg) +{ + u8 val; + + unsigned long flags; + spin_lock_irqsave(&winbond_lock, flags); + outb(reg, port + 0x01); + val = inb(port + 0x02); + spin_unlock_irqrestore(&winbond_lock, flags); + + return val; +} + +static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + struct ata_timing t; + struct winbond_data *winbond = ap->host->private_data; + int active, recovery; + u8 reg; + int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); + + reg = winbond_readcfg(winbond->config, 0x81); + + /* Get the timing data in cycles */ + if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ + ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); + else + ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); + + active = (FIT(t.active, 3, 17) - 1) & 0x0F; + recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F; + timing = (active << 4) | recovery; + winbond_writecfg(winbond->config, timing, reg); + + /* Load the setup timing */ + + reg = 0x35; + if (adev->class != ATA_DEV_ATA) + reg |= 0x08; /* FIFO off */ + if (!ata_pio_need_iordy(adev)) + reg |= 0x02; /* IORDY off */ + reg |= (FIT(t.setup, 0, 3) << 6); + winbond_writecfg(winbond->config, timing + 1, reg); +} + + +static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) +{ + struct ata_port *ap = adev->ap; + int slop = buflen & 3; + + if (ata_id_has_dword_io(adev->id)) { + if (write_data) + outsl(ap->ioaddr.data_addr, buf, buflen >> 2); + else + insl(ap->ioaddr.data_addr, buf, buflen >> 2); + + if (unlikely(slop)) { + u32 pad; + if (write_data) { + memcpy(&pad, buf + buflen - slop, slop); + outl(le32_to_cpu(pad), ap->ioaddr.data_addr); + } else { + pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); + memcpy(buf + buflen - slop, &pad, slop); + } + } + } else + ata_pio_data_xfer(adev, buf, buflen, write_data); +} + +static struct scsi_host_template winbond_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations winbond_port_ops = { + .port_disable = ata_port_disable, + .set_piomode = winbond_set_piomode, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .data_xfer = winbond_data_xfer, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop +}; + +/** + * winbond_init_one - attach a winbond interface + * @type: Type to display + * @io: I/O port start + * @irq: interrupt line + * @fast: True if on a > 33Mhz VLB + * + * Register a VLB bus IDE interface. Such interfaces are PIO and we + * assume do not support IRQ sharing. + */ + +static __init int winbond_init_one(unsigned long port) +{ + struct ata_probe_ent ae; + struct platform_device *pdev; + int ret; + u8 reg; + int i; + + reg = winbond_readcfg(port, 0x81); + reg |= 0x80; /* jumpered mode off */ + winbond_writecfg(port, 0x81, reg); + reg = winbond_readcfg(port, 0x83); + reg |= 0xF0; /* local control */ + winbond_writecfg(port, 0x83, reg); + reg = winbond_readcfg(port, 0x85); + reg |= 0xF0; /* programmable timing */ + winbond_writecfg(port, 0x85, reg); + + reg = winbond_readcfg(port, 0x81); + + if (!(reg & 0x03)) /* Disabled */ + return 0; + + for (i = 0; i < 2 ; i ++) { + + if (reg & (1 << i)) { + /* + * Fill in a probe structure first of all + */ + + pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0); + if (pdev == NULL) + return -ENOMEM; + + memset(&ae, 0, sizeof(struct ata_probe_ent)); + INIT_LIST_HEAD(&ae.node); + ae.dev = &pdev->dev; + + ae.port_ops = &winbond_port_ops; + ae.pio_mask = 0x1F; + + ae.sht = &winbond_sht; + + ae.n_ports = 1; + ae.irq = 14 + i; + ae.irq_flags = 0; + ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; + ae.port[0].cmd_addr = 0x1F0 - (0x80 * i); + ae.port[0].altstatus_addr = ae.port[0].cmd_addr + 0x0206; + ae.port[0].ctl_addr = ae.port[0].altstatus_addr; + ata_std_ports(&ae.port[0]); + /* + * Hook in a private data structure per channel + */ + ae.private_data = &winbond_data[nr_winbond_host]; + winbond_data[nr_winbond_host].config = port; + winbond_data[nr_winbond_host].platform_dev = pdev; + + ret = ata_device_add(&ae); + if (ret == 0) { + platform_device_unregister(pdev); + return -ENODEV; + } + winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev); + } + } + + return 0; +} + +/** + * winbond_init - attach winbond interfaces + * + * Attach winbond IDE interfaces by scanning the ports it may occupy. + */ + +static __init int winbond_init(void) +{ + static const unsigned long config[2] = { 0x130, 0x1B0 }; + + int ct = 0; + int i; + + if (probe_winbond == 0) + return -ENODEV; + + /* + * Check both base addresses + */ + + for (i = 0; i < 2; i++) { + if (probe_winbond & (1< Date: Tue, 10 Oct 2006 14:28:12 -0700 Subject: [PATCH] pci_module_init convertion in ata_generic.c pci_module_init convertion in ata_generic.c. Signed-off-by: Henrik Kretzschmar Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 4a80ff9..a44c20c 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -231,7 +231,7 @@ static struct pci_driver ata_generic_pci_driver = { static int __init ata_generic_init(void) { - return pci_module_init(&ata_generic_pci_driver); + return pci_register_driver(&ata_generic_pci_driver); } -- cgit v0.10.2 From 2f27ce03628acdb81ead4abe914c713e04a3229e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 10 Oct 2006 14:28:12 -0700 Subject: [PATCH] pci_module_init-convertion-in-ata_genericc fix Acked-by: Alan Cox but please apply as follows to keep revision id straight Cc: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index a44c20c..1b9ba4d 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -26,7 +26,7 @@ #include #define DRV_NAME "ata_generic" -#define DRV_VERSION "0.2.6" +#define DRV_VERSION "0.2.7" /* * A generic parallel ATA driver using libata -- cgit v0.10.2 From fc085150b491bfc186efbca90a14cf907a3060a9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 10 Oct 2006 14:28:11 -0700 Subject: [PATCH] libata: add 40pin "short" cable support, honour drive side speed detection [deweerdt@free.fr: build fix] Signed-off-by: Alan Cox Signed-off-by: Frederik Deweerdt Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 720174d..14b726b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -93,7 +93,7 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.00ac6" +#define DRV_VERSION "2.00ac7" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -571,6 +571,23 @@ module_param(force_pcs, int, 0444); MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); +struct ich_laptop { + u16 device; + u16 subvendor; + u16 subdevice; +}; + +/* + * List of laptops that use short cables rather than 80 wire + */ + +static const struct ich_laptop ich_laptop[] = { + /* devid, subvendor, subdev */ + { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ + /* end marker */ + { 0, } +}; + /** * piix_pata_cbl_detect - Probe host controller cable detect info * @ap: Port for which cable detect info is desired @@ -585,12 +602,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " static void ich_pata_cbl_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); + const struct ich_laptop *lap = &ich_laptop[0]; u8 tmp, mask; /* no 80c support in host controller? */ if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) goto cbl40; + /* Check for specials - Acer Aspire 5602WLMi */ + while (lap->device) { + if (lap->device == pdev->device && + lap->subvendor == pdev->subsystem_vendor && + lap->subdevice == pdev->subsystem_device) { + ap->cbl = ATA_CBL_PATA40_SHORT; + return; + } + lap++; + } + /* check BIOS cable detect results */ mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 915a55a..b896119 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3119,6 +3119,13 @@ static void ata_dev_xfermask(struct ata_device *dev) */ if (ap->cbl == ATA_CBL_PATA40) xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); + /* Apply drive side cable rule. Unknown or 80 pin cables reported + * host side are checked drive side as well. Cases where we know a + * 40wire cable is used safely for 80 are not checked here. + */ + if (ata_drive_40wire(dev->id) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80)) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); + xfer_mask &= ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, dev->udma_mask); diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 64eed99..e6d2b84 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -78,7 +78,7 @@ static int ali_c2_cable_detect(struct ata_port *ap) implement the detect logic */ if (ali_cable_override(pdev)) - return ATA_CBL_PATA80; + return ATA_CBL_PATA40_SHORT; /* Host view cable detect 0x4A bit 0 primary bit 1 secondary Bit set for 40 pin */ diff --git a/include/linux/ata.h b/include/linux/ata.h index d894419..1df9416 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -200,8 +200,9 @@ enum { ATA_CBL_NONE = 0, ATA_CBL_PATA40 = 1, ATA_CBL_PATA80 = 2, - ATA_CBL_PATA_UNK = 3, - ATA_CBL_SATA = 4, + ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */ + ATA_CBL_PATA_UNK = 4, + ATA_CBL_SATA = 5, /* SATA Status and Control Registers */ SCR_STATUS = 0, @@ -342,6 +343,15 @@ static inline int ata_id_is_cfa(const u16 *id) return 0; } +static inline int ata_drive_40wire(const u16 *dev_id) +{ + if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id)) + return 0; /* SATA */ + if (dev_id[93] & 0x4000) + return 0; /* 80 wire */ + return 1; +} + static inline int atapi_cdb_len(const u16 *dev_id) { u16 tmp = dev_id[0] & 0x3; -- cgit v0.10.2 From 72dc6794fcd7642200a87bf18e3a43e676314b63 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:29:24 -0700 Subject: [PATCH] pci_module_init() conversion for pata_pdc2027x pci_module_init() conversion for pata_pdc2027x Signed-off-by: Henrik Kretzschmar Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index beb6d10..ef85429 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -854,7 +854,7 @@ static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) */ static int __init pdc2027x_init(void) { - return pci_module_init(&pdc2027x_pci_driver); + return pci_register_driver(&pdc2027x_pci_driver); } /** -- cgit v0.10.2 From 75742cb41e4b5c7913f385b9688aad69c9fa7ada Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:40:06 +0100 Subject: [PATCH] pata_marvell: Marvell 6101/6145 PATA driver This is a legacy mode PATA driver for the 6101/45 and will also drive the SATA ports 1 & 2 in legacy mode as well if desired. Tested and confirmed working by users. The chip supports AHCI type behaviour for SATA and has a more advanced PATA interface as well so this driver will get it working but not get best performance for now. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index b38e2c3..9b07e70 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -328,6 +328,15 @@ config PATA_TRIFLEX If unsure, say N. +config PATA_MARVELL + tristate "Marvell PATA support via legacy mode" + depends on PCI + help + This option enables limited support for the Marvell 88SE6145 ATA + controller. + + If unsure, say N. + config PATA_MPIIX tristate "Intel PATA MPIIX support" depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index ff6c6db..ceba7d8 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o obj-$(CONFIG_PATA_OPTI) += pata_opti.o obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o +obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c new file mode 100644 index 0000000..2b8e00c --- /dev/null +++ b/drivers/ata/pata_marvell.c @@ -0,0 +1,221 @@ +/* + * Marvell PATA driver. + * + * For the moment we drive the PATA port in legacy mode. That + * isn't making full use of the device functionality but it is + * easy to get working. + * + * (c) 2006 Red Hat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pata_marvell" +#define DRV_VERSION "0.0.4t" + +/** + * marvell_pre_reset - check for 40/80 pin + * @ap: Port + * + * Perform the PATA port setup we need. + */ + +static int marvell_pre_reset(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u32 devices; + unsigned long bar5; + void __iomem *barp; + int i; + + /* Check if our port is enabled */ + + bar5 = pci_resource_start(pdev, 5); + barp = ioremap(bar5, 0x10); + if (barp == NULL) + return -ENOMEM; + printk("BAR5:"); + for(i = 0; i <= 0x0F; i++) + printk("%02X:%02X ", i, readb(barp + i)); + printk("\n"); + + devices = readl(barp + 0x0C); + iounmap(barp); + + if (pdev->device == 0x6145 && ap->port_no == 0 && !(devices & 0x10)) /* PATA enable ? */ + return -ENOENT; + + /* Cable type */ + switch(ap->port_no) + { + case 0: + /* Might be backward, docs unclear */ + if(inb(ap->ioaddr.bmdma_addr + 1) & 1) + ap->cbl = ATA_CBL_PATA80; + else + ap->cbl = ATA_CBL_PATA40; + + case 1: /* Legacy SATA port */ + ap->cbl = ATA_CBL_SATA; + break; + } + return ata_std_prereset(ap); +} + +/** + * marvell_error_handler - Setup and error handler + * @ap: Port to handle + * + * LOCKING: + * None (inherited from caller). + */ + +static void marvell_error_handler(struct ata_port *ap) +{ + return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL, ata_std_postreset); +} + +/* No PIO or DMA methods needed for this device */ + +static struct scsi_host_template marvell_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + /* Use standard CHS mapping rules */ + .bios_param = ata_std_bios_param, +}; + +static const struct ata_port_operations marvell_ops = { + .port_disable = ata_port_disable, + + /* Task file is PCI ATA format, use helpers */ + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = marvell_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + /* BMDMA handling is PCI ATA format, use helpers */ + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, + + /* Timeout handling */ + .eng_timeout = ata_eng_timeout, + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + /* Generic PATA PCI ATA helpers */ + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + + +/** + * marvell_init_one - Register Marvell ATA PCI device with kernel services + * @pdev: PCI device to register + * @ent: Entry in marvell_pci_tbl matching with @pdev + * + * Called from kernel PCI layer. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, or -ERRNO value. + */ + +static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id) +{ + static struct ata_port_info info = { + .sht = &marvell_sht, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x3f, + + .port_ops = &marvell_ops, + }; + static struct ata_port_info info_sata = { + .sht = &marvell_sht, + /* Slave possible as its magically mapped not real */ + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x7f, + + .port_ops = &marvell_ops, + }; + struct ata_port_info *port_info[2] = { &info, &info_sata }; + int n_port = 2; + + if (pdev->device == 0x6101) + n_port = 1; + + return ata_pci_init_one(pdev, port_info, n_port); +} + +static const struct pci_device_id marvell_pci_tbl[] = { + { PCI_DEVICE(0x11AB, 0x6101), }, + { PCI_DEVICE(0x11AB, 0x6145), }, + { } /* terminate list */ +}; + +static struct pci_driver marvell_pci_driver = { + .name = DRV_NAME, + .id_table = marvell_pci_tbl, + .probe = marvell_init_one, + .remove = ata_pci_remove_one, +}; + +static int __init marvell_init(void) +{ + return pci_register_driver(&marvell_pci_driver); +} + +static void __exit marvell_exit(void) +{ + pci_unregister_driver(&marvell_pci_driver); +} + +module_init(marvell_init); +module_exit(marvell_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, marvell_pci_tbl); +MODULE_VERSION(DRV_VERSION); + -- cgit v0.10.2 From 6e9d8629b5503175a4425722a1ef13eed232c650 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 21 Oct 2006 15:54:13 -0400 Subject: [libata] pata_marvell: minor and trivial cleanups - use pci_iomap() [Alan, version 0.0.5t] - fix Alan's version 0.0.5t change - line length, trailing whitespace, case indentation cleanups - don't use deprecated ->eng_timeout() in a driver that uses new EH Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 2b8e00c..1ea6407 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -20,7 +20,7 @@ #include #define DRV_NAME "pata_marvell" -#define DRV_VERSION "0.0.4t" +#define DRV_VERSION "0.0.5u" /** * marvell_pre_reset - check for 40/80 pin @@ -33,14 +33,12 @@ static int marvell_pre_reset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 devices; - unsigned long bar5; void __iomem *barp; int i; /* Check if our port is enabled */ - bar5 = pci_resource_start(pdev, 5); - barp = ioremap(bar5, 0x10); + barp = pci_iomap(pdev, 5, 0x10); if (barp == NULL) return -ENOMEM; printk("BAR5:"); @@ -49,24 +47,25 @@ static int marvell_pre_reset(struct ata_port *ap) printk("\n"); devices = readl(barp + 0x0C); - iounmap(barp); + pci_iounmap(pdev, barp); - if (pdev->device == 0x6145 && ap->port_no == 0 && !(devices & 0x10)) /* PATA enable ? */ + if ((pdev->device == 0x6145) && (ap->port_no == 0) && + (!(devices & 0x10))) /* PATA enable ? */ return -ENOENT; /* Cable type */ switch(ap->port_no) { - case 0: - /* Might be backward, docs unclear */ - if(inb(ap->ioaddr.bmdma_addr + 1) & 1) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - - case 1: /* Legacy SATA port */ - ap->cbl = ATA_CBL_SATA; - break; + case 0: + /* Might be backward, docs unclear */ + if (inb(ap->ioaddr.bmdma_addr + 1) & 1) + ap->cbl = ATA_CBL_PATA80; + else + ap->cbl = ATA_CBL_PATA40; + + case 1: /* Legacy SATA port */ + ap->cbl = ATA_CBL_SATA; + break; } return ata_std_prereset(ap); } @@ -81,7 +80,8 @@ static int marvell_pre_reset(struct ata_port *ap) static void marvell_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL, ata_std_postreset); + return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, + NULL, ata_std_postreset); } /* No PIO or DMA methods needed for this device */ @@ -130,7 +130,6 @@ static const struct ata_port_operations marvell_ops = { .data_xfer = ata_pio_data_xfer, /* Timeout handling */ - .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -159,7 +158,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i { static struct ata_port_info info = { .sht = &marvell_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -170,7 +169,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i static struct ata_port_info info_sata = { .sht = &marvell_sht, /* Slave possible as its magically mapped not real */ - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -180,10 +179,10 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i }; struct ata_port_info *port_info[2] = { &info, &info_sata }; int n_port = 2; - + if (pdev->device == 0x6101) n_port = 1; - + return ata_pci_init_one(pdev, port_info, n_port); } -- cgit v0.10.2 From fbbb262d9ea9bdbd79d7058271560e9990bc62d3 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Fri, 27 Oct 2006 19:08:41 -0700 Subject: [PATCH] sata_nv ADMA/NCQ support for nForce4 This patch adds support for ADMA mode on NVIDIA nForce4 (CK804/MCP04) SATA controllers to the sata_nv driver. Benefits of ADMA mode include: - NCQ support - Reduced CPU overhead (controller DMAs command information from memory instead of them being pushed in by the CPU) - Full 64-bit DMA support ADMA mode is enabled by default in this version. To disable it, set the module parameter adma_enabled=0. Signed-off-by: Robert Hancock Cc: Jeff Garzik Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 7645f2b..e178d6a 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -732,7 +732,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { u8 host_stat; - host_stat = ata_bmdma_status(ap); + host_stat = ap->ops->bmdma_status(ap); ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat); diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index d65ebfd..e5615be 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -29,6 +29,11 @@ * NV-specific details such as register offsets, SATA phy location, * hotplug info, etc. * + * CK804/MCP04 controllers support an alternate programming interface + * similar to the ADMA specification (with some modifications). + * This allows the use of NCQ. Non-DMA-mapped ATA commands are still + * sent through the legacy interface. + * */ #include @@ -40,10 +45,13 @@ #include #include #include +#include #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "2.0" +#define DRV_VERSION "3.1" + +#define NV_ADMA_DMA_BOUNDARY 0xffffffffUL enum { NV_PORTS = 2, @@ -78,8 +86,137 @@ enum { // For PCI config register 20 NV_MCP_SATA_CFG_20 = 0x50, NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04, + NV_MCP_SATA_CFG_20_PORT0_EN = (1 << 17), + NV_MCP_SATA_CFG_20_PORT1_EN = (1 << 16), + NV_MCP_SATA_CFG_20_PORT0_PWB_EN = (1 << 14), + NV_MCP_SATA_CFG_20_PORT1_PWB_EN = (1 << 12), + + NV_ADMA_MAX_CPBS = 32, + NV_ADMA_CPB_SZ = 128, + NV_ADMA_APRD_SZ = 16, + NV_ADMA_SGTBL_LEN = (1024 - NV_ADMA_CPB_SZ) / + NV_ADMA_APRD_SZ, + NV_ADMA_SGTBL_TOTAL_LEN = NV_ADMA_SGTBL_LEN + 5, + NV_ADMA_SGTBL_SZ = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ, + NV_ADMA_PORT_PRIV_DMA_SZ = NV_ADMA_MAX_CPBS * + (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ), + + /* BAR5 offset to ADMA general registers */ + NV_ADMA_GEN = 0x400, + NV_ADMA_GEN_CTL = 0x00, + NV_ADMA_NOTIFIER_CLEAR = 0x30, + + /* BAR5 offset to ADMA ports */ + NV_ADMA_PORT = 0x480, + + /* size of ADMA port register space */ + NV_ADMA_PORT_SIZE = 0x100, + + /* ADMA port registers */ + NV_ADMA_CTL = 0x40, + NV_ADMA_CPB_COUNT = 0x42, + NV_ADMA_NEXT_CPB_IDX = 0x43, + NV_ADMA_STAT = 0x44, + NV_ADMA_CPB_BASE_LOW = 0x48, + NV_ADMA_CPB_BASE_HIGH = 0x4C, + NV_ADMA_APPEND = 0x50, + NV_ADMA_NOTIFIER = 0x68, + NV_ADMA_NOTIFIER_ERROR = 0x6C, + + /* NV_ADMA_CTL register bits */ + NV_ADMA_CTL_HOTPLUG_IEN = (1 << 0), + NV_ADMA_CTL_CHANNEL_RESET = (1 << 5), + NV_ADMA_CTL_GO = (1 << 7), + NV_ADMA_CTL_AIEN = (1 << 8), + NV_ADMA_CTL_READ_NON_COHERENT = (1 << 11), + NV_ADMA_CTL_WRITE_NON_COHERENT = (1 << 12), + + /* CPB response flag bits */ + NV_CPB_RESP_DONE = (1 << 0), + NV_CPB_RESP_ATA_ERR = (1 << 3), + NV_CPB_RESP_CMD_ERR = (1 << 4), + NV_CPB_RESP_CPB_ERR = (1 << 7), + + /* CPB control flag bits */ + NV_CPB_CTL_CPB_VALID = (1 << 0), + NV_CPB_CTL_QUEUE = (1 << 1), + NV_CPB_CTL_APRD_VALID = (1 << 2), + NV_CPB_CTL_IEN = (1 << 3), + NV_CPB_CTL_FPDMA = (1 << 4), + + /* APRD flags */ + NV_APRD_WRITE = (1 << 1), + NV_APRD_END = (1 << 2), + NV_APRD_CONT = (1 << 3), + + /* NV_ADMA_STAT flags */ + NV_ADMA_STAT_TIMEOUT = (1 << 0), + NV_ADMA_STAT_HOTUNPLUG = (1 << 1), + NV_ADMA_STAT_HOTPLUG = (1 << 2), + NV_ADMA_STAT_CPBERR = (1 << 4), + NV_ADMA_STAT_SERROR = (1 << 5), + NV_ADMA_STAT_CMD_COMPLETE = (1 << 6), + NV_ADMA_STAT_IDLE = (1 << 8), + NV_ADMA_STAT_LEGACY = (1 << 9), + NV_ADMA_STAT_STOPPED = (1 << 10), + NV_ADMA_STAT_DONE = (1 << 12), + NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR | + NV_ADMA_STAT_TIMEOUT, + + /* port flags */ + NV_ADMA_PORT_REGISTER_MODE = (1 << 0), + +}; + +/* ADMA Physical Region Descriptor - one SG segment */ +struct nv_adma_prd { + __le64 addr; + __le32 len; + u8 flags; + u8 packet_len; + __le16 reserved; +}; + +enum nv_adma_regbits { + CMDEND = (1 << 15), /* end of command list */ + WNB = (1 << 14), /* wait-not-BSY */ + IGN = (1 << 13), /* ignore this entry */ + CS1n = (1 << (4 + 8)), /* std. PATA signals follow... */ + DA2 = (1 << (2 + 8)), + DA1 = (1 << (1 + 8)), + DA0 = (1 << (0 + 8)), +}; + +/* ADMA Command Parameter Block + The first 5 SG segments are stored inside the Command Parameter Block itself. + If there are more than 5 segments the remainder are stored in a separate + memory area indicated by next_aprd. */ +struct nv_adma_cpb { + u8 resp_flags; /* 0 */ + u8 reserved1; /* 1 */ + u8 ctl_flags; /* 2 */ + /* len is length of taskfile in 64 bit words */ + u8 len; /* 3 */ + u8 tag; /* 4 */ + u8 next_cpb_idx; /* 5 */ + __le16 reserved2; /* 6-7 */ + __le16 tf[12]; /* 8-31 */ + struct nv_adma_prd aprd[5]; /* 32-111 */ + __le64 next_aprd; /* 112-119 */ + __le64 reserved3; /* 120-127 */ }; + +struct nv_adma_port_priv { + struct nv_adma_cpb *cpb; + dma_addr_t cpb_dma; + struct nv_adma_prd *aprd; + dma_addr_t aprd_dma; + u8 flags; +}; + +#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) + static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void nv_ck804_host_stop(struct ata_host *host); static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); @@ -93,13 +230,27 @@ static void nv_nf2_thaw(struct ata_port *ap); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); static void nv_error_handler(struct ata_port *ap); +static int nv_adma_slave_config(struct scsi_device *sdev); +static void nv_adma_qc_prep(struct ata_queued_cmd *qc); +static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc); +static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance); +static void nv_adma_irq_clear(struct ata_port *ap); +static int nv_adma_port_start(struct ata_port *ap); +static void nv_adma_port_stop(struct ata_port *ap); +static void nv_adma_error_handler(struct ata_port *ap); +static void nv_adma_host_stop(struct ata_host *host); +static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); +static void nv_adma_bmdma_start(struct ata_queued_cmd *qc); +static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc); +static u8 nv_adma_bmdma_status(struct ata_port *ap); enum nv_host_type { GENERIC, NFORCE2, NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ - CK804 + CK804, + ADMA }; static const struct pci_device_id nv_pci_tbl[] = { @@ -160,6 +311,25 @@ static struct scsi_host_template nv_sht = { .bios_param = ata_std_bios_param, }; +static struct scsi_host_template nv_adma_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = NV_ADMA_MAX_CPBS, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = NV_ADMA_DMA_BOUNDARY, + .slave_configure = nv_adma_slave_config, + .slave_destroy = ata_scsi_slave_destroy, + .bios_param = ata_std_bios_param, +}; + static const struct ata_port_operations nv_generic_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, @@ -241,6 +411,33 @@ static const struct ata_port_operations nv_ck804_ops = { .host_stop = nv_ck804_host_stop, }; +static const struct ata_port_operations nv_adma_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + .bmdma_setup = nv_adma_bmdma_setup, + .bmdma_start = nv_adma_bmdma_start, + .bmdma_stop = nv_adma_bmdma_stop, + .bmdma_status = nv_adma_bmdma_status, + .qc_prep = nv_adma_qc_prep, + .qc_issue = nv_adma_qc_issue, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, + .error_handler = nv_adma_error_handler, + .post_internal_cmd = nv_adma_bmdma_stop, + .data_xfer = ata_mmio_data_xfer, + .irq_handler = nv_adma_interrupt, + .irq_clear = nv_adma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = nv_adma_port_start, + .port_stop = nv_adma_port_stop, + .host_stop = nv_adma_host_stop, +}; + static struct ata_port_info nv_port_info[] = { /* generic */ { @@ -269,6 +466,16 @@ static struct ata_port_info nv_port_info[] = { .udma_mask = NV_UDMA_MASK, .port_ops = &nv_ck804_ops, }, + /* ADMA */ + { + .sht = &nv_adma_sht, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_NCQ, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_adma_ops, + }, }; MODULE_AUTHOR("NVIDIA"); @@ -277,6 +484,614 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); +static int adma_enabled = 1; + +static int nv_adma_slave_config(struct scsi_device *sdev) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + u64 bounce_limit; + unsigned long segment_boundary; + unsigned short sg_tablesize; + int rc; + + rc = ata_scsi_slave_config(sdev); + + if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun) + /* Not a proper libata device, ignore */ + return rc; + + if (ap->device[sdev->id].class == ATA_DEV_ATAPI) { + /* + * NVIDIA reports that ADMA mode does not support ATAPI commands. + * Therefore ATAPI commands are sent through the legacy interface. + * However, the legacy interface only supports 32-bit DMA. + * Restrict DMA parameters as required by the legacy interface + * when an ATAPI device is connected. + */ + bounce_limit = ATA_DMA_MASK; + segment_boundary = ATA_DMA_BOUNDARY; + /* Subtract 1 since an extra entry may be needed for padding, see + libata-scsi.c */ + sg_tablesize = LIBATA_MAX_PRD - 1; + } + else { + bounce_limit = *ap->dev->dma_mask; + segment_boundary = NV_ADMA_DMA_BOUNDARY; + sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; + } + + blk_queue_bounce_limit(sdev->request_queue, bounce_limit); + blk_queue_segment_boundary(sdev->request_queue, segment_boundary); + blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); + ata_port_printk(ap, KERN_INFO, + "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n", + (unsigned long long)bounce_limit, segment_boundary, sg_tablesize); + return rc; +} + +static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, u16 *cpb) +{ + unsigned int idx = 0; + + cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device | WNB); + + if ((tf->flags & ATA_TFLAG_LBA48) == 0) { + cpb[idx++] = cpu_to_le16(IGN); + cpb[idx++] = cpu_to_le16(IGN); + cpb[idx++] = cpu_to_le16(IGN); + cpb[idx++] = cpu_to_le16(IGN); + cpb[idx++] = cpu_to_le16(IGN); + } + else { + cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature); + cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah); + } + cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature); + cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam); + cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah); + + cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND); + + return idx; +} + +static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, + unsigned int port_no) +{ + mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; + return mmio; +} + +static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) +{ + return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); +} + +static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) +{ + return (ap->host->mmio_base + NV_ADMA_GEN); +} + +static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) +{ + return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); +} + +static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) +{ + struct nv_adma_port_priv *pp = ap->private_data; + int complete = 0, have_err = 0; + u16 flags = pp->cpb[cpb_num].resp_flags; + + VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags); + + if (flags & NV_CPB_RESP_DONE) { + VPRINTK("CPB flags done, flags=0x%x\n", flags); + complete = 1; + } + if (flags & NV_CPB_RESP_ATA_ERR) { + ata_port_printk(ap, KERN_ERR, "CPB flags ATA err, flags=0x%x\n", flags); + have_err = 1; + complete = 1; + } + if (flags & NV_CPB_RESP_CMD_ERR) { + ata_port_printk(ap, KERN_ERR, "CPB flags CMD err, flags=0x%x\n", flags); + have_err = 1; + complete = 1; + } + if (flags & NV_CPB_RESP_CPB_ERR) { + ata_port_printk(ap, KERN_ERR, "CPB flags CPB err, flags=0x%x\n", flags); + have_err = 1; + complete = 1; + } + if(complete || force_err) + { + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); + if(likely(qc)) { + u8 ata_status = 0; + /* Only use the ATA port status for non-NCQ commands. + For NCQ commands the current status may have nothing to do with + the command just completed. */ + if(qc->tf.protocol != ATA_PROT_NCQ) + ata_status = readb(nv_adma_ctl_block(ap) + (ATA_REG_STATUS * 4)); + + if(have_err || force_err) + ata_status |= ATA_ERR; + + qc->err_mask |= ac_err_mask(ata_status); + DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num, + qc->err_mask); + ata_qc_complete(qc); + } + } +} + +static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + int i, handled = 0; + + spin_lock(&host->lock); + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { + struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = nv_adma_ctl_block(ap); + u16 status; + u32 gen_ctl; + int have_global_err = 0; + u32 notifier, notifier_error; + + /* if in ATA register mode, use standard ata interrupt handler */ + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { + struct ata_queued_cmd *qc; + VPRINTK("in ATA register mode\n"); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) + handled += ata_host_intr(ap, qc); + else { + /* No request pending? Clear interrupt status + anyway, in case there's one pending. */ + ap->ops->check_status(ap); + handled++; + } + continue; + } + + notifier = readl(mmio + NV_ADMA_NOTIFIER); + notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + + gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); + + /* Seems necessary to clear notifiers even when they were 0. + Otherwise we seem to stop receiving further interrupts. + Unsure why. */ + writel(notifier | notifier_error, nv_adma_notifier_clear_block(ap)); + + if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && + !notifier_error) + /* Nothing to do */ + continue; + + status = readw(mmio + NV_ADMA_STAT); + + /* Clear status. Ensure the controller sees the clearing before we start + looking at any of the CPB statuses, so that any CPB completions after + this point in the handler will raise another interrupt. */ + writew(status, mmio + NV_ADMA_STAT); + readw(mmio + NV_ADMA_STAT); /* flush posted write */ + rmb(); + + /* freeze if hotplugged */ + if (unlikely(status & (NV_ADMA_STAT_HOTPLUG | NV_ADMA_STAT_HOTUNPLUG))) { + ata_port_printk(ap, KERN_NOTICE, "Hotplug event, freezing\n"); + ata_port_freeze(ap); + handled++; + continue; + } + + if (status & NV_ADMA_STAT_TIMEOUT) { + ata_port_printk(ap, KERN_ERR, "timeout, stat=0x%x\n", status); + have_global_err = 1; + } + if (status & NV_ADMA_STAT_CPBERR) { + ata_port_printk(ap, KERN_ERR, "CPB error, stat=0x%x\n", status); + have_global_err = 1; + } + if ((status & NV_ADMA_STAT_DONE) || have_global_err) { + /** Check CPBs for completed commands */ + + if(ata_tag_valid(ap->active_tag)) + /* Non-NCQ command */ + nv_adma_check_cpb(ap, ap->active_tag, have_global_err || + (notifier_error & (1 << ap->active_tag))); + else { + int pos; + u32 active = ap->sactive; + while( (pos = ffs(active)) ) { + pos--; + nv_adma_check_cpb(ap, pos, have_global_err || + (notifier_error & (1 << pos)) ); + active &= ~(1 << pos ); + } + } + } + + handled++; /* irq handled if we got here */ + } + } + + spin_unlock(&host->lock); + + return IRQ_RETVAL(handled); +} + +static void nv_adma_irq_clear(struct ata_port *ap) +{ + void __iomem *mmio = nv_adma_ctl_block(ap); + u16 status = readw(mmio + NV_ADMA_STAT); + u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); + u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + + /* clear ADMA status */ + writew(status, mmio + NV_ADMA_STAT); + writel(notifier | notifier_error, + nv_adma_notifier_clear_block(ap)); + + /** clear legacy status */ + ap->flags &= ~ATA_FLAG_MMIO; + ata_bmdma_irq_clear(ap); + ap->flags |= ATA_FLAG_MMIO; +} + +static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + + if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) { + WARN_ON(1); + return; + } + + qc->ap->flags &= ~ATA_FLAG_MMIO; + ata_bmdma_setup(qc); + qc->ap->flags |= ATA_FLAG_MMIO; +} + +static void nv_adma_bmdma_start(struct ata_queued_cmd *qc) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + + if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) { + WARN_ON(1); + return; + } + + qc->ap->flags &= ~ATA_FLAG_MMIO; + ata_bmdma_start(qc); + qc->ap->flags |= ATA_FLAG_MMIO; +} + +static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + + if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) + return; + + qc->ap->flags &= ~ATA_FLAG_MMIO; + ata_bmdma_stop(qc); + qc->ap->flags |= ATA_FLAG_MMIO; +} + +static u8 nv_adma_bmdma_status(struct ata_port *ap) +{ + u8 status; + struct nv_adma_port_priv *pp = ap->private_data; + + WARN_ON(pp->flags & NV_ADMA_PORT_REGISTER_MODE); + + ap->flags &= ~ATA_FLAG_MMIO; + status = ata_bmdma_status(ap); + ap->flags |= ATA_FLAG_MMIO; + return status; +} + +static void nv_adma_register_mode(struct ata_port *ap) +{ + void __iomem *mmio = nv_adma_ctl_block(ap); + struct nv_adma_port_priv *pp = ap->private_data; + u16 tmp; + + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) + return; + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + + pp->flags |= NV_ADMA_PORT_REGISTER_MODE; +} + +static void nv_adma_mode(struct ata_port *ap) +{ + void __iomem *mmio = nv_adma_ctl_block(ap); + struct nv_adma_port_priv *pp = ap->private_data; + u16 tmp; + + if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) + return; + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + + pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE; +} + +static int nv_adma_port_start(struct ata_port *ap) +{ + struct device *dev = ap->host->dev; + struct nv_adma_port_priv *pp; + int rc; + void *mem; + dma_addr_t mem_dma; + void __iomem *mmio = nv_adma_ctl_block(ap); + u16 tmp; + + VPRINTK("ENTER\n"); + + rc = ata_port_start(ap); + if (rc) + return rc; + + pp = kzalloc(sizeof(*pp), GFP_KERNEL); + if (!pp) { + rc = -ENOMEM; + goto err_out; + } + + mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, + &mem_dma, GFP_KERNEL); + + if (!mem) { + rc = -ENOMEM; + goto err_out_kfree; + } + memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ); + + /* + * First item in chunk of DMA memory: + * 128-byte command parameter block (CPB) + * one for each command tag + */ + pp->cpb = mem; + pp->cpb_dma = mem_dma; + + writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); + writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + + mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; + mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; + + /* + * Second item: block of ADMA_SGTBL_LEN s/g entries + */ + pp->aprd = mem; + pp->aprd_dma = mem_dma; + + ap->private_data = pp; + + /* clear any outstanding interrupt conditions */ + writew(0xffff, mmio + NV_ADMA_STAT); + + /* initialize port variables */ + pp->flags = NV_ADMA_PORT_REGISTER_MODE; + + /* clear CPB fetch count */ + writew(0, mmio + NV_ADMA_CPB_COUNT); + + /* clear GO for register mode */ + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + udelay(1); + writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + + return 0; + +err_out_kfree: + kfree(pp); +err_out: + ata_port_stop(ap); + return rc; +} + +static void nv_adma_port_stop(struct ata_port *ap) +{ + struct device *dev = ap->host->dev; + struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = nv_adma_ctl_block(ap); + + VPRINTK("ENTER\n"); + + writew(0, mmio + NV_ADMA_CTL); + + ap->private_data = NULL; + dma_free_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, pp->cpb, pp->cpb_dma); + kfree(pp); + ata_port_stop(ap); +} + + +static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) +{ + void __iomem *mmio = probe_ent->mmio_base; + struct ata_ioports *ioport = &probe_ent->port[port]; + + VPRINTK("ENTER\n"); + + mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE; + + ioport->cmd_addr = (unsigned long) mmio; + ioport->data_addr = (unsigned long) mmio + (ATA_REG_DATA * 4); + ioport->error_addr = + ioport->feature_addr = (unsigned long) mmio + (ATA_REG_ERR * 4); + ioport->nsect_addr = (unsigned long) mmio + (ATA_REG_NSECT * 4); + ioport->lbal_addr = (unsigned long) mmio + (ATA_REG_LBAL * 4); + ioport->lbam_addr = (unsigned long) mmio + (ATA_REG_LBAM * 4); + ioport->lbah_addr = (unsigned long) mmio + (ATA_REG_LBAH * 4); + ioport->device_addr = (unsigned long) mmio + (ATA_REG_DEVICE * 4); + ioport->status_addr = + ioport->command_addr = (unsigned long) mmio + (ATA_REG_STATUS * 4); + ioport->altstatus_addr = + ioport->ctl_addr = (unsigned long) mmio + 0x20; +} + +static int nv_adma_host_init(struct ata_probe_ent *probe_ent) +{ + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); + unsigned int i; + u32 tmp32; + + VPRINTK("ENTER\n"); + + /* enable ADMA on the ports */ + pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); + tmp32 |= NV_MCP_SATA_CFG_20_PORT0_EN | + NV_MCP_SATA_CFG_20_PORT0_PWB_EN | + NV_MCP_SATA_CFG_20_PORT1_EN | + NV_MCP_SATA_CFG_20_PORT1_PWB_EN; + + pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); + + for (i = 0; i < probe_ent->n_ports; i++) + nv_adma_setup_port(probe_ent, i); + + for (i = 0; i < probe_ent->n_ports; i++) { + void __iomem *mmio = __nv_adma_ctl_block(probe_ent->mmio_base, i); + u16 tmp; + + /* enable interrupt, clear reset if not already clear */ + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); + } + + return 0; +} + +static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, + struct scatterlist *sg, + int idx, + struct nv_adma_prd *aprd) +{ + u32 flags; + + memset(aprd, 0, sizeof(struct nv_adma_prd)); + + flags = 0; + if (qc->tf.flags & ATA_TFLAG_WRITE) + flags |= NV_APRD_WRITE; + if (idx == qc->n_elem - 1) + flags |= NV_APRD_END; + else if (idx != 4) + flags |= NV_APRD_CONT; + + aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg))); + aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */ + aprd->flags = cpu_to_le32(flags); +} + +static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + unsigned int idx; + struct nv_adma_prd *aprd; + struct scatterlist *sg; + + VPRINTK("ENTER\n"); + + idx = 0; + + ata_for_each_sg(sg, qc) { + aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; + nv_adma_fill_aprd(qc, sg, idx, aprd); + idx++; + } + if (idx > 5) + cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); +} + +static void nv_adma_qc_prep(struct ata_queued_cmd *qc) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + struct nv_adma_cpb *cpb = &pp->cpb[qc->tag]; + u8 ctl_flags = NV_CPB_CTL_CPB_VALID | + NV_CPB_CTL_APRD_VALID | + NV_CPB_CTL_IEN; + + VPRINTK("qc->flags = 0x%lx\n", qc->flags); + + if (!(qc->flags & ATA_QCFLAG_DMAMAP) || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + ata_qc_prep(qc); + return; + } + + memset(cpb, 0, sizeof(struct nv_adma_cpb)); + + cpb->len = 3; + cpb->tag = qc->tag; + cpb->next_cpb_idx = 0; + + /* turn on NCQ flags for NCQ commands */ + if (qc->tf.protocol == ATA_PROT_NCQ) + ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA; + + nv_adma_tf_to_cpb(&qc->tf, cpb->tf); + + nv_adma_fill_sg(qc, cpb); + + /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are + finished filling in all of the contents */ + wmb(); + cpb->ctl_flags = ctl_flags; +} + +static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) +{ + void __iomem *mmio = nv_adma_ctl_block(qc->ap); + + VPRINTK("ENTER\n"); + + if (!(qc->flags & ATA_QCFLAG_DMAMAP) || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* use ATA register mode */ + VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags); + nv_adma_register_mode(qc->ap); + return ata_qc_issue_prot(qc); + } else + nv_adma_mode(qc->ap); + + /* write append register, command tag in lower 8 bits + and (number of cpbs to append -1) in top 8 bits */ + wmb(); + writew(qc->tag, mmio + NV_ADMA_APPEND); + + DPRINTK("Issued tag %u\n",qc->tag); + + return 0; +} + static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; @@ -466,6 +1281,56 @@ static void nv_error_handler(struct ata_port *ap) nv_hardreset, ata_std_postreset); } +static void nv_adma_error_handler(struct ata_port *ap) +{ + struct nv_adma_port_priv *pp = ap->private_data; + if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { + void __iomem *mmio = nv_adma_ctl_block(ap); + int i; + u16 tmp; + + u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); + u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + u32 gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); + u32 status = readw(mmio + NV_ADMA_STAT); + + ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " + "notifier_error 0x%X gen_ctl 0x%X status 0x%X\n", + notifier, notifier_error, gen_ctl, status); + + for( i=0;icpb[i]; + if( cpb->ctl_flags || cpb->resp_flags ) + ata_port_printk(ap, KERN_ERR, + "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", + i, cpb->ctl_flags, cpb->resp_flags); + } + + /* Push us back into port register mode for error handling. */ + nv_adma_register_mode(ap); + + ata_port_printk(ap, KERN_ERR, "Resetting port\n"); + + /* Mark all of the CPBs as invalid to prevent them from being executed */ + for( i=0;icpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID; + + /* clear CPB fetch count */ + writew(0, mmio + NV_ADMA_CPB_COUNT); + + /* Reset channel */ + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + udelay(1); + writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + } + + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, + nv_hardreset, ata_std_postreset); +} + static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; @@ -475,6 +1340,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) int rc; u32 bar; unsigned long base; + unsigned long type = ent->driver_data; + int mask_set = 0; // Make sure this is a SATA controller by counting the number of bars // (NVIDIA SATA controllers will always have six bars). Otherwise, @@ -483,7 +1350,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_resource_start(pdev, bar) == 0) return -ENODEV; - if (!printed_version++) + if ( !printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); @@ -496,16 +1363,26 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_disable; } - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; + if(type >= CK804 && adma_enabled) { + dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); + type = ADMA; + if(!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && + !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + mask_set = 1; + } + + if(!mask_set) { + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + } rc = -ENOMEM; - ppi[0] = ppi[1] = &nv_port_info[ent->driver_data]; + ppi[0] = ppi[1] = &nv_port_info[type]; probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) goto err_out_regions; @@ -522,7 +1399,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; /* enable SATA space for CK804 */ - if (ent->driver_data == CK804) { + if (type >= CK804) { u8 regval; pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); @@ -532,6 +1409,12 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); + if (type == ADMA) { + rc = nv_adma_host_init(probe_ent); + if (rc) + goto err_out_iounmap; + } + rc = ata_device_add(probe_ent); if (rc != NV_PORTS) goto err_out_iounmap; @@ -566,6 +1449,33 @@ static void nv_ck804_host_stop(struct ata_host *host) ata_pci_host_stop(host); } +static void nv_adma_host_stop(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + int i; + u32 tmp32; + + for (i = 0; i < host->n_ports; i++) { + void __iomem *mmio = __nv_adma_ctl_block(host->mmio_base, i); + u16 tmp; + + /* disable interrupt */ + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp & ~NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); + } + + /* disable ADMA on the ports */ + pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); + tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | + NV_MCP_SATA_CFG_20_PORT0_PWB_EN | + NV_MCP_SATA_CFG_20_PORT1_EN | + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + + pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); + + nv_ck804_host_stop(host); +} + static int __init nv_init(void) { return pci_register_driver(&nv_pci_driver); @@ -578,3 +1488,5 @@ static void __exit nv_exit(void) module_init(nv_init); module_exit(nv_exit); +module_param_named(adma, adma_enabled, bool, 0444); +MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); -- cgit v0.10.2 From 6919a0a6cfdad9e83d02cef5973826acd416560c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 27 Oct 2006 19:08:46 -0700 Subject: [PATCH] libata: Revamp blacklist support to allow multiple kinds of blacklisting flaws Signed-off-by: Alan Cox Cc: Jeff Garzik Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b896119..b4fbfeb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1345,7 +1345,10 @@ static void ata_dev_config_ncq(struct ata_device *dev, desc[0] = '\0'; return; } - + if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) { + snprintf(desc, desc_sz, "NCQ (not used)"); + return; + } if (ap->flags & ATA_FLAG_NCQ) { hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1); dev->flags |= ATA_DFLAG_NCQ; @@ -3014,37 +3017,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) return rc; } -static const char * const ata_dma_blacklist [] = { - "WDC AC11000H", NULL, - "WDC AC22100H", NULL, - "WDC AC32500H", NULL, - "WDC AC33100H", NULL, - "WDC AC31600H", NULL, - "WDC AC32100H", "24.09P07", - "WDC AC23200L", "21.10N21", - "Compaq CRD-8241B", NULL, - "CRD-8400B", NULL, - "CRD-8480B", NULL, - "CRD-8482B", NULL, - "CRD-84", NULL, - "SanDisk SDP3B", NULL, - "SanDisk SDP3B-64", NULL, - "SANYO CD-ROM CRD", NULL, - "HITACHI CDR-8", NULL, - "HITACHI CDR-8335", NULL, - "HITACHI CDR-8435", NULL, - "Toshiba CD-ROM XM-6202B", NULL, - "TOSHIBA CD-ROM XM-1702BC", NULL, - "CD-532E-A", NULL, - "E-IDE CD-ROM CR-840", NULL, - "CD-ROM Drive/F5A", NULL, - "WPI CDD-820", NULL, - "SAMSUNG CD-ROM SC-148C", NULL, - "SAMSUNG CD-ROM SC", NULL, - "SanDisk SDP3B-64", NULL, - "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, - "_NEC DV5800A", NULL, - "SAMSUNG CD-ROM SN-124", "N001" +struct ata_blacklist_entry { + const char *model_num; + const char *model_rev; + unsigned long horkage; +}; + +static const struct ata_blacklist_entry ata_device_blacklist [] = { + /* Devices with DMA related problems under Linux */ + { "WDC AC11000H", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC22100H", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC32500H", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC33100H", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC31600H", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC32100H", "24.09P07", ATA_HORKAGE_NODMA }, + { "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA }, + { "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA }, + { "CRD-8400B", NULL, ATA_HORKAGE_NODMA }, + { "CRD-8480B", NULL, ATA_HORKAGE_NODMA }, + { "CRD-8482B", NULL, ATA_HORKAGE_NODMA }, + { "CRD-84", NULL, ATA_HORKAGE_NODMA }, + { "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA }, + { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA }, + { "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA }, + { "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA }, + { "HITACHI CDR-8335", NULL, ATA_HORKAGE_NODMA }, + { "HITACHI CDR-8435", NULL, ATA_HORKAGE_NODMA }, + { "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA }, + { "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA }, + { "CD-532E-A", NULL, ATA_HORKAGE_NODMA }, + { "E-IDE CD-ROM CR-840",NULL, ATA_HORKAGE_NODMA }, + { "CD-ROM Drive/F5A", NULL, ATA_HORKAGE_NODMA }, + { "WPI CDD-820", NULL, ATA_HORKAGE_NODMA }, + { "SAMSUNG CD-ROM SC-148C", NULL, ATA_HORKAGE_NODMA }, + { "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA }, + { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA }, + { "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA }, + { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, + { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, + + /* Devices we expect to fail diagnostics */ + + /* Devices where NCQ should be avoided */ + /* NCQ is slow */ + { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, + + /* Devices with NCQ limits */ + + /* End Marker */ + { } }; static int ata_strim(char *s, size_t len) @@ -3059,20 +3080,12 @@ static int ata_strim(char *s, size_t len) return len; } -static int ata_dma_blacklisted(const struct ata_device *dev) +unsigned long ata_device_blacklisted(const struct ata_device *dev) { unsigned char model_num[40]; unsigned char model_rev[16]; unsigned int nlen, rlen; - int i; - - /* We don't support polling DMA. - * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) - * if the LLDD handles only interrupts in the HSM_ST_LAST state. - */ - if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && - (dev->flags & ATA_DFLAG_CDB_INTR)) - return 1; + const struct ata_blacklist_entry *ad = ata_device_blacklist; ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); @@ -3081,17 +3094,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev) nlen = ata_strim(model_num, sizeof(model_num)); rlen = ata_strim(model_rev, sizeof(model_rev)); - for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { - if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { - if (ata_dma_blacklist[i+1] == NULL) - return 1; - if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) - return 1; + while (ad->model_num) { + if (!strncmp(ad->model_num, model_num, nlen)) { + if (ad->model_rev == NULL) + return ad->horkage; + if (!strncmp(ad->model_rev, model_rev, rlen)) + return ad->horkage; } + ad++; } return 0; } +static int ata_dma_blacklisted(const struct ata_device *dev) +{ + /* We don't support polling DMA. + * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) + * if the LLDD handles only interrupts in the HSM_ST_LAST state. + */ + if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && + (dev->flags & ATA_DFLAG_CDB_INTR)) + return 1; + return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0; +} + /** * ata_dev_xfermask - Compute supported xfermask of the given device * @dev: Device to compute xfermask for @@ -6153,6 +6179,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend); EXPORT_SYMBOL_GPL(ata_host_resume); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); +EXPORT_SYMBOL_GPL(ata_device_blacklisted); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); diff --git a/include/linux/libata.h b/include/linux/libata.h index abd2deb..2300fcc 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -307,6 +307,8 @@ enum { (some horkage may be drive/controller pair dependant */ ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ + ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ + ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ }; enum hsm_task_states { @@ -787,6 +789,7 @@ extern void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); +extern unsigned long ata_device_blacklisted(const struct ata_device *dev); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); -- cgit v0.10.2 From a20c9e820864e18b59d2a4f2f04e8b6053986c95 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 27 Oct 2006 19:08:48 -0700 Subject: [PATCH] ata: Generic platform_device libata driver needs a changelog Signed-off-by: Paul Mundt Acked-by: Russell King Cc: Jeff Garzik Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 9b07e70..98d0f01 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -499,6 +499,15 @@ config PATA_WINBOND_VLB Support for the Winbond W83759A controller on Vesa Local Bus systems. +config PATA_PLATFORM + tristate "Generic platform device PATA support" + depends on EMBEDDED + help + This option enables support for generic directly connected ATA + devices commonly found on embedded systems. + + If unsure, say N. + endif endmenu diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index ceba7d8..f2b3ea2 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o obj-$(CONFIG_PATA_SIS) += pata_sis.o obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o +obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o # Should be last but one libata driver obj-$(CONFIG_ATA_GENERIC) += ata_generic.o # Should be last libata driver diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c new file mode 100644 index 0000000..63d6687 --- /dev/null +++ b/drivers/ata/pata_platform.c @@ -0,0 +1,295 @@ +/* + * Generic platform device PATA driver + * + * Copyright (C) 2006 Paul Mundt + * + * Based on pata_pcmcia: + * + * Copyright 2005-2006 Red Hat Inc , all rights reserved. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pata_platform" +#define DRV_VERSION "0.1.2" + +static int pio_mask = 1; + +/* + * Provide our own set_mode() as we don't want to change anything that has + * already been configured.. + */ +static void pata_platform_set_mode(struct ata_port *ap) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (ata_dev_enabled(dev)) { + /* We don't really care */ + dev->pio_mode = dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + } + } +} + +static void pata_platform_host_stop(struct ata_host *host) +{ + int i; + + /* + * Unmap the bases for MMIO + */ + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + if (ap->flags & ATA_FLAG_MMIO) { + iounmap((void __iomem *)ap->ioaddr.ctl_addr); + iounmap((void __iomem *)ap->ioaddr.cmd_addr); + } + } +} + +static struct scsi_host_template pata_platform_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations pata_platform_port_ops = { + .set_mode = pata_platform_set_mode, + + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .data_xfer = ata_pio_data_xfer_noirq, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = pata_platform_host_stop +}; + +static void pata_platform_setup_port(struct ata_ioports *ioaddr, + struct pata_platform_info *info) +{ + unsigned int shift = 0; + + /* Fixup the port shift for platforms that need it */ + if (info && info->ioport_shift) + shift = info->ioport_shift; + + ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); + ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); + ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); + ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << shift); + ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << shift); + ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << shift); + ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << shift); + ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << shift); + ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << shift); + ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << shift); +} + +/** + * pata_platform_probe - attach a platform interface + * @pdev: platform device + * + * Register a platform bus IDE interface. Such interfaces are PIO and we + * assume do not support IRQ sharing. + * + * Platform devices are expected to contain 3 resources per port: + * + * - I/O Base (IORESOURCE_IO or IORESOURCE_MEM) + * - CTL Base (IORESOURCE_IO or IORESOURCE_MEM) + * - IRQ (IORESOURCE_IRQ) + * + * If the base resources are both mem types, the ioremap() is handled + * here. For IORESOURCE_IO, it's assumed that there's no remapping + * necessary. + */ +static int __devinit pata_platform_probe(struct platform_device *pdev) +{ + struct resource *io_res, *ctl_res; + struct ata_probe_ent ae; + unsigned int mmio; + int ret; + + /* + * Simple resource validation .. + */ + if (unlikely(pdev->num_resources != 3)) { + dev_err(&pdev->dev, "invalid number of resources\n"); + return -EINVAL; + } + + /* + * Get the I/O base first + */ + io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (io_res == NULL) { + io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(io_res == NULL)) + return -EINVAL; + } + + /* + * Then the CTL base + */ + ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); + if (ctl_res == NULL) { + ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (unlikely(ctl_res == NULL)) + return -EINVAL; + } + + /* + * Check for MMIO + */ + mmio = (( io_res->flags == IORESOURCE_MEM) && + (ctl_res->flags == IORESOURCE_MEM)); + + /* + * Now that that's out of the way, wire up the port.. + */ + memset(&ae, 0, sizeof(struct ata_probe_ent)); + INIT_LIST_HEAD(&ae.node); + ae.dev = &pdev->dev; + ae.port_ops = &pata_platform_port_ops; + ae.sht = &pata_platform_sht; + ae.n_ports = 1; + ae.pio_mask = pio_mask; + ae.irq = platform_get_irq(pdev, 0); + ae.irq_flags = 0; + ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; + + /* + * Handle the MMIO case + */ + if (mmio) { + ae.port_flags |= ATA_FLAG_MMIO; + + ae.port[0].cmd_addr = (unsigned long)ioremap(io_res->start, + io_res->end - io_res->start + 1); + if (unlikely(!ae.port[0].cmd_addr)) { + dev_err(&pdev->dev, "failed to remap IO base\n"); + return -ENXIO; + } + + ae.port[0].ctl_addr = (unsigned long)ioremap(ctl_res->start, + ctl_res->end - ctl_res->start + 1); + if (unlikely(!ae.port[0].ctl_addr)) { + dev_err(&pdev->dev, "failed to remap CTL base\n"); + ret = -ENXIO; + goto bad_remap; + } + } else { + ae.port[0].cmd_addr = io_res->start; + ae.port[0].ctl_addr = ctl_res->start; + } + + ae.port[0].altstatus_addr = ae.port[0].ctl_addr; + + pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data); + + if (unlikely(ata_device_add(&ae) == 0)) { + ret = -ENODEV; + goto add_failed; + } + + return 0; + +add_failed: + if (ae.port[0].ctl_addr && mmio) + iounmap((void __iomem *)ae.port[0].ctl_addr); +bad_remap: + if (ae.port[0].cmd_addr && mmio) + iounmap((void __iomem *)ae.port[0].cmd_addr); + + return ret; +} + +/** + * pata_platform_remove - unplug a platform interface + * @pdev: platform device + * + * A platform bus ATA device has been unplugged. Perform the needed + * cleanup. Also called on module unload for any active devices. + */ +static int __devexit pata_platform_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ata_host *host = dev_get_drvdata(dev); + + ata_host_remove(host); + dev_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver pata_platform_driver = { + .probe = pata_platform_probe, + .remove = __devexit_p(pata_platform_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init pata_platform_init(void) +{ + return platform_driver_register(&pata_platform_driver); +} + +static void __exit pata_platform_exit(void) +{ + platform_driver_unregister(&pata_platform_driver); +} +module_init(pata_platform_init); +module_exit(pata_platform_exit); + +module_param(pio_mask, int, 0); + +MODULE_AUTHOR("Paul Mundt"); +MODULE_DESCRIPTION("low-level driver for platform device ATA"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h new file mode 100644 index 0000000..2d5fd64 --- /dev/null +++ b/include/linux/pata_platform.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_PATA_PLATFORM_H +#define __LINUX_PATA_PLATFORM_H + +struct pata_platform_info { + /* + * I/O port shift, for platforms with ports that are + * constantly spaced and need larger than the 1-byte + * spacing used by ata_std_ports(). + */ + unsigned int ioport_shift; +}; + +#endif /* __LINUX_PATA_PLATFORM_H */ -- cgit v0.10.2 From d1adc1bbd6dde3e05a91e2d3e6ab42d202ea61d5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Oct 2006 18:32:15 +0900 Subject: [PATCH] libata: handle 0xff status properly libata waits for !BSY even when the status register reports 0xff. This causes long boot delays when D8 isn't pulled down properly. This patch does the followings. * don't wait if status register is 0xff in all wait functions * make ata_busy_sleep() return 0 on success and -errno on failure. -ENODEV is returned on 0xff status and -EBUSY on other failures. * make ata_bus_softreset() succeed on 0xff status. 0xff status is not reset failure. It indicates no device. This removes unnecessary retries on such ports. Note that the code change assumes unoccupied port reporting 0xff status does not produce valid device signature. Signed-off-by: Tejun Heo Cc: Joe Jin Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b4fbfeb..d233667 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2328,11 +2328,14 @@ static inline void ata_tf_to_host(struct ata_port *ap, * Sleep until ATA Status register bit BSY clears, * or a timeout occurs. * - * LOCKING: None. + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. */ - -unsigned int ata_busy_sleep (struct ata_port *ap, - unsigned long tmout_pat, unsigned long tmout) +int ata_busy_sleep(struct ata_port *ap, + unsigned long tmout_pat, unsigned long tmout) { unsigned long timer_start, timeout; u8 status; @@ -2340,27 +2343,32 @@ unsigned int ata_busy_sleep (struct ata_port *ap, status = ata_busy_wait(ap, ATA_BUSY, 300); timer_start = jiffies; timeout = timer_start + tmout_pat; - while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { + while (status != 0xff && (status & ATA_BUSY) && + time_before(jiffies, timeout)) { msleep(50); status = ata_busy_wait(ap, ATA_BUSY, 3); } - if (status & ATA_BUSY) + if (status != 0xff && (status & ATA_BUSY)) ata_port_printk(ap, KERN_WARNING, "port is slow to respond, please be patient " "(Status 0x%x)\n", status); timeout = timer_start + tmout; - while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { + while (status != 0xff && (status & ATA_BUSY) && + time_before(jiffies, timeout)) { msleep(50); status = ata_chk_status(ap); } + if (status == 0xff) + return -ENODEV; + if (status & ATA_BUSY) { ata_port_printk(ap, KERN_ERR, "port failed to respond " "(%lu secs, Status 0x%x)\n", tmout / HZ, status); - return 1; + return -EBUSY; } return 0; @@ -2451,10 +2459,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * the bus shows 0xFF because the odd clown forgets the D7 * pulldown resistor. */ - if (ata_check_status(ap) == 0xFF) { - ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); - return AC_ERR_OTHER; - } + if (ata_check_status(ap) == 0xFF) + return 0; ata_bus_post_reset(ap, devmask); diff --git a/include/linux/libata.h b/include/linux/libata.h index 2300fcc..6c003d8 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -746,9 +746,8 @@ extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg); extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); extern void ata_host_resume(struct ata_host *host); extern int ata_ratelimit(void); -extern unsigned int ata_busy_sleep(struct ata_port *ap, - unsigned long timeout_pat, - unsigned long timeout); +extern int ata_busy_sleep(struct ata_port *ap, + unsigned long timeout_pat, unsigned long timeout); extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, unsigned long delay); extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, @@ -1064,7 +1063,7 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits, udelay(10); status = ata_chk_status(ap); max--; - } while ((status & bits) && (max > 0)); + } while (status != 0xff && (status & bits) && (max > 0)); return status; } @@ -1085,7 +1084,7 @@ static inline u8 ata_wait_idle(struct ata_port *ap) { u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - if (status & (ATA_BUSY | ATA_DRQ)) { + if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) { unsigned long l = ap->ioaddr.status_addr; if (ata_msg_warn(ap)) printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", -- cgit v0.10.2 From 90088bb41200b4da962282dfd45db82544adac3b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Oct 2006 11:10:26 +0900 Subject: [PATCH] libata: move ata_irq_on() into libata-sff.c ata_irq_on() isn't used outside of libata core layer. The function is TF/SFF interface specific but currently used by core path with some hack too. Move it from include/linux/libata.h to drivers/ata/libata-sff.c. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index e178d6a..37471d3 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -39,6 +39,35 @@ #include "libata.h" /** + * ata_irq_on - Enable interrupts on a port. + * @ap: Port on which interrupts are enabled. + * + * Enable interrupts on a legacy IDE device using MMIO or PIO, + * wait for idle, clear any pending interrupts. + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_irq_on(struct ata_port *ap) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u8 tmp; + + ap->ctl &= ~ATA_NIEN; + ap->last_ctl = ap->ctl; + + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); + tmp = ata_wait_idle(ap); + + ap->ops->irq_clear(ap); + + return tmp; +} + +/** * ata_tf_load_pio - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0ed263b..c833000 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -120,4 +120,7 @@ extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); +/* libata-sff.c */ +extern u8 ata_irq_on(struct ata_port *ap); + #endif /* __LIBATA_H__ */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 6c003d8..d3bf7b9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1150,37 +1150,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) } /** - * ata_irq_on - Enable interrupts on a port. - * @ap: Port on which interrupts are enabled. - * - * Enable interrupts on a legacy IDE device using MMIO or PIO, - * wait for idle, clear any pending interrupts. - * - * LOCKING: - * Inherited from caller. - */ - -static inline u8 ata_irq_on(struct ata_port *ap) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - u8 tmp; - - ap->ctl &= ~ATA_NIEN; - ap->last_ctl = ap->ctl; - - if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); - else - outb(ap->ctl, ioaddr->ctl_addr); - tmp = ata_wait_idle(ap); - - ap->ops->irq_clear(ap); - - return tmp; -} - - -/** * ata_irq_ack - Acknowledge a device interrupt. * @ap: Port on which interrupts are enabled. * -- cgit v0.10.2 From 722420fe6e2ab63bebc5a9ea346016b59076d75d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Sep 2006 17:49:22 +0900 Subject: [PATCH] sata_nv: SRST sometimes fails after hotplug, use HRST_TO_RESUME NV controllers sometimes fail to perform softreset after hotplug. Make it use hardreset to resume link. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index e5615be..a577101 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -442,7 +442,8 @@ static struct ata_port_info nv_port_info[] = { /* generic */ { .sht = &nv_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, @@ -451,7 +452,8 @@ static struct ata_port_info nv_port_info[] = { /* nforce2/3 */ { .sht = &nv_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, @@ -460,7 +462,8 @@ static struct ata_port_info nv_port_info[] = { /* ck804 */ { .sht = &nv_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_HRST_TO_RESUME, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, .udma_mask = NV_UDMA_MASK, -- cgit v0.10.2 From 309afcb5c87b5a41da51cc0c36f61c0e0d43ca9a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 30 Sep 2006 18:07:17 +0900 Subject: [PATCH] libata: make user scan wait for scan to complete Make user scan wait for scan to complete. This way user can wait for warm plug request to complete and is prevented from causing EH event storm by repetitively issuing scan request while EH is in progress. Signed-off-by: Tejun Heo Cc: Fajun Chen Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 47ea111..6b2553d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3182,10 +3182,12 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, rc = -EINVAL; } - if (rc == 0) + if (rc == 0) { ata_port_schedule_eh(ap); - - spin_unlock_irqrestore(ap->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); + ata_port_wait_eh(ap); + } else + spin_unlock_irqrestore(ap->lock, flags); return rc; } -- cgit v0.10.2 From 28c8f3b4f9ec9a5acffdc846effb0695839ecf37 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Oct 2006 08:47:18 +0900 Subject: [PATCH] sata_sil24: rename PMP related constants Rename PMP related constants for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 169e200..6488258 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -100,10 +100,10 @@ enum { */ PORT_REGS_SIZE = 0x2000, - PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */ + PORT_LRAM = 0x0000, /* 31 LRAM slots and PMP regs */ PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ - PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */ + PORT_PMP = 0x0f80, /* 8 bytes PMP * 16 (128 bytes) */ /* 32 bit regs */ PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */ PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */ @@ -139,9 +139,9 @@ enum { PORT_CS_INIT = (1 << 2), /* port initialize */ PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */ - PORT_CS_RESUME = (1 << 6), /* port resume */ + PORT_CS_PMP_RESUME = (1 << 6), /* PMP resume */ PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ - PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */ + PORT_CS_PMP_EN = (1 << 13), /* port multiplier enable */ PORT_CS_RDY = (1 << 31), /* port ready to accept commands */ /* PORT_IRQ_STAT/ENABLE_SET/CLR */ @@ -562,7 +562,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) /* do SRST */ prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); - prb->fis[1] = 0; /* no PM yet */ + prb->fis[1] = 0; /* no PMP yet */ writel((u32)paddr, port + PORT_CMD_ACTIVATE); writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); @@ -1050,7 +1050,8 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports, writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); /* Clear port multiplier enable and resume bits */ - writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); + writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, + port + PORT_CTRL_CLR); } /* Turn on interrupts */ -- cgit v0.10.2 From c0c559083a084f9a19443d522b7d95a33701505a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Oct 2006 08:47:18 +0900 Subject: [PATCH] sata_sil24: add PMP related constants Add PMP related constants. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 6488258..5aa288d 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -104,6 +104,10 @@ enum { PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ PORT_PMP = 0x0f80, /* 8 bytes PMP * 16 (128 bytes) */ + PORT_PMP_STATUS = 0x0000, /* port device status offset */ + PORT_PMP_QACTIVE = 0x0004, /* port device QActive offset */ + PORT_PMP_SIZE = 0x0008, /* 8 bytes per PMP */ + /* 32 bit regs */ PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */ PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */ @@ -126,6 +130,7 @@ enum { PORT_PHY_CFG = 0x1050, PORT_SLOT_STAT = 0x1800, PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */ + PORT_CONTEXT = 0x1e04, PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */ PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */ PORT_SCONTROL = 0x1f00, -- cgit v0.10.2 From 4aeb0e3283351351a5381a495ea24537f3bc21cb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 17:58:33 +0900 Subject: [PATCH] ahci: kill AHCI_FLAG_RESET_NEEDS_CLO Now that ahci_softreset() is fixed to automatically perform CLO if BSY/DRQ is set on entry, AHCI_FLAG_RESET_NEEDS_CLO is redundant. Kill it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index bddb14e..413270b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -167,9 +167,8 @@ enum { AHCI_FLAG_MSI = (1 << 0), /* 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 */ + AHCI_FLAG_NO_NCQ = (1 << 24), + AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ }; struct ahci_cmd_hdr { @@ -291,8 +290,7 @@ static const struct ata_port_info ahci_port_info[] = { .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_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, + ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -729,17 +727,6 @@ static int ahci_clo(struct ata_port *ap) return 0; } -static int ahci_prereset(struct ata_port *ap) -{ - if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && - (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { - /* ATA_BUSY hasn't cleared, so send a CLO */ - ahci_clo(ap); - } - - return ata_std_prereset(ap); -} - static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_port_priv *pp = ap->private_data; @@ -1196,7 +1183,7 @@ static void ahci_error_handler(struct ata_port *ap) } /* perform recovery */ - ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, + ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, ahci_postreset); } -- cgit v0.10.2 From b6103f6d1659e2024776bc759d28613fb36344a8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 17:59:53 +0900 Subject: [PATCH] libata: separate out and export sata_port_hardreset() Separate out sata_port_hardreset() from sata_std_hardreset(). This will be used by LLD hardreset implementation and later by PMP. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d233667..315f468 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2786,9 +2786,9 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) } /** - * sata_std_hardreset - reset host port via SATA phy reset + * sata_port_hardreset - reset port via SATA phy reset * @ap: port to reset - * @class: resulting class of attached device + * @timing: timing parameters { interval, duratinon, timeout } in msec * * SATA phy-reset host port using DET bits of SControl register. * @@ -2798,10 +2798,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) * RETURNS: * 0 on success, -errno otherwise. */ -int sata_std_hardreset(struct ata_port *ap, unsigned int *class) +int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing) { - struct ata_eh_context *ehc = &ap->eh_context; - const unsigned long *timing = sata_ehc_deb_timing(ehc); u32 scontrol; int rc; @@ -2814,24 +2812,24 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) * and Sil3124. */ if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) - return rc; + goto out; scontrol = (scontrol & 0x0f0) | 0x304; if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) - return rc; + goto out; sata_set_spd(ap); } /* issue phy wake/reset */ if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) - return rc; + goto out; scontrol = (scontrol & 0x0f0) | 0x301; if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) - return rc; + goto out; /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. @@ -2839,7 +2837,40 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) msleep(1); /* bring phy back */ - sata_phy_resume(ap, timing); + rc = sata_phy_resume(ap, timing); + out: + DPRINTK("EXIT, rc=%d\n", rc); + return rc; +} + +/** + * sata_std_hardreset - reset host port via SATA phy reset + * @ap: port to reset + * @class: resulting class of attached device + * + * SATA phy-reset host port using DET bits of SControl register, + * wait for !BSY and classify the attached device. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int sata_std_hardreset(struct ata_port *ap, unsigned int *class) +{ + const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context); + int rc; + + DPRINTK("ENTER\n"); + + /* do hardreset */ + rc = sata_port_hardreset(ap, timing); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "COMRESET failed (errno=%d)\n", rc); + return rc; + } /* TODO: phy layer with polling, timeouts, etc. */ if (ata_port_offline(ap)) { @@ -6159,6 +6190,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); +EXPORT_SYMBOL_GPL(sata_port_hardreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); EXPORT_SYMBOL_GPL(ata_dev_classify); diff --git a/include/linux/libata.h b/include/linux/libata.h index d3bf7b9..41fa089 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -702,6 +702,8 @@ extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param); extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); extern int ata_std_prereset(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); +extern int sata_port_hardreset(struct ata_port *ap, + const unsigned long *timing); 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 void ata_port_disable(struct ata_port *); -- cgit v0.10.2 From ad616ffbda8caf3ce76d2b43027e789d732abf48 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 18:00:24 +0900 Subject: [PATCH] ahci: update ahci-vt8251 reset sequence ahci-vt8251 * requires hardreset after PHY status change * doesn't clear BSY on signature FIS after hardreset * needs SError cleared for the port to operate after hardreset This patch implements ahci_vt8251_hardreset() and sets ATA_FLAG_HRST_TO_RESUME to handle the above behaviors. This fixes EH including hotplug on vt8251. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 413270b..8a1f4f0 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -215,6 +215,7 @@ static u8 ahci_check_status(struct ata_port *ap); static void ahci_freeze(struct ata_port *ap); static void ahci_thaw(struct ata_port *ap); static void ahci_error_handler(struct ata_port *ap); +static void ahci_vt8251_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); static int ahci_port_resume(struct ata_port *ap); @@ -274,6 +275,37 @@ static const struct ata_port_operations ahci_ops = { .port_stop = ahci_port_stop, }; +static const struct ata_port_operations ahci_vt8251_ops = { + .port_disable = ata_port_disable, + + .check_status = ahci_check_status, + .check_altstatus = ahci_check_status, + .dev_select = ata_noop_dev_select, + + .tf_read = ahci_tf_read, + + .qc_prep = ahci_qc_prep, + .qc_issue = ahci_qc_issue, + + .irq_handler = ahci_interrupt, + .irq_clear = ahci_irq_clear, + + .scr_read = ahci_scr_read, + .scr_write = ahci_scr_write, + + .freeze = ahci_freeze, + .thaw = ahci_thaw, + + .error_handler = ahci_vt8251_error_handler, + .post_internal_cmd = ahci_post_internal_cmd, + + .port_suspend = ahci_port_suspend, + .port_resume = ahci_port_resume, + + .port_start = ahci_port_start, + .port_stop = ahci_port_stop, +}; + static const struct ata_port_info ahci_port_info[] = { /* board_ahci */ { @@ -290,10 +322,11 @@ static const struct ata_port_info ahci_port_info[] = { .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_NO_NCQ, + ATA_FLAG_SKIP_D2H_BSY | + ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &ahci_ops, + .port_ops = &ahci_vt8251_ops, }, /* board_ahci_ign_iferr */ { @@ -864,6 +897,31 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) return rc; } +static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class) +{ + void __iomem *mmio = ap->host->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + int rc; + + DPRINTK("ENTER\n"); + + ahci_stop_engine(port_mmio); + + rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context)); + + /* vt8251 needs SError cleared for the port to operate */ + ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR)); + + ahci_start_engine(port_mmio); + + DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); + + /* vt8251 doesn't clear BSY on signature FIS reception, + * request follow-up softreset. + */ + return rc ?: -EAGAIN; +} + static void ahci_postreset(struct ata_port *ap, unsigned int *class) { void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -1187,6 +1245,22 @@ static void ahci_error_handler(struct ata_port *ap) ahci_postreset); } +static void ahci_vt8251_error_handler(struct ata_port *ap) +{ + void __iomem *mmio = ap->host->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + + if (!(ap->pflags & ATA_PFLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(port_mmio); + ahci_start_engine(port_mmio); + } + + /* perform recovery */ + ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset, + ahci_postreset); +} + static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; -- cgit v0.10.2 From efdaedc443e935eda82e9e78a6e65d1f993d242f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 18:38:52 +0900 Subject: [PATCH] libata: implement ATA_EHI_PRINTINFO Implement ehi flag ATA_EHI_PRINTINFO. This flag is set when device configuration needs to print out device info. This used to be handled by @print_info argument to ata_dev_configure() but LLDs also need to know about it in ->dev_config() callback. This patch replaces @print_info w/ ATA_EHI_PRINTINFO and make sata_sil print workaround messages only on the initial configuration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 315f468..e294731 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1377,7 +1377,6 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap) /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure - * @print_info: Enable device info printout * * Configure @dev according to @dev->id. Generic and low-level * driver specific fixups are also applied. @@ -1388,9 +1387,10 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap) * RETURNS: * 0 on success, -errno otherwise */ -int ata_dev_configure(struct ata_device *dev, int print_info) +int ata_dev_configure(struct ata_device *dev) { struct ata_port *ap = dev->ap; + int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; const u16 *id = dev->id; unsigned int xfer_mask; char revbuf[7]; /* XYZ-99\0 */ @@ -1638,7 +1638,9 @@ int ata_bus_probe(struct ata_port *ap) if (rc) goto fail; - rc = ata_dev_configure(dev, 1); + ap->eh_context.i.flags |= ATA_EHI_PRINTINFO; + rc = ata_dev_configure(dev); + ap->eh_context.i.flags &= ~ATA_EHI_PRINTINFO; if (rc) goto fail; } @@ -3045,7 +3047,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); /* configure device according to the new ID */ - rc = ata_dev_configure(dev, 0); + rc = ata_dev_configure(dev); if (rc == 0) return 0; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 02b2b27..7c44644 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1661,8 +1661,11 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, dev->class = ehc->classes[dev->devno]; rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); - if (rc == 0) - rc = ata_dev_configure(dev, 1); + if (rc == 0) { + ehc->i.flags |= ATA_EHI_PRINTINFO; + rc = ata_dev_configure(dev); + ehc->i.flags &= ~ATA_EHI_PRINTINFO; + } if (rc) { dev->class = ATA_DEV_UNKNOWN; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index c833000..e4ffb2e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -54,7 +54,7 @@ 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 ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index ca8d993..f844a1f 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -534,6 +534,7 @@ static void sil_thaw(struct ata_port *ap) */ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) { + int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; unsigned int n, quirks = 0; unsigned char model_num[41]; @@ -549,16 +550,18 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) if (slow_down || ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE))) { - ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix " - "(mod15write workaround)\n"); + if (print_info) + ata_dev_printk(dev, KERN_INFO, "applying Seagate " + "errata fix (mod15write workaround)\n"); dev->max_sectors = 15; return; } /* limit to udma5 */ if (quirks & SIL_QUIRK_UDMA5MAX) { - ata_dev_printk(dev, KERN_INFO, - "applying Maxtor errata fix %s\n", model_num); + if (print_info) + ata_dev_printk(dev, KERN_INFO, "applying Maxtor " + "errata fix %s\n", model_num); dev->udma_mask &= ATA_UDMA5; return; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 41fa089..9494846 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -283,6 +283,7 @@ enum { ATA_EHI_QUIET = (1 << 3), /* be quiet */ ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ + ATA_EHI_PRINTINFO = (1 << 17), /* print configuration info */ ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, -- cgit v0.10.2 From baa1e78a834c917984a4659fd282f712c17ee3bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 18:39:27 +0900 Subject: [PATCH] libata: implement ATA_EHI_SETMODE and ATA_EHI_POST_SETMODE libata EH used to perform ata_set_mode() iff the EH session performed reset as indicated by ATA_EHI_DID_RESET. This is incorrect because ->dev_config() called by revalidation is allowed to modify transfer mode which ata_set_mode() should take care of. This patch implements the following two flags. * ATA_EHI_SETMODE: set during EH to schedule ata_set_mode(). Both new device attachment and revalidation set this flag. * ATA_EHI_POST_SETMODE: set while the device is revalidated after ata_set_mode(). Post-setmode revalidation is different from initial configuaration and EH revalidation in that ->dev_config() is not allowed tune transfer mode. LLD can use this flag to determine whether it's allowed to tune transfer mode. Note that POST_SETMODE ->dev_config() is guaranteed to be preceded by non-POST_SETMODE ->dev_config(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e294731..5028396 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2158,6 +2158,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) static int ata_dev_set_mode(struct ata_device *dev) { + struct ata_eh_context *ehc = &dev->ap->eh_context; unsigned int err_mask; int rc; @@ -2172,7 +2173,9 @@ static int ata_dev_set_mode(struct ata_device *dev) return -EIO; } + ehc->i.flags |= ATA_EHI_POST_SETMODE; rc = ata_dev_revalidate(dev, 0); + ehc->i.flags &= ~ATA_EHI_POST_SETMODE; if (rc) return rc; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7c44644..4776488 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1653,6 +1653,11 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, ata_eh_done(ap, dev, ATA_EH_REVALIDATE); + /* Configuration may have changed, reconfigure + * transfer mode. + */ + ehc->i.flags |= ATA_EHI_SETMODE; + /* schedule the scsi_rescan_device() here */ queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); } else if (dev->class == ATA_DEV_UNKNOWN && @@ -1675,6 +1680,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; spin_unlock_irqrestore(ap->lock, flags); + + /* new device discovered, configure transfer mode */ + ehc->i.flags |= ATA_EHI_SETMODE; } } @@ -1990,13 +1998,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, if (rc) goto dev_fail; - /* configure transfer mode if the port has been reset */ - if (ehc->i.flags & ATA_EHI_DID_RESET) { + /* configure transfer mode if necessary */ + if (ehc->i.flags & ATA_EHI_SETMODE) { rc = ata_set_mode(ap, &dev); if (rc) { down_xfermask = 1; goto dev_fail; } + ehc->i.flags &= ~ATA_EHI_SETMODE; } /* suspend devices */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 9494846..0d0ddea 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -284,6 +284,8 @@ enum { ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ ATA_EHI_PRINTINFO = (1 << 17), /* print configuration info */ + ATA_EHI_SETMODE = (1 << 18), /* configure transfer mode */ + ATA_EHI_POST_SETMODE = (1 << 19), /* revaildating after setmode */ ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, -- cgit v0.10.2 From 914ed354b373680b648d913161cca6f742f32791 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 18:39:55 +0900 Subject: [PATCH] libata: move dev->max_sectors configuration into ata_dev_configure() Move dev->max_sectors configuration from ata_scsi_dev_config() to ata_dev_configure(). * more consistent. * allows LLDs to peek at the default dev->max_sectors value. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5028396..f531a89 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1533,6 +1533,11 @@ int ata_dev_configure(struct ata_device *dev) cdb_intr_string); } + /* determine max_sectors */ + dev->max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + dev->max_sectors = ATA_MAX_SECTORS_LBA48; + if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6b2553d..f13dd07 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -807,23 +807,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) static void ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) { - unsigned int max_sectors; + /* configure max sectors */ + blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); - /* TODO: 2048 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - max_sectors = ATA_MAX_SECTORS; - if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = ATA_MAX_SECTORS_LBA48; - if (dev->max_sectors) - max_sectors = dev->max_sectors; - - blk_queue_max_sectors(sdev->request_queue, max_sectors); - - /* - * SATA DMA transfers must be multiples of 4 byte, so + /* SATA DMA transfers must be multiples of 4 byte, so * we need to pad ATAPI transfers using an extra sg. * Decrement max hw segments accordingly. */ -- cgit v0.10.2 From 415ae2b5c03b6ed1a041a473885e502d297e1d37 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 1 Nov 2006 05:10:42 -0500 Subject: [libata] ahci: Match PCI class code for AHCI Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 8a1f4f0..bc6599e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -403,6 +403,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ + /* Generic, PCI class code for AHCI */ + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + 0x010601, 0xffffff, board_ahci }, + { } /* terminate list */ }; -- cgit v0.10.2 From ada406c8246b0792afe4d7f8ae7606093052de87 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 3 Nov 2006 13:18:06 +0000 Subject: [PATCH] pdc202xx_old: Fix name clashes with PA-RISC pdc_* functions are part of the global namespace for the PDC on PA-RISC systems and this means our choice of pdc_ causes collisions between the PDC globals and our static functions. Rename them to pdc202xx where they are for both 2024x and 2026x. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 6baf51b..ed8d985 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -21,7 +21,7 @@ #include #define DRV_NAME "pata_pdc202xx_old" -#define DRV_VERSION "0.2.1" +#define DRV_VERSION "0.2.2" /** * pdc2024x_pre_reset - probe begin @@ -63,7 +63,7 @@ static void pdc2026x_error_handler(struct ata_port *ap) } /** - * pdc_configure_piomode - set chip PIO timing + * pdc202xx_configure_piomode - set chip PIO timing * @ap: ATA interface * @adev: ATA device * @pio: PIO mode @@ -73,7 +73,7 @@ static void pdc2026x_error_handler(struct ata_port *ap) * versa */ -static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) +static void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; @@ -98,7 +98,7 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, } /** - * pdc_set_piomode - set initial PIO mode data + * pdc202xx_set_piomode - set initial PIO mode data * @ap: ATA interface * @adev: ATA device * @@ -106,13 +106,13 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, * but we want to set the PIO timing by default. */ -static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void pdc202xx_set_piomode(struct ata_port *ap, struct ata_device *adev) { - pdc_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); + pdc202xx_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); } /** - * pdc_configure_dmamode - set DMA mode in chip + * pdc202xx_configure_dmamode - set DMA mode in chip * @ap: ATA interface * @adev: ATA device * @@ -120,7 +120,7 @@ static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) * to occur. */ -static void pdc_set_dmamode(struct ata_port *ap, struct ata_device *adev) +static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; @@ -184,7 +184,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) /* The DMA clocks may have been trashed by a reset. FIXME: make conditional and move to qc_issue ? */ - pdc_set_dmamode(ap, qc->dev); + pdc202xx_set_dmamode(ap, qc->dev); /* Cases the state machine will not complete correctly without help */ if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) @@ -254,7 +254,7 @@ static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev) adev->max_sectors = 256; } -static struct scsi_host_template pdc_sht = { +static struct scsi_host_template pdc202xx_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, @@ -275,8 +275,8 @@ static struct scsi_host_template pdc_sht = { static struct ata_port_operations pdc2024x_port_ops = { .port_disable = ata_port_disable, - .set_piomode = pdc_set_piomode, - .set_dmamode = pdc_set_dmamode, + .set_piomode = pdc202xx_set_piomode, + .set_dmamode = pdc202xx_set_dmamode, .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -308,8 +308,8 @@ static struct ata_port_operations pdc2024x_port_ops = { static struct ata_port_operations pdc2026x_port_ops = { .port_disable = ata_port_disable, - .set_piomode = pdc_set_piomode, - .set_dmamode = pdc_set_dmamode, + .set_piomode = pdc202xx_set_piomode, + .set_dmamode = pdc202xx_set_dmamode, .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -340,11 +340,11 @@ static struct ata_port_operations pdc2026x_port_ops = { .host_stop = ata_host_stop }; -static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) +static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static struct ata_port_info info[3] = { { - .sht = &pdc_sht, + .sht = &pdc202xx_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -352,7 +352,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &pdc2024x_port_ops }, { - .sht = &pdc_sht, + .sht = &pdc202xx_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -360,7 +360,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &pdc2026x_port_ops }, { - .sht = &pdc_sht, + .sht = &pdc202xx_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -386,7 +386,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) return ata_pci_init_one(dev, port_info, 2); } -static const struct pci_device_id pdc[] = { +static const struct pci_device_id pdc202xx[] = { { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, @@ -396,28 +396,28 @@ static const struct pci_device_id pdc[] = { { }, }; -static struct pci_driver pdc_pci_driver = { +static struct pci_driver pdc202xx_pci_driver = { .name = DRV_NAME, - .id_table = pdc, - .probe = pdc_init_one, + .id_table = pdc202xx, + .probe = pdc202xx_init_one, .remove = ata_pci_remove_one }; -static int __init pdc_init(void) +static int __init pdc202xx_init(void) { - return pci_register_driver(&pdc_pci_driver); + return pci_register_driver(&pdc202xx_pci_driver); } -static void __exit pdc_exit(void) +static void __exit pdc202xx_exit(void) { - pci_unregister_driver(&pdc_pci_driver); + pci_unregister_driver(&pdc202xx_pci_driver); } MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267"); MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pdc); +MODULE_DEVICE_TABLE(pci, pdc202xx); MODULE_VERSION(DRV_VERSION); -module_init(pdc_init); -module_exit(pdc_exit); +module_init(pdc202xx_init); +module_exit(pdc202xx_exit); -- cgit v0.10.2 From 98fa4b60c673526fdd478d9719e41cd9e2b84986 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Nov 2006 12:17:23 +0900 Subject: [PATCH] ahci: preserve PORTS_IMPL over host resets Instead of writing 0xf blindly, preserve the content of write-once PORTS_IMPL register over host resets. This patch is taken from Jeff Garzik's AHCI init update patch. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index bc6599e..f2277be 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -421,6 +421,11 @@ static struct pci_driver ahci_pci_driver = { }; +static inline int ahci_nr_ports(u32 cap) +{ + return (cap & 0x1f) + 1; +} + static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port) { return base + 0x100 + (port * 0x80); @@ -630,11 +635,12 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) { - u32 cap_save, tmp; + u32 cap_save, impl_save, tmp; cap_save = readl(mmio + HOST_CAP); cap_save &= ( (1<<28) | (1<<17) ); cap_save |= (1 << 27); + impl_save = readl(mmio + HOST_PORTS_IMPL); /* global controller reset */ tmp = readl(mmio + HOST_CTL); @@ -655,10 +661,21 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) return -EIO; } + /* turn on AHCI mode */ writel(HOST_AHCI_EN, mmio + HOST_CTL); (void) readl(mmio + HOST_CTL); /* flush */ + + /* These write-once registers are normally cleared on reset. + * Restore BIOS values... which we HOPE were present before + * reset. + */ + if (!impl_save) { + impl_save = (1 << ahci_nr_ports(cap_save)) - 1; + dev_printk(KERN_WARNING, &pdev->dev, + "PORTS_IMPL is zero, forcing 0x%x\n", impl_save); + } writel(cap_save, mmio + HOST_CAP); - writel(0xf, mmio + HOST_PORTS_IMPL); + writel(impl_save, mmio + HOST_PORTS_IMPL); (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ if (pdev->vendor == PCI_VENDOR_ID_INTEL) { @@ -1467,7 +1484,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) hpriv->cap = readl(mmio + HOST_CAP); hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); - probe_ent->n_ports = (hpriv->cap & 0x1f) + 1; + probe_ent->n_ports = ahci_nr_ports(hpriv->cap); VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", hpriv->cap, hpriv->port_map, probe_ent->n_ports); -- cgit v0.10.2 From 4adccf6f447dfa7af6f3af7e12f87829a6fac8dd Mon Sep 17 00:00:00 2001 From: Uwe Koziolek Date: Wed, 8 Nov 2006 09:57:00 +0100 Subject: [PATCH] sata_sis: slave support on SiS965 SiS965 and SiS180 chips must support slave mode, SiS965L and SiS964 chips must not support slave mode. SCR_STATUS for SATA ports in powerdown state fixed. Now returning 0x0113 instead of 0x0117. Avoids problem on detecting sata_sis controller. Signed-off-by: Uwe Koziolek Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 9d1235b..9c25a1e 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -173,7 +173,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) pci_read_config_dword(pdev, cfg_addr+0x10, &val2); - return val|val2; + return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */ } static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) @@ -212,7 +212,7 @@ static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); - return val | val2; + return (val | val2) & 0xfffffffb; } static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) @@ -239,7 +239,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; struct ata_probe_ent *probe_ent = NULL; int rc; - u32 genctl; + u32 genctl, val; struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi }; int pci_dev_busy = 0; u8 pmr; @@ -285,17 +285,24 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (ent->device != 0x182) { if ((pmr & SIS_PMR_COMBINED) == 0) { dev_printk(KERN_INFO, &pdev->dev, - "Detected SiS 180/181 chipset in SATA mode\n"); + "Detected SiS 180/181/964 chipset in SATA mode\n"); port2_start = 64; } else { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in combined mode\n"); port2_start=0; + pi.flags |= ATA_FLAG_SLAVE_POSS; } } else { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n"); + pci_read_config_dword ( pdev, 0x6C, &val); + if (val & (1L << 31)) { + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n"); + pi.flags |= ATA_FLAG_SLAVE_POSS; + } + else + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n"); port2_start = 0x20; } -- cgit v0.10.2 From 0df0d0a0ea9ffcee4e56f96cd9d9e32b0644eb21 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Tue, 14 Nov 2006 13:43:21 -0500 Subject: [libata] ARM: add ixp4xx PATA driver Signed-off-by: Alessandro Zummo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 98d0f01..984ab28 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -508,6 +508,16 @@ config PATA_PLATFORM If unsure, say N. +config PATA_IXP4XX_CF + tristate "IXP4XX Compact Flash support" + depends on ARCH_IXP4XX + help + This option enables support for a Compact Flash connected on + the ixp4xx expansion bus. This driver had been written for + Loft/Avila boards in mind but can work with others. + + If unsure, say N. + endif endmenu diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index f2b3ea2..bc3d81a 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o obj-$(CONFIG_PATA_SIS) += pata_sis.o obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o +obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o # Should be last but one libata driver obj-$(CONFIG_ATA_GENERIC) += ata_generic.o diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c new file mode 100644 index 0000000..d2268bf --- /dev/null +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -0,0 +1,271 @@ +/* + * ixp4xx PATA/Compact Flash driver + * Copyright (c) 2006 Tower Technologies + * Author: Alessandro Zummo + * + * An ATA driver to handle a Compact Flash connected + * to the ixp4xx expansion bus in TrueIDE mode. The CF + * must have it chip selects connected to two CS lines + * on the ixp4xx. The interrupt line is optional, if not + * specified the driver will run in polling mode. + * + * 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 + +#define DRV_NAME "pata_ixp4xx_cf" +#define DRV_VERSION "0.1.1" + +static void ixp4xx_set_mode(struct ata_port *ap) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_enabled(dev)) { + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + } + } +} + +static void ixp4xx_phy_reset(struct ata_port *ap) +{ + ap->cbl = ATA_CBL_PATA40; + ata_port_probe(ap); + ata_bus_reset(ap); +} + +static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned int i; + unsigned int words = buflen >> 1; + u16 *buf16 = (u16 *) buf; + struct ata_port *ap = adev->ap; + void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; + struct ixp4xx_pata_data *data = ap->host->dev->platform_data; + + /* set the expansion bus in 16bit mode and restore + * 8 bit mode after the transaction. + */ + *data->cs0_cfg &= ~(0x01); + udelay(100); + + /* Transfer multiple of 2 bytes */ + if (write_data) { + for (i = 0; i < words; i++) + writew(buf16[i], mmio); + } else { + for (i = 0; i < words; i++) + buf16[i] = readw(mmio); + } + + /* Transfer trailing 1 byte, if any. */ + if (unlikely(buflen & 0x01)) { + u16 align_buf[1] = { 0 }; + unsigned char *trailing_buf = buf + buflen - 1; + + if (write_data) { + memcpy(align_buf, trailing_buf, 1); + writew(align_buf[0], mmio); + } else { + align_buf[0] = readw(mmio); + memcpy(trailing_buf, align_buf, 1); + } + } + + udelay(100); + *data->cs0_cfg |= 0x01; +} + +static void ixp4xx_irq_clear(struct ata_port *ap) +{ +} + +static void ixp4xx_host_stop (struct ata_host *host) +{ + struct ixp4xx_pata_data *data = host->dev->platform_data; + + iounmap(data->cs0); + iounmap(data->cs1); +} + +static struct scsi_host_template ixp4xx_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations ixp4xx_port_ops = { + .set_mode = ixp4xx_set_mode, + .mode_filter = ata_pci_default_filter, + + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + .data_xfer = ixp4xx_mmio_data_xfer, + + .irq_handler = ata_interrupt, + .irq_clear = ixp4xx_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ixp4xx_host_stop, + + .phy_reset = ixp4xx_phy_reset, +}; + +static void ixp4xx_setup_port(struct ata_ioports *ioaddr, + struct ixp4xx_pata_data *data) +{ + ioaddr->cmd_addr = (unsigned long) data->cs0; + ioaddr->altstatus_addr = (unsigned long) data->cs1 + 0x06; + ioaddr->ctl_addr = (unsigned long) data->cs1 + 0x06; + + ata_std_ports(ioaddr); + +#ifndef __ARMEB__ + + /* adjust the addresses to handle the address swizzling of the + * ixp4xx in little endian mode. + */ + + ioaddr->data_addr ^= 0x02; + ioaddr->cmd_addr ^= 0x03; + ioaddr->altstatus_addr ^= 0x03; + ioaddr->ctl_addr ^= 0x03; + ioaddr->error_addr ^= 0x03; + ioaddr->feature_addr ^= 0x03; + ioaddr->nsect_addr ^= 0x03; + ioaddr->lbal_addr ^= 0x03; + ioaddr->lbam_addr ^= 0x03; + ioaddr->lbah_addr ^= 0x03; + ioaddr->device_addr ^= 0x03; + ioaddr->status_addr ^= 0x03; + ioaddr->command_addr ^= 0x03; +#endif +} + +static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) +{ + int ret; + unsigned int irq; + struct resource *cs0, *cs1; + struct ata_probe_ent ae; + + struct ixp4xx_pata_data *data = pdev->dev.platform_data; + + cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); + + if (!cs0 || !cs1) + return -EINVAL; + + pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; + + data->cs0 = ioremap(cs0->start, 0x1000); + data->cs1 = ioremap(cs1->start, 0x1000); + + irq = platform_get_irq(pdev, 0); + if (irq) + set_irq_type(irq, IRQT_HIGH); + + /* Setup expansion bus chip selects */ + *data->cs0_cfg = data->cs0_bits; + *data->cs1_cfg = data->cs1_bits; + + memset(&ae, 0, sizeof(struct ata_probe_ent)); + INIT_LIST_HEAD(&ae.node); + + ae.dev = &pdev->dev; + ae.port_ops = &ixp4xx_port_ops; + ae.sht = &ixp4xx_sht; + ae.n_ports = 1; + ae.pio_mask = 0x1f; /* PIO4 */ + ae.irq = irq; + ae.irq_flags = 0; + ae.port_flags = ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY + | ATA_FLAG_NO_ATAPI | ATA_FLAG_SRST; + + /* run in polling mode if no irq has been assigned */ + if (!irq) + ae.port_flags |= ATA_FLAG_PIO_POLLING; + + ixp4xx_setup_port(&ae.port[0], data); + + dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); + + ret = ata_device_add(&ae); + if (ret == 0) + return -ENODEV; + + return 0; +} + +static __devexit int ixp4xx_pata_remove(struct platform_device *dev) +{ + struct ata_host *host = platform_get_drvdata(dev); + + ata_host_remove(host); + platform_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver ixp4xx_pata_platform_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ixp4xx_pata_probe, + .remove = __devexit_p(ixp4xx_pata_remove), +}; + +static int __init ixp4xx_pata_init(void) +{ + return platform_driver_register(&ixp4xx_pata_platform_driver); +} + +static void __exit ixp4xx_pata_exit(void) +{ + platform_driver_unregister(&ixp4xx_pata_platform_driver); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(ixp4xx_pata_init); +module_exit(ixp4xx_pata_exit); diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index 8d10a91..ab194e5 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h @@ -86,6 +86,19 @@ struct ixp4xx_i2c_pins { unsigned long scl_pin; }; +/* + * This structure provide a means for the board setup code + * to give information to th pata_ixp4xx driver. It is + * passed as platform_data. + */ +struct ixp4xx_pata_data { + volatile u32 *cs0_cfg; + volatile u32 *cs1_cfg; + unsigned long cs0_bits; + unsigned long cs1_bits; + void __iomem *cs0; + void __iomem *cs1; +}; struct sys_timer; -- cgit v0.10.2 From 648a88be4a016d2637ace3ae74b85a0512255ee8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Nov 2006 15:08:40 +0900 Subject: [PATCH] ahci: honor PORTS_IMPL on ICH8s Some ICH8s use non-linear port mapping. ahci driver didn't use to honor PORTS_IMPL and this made ports after hole nonfunctional. This patch makes ahci mark those ports as dummy and properly initialize all the implemented ports after the dummies. As it's unknown whether other AHCIs implement PORTS_IMPL register properly, new board id board_ahci_pi is added and selectively applied to ICH8s. All other AHCIs continue to use linear mapping regardless of PORTS_IMPL value. Signed-off-by: Tejun Heo Cc: Robin H. Johnson Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f2277be..af3565d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -53,6 +53,7 @@ enum { AHCI_PCI_BAR = 5, + AHCI_MAX_PORTS = 32, AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, @@ -77,8 +78,9 @@ enum { RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ board_ahci = 0, - board_ahci_vt8251 = 1, - board_ahci_ign_iferr = 2, + board_ahci_pi = 1, + board_ahci_vt8251 = 2, + board_ahci_ign_iferr = 3, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -169,6 +171,7 @@ enum { /* ap->flags bits */ AHCI_FLAG_NO_NCQ = (1 << 24), AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ + AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ }; struct ahci_cmd_hdr { @@ -317,6 +320,16 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_pi */ + { + .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_HONOR_PI, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, /* board_ahci_vt8251 */ { .sht = &ahci_sht, @@ -353,22 +366,22 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ - { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ - { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */ - { 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 */ + { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */ + { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */ + { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ /* JMicron */ { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ @@ -691,7 +704,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) } static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, - int n_ports, u32 cap) + int n_ports, unsigned int port_flags, + struct ahci_host_priv *hpriv) { int i, rc; u32 tmp; @@ -700,13 +714,12 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, void __iomem *port_mmio = ahci_port_base(mmio, i); const char *emsg = NULL; -#if 0 /* BIOSen initialize this incorrectly */ - if (!(hpriv->port_map & (1 << i))) + if ((port_flags & AHCI_FLAG_HONOR_PI) && + !(hpriv->port_map & (1 << i))) continue; -#endif /* make sure port is not active */ - rc = ahci_deinit_port(port_mmio, cap, &emsg); + rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); if (rc) dev_printk(KERN_WARNING, &pdev->dev, "%s (%d)\n", emsg, rc); @@ -1363,7 +1376,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) if (rc) return rc; - ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap); + ahci_init_controller(mmio, pdev, host->n_ports, + host->ports[0]->flags, hpriv); } ata_host_resume(host); @@ -1475,7 +1489,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) struct ahci_host_priv *hpriv = probe_ent->private_data; struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void __iomem *mmio = probe_ent->mmio_base; - unsigned int i, using_dac; + unsigned int i, cap_n_ports, using_dac; int rc; rc = ahci_reset_controller(mmio, pdev); @@ -1484,10 +1498,34 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) hpriv->cap = readl(mmio + HOST_CAP); hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); - probe_ent->n_ports = ahci_nr_ports(hpriv->cap); + cap_n_ports = ahci_nr_ports(hpriv->cap); VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", - hpriv->cap, hpriv->port_map, probe_ent->n_ports); + hpriv->cap, hpriv->port_map, cap_n_ports); + + if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) { + unsigned int n_ports = cap_n_ports; + u32 port_map = hpriv->port_map; + int max_port = 0; + + for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) { + if (port_map & (1 << i)) { + n_ports--; + port_map &= ~(1 << i); + max_port = i; + } else + probe_ent->dummy_port_mask |= 1 << i; + } + + if (n_ports || port_map) + dev_printk(KERN_WARNING, &pdev->dev, + "nr_ports (%u) and implemented port map " + "(0x%x) don't match\n", + cap_n_ports, hpriv->port_map); + + probe_ent->n_ports = max_port + 1; + } else + probe_ent->n_ports = cap_n_ports; using_dac = hpriv->cap & HOST_CAP_64; if (using_dac && @@ -1519,7 +1557,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) for (i = 0; i < probe_ent->n_ports; i++) ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); - ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap); + ahci_init_controller(mmio, pdev, probe_ent->n_ports, + probe_ent->port_flags, hpriv); pci_set_master(pdev); -- cgit v0.10.2 From 6fc49adb9417b9c793e8f88d485387bb89ceb733 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Nov 2006 20:10:45 +0900 Subject: [PATCH] libata: use FLUSH_EXT only when driver is larger than LBA28 limit Many drives support LBA48 even when its capacity is smaller than 1<<28, as LBA48 is required for many functionalities. FLUSH_EXT is mandatory for drives w/ LBA48 support. Interestingly, at least one of such drives (ST960812A) has problems dealing with FLUSH_EXT. It eventually completes the command but takes around 7 seconds to finish in many cases thus drastically slowing down IO transactions. This seems to be a firmware bug which sneaked into production probably because no other ATA driver including linux IDE issues FLUSH_EXT to drives which report support for LBA48 & FLUSH_EXT but is smaller than 1<<28 blocks. This patch adds ATA_DFLAG_FLUSH_EXT which is set iff the drive supports LBA48 & FLUSH_EXT and is larger than LBA28 limit. Both cache flush paths are updated to issue FLUSH_EXT only when the flag is set. Note that the changed behavior is more inline with the rest of libata. libata prefers shorter commands whenever possible. Signed-off-by: Tejun Heo Cc: Danny Kukawka Cc: Stefan Seyfried Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f531a89..d94b8a0 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1457,6 +1457,10 @@ int ata_dev_configure(struct ata_device *dev) if (ata_id_has_lba48(id)) { dev->flags |= ATA_DFLAG_LBA48; lba_desc = "LBA48"; + + if (dev->n_sectors >= (1UL << 28) && + ata_id_has_flush_ext(id)) + dev->flags |= ATA_DFLAG_FLUSH_EXT; } /* config NCQ */ @@ -5128,7 +5132,7 @@ int ata_flush_cache(struct ata_device *dev) if (!ata_try_flush_cache(dev)) return 0; - if (ata_id_has_flush_ext(dev->id)) + if (dev->flags & ATA_DFLAG_FLUSH_EXT) cmd = ATA_CMD_FLUSH_EXT; else cmd = ATA_CMD_FLUSH; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f13dd07..7a55c2e4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1027,8 +1027,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs tf->flags |= ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; - if ((qc->dev->flags & ATA_DFLAG_LBA48) && - (ata_id_has_flush_ext(qc->dev->id))) + if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT) tf->command = ATA_CMD_FLUSH_EXT; else tf->command = ATA_CMD_FLUSH; diff --git a/include/linux/libata.h b/include/linux/libata.h index 0d0ddea..36e233c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -140,6 +140,7 @@ enum { ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ + ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */ ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ -- cgit v0.10.2 From b3362f88a8f938fb700fdedf074ec222cba7cf83 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Nov 2006 18:08:10 +0900 Subject: [PATCH] ata_piix: clean up port flags * move common flags into PIIX_PATA_FLAGS and PIIX_SATA_FLAGS * kill unnecessary ATA_FLAG_SRST Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 14b726b..90ac33a 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -106,6 +106,9 @@ enum { PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ + PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, + PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, + /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. */ @@ -438,7 +441,7 @@ static struct ata_port_info piix_port_info[] = { /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ { .sht = &piix_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ .udma_mask = ATA_UDMA_MASK_40C, @@ -448,7 +451,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ .udma_mask = ATA_UDMA2, /* UDMA33 */ @@ -457,7 +460,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_66: 2 ICH controllers up to 66MHz */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ .udma_mask = ATA_UDMA4, @@ -467,7 +470,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_100: 3 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x06, /* mwdma1-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ @@ -477,7 +480,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_133: 4 ICH with full UDMA6 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ .udma_mask = ATA_UDMA6, /* UDMA133 */ @@ -487,8 +490,7 @@ static struct ata_port_info piix_port_info[] = { /* ich5_sata: 5 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | - PIIX_FLAG_IGNORE_PCS, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -498,8 +500,7 @@ static struct ata_port_info piix_port_info[] = { /* i6300esb_sata: 6 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -509,8 +510,7 @@ static struct ata_port_info piix_port_info[] = { /* ich6_sata: 7 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -520,8 +520,7 @@ static struct ata_port_info piix_port_info[] = { /* ich6_sata_ahci: 8 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -532,8 +531,7 @@ static struct ata_port_info piix_port_info[] = { /* ich6m_sata_ahci: 9 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -544,8 +542,7 @@ static struct ata_port_info piix_port_info[] = { /* ich8_sata_ahci: 10 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ -- cgit v0.10.2 From bff0464769f2a1bd348265de704471747378e247 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Nov 2006 18:08:10 +0900 Subject: [PATCH] libata: convert @post_reset to @flags in ata_dev_read_id() Make ata_dev_read_id() take @flags instead of @post_reset. Currently there is only one flag defined - ATA_READID_POSTRESET, which is equivalent to @post_reset. This is preparation for polling presence detection. Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d94b8a0..090abe4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1224,7 +1224,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * ata_dev_read_id - Read ID data from the specified device * @dev: target device * @p_class: pointer to class of the target device (may be changed) - * @post_reset: is this read ID post-reset? + * @flags: ATA_READID_* flags * @id: buffer to read IDENTIFY data into * * Read ID data from the specified device. ATA_CMD_ID_ATA is @@ -1239,7 +1239,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * 0 on success, -errno otherwise. */ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, - int post_reset, u16 *id) + unsigned int flags, u16 *id) { struct ata_port *ap = dev->ap; unsigned int class = *p_class; @@ -1294,7 +1294,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, goto err_out; } - if (post_reset && class == ATA_DEV_ATA) { + if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { /* * The exact sequence expected by certain pre-ATA4 drives is: * SRST RESET @@ -1314,7 +1314,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, /* current CHS translation info (id[53-58]) might be * changed. reread the identify device info. */ - post_reset = 0; + flags &= ~ATA_READID_POSTRESET; goto retry; } } @@ -1643,7 +1643,8 @@ int ata_bus_probe(struct ata_port *ap) if (!ata_dev_enabled(dev)) continue; - rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET, + dev->id); if (rc) goto fail; @@ -3023,7 +3024,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, /** * ata_dev_revalidate - Revalidate ATA device * @dev: device to revalidate - * @post_reset: is this revalidation after reset? + * @readid_flags: read ID flags * * Re-read IDENTIFY page and make sure @dev is still attached to * the port. @@ -3034,7 +3035,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, * RETURNS: * 0 on success, negative errno otherwise */ -int ata_dev_revalidate(struct ata_device *dev, int post_reset) +int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags) { unsigned int class = dev->class; u16 *id = (void *)dev->ap->sector_buf; @@ -3046,7 +3047,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) } /* read ID data */ - rc = ata_dev_read_id(dev, &class, post_reset, id); + rc = ata_dev_read_id(dev, &class, readid_flags, id); if (rc) goto fail; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 4776488..755fc68 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1634,11 +1634,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, DPRINTK("ENTER\n"); for (i = 0; i < ATA_MAX_DEVICES; i++) { - unsigned int action; + unsigned int action, readid_flags = 0; dev = &ap->device[i]; action = ata_eh_dev_action(dev); + if (ehc->i.flags & ATA_EHI_DID_RESET) + readid_flags |= ATA_READID_POSTRESET; + if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { if (ata_port_offline(ap)) { rc = -EIO; @@ -1646,8 +1649,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, } ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); - rc = ata_dev_revalidate(dev, - ehc->i.flags & ATA_EHI_DID_RESET); + rc = ata_dev_revalidate(dev, readid_flags); if (rc) break; @@ -1665,7 +1667,8 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, ata_class_enabled(ehc->classes[dev->devno])) { dev->class = ehc->classes[dev->devno]; - rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + rc = ata_dev_read_id(dev, &dev->class, readid_flags, + dev->id); if (rc == 0) { ehc->i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index e4ffb2e..bb98390 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -39,6 +39,11 @@ struct ata_scsi_args { }; /* libata-core.c */ +enum { + /* flags for ata_dev_read_id() */ + ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ +}; + extern struct workqueue_struct *ata_aux_wq; extern int atapi_enabled; extern int atapi_dmadir; @@ -52,8 +57,8 @@ extern unsigned ata_exec_internal(struct ata_device *dev, int dma_dir, void *buf, unsigned int buflen); 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); + unsigned int flags, u16 *id); +extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags); extern int ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); -- cgit v0.10.2 From 55a8e2c83ce50548dfef74bb19dfe2b809cb3099 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Nov 2006 18:08:10 +0900 Subject: [PATCH] libata: implement presence detection via polling IDENTIFY On some controllers (ICHs in piix mode), there is *NO* reliable way to determine device presence other than issuing IDENTIFY and see how the transaction proceeds by watching the TF status register. libata acted this way before irq-pio and phantom devices caused very little problem but now that IDENTIFY is performed using IRQ drive PIO, such phantom devices now result in multiple 30sec timeouts during boot. This patch implements ATA_FLAG_DETECT_POLLING. If a LLD sets this flag, libata core issues the initial IDENTIFY in polling mode and if the initial data transfer fails w/ HSM violation, the port is considered to be empty thus replicating the old libata and IDE behavior. Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 090abe4..21f8d61 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1272,9 +1272,20 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, tf.protocol = ATA_PROT_PIO; + /* presence detection using polling IDENTIFY? */ + if (flags & ATA_READID_DETECT) + tf.flags |= ATA_TFLAG_POLLING; + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { + if ((flags & ATA_READID_DETECT) && + (err_mask & AC_ERR_NODEV_HINT)) { + DPRINTK("ata%u.%d: NODEV after polling detection\n", + ap->id, dev->devno); + return -ENOENT; + } + rc = -EIO; reason = "I/O error"; goto err_out; @@ -4285,8 +4296,12 @@ fsm_start: /* device stops HSM for abort/error */ qc->err_mask |= AC_ERR_DEV; else - /* HSM violation. Let EH handle this */ - qc->err_mask |= AC_ERR_HSM; + /* HSM violation. Let EH handle this. + * Phantom devices also trigger this + * condition. Mark hint. + */ + qc->err_mask |= AC_ERR_HSM | + AC_ERR_NODEV_HINT; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 755fc68..e69f3df 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1667,12 +1667,23 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, ata_class_enabled(ehc->classes[dev->devno])) { dev->class = ehc->classes[dev->devno]; + if (ap->flags & ATA_FLAG_DETECT_POLLING) + readid_flags |= ATA_READID_DETECT; + rc = ata_dev_read_id(dev, &dev->class, readid_flags, dev->id); if (rc == 0) { ehc->i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ehc->i.flags &= ~ATA_EHI_PRINTINFO; + } else if (rc == -ENOENT) { + /* IDENTIFY was issued to non-existent + * device. No need to reset. Just + * thaw and kill the device. + */ + ata_eh_thaw_port(ap); + dev->class = ATA_DEV_UNKNOWN; + rc = 0; } if (rc) { @@ -1680,12 +1691,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, break; } - spin_lock_irqsave(ap->lock, flags); - ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; - spin_unlock_irqrestore(ap->lock, flags); + if (ata_dev_enabled(dev)) { + spin_lock_irqsave(ap->lock, flags); + ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; + spin_unlock_irqrestore(ap->lock, flags); - /* new device discovered, configure transfer mode */ - ehc->i.flags |= ATA_EHI_SETMODE; + /* new device discovered, configure xfermode */ + ehc->i.flags |= ATA_EHI_SETMODE; + } } } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index bb98390..be2ac39 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -42,6 +42,8 @@ struct ata_scsi_args { enum { /* flags for ata_dev_read_id() */ ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ + ATA_READID_DETECT = (1 << 1), /* perform presence detection + * using polling IDENTIFY */ }; extern struct workqueue_struct *ata_aux_wq; diff --git a/include/linux/libata.h b/include/linux/libata.h index 36e233c..9080789 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -176,6 +176,8 @@ enum { ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H * Register FIS clearing BSY */ ATA_FLAG_DEBUGMSG = (1 << 13), + ATA_FLAG_DETECT_POLLING = (1 << 14), /* detect device presence by + * polling IDENTIFY */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be @@ -335,6 +337,7 @@ enum ata_completion_errors { AC_ERR_SYSTEM = (1 << 6), /* system error */ AC_ERR_INVALID = (1 << 7), /* invalid argument */ AC_ERR_OTHER = (1 << 8), /* unknown */ + AC_ERR_NODEV_HINT = (1 << 9), /* polling device detection hint */ }; /* forward declarations */ -- cgit v0.10.2 From 228c1590be39872022006ab81fda112a4f35ce47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Nov 2006 18:08:10 +0900 Subject: [PATCH] ata_piix: apply device detection via polling IDENTIFY PATA PIIX uses reset signature + TF r/w test for device presence detection, which doesn't always work. It sometimes reports phantom device which results in IDENTIFY timeouts. SATA PIIX uses some combination of PCS + reset signature + TF r/w test for device presence detection. No combination satifies all and for some controllers, there doesn't seem to be any combination which works reliably. This patch makes both PATA and SATA piix's use reset signature + TF r/w + polling IDENTIFY for device detection. This is what the old libata (before irq-pio and new EH) did and what IDE does. This patch also removes now obsolete PIIX_FLAG_IGNORE_PCS, force_pcs and related code. Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 90ac33a..7bf2386 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -101,13 +101,13 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ - PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */ PIIX_FLAG_SCR = (1 << 26), /* SCR available */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ - PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, - PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, + PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS | ATA_FLAG_DETECT_POLLING, + PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | + ATA_FLAG_DETECT_POLLING, /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. @@ -490,7 +490,7 @@ static struct ata_port_info piix_port_info[] = { /* ich5_sata: 5 */ { .sht = &piix_sht, - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS, + .flags = PIIX_SATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -500,7 +500,7 @@ static struct ata_port_info piix_port_info[] = { /* i6300esb_sata: 6 */ { .sht = &piix_sht, - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS, + .flags = PIIX_SATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -563,11 +563,6 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, piix_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int force_pcs = 0; -module_param(force_pcs, int, 0444); -MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " - "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); - struct ich_laptop { u16 device; u16 subvendor; @@ -685,84 +680,9 @@ static void ich_pata_error_handler(struct ata_port *ap) ata_std_postreset); } -/** - * piix_sata_present_mask - determine present mask for SATA host controller - * @ap: Target port - * - * Reads SATA PCI device's PCI config register Port Configuration - * and Status (PCS) to determine port and device availability. - * - * LOCKING: - * None (inherited from caller). - * - * RETURNS: - * determined present_mask - */ -static unsigned int piix_sata_present_mask(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct piix_host_priv *hpriv = ap->host->private_data; - const unsigned int *map = hpriv->map; - int base = 2 * ap->port_no; - unsigned int present_mask = 0; - int port, i; - u16 pcs; - - pci_read_config_word(pdev, ICH5_PCS, &pcs); - DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); - - for (i = 0; i < 2; i++) { - port = map[base + i]; - if (port < 0) - continue; - if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || - (pcs & 1 << (hpriv->map_db->present_shift + port))) - present_mask |= 1 << i; - } - - DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", - ap->id, pcs, present_mask); - - return present_mask; -} - -/** - * piix_sata_softreset - reset SATA host port via ATA SRST - * @ap: port to reset - * @classes: resulting classes of attached devices - * - * Reset SATA host port via ATA SRST. On controllers with - * reliable PCS present bits, the bits are used to determine - * device presence. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes) -{ - unsigned int present_mask; - int i, rc; - - present_mask = piix_sata_present_mask(ap); - - rc = ata_std_softreset(ap, classes); - if (rc) - return rc; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (!(present_mask & (1 << i))) - classes[i] = ATA_DEV_NONE; - } - - return 0; -} - static void piix_sata_error_handler(struct ata_port *ap) { - ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL, + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL, ata_std_postreset); } @@ -1077,18 +997,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev, pci_write_config_word(pdev, ICH5_PCS, new_pcs); msleep(150); } - - if (force_pcs == 1) { - dev_printk(KERN_INFO, &pdev->dev, - "force ignoring PCS (0x%x)\n", new_pcs); - pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS; - pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS; - } else if (force_pcs == 2) { - dev_printk(KERN_INFO, &pdev->dev, - "force honoring PCS (0x%x)\n", new_pcs); - pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS; - pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS; - } } static void __devinit piix_init_sata_map(struct pci_dev *pdev, -- cgit v0.10.2 From 5e56a37c3706498b25049bb556928c461875250f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Nov 2006 18:08:10 +0900 Subject: [PATCH] ata_piix: strip now unneded MAP related stuff Now that PCS isn't used for device detection anymore... * esb_sata is identical to ich5_sata * no reason to know present_shift * no reason to store map_db in host private area The MAP table itself is left because it can be used for SCR access. Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 7bf2386..788a269 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -125,11 +125,10 @@ enum { ich_pata_100 = 3, /* ICH up to UDMA 100 */ ich_pata_133 = 4, /* ICH up to UDMA 133 */ ich5_sata = 5, - esb_sata = 6, - ich6_sata = 7, - ich6_sata_ahci = 8, - ich6m_sata_ahci = 9, - ich8_sata_ahci = 10, + ich6_sata = 6, + ich6_sata_ahci = 7, + ich6m_sata_ahci = 8, + ich8_sata_ahci = 9, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -146,13 +145,11 @@ enum { struct piix_map_db { const u32 mask; const u16 port_enable; - const int present_shift; const int map[][4]; }; struct piix_host_priv { const int *map; - const struct piix_map_db *map_db; }; static int piix_init_one (struct pci_dev *pdev, @@ -217,9 +214,9 @@ static const struct pci_device_id piix_pci_tbl[] = { /* 82801EB (ICH5) */ { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 6300ESB (ICH5 variant with broken PCS present bits) */ - { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 6300ESB pretending RAID */ - { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 82801FB/FW (ICH6/ICH6W) */ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, /* 82801FR/FRW (ICH6R/ICH6RW) */ @@ -370,7 +367,6 @@ static const struct ata_port_operations piix_sata_ops = { static const struct piix_map_db ich5_map_db = { .mask = 0x7, .port_enable = 0x3, - .present_shift = 4, .map = { /* PM PS SM SS MAP */ { P0, NA, P1, NA }, /* 000b */ @@ -387,7 +383,6 @@ static const struct piix_map_db ich5_map_db = { static const struct piix_map_db ich6_map_db = { .mask = 0x3, .port_enable = 0xf, - .present_shift = 4, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b */ @@ -400,7 +395,6 @@ static const struct piix_map_db ich6_map_db = { static const struct piix_map_db ich6m_map_db = { .mask = 0x3, .port_enable = 0x5, - .present_shift = 4, /* Map 01b isn't specified in the doc but some notebooks use * it anyway. MAP 01b have been spotted on both ICH6M and @@ -418,7 +412,6 @@ static const struct piix_map_db ich6m_map_db = { static const struct piix_map_db ich8_map_db = { .mask = 0x3, .port_enable = 0x3, - .present_shift = 8, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ @@ -430,7 +423,6 @@ static const struct piix_map_db ich8_map_db = { static const struct piix_map_db *piix_map_db_table[] = { [ich5_sata] = &ich5_map_db, - [esb_sata] = &ich5_map_db, [ich6_sata] = &ich6_map_db, [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, @@ -497,17 +489,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* i6300esb_sata: 6 */ - { - .sht = &piix_sht, - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ - .port_ops = &piix_sata_ops, - }, - - /* ich6_sata: 7 */ + /* ich6_sata: 6 */ { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, @@ -517,7 +499,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6_sata_ahci: 8 */ + /* ich6_sata_ahci: 7 */ { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -528,7 +510,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6m_sata_ahci: 9 */ + /* ich6m_sata_ahci: 8 */ { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -539,7 +521,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich8_sata_ahci: 10 */ + /* ich8_sata_ahci: 9 */ { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -1046,7 +1028,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, "invalid MAP value %u\n", map_value); hpriv->map = map; - hpriv->map_db = map_db; } /** -- cgit v0.10.2 From 8a93758170a58b5afe3e45d7d5bebbdd401a24c2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:36:12 +0900 Subject: [PATCH] libata: improve failed qc reporting Improve failed qc reporting. The original message didn't include the actual command nor full error status and it was necessary to temporarily patch the code to find out exactly which command is causing problem. This patch makes EH report full command and result TFs along with data direction and length. This change will make bug reports more useful. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e69f3df..3771eb8 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1433,16 +1433,38 @@ static void ata_eh_report(struct ata_port *ap) } for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + static const char *dma_str[] = { + [DMA_BIDIRECTIONAL] = "bidi", + [DMA_TO_DEVICE] = "out", + [DMA_FROM_DEVICE] = "in", + [DMA_NONE] = "", + }; struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; + unsigned int nbytes; if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) continue; - ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x " - "Emask 0x%x stat 0x%x err 0x%x (%s)\n", - qc->tag, qc->tf.command, qc->err_mask, - qc->result_tf.command, qc->result_tf.feature, - ata_err_string(qc->err_mask)); + nbytes = qc->nbytes; + if (!nbytes) + nbytes = qc->nsect << 9; + + ata_dev_printk(qc->dev, KERN_ERR, + "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " + "tag %d data %u %s\n " + "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " + "Emask 0x%x (%s)\n", + cmd->command, cmd->feature, cmd->nsect, + cmd->lbal, cmd->lbam, cmd->lbah, + cmd->hob_feature, cmd->hob_nsect, + cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, + cmd->device, qc->tag, nbytes, dma_str[qc->dma_dir], + res->command, res->feature, res->nsect, + res->lbal, res->lbam, res->lbah, + res->hob_feature, res->hob_nsect, + res->hob_lbal, res->hob_lbam, res->hob_lbah, + res->device, qc->err_mask, ata_err_string(qc->err_mask)); } } -- cgit v0.10.2 From 61c0596c5fbef99df5518ae449be4ab49a2c2233 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:35:43 +0900 Subject: [PATCH] libata: trivial updates to ata_sg_init_one() There's no need to memset &qc->sgent manually, sg_init_one() clears sgent inside it. Also, kill not-so-necessary sg local variable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 21f8d61..a52c071 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3491,19 +3491,15 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) { - struct scatterlist *sg; - qc->flags |= ATA_QCFLAG_SINGLE; - memset(&qc->sgent, 0, sizeof(qc->sgent)); qc->__sg = &qc->sgent; qc->n_elem = 1; qc->orig_n_elem = 1; qc->buf_virt = buf; qc->nbytes = buflen; - sg = qc->__sg; - sg_init_one(sg, buf, buflen); + sg_init_one(&qc->sgent, buf, buflen); } /** -- cgit v0.10.2 From 39599a5334decc2669ba794fb0ccd2b112ef1ba4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:37:35 +0900 Subject: [PATCH] libata: sync result_tf.flags w/ command tf.flags libata didn't initialize result_tf.flags which indicates transfer type (RW/FUA) and address type (CHS/LBA/LBA48). ata_gen_fixed_sense() assumed result_tf.flags equals command tf.flags and failed to report the first failed block to SCSI layer because zero tf flags indicates CHS and bad block reporting for CHS is not implemented. Implement fill_result_tf() which sets result_tf.flags to command tf.flags and use it to fill result_tf. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a52c071..13dcef8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4536,6 +4536,14 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) qc->complete_fn(qc); } +static void fill_result_tf(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + ap->ops->tf_read(ap, &qc->result_tf); + qc->result_tf.flags = qc->tf.flags; +} + /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete @@ -4573,7 +4581,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { if (!ata_tag_internal(qc->tag)) { /* always fill result TF for failed qc */ - ap->ops->tf_read(ap, &qc->result_tf); + fill_result_tf(qc); ata_qc_schedule_eh(qc); return; } @@ -4581,7 +4589,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) /* read result TF if requested */ if (qc->flags & ATA_QCFLAG_RESULT_TF) - ap->ops->tf_read(ap, &qc->result_tf); + fill_result_tf(qc); __ata_qc_complete(qc); } else { @@ -4590,7 +4598,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) /* read result TF if failed or requested */ if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) - ap->ops->tf_read(ap, &qc->result_tf); + fill_result_tf(qc); __ata_qc_complete(qc); } -- cgit v0.10.2 From f38621b3109068adc8430bc2d170ccea59df4261 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:37:35 +0900 Subject: [PATCH] libata: fix passthru sense data header sb[7] should contain the length of whole information sense data descriptor while desc[1] should contain the number of following bytes in the descriptor. ie. 14 for sb[7] but 12 for desc[1]. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7a55c2e4..87f8282 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -713,12 +713,9 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) desc[0] = 0x09; - /* - * Set length of additional sense data. - * Since we only populate descriptor 0, the total - * length is the same (fixed) length as descriptor 0. - */ - desc[1] = sb[7] = 14; + /* set length of additional sense data */ + sb[7] = 14; + desc[1] = 12; /* * Copy registers into sense buffer. -- cgit v0.10.2 From 750426aa1ad1ddd1fa8bb4ed531a7956f3b9a27c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:37:35 +0900 Subject: [PATCH] libata: cosmetic changes to sense generation functions * s/ata_gen_ata_desc_sense/ata_gen_passthru_sense/ * s/ata_gen_fixed_sense/ata_gen_ata_sense/ * make both functions static * neither function has locking requirement, change it to None. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 87f8282..6626ee1 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -671,7 +671,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, } /* - * ata_gen_ata_desc_sense - Generate check condition sense block. + * ata_gen_passthru_sense - Generate check condition sense block. * @qc: Command that completed. * * This function is specific to the ATA descriptor format sense @@ -681,9 +681,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, * block. Clear sense key, ASC & ASCQ if there is no error. * * LOCKING: - * spin_lock_irqsave(host lock) + * None. */ -void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) +static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; struct ata_taskfile *tf = &qc->result_tf; @@ -743,16 +743,16 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) } /** - * ata_gen_fixed_sense - generate a SCSI fixed sense block + * ata_gen_ata_sense - generate a SCSI fixed sense block * @qc: Command that we are erroring out * * Leverage ata_to_sense_error() to give us the codes. Fit our * LBA in here if there's room. * * LOCKING: - * inherited from caller + * None. */ -void ata_gen_fixed_sense(struct ata_queued_cmd *qc) +static void ata_gen_ata_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; struct ata_taskfile *tf = &qc->result_tf; @@ -1460,7 +1460,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) { - ata_gen_ata_desc_sense(qc); + ata_gen_passthru_sense(qc); } else { if (!need_sense) { cmd->result = SAM_STAT_GOOD; @@ -1471,7 +1471,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * good for smaller LBA (and maybe CHS?) * devices. */ - ata_gen_fixed_sense(qc); + ata_gen_ata_sense(qc); } } @@ -2302,7 +2302,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) * a sense descriptors, since that's only * correct for ATA, not ATAPI */ - ata_gen_ata_desc_sense(qc); + ata_gen_passthru_sense(qc); } qc->scsidone(qc->scsicmd); @@ -2377,7 +2377,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) * sense descriptors, since that's only * correct for ATA, not ATAPI */ - ata_gen_ata_desc_sense(qc); + ata_gen_passthru_sense(qc); } /* SCSI EH automatically locks door if sdev->locked is @@ -2410,7 +2410,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) * a sense descriptors, since that's only * correct for ATA, not ATAPI */ - ata_gen_ata_desc_sense(qc); + ata_gen_passthru_sense(qc); } else { u8 *scsicmd = cmd->cmnd; -- cgit v0.10.2 From 35b649fe2587b2e569c17c022ba3506ba441b6a2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:37:35 +0900 Subject: [PATCH] libata: implement ata_tf_read_block() Implement ata_tf_read_block(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 13dcef8..3fd7c79 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -240,6 +240,49 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) } /** + * ata_tf_read_block - Read block address from ATA taskfile + * @tf: ATA taskfile of interest + * @dev: ATA device @tf belongs to + * + * LOCKING: + * None. + * + * Read block address from @tf. This function can handle all + * three address formats - LBA, LBA48 and CHS. tf->protocol and + * flags select the address format to use. + * + * RETURNS: + * Block address read from @tf. + */ +u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) +{ + u64 block = 0; + + if (tf->flags & ATA_TFLAG_LBA) { + if (tf->flags & ATA_TFLAG_LBA48) { + block |= (u64)tf->hob_lbah << 40; + block |= (u64)tf->hob_lbam << 32; + block |= tf->hob_lbal << 24; + } else + block |= (tf->device & 0xf) << 24; + + block |= tf->lbah << 16; + block |= tf->lbam << 8; + block |= tf->lbal; + } else { + u32 cyl, head, sect; + + cyl = tf->lbam | (tf->lbah << 8); + head = tf->device & 0xf; + sect = tf->lbal; + + block = (cyl * dev->heads + head) * dev->sectors + sect; + } + + return block; +} + +/** * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask * @pio_mask: pio_mask * @mwdma_mask: mwdma_mask diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index be2ac39..2d532da 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -52,6 +52,7 @@ extern int atapi_dmadir; extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); extern void ata_dev_disable(struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); extern unsigned ata_exec_internal(struct ata_device *dev, -- cgit v0.10.2 From d25614bad6eec8fb80f3ef5bffbf720ebb7d2412 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 Nov 2006 22:37:35 +0900 Subject: [PATCH] libata: improve SCSI sense data generation Update ata_gen_ata_sense() to use desc format sense data to report the first failed block. The first failed block is read from result_tf using ata_tf_read_block() which can handle all three address formats. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6626ee1..56d7e1e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -746,53 +746,53 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) * ata_gen_ata_sense - generate a SCSI fixed sense block * @qc: Command that we are erroring out * - * Leverage ata_to_sense_error() to give us the codes. Fit our - * LBA in here if there's room. + * Generate sense block for a failed ATA command @qc. Descriptor + * format is used to accomodate LBA48 block address. * * LOCKING: * None. */ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) { + struct ata_device *dev = qc->dev; struct scsi_cmnd *cmd = qc->scsicmd; struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; + unsigned char *desc = sb + 8; int verbose = qc->ap->ops->error_handler == NULL; + u64 block; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* - * Use ata_to_sense_error() to map status register bits + /* sense data is current and format is descriptor */ + sb[0] = 0x72; + + /* Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ if (qc->err_mask || tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, - &sb[2], &sb[12], &sb[13], verbose); - sb[2] &= 0x0f; + &sb[1], &sb[2], &sb[3], verbose); + sb[1] &= 0x0f; } - sb[0] = 0x70; - sb[7] = 0x0a; + block = ata_tf_read_block(&qc->result_tf, dev); - if (tf->flags & ATA_TFLAG_LBA48) { - /* TODO: find solution for LBA48 descriptors */ - } + /* information sense data descriptor */ + sb[7] = 12; + desc[0] = 0x00; + desc[1] = 10; - else if (tf->flags & ATA_TFLAG_LBA) { - /* A small (28b) LBA will fit in the 32b info field */ - sb[0] |= 0x80; /* set valid bit */ - sb[3] = tf->device & 0x0f; - sb[4] = tf->lbah; - sb[5] = tf->lbam; - sb[6] = tf->lbal; - } - - else { - /* TODO: C/H/S */ - } + desc[2] |= 0x80; /* valid */ + desc[6] = block >> 40; + desc[7] = block >> 32; + desc[8] = block >> 24; + desc[9] = block >> 16; + desc[10] = block >> 8; + desc[11] = block; } static void ata_scsi_sdev_config(struct scsi_device *sdev) -- cgit v0.10.2 From 46b027cc30b6f6571191826afc718fa942403fc8 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 14 Nov 2006 14:46:17 -0500 Subject: [libata] sata_promise: fix TBG mode register offset Fixes crashes on sparc, and may correct weird behavior reported on occasions, because we were never programming this register correctly (or at all). Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 72eda51..9c4389b 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -46,15 +46,14 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "1.04" +#define DRV_VERSION "1.05" enum { PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ - PDC_TBG_MODE = 0x41, /* TBG mode */ + PDC_TBG_MODE = 0x41C, /* TBG mode */ PDC_FLASH_CTL = 0x44, /* Flash control register */ - PDC_PCI_CTL = 0x48, /* PCI control and status register */ PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ -- cgit v0.10.2 From b2d1eee1e99e15a80fa9623724d6861a81d2aba4 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 22 Nov 2006 22:00:15 +0100 Subject: [PATCH] sata_promise fixes and updates This patch updates the sata_promise driver as follows: - Correct typo in definition of PDC_TBG_MODE: it's at 0x41C not 0x41 in first-generation chips. This error caused PCI access alignment exceptions on SPARC64, and on all platforms it disabled the expected initialisation of TBG mode. - Add flags field to struct pdc_host_priv. Define PDC_FLAG_GEN_II and use it to distinguish first- and second-generation chips. - Prevent the FLASH_CTL FIFO_SHD bit from being set to 1 on second- generation chips. This matches Promises' ulsata2 driver. - Prevent TBG mode and SLEW rate initialisation in second-generation chips. These two registers have moved, TBG mode has been redefined, and Promise's ulsata2 driver no longer attempts to initialise them. - Correct PCI device table so devices 0x3570, 0x3571, and 0x3d73 are marked as 2057x (2nd gen) not 2037x (1st gen). - Correct PCI device table so device 0x3d17 is marked as 40518 (2nd gen 4 ports) not 20319 (1st gen 4 ports). - Correct pdc_ata_init_one() to treat 20771 as a second-generation chip. Tested on 0x3d75 (2nd gen), 0x3d73 (2nd gen), and 0x3373 (1st gen) chips. The information comes from the newly uploaded Promise SATA HW specs, Promise's ultra and ulsata2 drivers, and debugging on 3d75/3d73/3373 chips. hp->hotplug_offset could now be removed and its value recomputed in pdc_host_init() using hp->flags, but that would be a cleanup not a functional change, so I'm ignoring it for now. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 9c4389b..8daf5d6 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -52,13 +52,13 @@ enum { PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ - PDC_TBG_MODE = 0x41C, /* TBG mode */ PDC_FLASH_CTL = 0x44, /* Flash control register */ PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ - PDC_SLEW_CTL = 0x470, /* slew rate control reg */ + PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ + PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */ PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<8) | (1<<9) | (1<<10), @@ -77,6 +77,9 @@ enum { PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, + + /* hp->flags bits */ + PDC_FLAG_GEN_II = (1 << 0), }; @@ -86,6 +89,7 @@ struct pdc_port_priv { }; struct pdc_host_priv { + unsigned long flags; int hotplug_offset; }; @@ -234,20 +238,20 @@ static const struct ata_port_info pdc_port_info[] = { static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3371), board_2037x }, - { PCI_VDEVICE(PROMISE, 0x3570), board_2037x }, - { PCI_VDEVICE(PROMISE, 0x3571), board_2037x }, { PCI_VDEVICE(PROMISE, 0x3373), board_2037x }, { PCI_VDEVICE(PROMISE, 0x3375), board_2037x }, { PCI_VDEVICE(PROMISE, 0x3376), board_2037x }, + { PCI_VDEVICE(PROMISE, 0x3570), board_2057x }, + { PCI_VDEVICE(PROMISE, 0x3571), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, + { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, - { PCI_VDEVICE(PROMISE, 0x3d73), board_2037x }, { PCI_VDEVICE(PROMISE, 0x3318), board_20319 }, { PCI_VDEVICE(PROMISE, 0x3319), board_20319 }, { PCI_VDEVICE(PROMISE, 0x3515), board_20319 }, { PCI_VDEVICE(PROMISE, 0x3519), board_20319 }, - { PCI_VDEVICE(PROMISE, 0x3d17), board_20319 }, + { PCI_VDEVICE(PROMISE, 0x3d17), board_40518 }, { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 }, { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, @@ -639,9 +643,11 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) * "TODO: figure out why we do this" */ - /* change FIFO_SHD to 8 dwords, enable BMR_BURST */ + /* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */ tmp = readl(mmio + PDC_FLASH_CTL); - tmp |= 0x12000; /* bit 16 (fifo 8 dw) and 13 (bmr burst?) */ + tmp |= 0x02000; /* bit 13 (enable bmr burst) */ + if (!(hp->flags & PDC_FLAG_GEN_II)) + tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */ writel(tmp, mmio + PDC_FLASH_CTL); /* clear plug/unplug flags for all ports */ @@ -652,6 +658,10 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) tmp = readl(mmio + hotplug_offset); writel(tmp | 0xff0000, mmio + hotplug_offset); + /* don't initialise TBG or SLEW on 2nd generation chips */ + if (hp->flags & PDC_FLAG_GEN_II) + return; + /* reduce TBG clock to 133 Mhz. */ tmp = readl(mmio + PDC_TBG_MODE); tmp &= ~0x30000; /* clear bit 17, 16*/ @@ -745,6 +755,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e /* notice 4-port boards */ switch (board_idx) { case board_40518: + hp->flags |= PDC_FLAG_GEN_II; /* Override hotplug offset for SATAII150 */ hp->hotplug_offset = PDC2_SATA_PLUG_CSR; /* Fall through */ @@ -758,15 +769,14 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e probe_ent->port[3].scr_addr = base + 0x700; break; case board_2057x: + case board_20771: + hp->flags |= PDC_FLAG_GEN_II; /* Override hotplug offset for SATAII150 */ hp->hotplug_offset = PDC2_SATA_PLUG_CSR; /* Fall through */ case board_2037x: probe_ent->n_ports = 2; break; - case board_20771: - probe_ent->n_ports = 2; - break; case board_20619: probe_ent->n_ports = 4; -- cgit v0.10.2 From 54083f114efad2d4fa993c52024f8973c70b9edb Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 15 Nov 2006 16:17:13 +0000 Subject: [PATCH] pata_hpt366 enablebits More enablebits Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index c0e150a9..c15c8dc 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -27,7 +27,7 @@ #include #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.5.1" struct hpt_clock { u8 xfer_speed; @@ -222,9 +222,17 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed) static int hpt36x_pre_reset(struct ata_port *ap) { + static const struct pci_bits hpt36x_enable_bits[] = { + { 0x50, 1, 0x04, 0x04 }, + { 0x54, 1, 0x04, 0x04 } + }; + u8 ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); + if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no])) + return -ENOENT; + pci_read_config_byte(pdev, 0x5A, &ata66); if (ata66 & (1 << ap->port_no)) ap->cbl = ATA_CBL_PATA40; -- cgit v0.10.2 From f7e37ba83fd3e92411dfc97d08eaf9d85dfac2ee Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:21:03 +0000 Subject: [PATCH] pata_cs5530: suspend/resume support The 5530 needs various set up performing both at init time and resume time. To keep the code clean the common setup code is moved into a new function and called from both handlers. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 981f492..265012b 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -35,7 +35,7 @@ #include #define DRV_NAME "pata_cs5530" -#define DRV_VERSION "0.6" +#define DRV_VERSION "0.7.1" /** * cs5530_set_piomode - PIO setup @@ -182,6 +182,8 @@ static struct scsi_host_template cs5530_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations cs5530_port_ops = { @@ -239,38 +241,18 @@ static int cs5530_is_palmax(void) return 0; } + /** - * cs5530_init_one - Initialise a CS5530 - * @dev: PCI device - * @id: Entry in match table + * cs5530_init_chip - Chipset init * - * Install a driver for the newly found CS5530 companion chip. Most of - * this is just housekeeping. We have to set the chip up correctly and - * turn off various bits of emulation magic. + * Perform the chip initialisation work that is shared between both + * setup and resume paths */ - -static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) + +static int cs5530_init_chip(void) { - int compiler_warning_pointless_fix; - struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; - static struct ata_port_info info = { - .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &cs5530_port_ops - }; - /* The docking connector doesn't do UDMA, and it seems not MWDMA */ - static struct ata_port_info info_palmax_secondary = { - .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .port_ops = &cs5530_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; + struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL; - dev = NULL; while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { switch (dev->device) { case PCI_DEVICE_ID_CYRIX_PCI_MASTER: @@ -291,7 +273,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) } pci_set_master(cs5530_0); - compiler_warning_pointless_fix = pci_set_mwi(cs5530_0); + pci_set_mwi(cs5530_0); /* * Set PCI CacheLineSize to 16-bytes: @@ -339,13 +321,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) pci_dev_put(master_0); pci_dev_put(cs5530_0); - - if (cs5530_is_palmax()) - port_info[1] = &info_palmax_secondary; - - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); - + return 0; fail_put: if (master_0) pci_dev_put(master_0); @@ -354,6 +330,53 @@ fail_put: return -ENODEV; } +/** + * cs5530_init_one - Initialise a CS5530 + * @dev: PCI device + * @id: Entry in match table + * + * Install a driver for the newly found CS5530 companion chip. Most of + * this is just housekeeping. We have to set the chip up correctly and + * turn off various bits of emulation magic. + */ + +static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + static struct ata_port_info info = { + .sht = &cs5530_sht, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x07, + .port_ops = &cs5530_port_ops + }; + /* The docking connector doesn't do UDMA, and it seems not MWDMA */ + static struct ata_port_info info_palmax_secondary = { + .sht = &cs5530_sht, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, + .pio_mask = 0x1f, + .port_ops = &cs5530_port_ops + }; + static struct ata_port_info *port_info[2] = { &info, &info }; + + /* Chip initialisation */ + if (cs5530_init_chip()) + return -ENODEV; + + if (cs5530_is_palmax()) + port_info[1] = &info_palmax_secondary; + + /* Now kick off ATA set up */ + return ata_pci_init_one(pdev, port_info, 2); +} + +static int cs5530_reinit_one(struct pci_dev *pdev) +{ + /* If we fail on resume we are doomed */ + BUG_ON(cs5530_init_chip()); + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id cs5530[] = { { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, @@ -364,7 +387,9 @@ static struct pci_driver cs5530_pci_driver = { .name = DRV_NAME, .id_table = cs5530, .probe = cs5530_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = cs5530_reinit_one, }; static int __init cs5530_init(void) -- cgit v0.10.2 From d39ca896fb9a25f80465d3e52872cf5c510762a8 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:18:30 +0000 Subject: [PATCH] pata_jmicron: fix JMB368 support, add suspend/resume handling This (and the pci resume quirk code) get the JMicron controllers to resume properly. Without this patch the drive mapping changes when you suspend/resume which is not good at all.... Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 0210b10..c9f0a54 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -19,7 +19,7 @@ #include #define DRV_NAME "pata_jmicron" -#define DRV_VERSION "0.1.2" +#define DRV_VERSION "0.1.4" typedef enum { PORT_PATA0 = 0, @@ -213,12 +213,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i /* FIXME: We may want a way to override this in future */ pci_write_config_byte(pdev, 0x41, 0xa1); - } - - /* PATA controller is fn 1, AHCI is fn 0 */ - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; + /* PATA controller is fn 1, AHCI is fn 0 */ + if (PCI_FUNC(pdev->devfn) != 1) + return -ENODEV; + } if ( id->driver_data == 365 || id->driver_data == 366) { /* The 365/66 have two PATA channels, redirect the second */ pci_read_config_dword(pdev, 0x80, ®); @@ -229,6 +228,27 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i return ata_pci_init_one(pdev, port_info, 2); } +static int jmicron_reinit_one(struct pci_dev *pdev) +{ + u32 reg; + + switch(pdev->device) { + case PCI_DEVICE_ID_JMICRON_JMB368: + break; + case PCI_DEVICE_ID_JMICRON_JMB365: + case PCI_DEVICE_ID_JMICRON_JMB366: + /* Restore mapping or disks swap and boy does it get ugly */ + pci_read_config_dword(pdev, 0x80, ®); + reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ + pci_write_config_dword(pdev, 0x80, reg); + /* Fall through */ + default: + /* Make sure AHCI is turned back on */ + pci_write_config_byte(pdev, 0x41, 0xa1); + } + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id jmicron_pci_tbl[] = { { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361}, { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363}, @@ -244,6 +264,8 @@ static struct pci_driver jmicron_pci_driver = { .id_table = jmicron_pci_tbl, .probe = jmicron_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = jmicron_reinit_one, }; static int __init jmicron_init(void) -- cgit v0.10.2 From 34d8dfb1e6b51dbd6eefcb449b531c7ee773664c Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:26:06 +0000 Subject: [PATCH] pata_ali: suspend/resume support Various chipset functions must be reprogrammed on a resume from RAM, without this things like ATAPI DMA stop working on resume with some chipset variants. Split the chipset programming and init time method selection into two functions. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index e6d2b84..ae6d573 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -34,7 +34,7 @@ #include #define DRV_NAME "pata_ali" -#define DRV_VERSION "0.6.6" +#define DRV_VERSION "0.7.1" /* * Cable special cases @@ -348,6 +348,8 @@ static struct scsi_host_template ali_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; /* @@ -497,6 +499,69 @@ static struct ata_port_operations ali_c5_port_ops = { .host_stop = ata_host_stop }; + +/** + * ali_init_chipset - chip setup function + * @pdev: PCI device of ATA controller + * + * Perform the setup on the device that must be done both at boot + * and at resume time. + */ + +static void ali_init_chipset(struct pci_dev *pdev) +{ + u8 rev, tmp; + struct pci_dev *north, *isa_bridge; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + + /* + * The chipset revision selects the driver operations and + * mode data. + */ + + if (rev >= 0x20 && rev < 0xC2) { + /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ + pci_read_config_byte(pdev, 0x4B, &tmp); + /* Clear CD-ROM DMA write bit */ + tmp &= 0x7F; + pci_write_config_byte(pdev, 0x4B, tmp); + } else if (rev >= 0xC2) { + /* Enable cable detection logic */ + pci_read_config_byte(pdev, 0x4B, &tmp); + pci_write_config_byte(pdev, 0x4B, tmp | 0x08); + } + north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0)); + isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + + if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) { + /* Configure the ALi bridge logic. For non ALi rely on BIOS. + Set the south bridge enable bit */ + pci_read_config_byte(isa_bridge, 0x79, &tmp); + if (rev == 0xC2) + pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); + else if (rev > 0xC2) + pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); + } + if (rev >= 0x20) { + /* + * CD_ROM DMA on (0x53 bit 0). Enable this even if we want + * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control + * via 0x54/55. + */ + pci_read_config_byte(pdev, 0x53, &tmp); + if (rev <= 0x20) + tmp &= ~0x02; + if (rev >= 0xc7) + tmp |= 0x03; + else + tmp |= 0x01; /* CD_ROM enable for DMA */ + pci_write_config_byte(pdev, 0x53, tmp); + } + pci_dev_put(isa_bridge); + pci_dev_put(north); + ata_pci_clear_simplex(pdev); +} /** * ali_init_one - discovery callback * @pdev: PCI device ID @@ -570,7 +635,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static struct ata_port_info *port_info[2]; u8 rev, tmp; - struct pci_dev *north, *isa_bridge; + struct pci_dev *isa_bridge; pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); @@ -582,11 +647,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (rev < 0x20) { port_info[0] = port_info[1] = &info_early; } else if (rev < 0xC2) { - /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ - pci_read_config_byte(pdev, 0x4B, &tmp); - /* Clear CD-ROM DMA write bit */ - tmp &= 0x7F; - pci_write_config_byte(pdev, 0x4B, tmp); port_info[0] = port_info[1] = &info_20; } else if (rev == 0xC2) { port_info[0] = port_info[1] = &info_c2; @@ -597,54 +657,25 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } else port_info[0] = port_info[1] = &info_c5; - if (rev >= 0xC2) { - /* Enable cable detection logic */ - pci_read_config_byte(pdev, 0x4B, &tmp); - pci_write_config_byte(pdev, 0x4B, tmp | 0x08); - } - - north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0)); + ali_init_chipset(pdev); + isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - if (north && north->vendor == PCI_VENDOR_ID_AL) { - /* Configure the ALi bridge logic. For non ALi rely on BIOS. - Set the south bridge enable bit */ - pci_read_config_byte(isa_bridge, 0x79, &tmp); - if (rev == 0xC2) - pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); - else if (rev > 0xC2) - pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); + if (isa_bridge && rev >= 0x20 && rev < 0xC2) { + /* Are we paired with a UDMA capable chip */ + pci_read_config_byte(isa_bridge, 0x5E, &tmp); + if ((tmp & 0x1E) == 0x12) + port_info[0] = port_info[1] = &info_20_udma; + pci_dev_put(isa_bridge); } - - if (rev >= 0x20) { - if (rev < 0xC2) { - /* Are we paired with a UDMA capable chip */ - pci_read_config_byte(isa_bridge, 0x5E, &tmp); - if ((tmp & 0x1E) == 0x12) - port_info[0] = port_info[1] = &info_20_udma; - } - /* - * CD_ROM DMA on (0x53 bit 0). Enable this even if we want - * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control - * via 0x54/55. - */ - pci_read_config_byte(pdev, 0x53, &tmp); - if (rev <= 0x20) - tmp &= ~0x02; - if (rev >= 0xc7) - tmp |= 0x03; - else - tmp |= 0x01; /* CD_ROM enable for DMA */ - pci_write_config_byte(pdev, 0x53, tmp); - } - - pci_dev_put(isa_bridge); - pci_dev_put(north); - - ata_pci_clear_simplex(pdev); return ata_pci_init_one(pdev, port_info, 2); } +static int ali_reinit_one(struct pci_dev *pdev) +{ + ali_init_chipset(pdev); + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id ali[] = { { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), }, { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), }, @@ -656,7 +687,9 @@ static struct pci_driver ali_pci_driver = { .name = DRV_NAME, .id_table = ali, .probe = ali_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ali_reinit_one, }; static int __init ali_init(void) -- cgit v0.10.2 From ad4a42d287546888349ad24d351673a59f429ee8 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:23:37 +0000 Subject: [PATCH] pata_rz1000: Force readahead off on resume The RZ1000 is a generic device except that it has a readahead fifo flaw that corrupts. We force this off at init time but we want to be paranoid and force it off at resume as well. I don't know of any actual hardware that supports both RZ1000 and suspend to RAM but given its a disk muncher better safe than sorry. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index e4e5ea4..21567ab 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -21,7 +21,7 @@ #include #define DRV_NAME "pata_rz1000" -#define DRV_VERSION "0.2.2" +#define DRV_VERSION "0.2.3" /** @@ -92,6 +92,8 @@ static struct scsi_host_template rz1000_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations rz1000_port_ops = { @@ -129,6 +131,19 @@ static struct ata_port_operations rz1000_port_ops = { .host_stop = ata_host_stop }; +static int rz1000_fifo_disable(struct pci_dev *pdev) +{ + u16 reg; + /* Be exceptionally paranoid as we must be sure to apply the fix */ + if (pci_read_config_word(pdev, 0x40, ®) != 0) + return -1; + reg &= 0xDFFF; + if (pci_write_config_word(pdev, 0x40, reg) != 0) + return -1; + printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); + return 0; +} + /** * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services * @pdev: PCI device to register @@ -143,7 +158,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en { static int printed_version; struct ata_port_info *port_info[2]; - u16 reg; static struct ata_port_info info = { .sht = &rz1000_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -154,23 +168,25 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); - /* Be exceptionally paranoid as we must be sure to apply the fix */ - if (pci_read_config_word(pdev, 0x40, ®) != 0) - goto fail; - reg &= 0xDFFF; - if (pci_write_config_word(pdev, 0x40, reg) != 0) - goto fail; - printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); - - port_info[0] = &info; - port_info[1] = &info; - return ata_pci_init_one(pdev, port_info, 2); -fail: + if (rz1000_fifo_disable(pdev) == 0) { + port_info[0] = &info; + port_info[1] = &info; + return ata_pci_init_one(pdev, port_info, 2); + } printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); /* Not safe to use so skip */ return -ENODEV; } +static int rz1000_reinit_one(struct pci_dev *pdev) +{ + /* If this fails on resume (which is a "cant happen" case), we + must stop as any progress risks data loss */ + if (rz1000_fifo_disable(pdev)) + panic("rz1000 fifo"); + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id pata_rz1000[] = { { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, @@ -182,7 +198,9 @@ static struct pci_driver rz1000_pci_driver = { .name = DRV_NAME, .id_table = pata_rz1000, .probe = rz1000_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = rz1000_reinit_one, }; static int __init rz1000_init(void) -- cgit v0.10.2 From 8550c1637ba7dd96a76353eb52d31088f9c2f5fe Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:28:41 +0000 Subject: [PATCH] pata_sil680 suspend/resume The SI680 can come back from s2ram with the clocks disabled (crash time) or wrong (ugly as this can cause CRC errors, and in theory corruption). On a resume we must put the clock back. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 11942fd..5d3b42e 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -33,7 +33,7 @@ #include #define DRV_NAME "pata_sil680" -#define DRV_VERSION "0.3.2" +#define DRV_VERSION "0.4.1" /** * sil680_selreg - return register base @@ -263,32 +263,20 @@ static struct ata_port_operations sil680_port_ops = { .host_stop = ata_host_stop }; -static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +/** + * sil680_init_chip - chip setup + * @pdev: PCI device + * + * Perform all the chip setup which must be done both when the device + * is powered up on boot and when we resume in case we resumed from RAM. + * Returns the final clock settings. + */ + +static u8 sil680_init_chip(struct pci_dev *pdev) { - static struct ata_port_info info = { - .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &sil680_port_ops - }; - static struct ata_port_info info_slow = { - .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, - .port_ops = &sil680_port_ops - }; - static struct ata_port_info *port_info[2] = {&info, &info}; - static int printed_version; u32 class_rev = 0; u8 tmpbyte = 0; - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; /* FIXME: double check */ @@ -323,8 +311,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_read_config_byte(pdev, 0x8A, &tmpbyte); printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", tmpbyte & 1, tmpbyte & 0x30); - if ((tmpbyte & 0x30) == 0) - port_info[0] = port_info[1] = &info_slow; pci_write_config_byte(pdev, 0xA1, 0x72); pci_write_config_word(pdev, 0xA2, 0x328A); @@ -343,11 +329,51 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; /* This last case is _NOT_ ok */ case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); - return -EIO; + } + return tmpbyte & 0x30; +} + +static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + static struct ata_port_info info = { + .sht = &sil680_sht, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x7f, + .port_ops = &sil680_port_ops + }; + static struct ata_port_info info_slow = { + .sht = &sil680_sht, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x3f, + .port_ops = &sil680_port_ops + }; + static struct ata_port_info *port_info[2] = {&info, &info}; + static int printed_version; + + if (!printed_version++) + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + + switch(sil680_init_chip(pdev)) + { + case 0: + port_info[0] = port_info[1] = &info_slow; + break; + case 0x30: + return -ENODEV; } return ata_pci_init_one(pdev, port_info, 2); } +static int sil680_reinit_one(struct pci_dev *pdev) +{ + sil680_init_chip(pdev); + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id sil680[] = { { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, @@ -358,7 +384,9 @@ static struct pci_driver sil680_pci_driver = { .name = DRV_NAME, .id_table = sil680, .probe = sil680_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = sil680_reinit_one, }; static int __init sil680_init(void) -- cgit v0.10.2 From 30ced0f0d211999f316930eff7287aa5a9995bef Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 16:57:36 +0000 Subject: [PATCH] PATA libata: suspend/resume simple cases This patch adds the suspend/resume callbacks for drivers which don't need any additional help (beyond the pci resume quirk patch I posted earlier anyway). Also bring version numbers back inline with master copies. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 1b9ba4d..c7e8f03 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -26,7 +26,7 @@ #include #define DRV_NAME "ata_generic" -#define DRV_VERSION "0.2.7" +#define DRV_VERSION "0.2.10" /* * A generic parallel ATA driver using libata @@ -118,6 +118,8 @@ static struct scsi_host_template generic_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations generic_port_ops = { @@ -226,7 +228,9 @@ static struct pci_driver ata_generic_pci_driver = { .name = DRV_NAME, .id_table = ata_generic, .probe = ata_generic_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init ata_generic_init(void) diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 4e1d3b5..7d9e391 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -22,7 +22,7 @@ #include #define DRV_NAME "pata_atiixp" -#define DRV_VERSION "0.4.3" +#define DRV_VERSION "0.4.4" enum { ATIIXP_IDE_PIO_TIMING = 0x40, @@ -218,6 +218,8 @@ static struct scsi_host_template atiixp_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations atiixp_port_ops = { @@ -281,7 +283,9 @@ static struct pci_driver atiixp_pci_driver = { .name = DRV_NAME, .id_table = atiixp, .probe = atiixp_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .resume = ata_pci_device_resume, + .suspend = ata_pci_device_suspend, }; static int __init atiixp_init(void) diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 8dafa4a..38c00f6 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -39,7 +39,7 @@ #include #define DRV_NAME "cs5535" -#define DRV_VERSION "0.2.10" +#define DRV_VERSION "0.2.11" /* * The Geode (Aka Athlon GX now) uses an internal MSR based @@ -186,6 +186,8 @@ static struct scsi_host_template cs5535_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations cs5535_port_ops = { @@ -269,6 +271,8 @@ static struct pci_driver cs5535_pci_driver = { .id_table = cs5535, .probe = cs5535_init_one, .remove = ata_pci_remove_one + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init cs5535_init(void) diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 5a0b811..6352bc7 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -18,7 +18,7 @@ #include #define DRV_NAME "pata_cypress" -#define DRV_VERSION "0.1.2" +#define DRV_VERSION "0.1.4" /* here are the offset definitions for the registers */ @@ -137,6 +137,8 @@ static struct scsi_host_template cy82c693_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations cy82c693_port_ops = { @@ -204,7 +206,9 @@ static struct pci_driver cy82c693_pci_driver = { .name = DRV_NAME, .id_table = cy82c693, .probe = cy82c693_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init cy82c693_init(void) diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 755f792..5658983 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -22,7 +22,7 @@ #include #define DRV_NAME "pata_efar" -#define DRV_VERSION "0.4.2" +#define DRV_VERSION "0.4.3" /** * efar_pre_reset - check for 40/80 pin @@ -235,6 +235,8 @@ static struct scsi_host_template efar_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations efar_ops = { @@ -316,6 +318,8 @@ static struct pci_driver efar_pci_driver = { .id_table = efar_pci_tbl, .probe = efar_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init efar_init(void) diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 1ea6407..a5953c3 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -20,7 +20,7 @@ #include #define DRV_NAME "pata_marvell" -#define DRV_VERSION "0.0.5u" +#define DRV_VERSION "0.1.1" /** * marvell_pre_reset - check for 40/80 pin @@ -103,6 +103,8 @@ static struct scsi_host_template marvell_sht = { .slave_configure = ata_scsi_slave_config, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations marvell_ops = { @@ -197,6 +199,8 @@ static struct pci_driver marvell_pci_driver = { .id_table = marvell_pci_tbl, .probe = marvell_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init marvell_init(void) diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index e00d406..752a741 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -35,7 +35,7 @@ #include #define DRV_NAME "pata_mpiix" -#define DRV_VERSION "0.7.2" +#define DRV_VERSION "0.7.3" enum { IDETIM = 0x6C, /* IDE control register */ @@ -168,6 +168,8 @@ static struct scsi_host_template mpiix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations mpiix_port_ops = { @@ -285,7 +287,9 @@ static struct pci_driver mpiix_pci_driver = { .name = DRV_NAME, .id_table = mpiix, .probe = mpiix_init_one, - .remove = mpiix_remove_one + .remove = mpiix_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init mpiix_init(void) diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 1963a4d..9566167 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -16,7 +16,7 @@ #include #define DRV_NAME "pata_netcell" -#define DRV_VERSION "0.1.5" +#define DRV_VERSION "0.1.6" /** * netcell_probe_init - check for 40/80 pin @@ -65,6 +65,8 @@ static struct scsi_host_template netcell_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations netcell_ops = { @@ -153,6 +155,8 @@ static struct pci_driver netcell_pci_driver = { .id_table = netcell_pci_tbl, .probe = netcell_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init netcell_init(void) diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 7ec800f..428e6b5 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -28,7 +28,7 @@ #include #define DRV_NAME "pata_ns87410" -#define DRV_VERSION "0.4.2" +#define DRV_VERSION "0.4.3" /** * ns87410_pre_reset - probe begin @@ -158,6 +158,8 @@ static struct scsi_host_template ns87410_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations ns87410_port_ops = { @@ -210,7 +212,9 @@ static struct pci_driver ns87410_pci_driver = { .name = DRV_NAME, .id_table = ns87410, .probe = ns87410_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init ns87410_init(void) diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 8837256..1283fb7 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -233,6 +233,8 @@ static struct scsi_host_template oldpiix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations oldpiix_pata_ops = { @@ -314,6 +316,8 @@ static struct pci_driver oldpiix_pci_driver = { .id_table = oldpiix_pci_tbl, .probe = oldpiix_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init oldpiix_init(void) diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index c6319cf..66f561d 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -34,7 +34,7 @@ #include #define DRV_NAME "pata_opti" -#define DRV_VERSION "0.2.5" +#define DRV_VERSION "0.2.7" enum { READ_REG = 0, /* index of Read cycle timing register */ @@ -109,30 +109,6 @@ static void opti_write_reg(struct ata_port *ap, u8 val, int reg) outb(0x83, regio + 2); } -#if 0 -/** - * opti_read_reg - control register read - * @ap: ATA port - * @reg: control register number - * - * The Opti uses magic 'trapdoor' register accesses to do configuration - * rather than using PCI space as other controllers do. The double inw - * on the error register activates configuration mode. We can then read - * the control register - */ - -static u8 opti_read_reg(struct ata_port *ap, int reg) -{ - unsigned long regio = ap->ioaddr.cmd_addr; - u8 ret; - inw(regio + 1); - inw(regio + 1); - outb(3, regio + 2); - ret = inb(regio + reg); - outb(0x83, regio + 2); -} -#endif - /** * opti_set_piomode - set initial PIO mode data * @ap: ATA interface @@ -204,12 +180,13 @@ static struct scsi_host_template opti_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations opti_port_ops = { .port_disable = ata_port_disable, .set_piomode = opti_set_piomode, -/* .set_dmamode = opti_set_dmamode, */ .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, @@ -267,7 +244,9 @@ static struct pci_driver opti_pci_driver = { .name = DRV_NAME, .id_table = opti, .probe = opti_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init opti_init(void) diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 2f4770c..d898e42 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -33,7 +33,7 @@ #include #define DRV_NAME "pata_optidma" -#define DRV_VERSION "0.2.2" +#define DRV_VERSION "0.2.3" enum { READ_REG = 0, /* index of Read cycle timing register */ @@ -361,6 +361,8 @@ static struct scsi_host_template optidma_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations optidma_port_ops = { @@ -522,7 +524,9 @@ static struct pci_driver optidma_pci_driver = { .name = DRV_NAME, .id_table = optidma, .probe = optidma_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init optidma_init(void) diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 048c2bb..5fe7ffc 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -229,6 +229,8 @@ static struct scsi_host_template radisys_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations radisys_pata_ops = { @@ -311,6 +313,8 @@ static struct pci_driver radisys_pci_driver = { .id_table = radisys_pci_tbl, .probe = radisys_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init radisys_init(void) diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 0c75dae..0c5393a 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -40,7 +40,7 @@ #include #define DRV_NAME "sc1200" -#define DRV_VERSION "0.2.3" +#define DRV_VERSION "0.2.4" #define SC1200_REV_A 0x00 #define SC1200_REV_B1 0x01 @@ -195,6 +195,8 @@ static struct scsi_host_template sc1200_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations sc1200_port_ops = { @@ -264,7 +266,9 @@ static struct pci_driver sc1200_pci_driver = { .name = DRV_NAME, .id_table = sc1200, .probe = sc1200_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init sc1200_init(void) diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index bfda1f7..ece9cb7 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -43,7 +43,7 @@ #include #define DRV_NAME "pata_triflex" -#define DRV_VERSION "0.2.5" +#define DRV_VERSION "0.2.7" /** * triflex_prereset - probe begin @@ -194,6 +194,8 @@ static struct scsi_host_template triflex_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations triflex_port_ops = { @@ -258,7 +260,9 @@ static struct pci_driver triflex_pci_driver = { .name = DRV_NAME, .id_table = triflex, .probe = triflex_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init triflex_init(void) -- cgit v0.10.2 From 8501120f1df1aa6abe38b51ab91df08ccaa1b971 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 17:01:06 +0000 Subject: [PATCH] pata_cs5520: resume support The CS5520 doesn't need much help to resume but we do need to restore pcicfg which may have been reset to the BIOS default which is sometimes incorrect. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 33d2b88f..f839c03 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -41,7 +41,7 @@ #include #define DRV_NAME "pata_cs5520" -#define DRV_VERSION "0.6.2" +#define DRV_VERSION "0.6.3" struct pio_clocks { @@ -168,6 +168,8 @@ static struct scsi_host_template cs5520_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations cs5520_port_ops = { @@ -297,6 +299,22 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev) dev_set_drvdata(dev, NULL); } +/** + * cs5520_reinit_one - device resume + * @pdev: PCI device + * + * Do any reconfiguration work needed by a resume from RAM. We need + * to restore DMA mode support on BIOSen which disabled it + */ + +static int cs5520_reinit_one(struct pci_dev *pdev) +{ + u8 pcicfg; + pci_read_config_byte(pdev, 0x60, &pcicfg); + if ((pcicfg & 0x40) == 0) + pci_write_config_byte(pdev, 0x60, pcicfg | 0x40); + return ata_pci_device_resume(pdev); +} /* For now keep DMA off. We can set it for all but A rev CS5510 once the core ATA code can handle it */ @@ -311,7 +329,9 @@ static struct pci_driver cs5520_pci_driver = { .name = DRV_NAME, .id_table = pata_cs5520, .probe = cs5520_init_one, - .remove = cs5520_remove_one + .remove = cs5520_remove_one, + .suspend = ata_pci_device_suspend, + .resume = cs5520_reinit_one, }; static int __init cs5520_init(void) -- cgit v0.10.2 From 7f72a379146913dc5f2751383722cdedb8998bc9 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 16:59:07 +0000 Subject: [PATCH] pata_cmd64x: suspend/resume On a resume of the CMD64x we must restore MRDMODE and latency if the BIOS didn't get them right originally. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 29a60df..3376f3f 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -31,7 +31,7 @@ #include #define DRV_NAME "pata_cmd64x" -#define DRV_VERSION "0.2.1" +#define DRV_VERSION "0.2.2" /* * CMD64x specific registers definition. @@ -277,6 +277,8 @@ static struct scsi_host_template cmd64x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations cmd64x_port_ops = { @@ -469,6 +471,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +static int cmd64x_reinit_one(struct pci_dev *pdev) +{ + u8 mrdmode; + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_read_config_byte(pdev, MRDMODE, &mrdmode); + mrdmode &= ~ 0x30; /* IRQ set up */ + mrdmode |= 0x02; /* Memory read line enable */ + pci_write_config_byte(pdev, MRDMODE, mrdmode); +#ifdef CONFIG_PPC + pci_write_config_byte(pdev, UDIDETCR0, 0xF0); +#endif + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id cmd64x[] = { { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, @@ -482,7 +498,9 @@ static struct pci_driver cmd64x_pci_driver = { .name = DRV_NAME, .id_table = cmd64x, .probe = cmd64x_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = cmd64x_reinit_one, }; static int __init cmd64x_init(void) -- cgit v0.10.2 From 38e0d56e67849720d306e2d7cd1a2793deec9644 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:16:35 +0000 Subject: [PATCH] pata_serverworks suspend/resume The Serverworks chips need various fixups doing on a resume from RAM. Conveniently the needed functions were already split out ready for re-use Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index be7f60e..0fa803e 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -41,7 +41,7 @@ #include #define DRV_NAME "pata_serverworks" -#define DRV_VERSION "0.3.7" +#define DRV_VERSION "0.3.9" #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ @@ -327,6 +327,8 @@ static struct scsi_host_template serverworks_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations serverworks_osb4_port_ops = { @@ -554,6 +556,30 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id return ata_pci_init_one(pdev, port_info, ports); } +static int serverworks_reinit_one(struct pci_dev *pdev) +{ + /* Force master latency timer to 64 PCI clocks */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); + + switch (pdev->device) + { + case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: + serverworks_fixup_osb4(pdev); + break; + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + ata_pci_clear_simplex(pdev); + /* fall through */ + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: + serverworks_fixup_csb(pdev); + break; + case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: + serverworks_fixup_ht1000(pdev); + break; + } + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id serverworks[] = { { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2}, @@ -568,7 +594,9 @@ static struct pci_driver serverworks_pci_driver = { .name = DRV_NAME, .id_table = serverworks, .probe = serverworks_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = serverworks_reinit_one, }; static int __init serverworks_init(void) -- cgit v0.10.2 From f535d53f3f8bc8243ad2167d7127f6efba9b46cb Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:14:36 +0000 Subject: [PATCH] pata_it821x: Suspend/Resume support If you are using the noraid option then after a suspend/resume sequence we need to reset the card back out of raid mode again. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 7f68f14..d57ac74 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -80,7 +80,7 @@ #define DRV_NAME "pata_it821x" -#define DRV_VERSION "0.3.2" +#define DRV_VERSION "0.3.3" struct it821x_dev { @@ -677,6 +677,8 @@ static struct scsi_host_template it821x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations it821x_smart_port_ops = { @@ -809,6 +811,14 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +static int it821x_reinit_one(struct pci_dev *pdev) +{ + /* Resume - turn raid back off if need be */ + if (it8212_noraid) + it821x_disable_raid(pdev); + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id it821x[] = { { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), }, { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), }, @@ -820,7 +830,9 @@ static struct pci_driver it821x_pci_driver = { .name = DRV_NAME, .id_table = it821x, .probe = it821x_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = it821x_reinit_one, }; static int __init it821x_init(void) -- cgit v0.10.2 From c304193a005b5262671c1389b1cae96d7afc952a Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:21:24 +0000 Subject: [PATCH] pata_amd: suspend/resume Early AMD chips require FIFO and/or simplex flag clearing work on resume from RAM. Most devices need no help Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 8be46a6..d957120 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_amd" -#define DRV_VERSION "0.2.4" +#define DRV_VERSION "0.2.7" /** * timing_setup - shared timing computation and load @@ -335,6 +335,8 @@ static struct scsi_host_template amd_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations amd33_port_ops = { @@ -662,6 +664,23 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +static int amd_reinit_one(struct pci_dev *pdev) +{ + if (pdev->vendor == PCI_VENDOR_ID_AMD) { + u8 fifo; + pci_read_config_byte(pdev, 0x41, &fifo); + if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) + /* FIFO is broken */ + pci_write_config_byte(pdev, 0x41, fifo & 0x0F); + else + pci_write_config_byte(pdev, 0x41, fifo | 0xF0); + if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 || + pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401) + ata_pci_clear_simplex(pdev); + } + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id amd[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 }, @@ -689,7 +708,9 @@ static struct pci_driver amd_pci_driver = { .name = DRV_NAME, .id_table = amd, .probe = amd_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = amd_reinit_one, }; static int __init amd_init(void) -- cgit v0.10.2 From 627d2d3261a42c9b5b0a02a1f8d0ae5414729cb9 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:19:36 +0000 Subject: [PATCH] pata_via suspend/resume support The major VIA issues were handled by the quirks update for resume quirks. The ATA driver also has to do some work however when resuming from RAM. Certain chips need the FIFO reconfiguring, and the 66MHz clock setup updating. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index c5f1616..489bd57 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -60,7 +60,7 @@ #include #define DRV_NAME "pata_via" -#define DRV_VERSION "0.1.14" +#define DRV_VERSION "0.2.0" /* * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx @@ -297,6 +297,8 @@ static struct scsi_host_template via_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations via_port_ops = { @@ -370,8 +372,42 @@ static struct ata_port_operations via_port_ops_noirq = { }; /** + * via_config_fifo - set up the FIFO + * @pdev: PCI device + * @flags: configuration flags + * + * Set the FIFO properties for this device if neccessary. Used both on + * set up and on and the resume path + */ + +static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) +{ + u8 enable; + + /* 0x40 low bits indicate enabled channels */ + pci_read_config_byte(pdev, 0x40 , &enable); + enable &= 3; + + if (flags & VIA_SET_FIFO) { + u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; + u8 fifo; + + pci_read_config_byte(pdev, 0x43, &fifo); + + /* Clear PREQ# until DDACK# for errata */ + if (flags & VIA_BAD_PREQ) + fifo &= 0x7F; + else + fifo &= 0x9f; + /* Turn on FIFO for enabled channels */ + fifo |= fifo_setting[enable]; + pci_write_config_byte(pdev, 0x43, fifo); + } +} + +/** * via_init_one - discovery callback - * @pdev: PCI device ID + * @pdev: PCI device * @id: PCI table info * * A VIA IDE interface has been discovered. Figure out what revision @@ -471,21 +507,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } /* Initialise the FIFO for the enabled channels. */ - if (config->flags & VIA_SET_FIFO) { - u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; - u8 fifo; - - pci_read_config_byte(pdev, 0x43, &fifo); - - /* Clear PREQ# until DDACK# for errata */ - if (config->flags & VIA_BAD_PREQ) - fifo &= 0x7F; - else - fifo &= 0x9f; - /* Turn on FIFO for enabled channels */ - fifo |= fifo_setting[enable]; - pci_write_config_byte(pdev, 0x43, fifo); - } + via_config_fifo(pdev, config->flags); + /* Clock set up */ switch(config->flags & VIA_UDMA) { case VIA_UDMA_NONE: @@ -529,6 +552,39 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +/** + * via_reinit_one - reinit after resume + * @pdev; PCI device + * + * Called when the VIA PATA device is resumed. We must then + * reconfigure the fifo and other setup we may have altered. In + * addition the kernel needs to have the resume methods on PCI + * quirk supported. + */ + +static int via_reinit_one(struct pci_dev *pdev) +{ + u32 timing; + struct ata_host *host = dev_get_drvdata(&pdev->dev); + const struct via_isa_bridge *config = host->private_data; + + via_config_fifo(pdev, config->flags); + + if ((config->flags & VIA_UDMA) == VIA_UDMA_66) { + /* The 66 MHz devices require we enable the clock */ + pci_read_config_dword(pdev, 0x50, &timing); + timing |= 0x80008; + pci_write_config_dword(pdev, 0x50, timing); + } + if (config->flags & VIA_BAD_CLK66) { + /* Disable the 66MHz clock on problem devices */ + pci_read_config_dword(pdev, 0x50, &timing); + timing &= ~0x80008; + pci_write_config_dword(pdev, 0x50, timing); + } + return ata_pci_device_resume(pdev); +} + static const struct pci_device_id via[] = { { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, @@ -542,7 +598,9 @@ static struct pci_driver via_pci_driver = { .name = DRV_NAME, .id_table = via, .probe = via_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = via_reinit_one, }; static int __init via_init(void) -- cgit v0.10.2 From aa54ab1eff30f1e5859acf4e15f0730288373ee5 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:24:15 +0000 Subject: [PATCH] hpt36x: Suspend/resume support Another chipset which needs some reconfiguration after a resume. All the chip setup is moved to a new function called in both setup and resume. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index c15c8dc..25d3cd7 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -27,7 +27,7 @@ #include #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.5.1" +#define DRV_VERSION "0.5.3" struct hpt_clock { u8 xfer_speed; @@ -339,6 +339,8 @@ static struct scsi_host_template hpt36x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; /* @@ -381,6 +383,27 @@ static struct ata_port_operations hpt366_port_ops = { }; /** + * hpt36x_init_chipset - common chip setup + * @dev: PCI device + * + * Perform the chip setup work that must be done at both init and + * resume time + */ + +static void hpt36x_init_chipset(struct pci_dev *dev) +{ + u8 drive_fast; + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); +} + +/** * hpt36x_init_one - Initialise an HPT366/368 * @dev: PCI device * @id: Entry in match table @@ -415,7 +438,6 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) u32 class_rev; u32 reg1; - u8 drive_fast; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xFF; @@ -425,14 +447,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (class_rev > 2) return -ENODEV; - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + hpt36x_init_chipset(dev); pci_read_config_dword(dev, 0x40, ®1); @@ -453,9 +468,15 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) return ata_pci_init_one(dev, port_info, 2); } +static int hpt36x_reinit_one(struct pci_dev *dev) +{ + hpt36x_init_chipset(dev); + return ata_pci_device_resume(dev); +} + + static const struct pci_device_id hpt36x[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, - { }, }; @@ -463,7 +484,9 @@ static struct pci_driver hpt36x_pci_driver = { .name = DRV_NAME, .id_table = hpt36x, .probe = hpt36x_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = hpt36x_reinit_one, }; static int __init hpt36x_init(void) @@ -471,13 +494,11 @@ static int __init hpt36x_init(void) return pci_register_driver(&hpt36x_pci_driver); } - static void __exit hpt36x_exit(void) { pci_unregister_driver(&hpt36x_pci_driver); } - MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 62d64ae0ec76360736c9dc4ca2067ae8de0ba9f2 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:27:20 +0000 Subject: [PATCH] pata : more drivers that need only standard suspend and resume Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index ed8d985..81a134c 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -21,7 +21,7 @@ #include #define DRV_NAME "pata_pdc202xx_old" -#define DRV_VERSION "0.2.2" +#define DRV_VERSION "0.2.3" /** * pdc2024x_pre_reset - probe begin @@ -271,6 +271,8 @@ static struct scsi_host_template pdc202xx_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations pdc2024x_port_ops = { @@ -400,7 +402,9 @@ static struct pci_driver pdc202xx_pci_driver = { .name = DRV_NAME, .id_table = pdc202xx, .probe = pdc202xx_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init pdc202xx_init(void) diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 91e85f9..695e571 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -34,7 +34,7 @@ #include #define DRV_NAME "pata_sis" -#define DRV_VERSION "0.4.4" +#define DRV_VERSION "0.4.5" struct sis_chipset { u16 device; /* PCI host ID */ @@ -547,6 +547,8 @@ static struct scsi_host_template sis_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations sis_133_ops = { @@ -1000,6 +1002,8 @@ static struct pci_driver sis_pci_driver = { .id_table = sis_pci_tbl, .probe = sis_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init sis_init(void) -- cgit v0.10.2 From aff0df0593f4beea42800115c0658f58c03dfe9f Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:25:51 +0000 Subject: [PATCH] pata_hpt3x3: suspend/resume support Again split the chipset init away and call it both on resume and on setup Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d216cc5..e9fb029 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -23,7 +23,7 @@ #include #define DRV_NAME "pata_hpt3x3" -#define DRV_VERSION "0.4.1" +#define DRV_VERSION "0.4.2" static int hpt3x3_probe_init(struct ata_port *ap) { @@ -120,6 +120,8 @@ static struct scsi_host_template hpt3x3_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static struct ata_port_operations hpt3x3_port_ops = { @@ -158,6 +160,27 @@ static struct ata_port_operations hpt3x3_port_ops = { }; /** + * hpt3x3_init_chipset - chip setup + * @dev: PCI device + * + * Perform the setup required at boot and on resume. + */ + +static void hpt3x3_init_chipset(struct pci_dev *dev) +{ + u16 cmd; + /* Initialize the board */ + pci_write_config_word(dev, 0x80, 0x00); + /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_MEMORY) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); + else + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); +} + + +/** * hpt3x3_init_one - Initialise an HPT343/363 * @dev: PCI device * @id: Entry in match table @@ -178,21 +201,18 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt3x3_port_ops }; static struct ata_port_info *port_info[2] = { &info, &info }; - u16 cmd; - - /* Initialize the board */ - pci_write_config_word(dev, 0x80, 0x00); - /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (cmd & PCI_COMMAND_MEMORY) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); - else - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); + hpt3x3_init_chipset(dev); /* Now kick off ATA set up */ return ata_pci_init_one(dev, port_info, 2); } +static int hpt3x3_reinit_one(struct pci_dev *dev) +{ + hpt3x3_init_chipset(dev); + return ata_pci_device_resume(dev); +} + static const struct pci_device_id hpt3x3[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), }, @@ -203,7 +223,9 @@ static struct pci_driver hpt3x3_pci_driver = { .name = DRV_NAME, .id_table = hpt3x3, .probe = hpt3x3_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = hpt3x3_reinit_one, }; static int __init hpt3x3_init(void) -- cgit v0.10.2 From 099156db555aabf54dc80b40abb628ce35d90065 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:37:52 +0000 Subject: [PATCH] pata_marvell: merge Mandriva patches Correct and complete the Marvell PATA cable detection logic. From: Arnaud Patard Signed-off-by: Arnaud Patard Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index a5953c3..25f7a79 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -57,11 +57,11 @@ static int marvell_pre_reset(struct ata_port *ap) switch(ap->port_no) { case 0: - /* Might be backward, docs unclear */ if (inb(ap->ioaddr.bmdma_addr + 1) & 1) - ap->cbl = ATA_CBL_PATA80; - else ap->cbl = ATA_CBL_PATA40; + else + ap->cbl = ATA_CBL_PATA80; + break; case 1: /* Legacy SATA port */ ap->cbl = ATA_CBL_SATA; -- cgit v0.10.2 From 2dec7555e6bf2772749113ea0ad454fcdb8cf861 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Sun, 26 Nov 2006 14:20:19 -0600 Subject: [PATCH] sata_nv: fix ATAPI in ADMA mode The attached patch against 2.6.19-rc6-mm1 fixes some problems in sata_nv with ATAPI devices on controllers running in ADMA mode. Some of the logic in the nv_adma_bmdma_* functions was inverted causing a bunch of warnings and caused those functions not to work properly. Also, when an ATAPI device is connected, we need to use the legacy DMA engine. The code now disables the PCI configuration register bits for ADMA so that this works, and ensures that no ATAPI DMA commands go through until this is done. Fixes Bugzilla http://bugzilla.kernel.org/show_bug.cgi?id=7538 Signed-off-by: Robert Hancock Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index a577101..27d2225 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -49,7 +49,7 @@ #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "3.1" +#define DRV_VERSION "3.2" #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL @@ -165,6 +165,7 @@ enum { /* port flags */ NV_ADMA_PORT_REGISTER_MODE = (1 << 0), + NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1), }; @@ -231,6 +232,7 @@ static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); static void nv_error_handler(struct ata_port *ap); static int nv_adma_slave_config(struct scsi_device *sdev); +static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance); @@ -415,6 +417,7 @@ static const struct ata_port_operations nv_adma_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = nv_adma_check_atapi_dma, .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, @@ -489,13 +492,71 @@ MODULE_VERSION(DRV_VERSION); static int adma_enabled = 1; +static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, + unsigned int port_no) +{ + mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; + return mmio; +} + +static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) +{ + return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); +} + +static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) +{ + return (ap->host->mmio_base + NV_ADMA_GEN); +} + +static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) +{ + return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); +} + +static void nv_adma_register_mode(struct ata_port *ap) +{ + void __iomem *mmio = nv_adma_ctl_block(ap); + struct nv_adma_port_priv *pp = ap->private_data; + u16 tmp; + + if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) + return; + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + + pp->flags |= NV_ADMA_PORT_REGISTER_MODE; +} + +static void nv_adma_mode(struct ata_port *ap) +{ + void __iomem *mmio = nv_adma_ctl_block(ap); + struct nv_adma_port_priv *pp = ap->private_data; + u16 tmp; + + if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) + return; + + WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + + pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE; +} + static int nv_adma_slave_config(struct scsi_device *sdev) { struct ata_port *ap = ata_shost_to_port(sdev->host); + struct nv_adma_port_priv *pp = ap->private_data; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); u64 bounce_limit; unsigned long segment_boundary; unsigned short sg_tablesize; int rc; + int adma_enable; + u32 current_reg, new_reg, config_mask; rc = ata_scsi_slave_config(sdev); @@ -516,13 +577,40 @@ static int nv_adma_slave_config(struct scsi_device *sdev) /* Subtract 1 since an extra entry may be needed for padding, see libata-scsi.c */ sg_tablesize = LIBATA_MAX_PRD - 1; + + /* Since the legacy DMA engine is in use, we need to disable ADMA + on the port. */ + adma_enable = 0; + nv_adma_register_mode(ap); } else { bounce_limit = *ap->dev->dma_mask; segment_boundary = NV_ADMA_DMA_BOUNDARY; sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; + adma_enable = 1; } - + + pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg); + + if(ap->port_no == 1) + config_mask = NV_MCP_SATA_CFG_20_PORT1_EN | + NV_MCP_SATA_CFG_20_PORT1_PWB_EN; + else + config_mask = NV_MCP_SATA_CFG_20_PORT0_EN | + NV_MCP_SATA_CFG_20_PORT0_PWB_EN; + + if(adma_enable) { + new_reg = current_reg | config_mask; + pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE; + } + else { + new_reg = current_reg & ~config_mask; + pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE; + } + + if(current_reg != new_reg) + pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); + blk_queue_bounce_limit(sdev->request_queue, bounce_limit); blk_queue_segment_boundary(sdev->request_queue, segment_boundary); blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); @@ -532,7 +620,13 @@ static int nv_adma_slave_config(struct scsi_device *sdev) return rc; } -static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, u16 *cpb) +static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct nv_adma_port_priv *pp = qc->ap->private_data; + return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); +} + +static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) { unsigned int idx = 0; @@ -563,33 +657,11 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, u16 *cpb) return idx; } -static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, - unsigned int port_no) -{ - mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; - return mmio; -} - -static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) -{ - return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); -} - -static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) -{ - return (ap->host->mmio_base + NV_ADMA_GEN); -} - -static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) -{ - return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); -} - static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) { struct nv_adma_port_priv *pp = ap->private_data; int complete = 0, have_err = 0; - u16 flags = pp->cpb[cpb_num].resp_flags; + u8 flags = pp->cpb[cpb_num].resp_flags; VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags); @@ -634,15 +706,48 @@ static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) } } +static int nv_host_intr(struct ata_port *ap, u8 irq_stat) +{ + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + int handled; + + /* freeze if hotplugged */ + if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { + ata_port_freeze(ap); + return 1; + } + + /* bail out if not our interrupt */ + if (!(irq_stat & NV_INT_DEV)) + return 0; + + /* DEV interrupt w/ no active qc? */ + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { + ata_check_status(ap); + return 1; + } + + /* handle interrupt */ + handled = ata_host_intr(ap, qc); + if (unlikely(!handled)) { + /* spurious, clear it */ + ata_check_status(ap); + } + + return 1; +} + static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; int i, handled = 0; + u32 notifier_clears[2]; spin_lock(&host->lock); for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; + notifier_clears[i] = 0; if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct nv_adma_port_priv *pp = ap->private_data; @@ -654,30 +759,18 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) /* if in ATA register mode, use standard ata interrupt handler */ if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { - struct ata_queued_cmd *qc; - VPRINTK("in ATA register mode\n"); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) - handled += ata_host_intr(ap, qc); - else { - /* No request pending? Clear interrupt status - anyway, in case there's one pending. */ - ap->ops->check_status(ap); - handled++; - } + u8 irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804) + >> (NV_INT_PORT_SHIFT * i); + handled += nv_host_intr(ap, irq_stat); continue; } notifier = readl(mmio + NV_ADMA_NOTIFIER); notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + notifier_clears[i] = notifier | notifier_error; gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); - /* Seems necessary to clear notifiers even when they were 0. - Otherwise we seem to stop receiving further interrupts. - Unsure why. */ - writel(notifier | notifier_error, nv_adma_notifier_clear_block(ap)); - if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && !notifier_error) /* Nothing to do */ @@ -730,6 +823,15 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) handled++; /* irq handled if we got here */ } } + + if(notifier_clears[0] || notifier_clears[1]) { + /* Note: Both notifier clear registers must be written + if either is set, even if one is zero, according to NVIDIA. */ + writel(notifier_clears[0], + nv_adma_notifier_clear_block(host->ports[0])); + writel(notifier_clears[1], + nv_adma_notifier_clear_block(host->ports[1])); + } spin_unlock(&host->lock); @@ -742,6 +844,7 @@ static void nv_adma_irq_clear(struct ata_port *ap) u16 status = readw(mmio + NV_ADMA_STAT); u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + unsigned long dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; /* clear ADMA status */ writew(status, mmio + NV_ADMA_STAT); @@ -749,92 +852,76 @@ static void nv_adma_irq_clear(struct ata_port *ap) nv_adma_notifier_clear_block(ap)); /** clear legacy status */ - ap->flags &= ~ATA_FLAG_MMIO; - ata_bmdma_irq_clear(ap); - ap->flags |= ATA_FLAG_MMIO; + outb(inb(dma_stat_addr), dma_stat_addr); } static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc) { - struct nv_adma_port_priv *pp = qc->ap->private_data; + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + struct nv_adma_port_priv *pp = ap->private_data; + u8 dmactl; - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) { + if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { WARN_ON(1); return; } - qc->ap->flags &= ~ATA_FLAG_MMIO; - ata_bmdma_setup(qc); - qc->ap->flags |= ATA_FLAG_MMIO; + /* load PRD table addr. */ + outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); + + /* specify data direction, triple-check start bit is clear */ + dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); + if (!rw) + dmactl |= ATA_DMA_WR; + + outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + + /* issue r/w command */ + ata_exec_command(ap, &qc->tf); } static void nv_adma_bmdma_start(struct ata_queued_cmd *qc) { - struct nv_adma_port_priv *pp = qc->ap->private_data; + struct ata_port *ap = qc->ap; + struct nv_adma_port_priv *pp = ap->private_data; + u8 dmactl; - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) { + if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { WARN_ON(1); return; } - qc->ap->flags &= ~ATA_FLAG_MMIO; - ata_bmdma_start(qc); - qc->ap->flags |= ATA_FLAG_MMIO; + /* start host DMA transaction */ + dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + outb(dmactl | ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); } static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc) { - struct nv_adma_port_priv *pp = qc->ap->private_data; - - if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) - return; - - qc->ap->flags &= ~ATA_FLAG_MMIO; - ata_bmdma_stop(qc); - qc->ap->flags |= ATA_FLAG_MMIO; -} - -static u8 nv_adma_bmdma_status(struct ata_port *ap) -{ - u8 status; - struct nv_adma_port_priv *pp = ap->private_data; - - WARN_ON(pp->flags & NV_ADMA_PORT_REGISTER_MODE); - - ap->flags &= ~ATA_FLAG_MMIO; - status = ata_bmdma_status(ap); - ap->flags |= ATA_FLAG_MMIO; - return status; -} - -static void nv_adma_register_mode(struct ata_port *ap) -{ - void __iomem *mmio = nv_adma_ctl_block(ap); + struct ata_port *ap = qc->ap; struct nv_adma_port_priv *pp = ap->private_data; - u16 tmp; - if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) + if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) return; - tmp = readw(mmio + NV_ADMA_CTL); - writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + /* clear start/stop bit */ + outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - pp->flags |= NV_ADMA_PORT_REGISTER_MODE; + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ } -static void nv_adma_mode(struct ata_port *ap) +static u8 nv_adma_bmdma_status(struct ata_port *ap) { - void __iomem *mmio = nv_adma_ctl_block(ap); struct nv_adma_port_priv *pp = ap->private_data; - u16 tmp; - - if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) - return; - tmp = readw(mmio + NV_ADMA_CTL); - writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)); - pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE; + return inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); } static int nv_adma_port_start(struct ata_port *ap) @@ -997,7 +1084,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, int idx, struct nv_adma_prd *aprd) { - u32 flags; + u8 flags; memset(aprd, 0, sizeof(struct nv_adma_prd)); @@ -1011,7 +1098,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg))); aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */ - aprd->flags = cpu_to_le32(flags); + aprd->flags = flags; } static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) @@ -1045,7 +1132,8 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) VPRINTK("qc->flags = 0x%lx\n", qc->flags); if (!(qc->flags & ATA_QCFLAG_DMAMAP) || - qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { + nv_adma_register_mode(qc->ap); ata_qc_prep(qc); return; } @@ -1072,12 +1160,13 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) { + struct nv_adma_port_priv *pp = qc->ap->private_data; void __iomem *mmio = nv_adma_ctl_block(qc->ap); VPRINTK("ENTER\n"); if (!(qc->flags & ATA_QCFLAG_DMAMAP) || - qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { /* use ATA register mode */ VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags); nv_adma_register_mode(qc->ap); @@ -1128,37 +1217,6 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static int nv_host_intr(struct ata_port *ap, u8 irq_stat) -{ - struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - int handled; - - /* freeze if hotplugged */ - if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { - ata_port_freeze(ap); - return 1; - } - - /* bail out if not our interrupt */ - if (!(irq_stat & NV_INT_DEV)) - return 0; - - /* DEV interrupt w/ no active qc? */ - if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { - ata_check_status(ap); - return 1; - } - - /* handle interrupt */ - handled = ata_host_intr(ap, qc); - if (unlikely(!handled)) { - /* spurious, clear it */ - ata_check_status(ap); - } - - return 1; -} - static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat) { int i, handled = 0; -- cgit v0.10.2 From 664e8503fee2f299d0f96eaab0f5f8fae8fad325 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 20 Nov 2006 16:05:34 +0900 Subject: [PATCH] libata: print cdb[0] in failed qc report Print cdb[0] in failed qc report. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 3771eb8..5aa7f09 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1452,14 +1452,15 @@ static void ata_eh_report(struct ata_port *ap) ata_dev_printk(qc->dev, KERN_ERR, "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " - "tag %d data %u %s\n " + "tag %d cdb 0x%x data %u %s\n " "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " "Emask 0x%x (%s)\n", cmd->command, cmd->feature, cmd->nsect, cmd->lbal, cmd->lbam, cmd->lbah, cmd->hob_feature, cmd->hob_nsect, cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, - cmd->device, qc->tag, nbytes, dma_str[qc->dma_dir], + cmd->device, qc->tag, qc->cdb[0], nbytes, + dma_str[qc->dma_dir], res->command, res->feature, res->nsect, res->lbal, res->lbam, res->lbah, res->hob_feature, res->hob_nsect, -- cgit v0.10.2 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 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index ecb61f8..f994f12 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 320f832..bcd1efb 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 0000000..29666c8 --- /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 v0.10.2 From 13df29f69749a61b5209d52b71fcbf7300e5d6fb Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 3 Oct 2006 16:18:28 +0100 Subject: [PATCH] 2.6.18: sb1250-mac: Missing inclusions from The uses some types and macros defined in , , and , but fails to include these headers. Signed-off-by: Maciej W. Rozycki patch-mips-2.6.18-20060920-include-phy-16 Signed-off-by: Jeff Garzik diff --git a/include/linux/phy.h b/include/linux/phy.h index 9447a57..ce8bc80 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -20,6 +20,10 @@ #include #include +#include +#include +#include +#include #define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ SUPPORTED_10baseT_Full | \ -- cgit v0.10.2 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 diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3af9fcf..95f0419 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 v0.10.2 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 diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index c5ed635..87af5e4 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 v0.10.2 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 diff --git a/drivers/net/depca.c b/drivers/net/depca.c index f87f6e3..5113eef 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 v0.10.2 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 diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index cd142d0..8f4ecc1 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 v0.10.2 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 diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c index e5cb5b5..3646069 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 v0.10.2 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 diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index d4913c3..a5d41eb 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 v0.10.2 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 diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 3d1c599..a828076 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 f44f122..fae4aa9 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 f270bc4..53ccc33 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 4ae9897..747a71f 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 0000000..e726c06 --- /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 v0.10.2 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 diff --git a/drivers/net/8390.h b/drivers/net/8390.h index fae4aa9..b8991fc 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 53ccc33..42bf31ea 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 91326ea..f970bfb 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 ade6ff8..a12bb64 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 df04e05..d85e2ea 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 v0.10.2 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 diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 747a71f..f3faa4f 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 v0.10.2 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 diff --git a/drivers/net/8390.h b/drivers/net/8390.h index b8991fc..414de5b 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 42bf31ea..7d36184 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 eb893d7..38fd525 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index d6a8bf0..5f43d7f 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 a1b7838..2ffc0d5 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 d27016f..12043f8 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 v0.10.2 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 diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a15b095..435e16e 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 12043f8..a659442 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 0159e4e..a957bc86 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 b174ebb..cb25543 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 2759312..d926519 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 v0.10.2 From 42a4cf9576f036db69e15fa6b4e72986e17f0359 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Thu, 28 Sep 2006 19:57:25 +0200 Subject: [PATCH] ieee80211: allow mtu bigger than 1500 Hi this patch allow to set the mtu between 1500 and 2304 (max octets in an MSDU) for devices using ieee80211 linux stack. Signed-off-by: Matthieu CASTET Signed-off-by: John W. Linville diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 13b1e5f..2b14c2f 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -118,6 +118,14 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } +static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -133,6 +141,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) } ieee = netdev_priv(dev); dev->hard_start_xmit = ieee80211_xmit; + dev->change_mtu = ieee80211_change_mtu; ieee->dev = dev; -- cgit v0.10.2 From 837925df022a667c302b24aad9d6a58f94efd959 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 3 Oct 2006 18:49:32 -0500 Subject: [PATCH] ieee80211: Drop and count duplicate data frames to remove 'replay detected' log messages In the SoftMAC version of the IEEE 802.11 stack, not all duplicate messages are detected. For the most part, there is no difficulty; however for TKIP and CCMP encryption, the duplicates result in a "replay detected" log message where the received and previous values of the TSC are identical. This change adds a new variable to the ieee80211_device structure that holds the 'seq_ctl' value for the previous frame. When a new frame repeats the value, the frame is dropped and the appropriate counter is incremented. Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index cb25543..e6af381 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1080,6 +1080,8 @@ struct ieee80211_device { int perfect_rssi; int worst_rssi; + u16 prev_seq_ctl; /* used to drop duplicate frames */ + /* Callback functions */ void (*set_security) (struct net_device * dev, struct ieee80211_security * sec); diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index d926519..ce28d57 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -478,6 +478,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_exit; } #endif + /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ + if (sc == ieee->prev_seq_ctl) + goto rx_dropped; + else + ieee->prev_seq_ctl = sc; /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_3ADDR_LEN) -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 0c07b8b..3a6397f 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 v0.10.2 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 diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 3a6397f..c253e9a 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 v0.10.2 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 diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index c253e9a..74c800f 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 7856640..5c41098 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 3bfa791..92f87fb 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 v0.10.2 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 diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index a8261d8..bfbafe9 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 v0.10.2 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 diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 23deee6..02fc67b 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 8af2098..3fadcb6 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 286325c..4a20e45 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 65f33ac..e8183d3 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 419edf7..ab53227 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 ec1c00f..1e0603c 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 2f7e525..a9aa166 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 bfbafe9..676d838 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 bc9d7a6..2678945 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 f692dcc..f6354b1 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 2e061a8..036a875 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 2982be3..fc53b58 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 ebb2387..fbc52b6 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 d71eca5..aa1d174 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 v0.10.2 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 diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 74c800f..10bcb48 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 v0.10.2 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 diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index ab53227..b7534c2 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 v0.10.2 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 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 5f43d7f..94dfb92 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 2ffc0d5..c6bd868 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 6569da3..7e774f4 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 v0.10.2 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 diff --git a/MAINTAINERS b/MAINTAINERS index 846e77a..0e17432 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 d3abf80..112d4cd 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 7d36184..7889e4c 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 0000000..a07cdc6 --- /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 0000000..c7d76c1 --- /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 0000000..caf6cc1 --- /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 0000000..965cf62 --- /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 0000000..c7d9705 --- /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 0000000..fb1a025 --- /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 0000000..d122e51 --- /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 0000000..806818e --- /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 0000000..f1c3e5af --- /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 0000000..b54ea16 --- /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 0000000..6e421c8 --- /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 0000000..863645e --- /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 v0.10.2 From fe75f7471ba5604fe65435f717e3612a482c28cb Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 2 Oct 2006 19:55:22 +0200 Subject: [PATCH] wext: extend MLME support This patch adds two new defines for the SIOCSIWMLME to cover all kinds MLMEs (well, except REASSOC) through a ioctl. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/include/linux/wireless.h b/include/linux/wireless.h index a50a013..7c269f49 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -546,6 +546,8 @@ /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 +#define IW_MLME_AUTH 2 +#define IW_MLME_ASSOC 3 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF -- cgit v0.10.2 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 diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 435e16e..7917153 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index c564adb..82d2c78 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 796c4f7d..29e6f6a 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 449a603..b32a0c3 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 726ec5e..7b1c092 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 a464cb2..3b7eb7c 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7b1c092..35d6d08 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 7ecce43..3f0be02 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 82d2c78..b9c0927 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 35d6d08..38ee39e 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 38ee39e..93b97c6 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 93b97c6..681b738 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 29e6f6a..0e2ccf5 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 b32a0c3..31bea32 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 31bea32..f247f26 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 681b738..44ba522 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 44ba522..9d82bbb 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index b9c0927..dbac71ba 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 0e2ccf5..0bb9dd8 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 f247f26..93c1e26 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 9d82bbb..96e44a8 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 3f0be02..896ea8a 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 dbac71ba..da459f7 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 96e44a8..705e654 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 0bb9dd8..3655d90 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 93c1e26..3321fb1 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 3b7eb7c..18afc0c 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 705e654..fe22ae8 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 9c3c1ac..e4f8892 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fe22ae8..35e4e32 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 896ea8a..f091042 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 35e4e32..56be5c8 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 e4f8892..cbfcd7f 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 v0.10.2 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 56be5c8..a2f1464 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 v0.10.2 From de3edab4276c3c789f64dc3d78eea027709fef0e Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:48:18 -0800 Subject: e1000: update README for e1000 Signed-off-by: Auke Kok diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt index 5c0a5cc..61b171c 100644 --- a/Documentation/networking/e1000.txt +++ b/Documentation/networking/e1000.txt @@ -1,7 +1,7 @@ Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters =============================================================== -November 15, 2005 +September 26, 2006 Contents @@ -9,6 +9,7 @@ Contents - In This Release - Identifying Your Adapter +- Building and Installation - Command Line Parameters - Speed and Duplex Configuration - Additional Configurations @@ -41,6 +42,9 @@ or later), lspci, and ifconfig to obtain the same information. Instructions on updating ethtool can be found in the section "Additional Configurations" later in this document. +NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100 +support. + Identifying Your Adapter ======================== @@ -51,28 +55,27 @@ Driver ID Guide at: http://support.intel.com/support/network/adapter/pro100/21397.htm For the latest Intel network drivers for Linux, refer to the following -website. In the search field, enter your adapter name or type, or use the +website. In the search field, enter your adapter name or type, or use the networking link on the left to search for your adapter: http://downloadfinder.intel.com/scripts-df/support_intel.asp -Command Line Parameters ======================= +Command Line Parameters +======================= If the driver is built as a module, the following optional parameters -are used by entering them on the command line with the modprobe or insmod -command using this syntax: +are used by entering them on the command line with the modprobe command +using this syntax: modprobe e1000 [