diff options
Diffstat (limited to 'drivers')
215 files changed, 3000 insertions, 2515 deletions
diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile index 2fa9a8bf48a..d006c9f168d 100644 --- a/drivers/acorn/char/Makefile +++ b/drivers/acorn/char/Makefile @@ -2,5 +2,4 @@ # Makefile for the acorn character device drivers. # -obj-$(CONFIG_ARCH_ACORN) += i2c.o pcf8583.o obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c deleted file mode 100644 index d276fd14d63..00000000000 --- a/drivers/acorn/char/i2c.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * linux/drivers/acorn/char/i2c.c - * - * Copyright (C) 2000 Russell King - * - * 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. - * - * ARM IOC/IOMD i2c driver. - * - * On Acorn machines, the following i2c devices are on the bus: - * - PCF8583 real time clock & static RAM - */ -#include <linux/capability.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/miscdevice.h> -#include <linux/rtc.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/fs.h> - -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/hardware/ioc.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#include "pcf8583.h" - -extern int (*set_rtc)(void); - -static struct i2c_client *rtc_client; -static const unsigned char days_in_mon[] = - { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -#define CMOS_CHECKSUM (63) - -/* - * Acorn machines store the year in the static RAM at - * location 128. - */ -#define CMOS_YEAR (64 + 128) - -static inline int rtc_command(int cmd, void *data) -{ - int ret = -EIO; - - if (rtc_client) - ret = rtc_client->driver->command(rtc_client, cmd, data); - - return ret; -} - -/* - * Update the century + year bytes in the CMOS RAM, ensuring - * that the check byte is correctly adjusted for the change. - */ -static int rtc_update_year(unsigned int new_year) -{ - unsigned char yr[2], chk; - struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr }; - struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; - int ret; - - ret = rtc_command(MEM_READ, &cmos_check); - if (ret) - goto out; - ret = rtc_command(MEM_READ, &cmos_year); - if (ret) - goto out; - - chk -= yr[1] + yr[0]; - - yr[1] = new_year / 100; - yr[0] = new_year % 100; - - chk += yr[1] + yr[0]; - - ret = rtc_command(MEM_WRITE, &cmos_year); - if (ret == 0) - ret = rtc_command(MEM_WRITE, &cmos_check); - out: - return ret; -} - -/* - * Read the current RTC time and date, and update xtime. - */ -static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year) -{ - unsigned char ctrl, yr[2]; - struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr }; - int real_year, year_offset; - - /* - * Ensure that the RTC is running. - */ - rtc_command(RTC_GETCTRL, &ctrl); - if (ctrl & 0xc0) { - unsigned char new_ctrl = ctrl & ~0xc0; - - printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", - ctrl, new_ctrl); - - rtc_command(RTC_SETCTRL, &new_ctrl); - } - - if (rtc_command(RTC_GETDATETIME, rtctm) || - rtc_command(MEM_READ, &rtcmem)) - return; - - real_year = yr[0]; - - /* - * The RTC year holds the LSB two bits of the current - * year, which should reflect the LSB two bits of the - * CMOS copy of the year. Any difference indicates - * that we have to correct the CMOS version. - */ - year_offset = rtctm->year_off - (real_year & 3); - if (year_offset < 0) - /* - * RTC year wrapped. Adjust it appropriately. - */ - year_offset += 4; - - *year = real_year + year_offset + yr[1] * 100; -} - -static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year) -{ - unsigned char leap; - int ret; - - leap = (!(year % 4) && (year % 100)) || !(year % 400); - - if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0) - return -EINVAL; - - if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap))) - return -EINVAL; - - if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60) - return -EINVAL; - - /* - * The RTC's own 2-bit year must reflect the least - * significant two bits of the CMOS year. - */ - rtctm->year_off = (year % 100) & 3; - - ret = rtc_command(RTC_SETDATETIME, rtctm); - if (ret == 0) - ret = rtc_update_year(year); - - return ret; -} - -/* - * Set the RTC time only. Note that - * we do not touch the date. - */ -static int k_set_rtc_time(void) -{ - struct rtc_tm new_rtctm, old_rtctm; - unsigned long nowtime = xtime.tv_sec; - - if (rtc_command(RTC_GETDATETIME, &old_rtctm)) - return 0; - - new_rtctm.cs = xtime.tv_nsec / 10000000; - new_rtctm.secs = nowtime % 60; nowtime /= 60; - new_rtctm.mins = nowtime % 60; nowtime /= 60; - new_rtctm.hours = nowtime % 24; - - /* - * avoid writing when we're going to change the day - * of the month. We will retry in the next minute. - * This basically means that if the RTC must not drift - * by more than 1 minute in 11 minutes. - * - * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00, - * rtc gets set to 1/1/2000 00:01:00 ] - */ - if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) || - (new_rtctm.hours == 23 && new_rtctm.mins == 59)) - return 1; - - return rtc_command(RTC_SETTIME, &new_rtctm); -} - -static int rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned int year; - struct rtc_time rtctm; - struct rtc_tm rtc_raw; - - switch (cmd) { - case RTC_ALM_READ: - case RTC_ALM_SET: - break; - - case RTC_RD_TIME: - memset(&rtctm, 0, sizeof(struct rtc_time)); - get_rtc_time(&rtc_raw, &year); - rtctm.tm_sec = rtc_raw.secs; - rtctm.tm_min = rtc_raw.mins; - rtctm.tm_hour = rtc_raw.hours; - rtctm.tm_mday = rtc_raw.mday; - rtctm.tm_mon = rtc_raw.mon - 1; /* month starts at 0 */ - rtctm.tm_year = year - 1900; /* starts at 1900 */ - return copy_to_user((void *)arg, &rtctm, sizeof(rtctm)) - ? -EFAULT : 0; - - case RTC_SET_TIME: - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&rtctm, (void *)arg, sizeof(rtctm))) - return -EFAULT; - rtc_raw.secs = rtctm.tm_sec; - rtc_raw.mins = rtctm.tm_min; - rtc_raw.hours = rtctm.tm_hour; - rtc_raw.mday = rtctm.tm_mday; - rtc_raw.mon = rtctm.tm_mon + 1; - year = rtctm.tm_year + 1900; - return set_rtc_time(&rtc_raw, year); - break; - - case RTC_EPOCH_READ: - return put_user(1900, (unsigned long *)arg); - - } - return -EINVAL; -} - -static const struct file_operations rtc_fops = { - .ioctl = rtc_ioctl, -}; - -static struct miscdevice rtc_dev = { - .minor = RTC_MINOR, - .name = "rtc", - .fops = &rtc_fops, -}; - -/* IOC / IOMD i2c driver */ - -#define FORCE_ONES 0xdc -#define SCL 0x02 -#define SDA 0x01 - -/* - * We must preserve all non-i2c output bits in IOC_CONTROL. - * Note also that we need to preserve the value of SCL and - * SDA outputs as well (which may be different from the - * values read back from IOC_CONTROL). - */ -static u_int force_ones; - -static void ioc_setscl(void *data, int state) -{ - u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); - u_int ones = force_ones; - - if (state) - ones |= SCL; - else - ones &= ~SCL; - - force_ones = ones; - - ioc_writeb(ioc_control | ones, IOC_CONTROL); -} - -static void ioc_setsda(void *data, int state) -{ - u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); - u_int ones = force_ones; - - if (state) - ones |= SDA; - else - ones &= ~SDA; - - force_ones = ones; - - ioc_writeb(ioc_control | ones, IOC_CONTROL); -} - -static int ioc_getscl(void *data) -{ - return (ioc_readb(IOC_CONTROL) & SCL) != 0; -} - -static int ioc_getsda(void *data) -{ - return (ioc_readb(IOC_CONTROL) & SDA) != 0; -} - -static struct i2c_algo_bit_data ioc_data = { - .setsda = ioc_setsda, - .setscl = ioc_setscl, - .getsda = ioc_getsda, - .getscl = ioc_getscl, - .udelay = 80, - .timeout = 100 -}; - -static int ioc_client_reg(struct i2c_client *client) -{ - if (client->driver->id == I2C_DRIVERID_PCF8583 && - client->addr == 0x50) { - struct rtc_tm rtctm; - unsigned int year; - struct timespec tv; - - rtc_client = client; - get_rtc_time(&rtctm, &year); - - tv.tv_nsec = rtctm.cs * 10000000; - tv.tv_sec = mktime(year, rtctm.mon, rtctm.mday, - rtctm.hours, rtctm.mins, rtctm.secs); - do_settimeofday(&tv); - set_rtc = k_set_rtc_time; - } - - return 0; -} - -static int ioc_client_unreg(struct i2c_client *client) -{ - if (client == rtc_client) { - set_rtc = NULL; - rtc_client = NULL; - } - - return 0; -} - -static struct i2c_adapter ioc_ops = { - .id = I2C_HW_B_IOC, - .algo_data = &ioc_data, - .client_register = ioc_client_reg, - .client_unregister = ioc_client_unreg, -}; - -static int __init i2c_ioc_init(void) -{ - int ret; - - force_ones = FORCE_ONES | SCL | SDA; - - ret = i2c_bit_add_bus(&ioc_ops); - - if (ret >= 0){ - ret = misc_register(&rtc_dev); - if(ret < 0) - i2c_del_adapter(&ioc_ops); - } - - return ret; -} - -__initcall(i2c_ioc_init); diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c deleted file mode 100644 index 9b49f316ae9..00000000000 --- a/drivers/acorn/char/pcf8583.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * linux/drivers/acorn/char/pcf8583.c - * - * Copyright (C) 2000 Russell King - * - * 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. - * - * Driver for PCF8583 RTC & RAM chip - */ -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/mc146818rtc.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/bcd.h> - -#include "pcf8583.h" - -static struct i2c_driver pcf8583_driver; - -static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; -static unsigned short *forces[] = { NULL }; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, - .forces = forces, -}; - -#define set_ctrl(x, v) i2c_set_clientdata(x, (void *)(unsigned int)(v)) -#define get_ctrl(x) ((unsigned int)i2c_get_clientdata(x)) - -static int -pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct i2c_client *c; - unsigned char buf[1], ad[1] = { 0 }; - struct i2c_msg msgs[2] = { - { - .addr = addr, - .flags = 0, - .len = 1, - .buf = ad, - }, { - .addr = addr, - .flags = I2C_M_RD, - .len = 1, - .buf = buf, - } - }; - - c = kmalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return -ENOMEM; - - memset(c, 0, sizeof(*c)); - c->addr = addr; - c->adapter = adap; - c->driver = &pcf8583_driver; - - if (i2c_transfer(c->adapter, msgs, 2) == 2) - set_ctrl(c, buf[0]); - - return i2c_attach_client(c); -} - -static int -pcf8583_probe(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, pcf8583_attach); -} - -static int -pcf8583_detach(struct i2c_client *client) -{ - i2c_detach_client(client); - kfree(client); - return 0; -} - -static int -pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt) -{ - unsigned char buf[8], addr[1] = { 1 }; - struct i2c_msg msgs[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = addr, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 6, - .buf = buf, - } - }; - int ret = -EIO; - - memset(buf, 0, sizeof(buf)); - - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) { - dt->year_off = buf[4] >> 6; - dt->wday = buf[5] >> 5; - - buf[4] &= 0x3f; - buf[5] &= 0x1f; - - dt->cs = BCD_TO_BIN(buf[0]); - dt->secs = BCD_TO_BIN(buf[1]); - dt->mins = BCD_TO_BIN(buf[2]); - dt->hours = BCD_TO_BIN(buf[3]); - dt->mday = BCD_TO_BIN(buf[4]); - dt->mon = BCD_TO_BIN(buf[5]); - - ret = 0; - } - - return ret; -} - -static int -pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) -{ - unsigned char buf[8]; - int ret, len = 6; - - buf[0] = 0; - buf[1] = get_ctrl(client) | 0x80; - buf[2] = BIN_TO_BCD(dt->cs); - buf[3] = BIN_TO_BCD(dt->secs); - buf[4] = BIN_TO_BCD(dt->mins); - buf[5] = BIN_TO_BCD(dt->hours); - - if (datetoo) { - len = 8; - buf[6] = BIN_TO_BCD(dt->mday) | (dt->year_off << 6); - buf[7] = BIN_TO_BCD(dt->mon) | (dt->wday << 5); - } - - ret = i2c_master_send(client, (char *)buf, len); - if (ret == len) - ret = 0; - - buf[1] = get_ctrl(client); - i2c_master_send(client, (char *)buf, 2); - - return ret; -} - -static int -pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl) -{ - *ctrl = get_ctrl(client); - return 0; -} - -static int -pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl) -{ - unsigned char buf[2]; - - buf[0] = 0; - buf[1] = *ctrl; - set_ctrl(client, *ctrl); - - return i2c_master_send(client, (char *)buf, 2); -} - -static int -pcf8583_read_mem(struct i2c_client *client, struct mem *mem) -{ - unsigned char addr[1]; - struct i2c_msg msgs[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = addr, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = mem->nr, - .buf = mem->data, - } - }; - - if (mem->loc < 8) - return -EINVAL; - - addr[0] = mem->loc; - - return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; -} - -static int -pcf8583_write_mem(struct i2c_client *client, struct mem *mem) -{ - unsigned char addr[1]; - struct i2c_msg msgs[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = addr, - }, { - .addr = client->addr, - .flags = I2C_M_NOSTART, - .len = mem->nr, - .buf = mem->data, - } - }; - - if (mem->loc < 8) - return -EINVAL; - - addr[0] = mem->loc; - - return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; -} - -static int -pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - switch (cmd) { - case RTC_GETDATETIME: - return pcf8583_get_datetime(client, arg); - - case RTC_SETTIME: - return pcf8583_set_datetime(client, arg, 0); - - case RTC_SETDATETIME: - return pcf8583_set_datetime(client, arg, 1); - - case RTC_GETCTRL: - return pcf8583_get_ctrl(client, arg); - - case RTC_SETCTRL: - return pcf8583_set_ctrl(client, arg); - - case MEM_READ: - return pcf8583_read_mem(client, arg); - - case MEM_WRITE: - return pcf8583_write_mem(client, arg); - - default: - return -EINVAL; - } -} - -static struct i2c_driver pcf8583_driver = { - .driver = { - .name = "PCF8583", - }, - .id = I2C_DRIVERID_PCF8583, - .attach_adapter = pcf8583_probe, - .detach_client = pcf8583_detach, - .command = pcf8583_command -}; - -static __init int pcf8583_init(void) -{ - return i2c_add_driver(&pcf8583_driver); -} - -static __exit void pcf8583_exit(void) -{ - i2c_del_driver(&pcf8583_driver); -} - -module_init(pcf8583_init); -module_exit(pcf8583_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("PCF8583 I2C RTC driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/acorn/char/pcf8583.h b/drivers/acorn/char/pcf8583.h deleted file mode 100644 index 847f7fdb876..00000000000 --- a/drivers/acorn/char/pcf8583.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * linux/drivers/acorn/char/pcf8583.h - * - * Copyright (C) 2000 Russell King - * - * 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. - */ -struct rtc_tm { - unsigned char cs; - unsigned char secs; - unsigned char mins; - unsigned char hours; - unsigned char mday; - unsigned char mon; - unsigned char year_off; - unsigned char wday; -}; - -struct mem { - unsigned int loc; - unsigned int nr; - unsigned char *data; -}; - -#define RTC_GETDATETIME 0 -#define RTC_SETTIME 1 -#define RTC_SETDATETIME 2 -#define RTC_GETCTRL 3 -#define RTC_SETCTRL 4 -#define MEM_READ 5 -#define MEM_WRITE 6 - -#define CTRL_STOP 0x80 -#define CTRL_HOLD 0x40 -#define CTRL_32KHZ 0x00 -#define CTRL_MASK 0x08 -#define CTRL_ALARMEN 0x04 -#define CTRL_ALARM 0x02 -#define CTRL_TIMER 0x01 diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index e942ffe8b57..7c49e103cf8 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -149,6 +149,7 @@ config ACPI_DOCK config ACPI_BAY tristate "Removable Drive Bay (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on ACPI_DOCK help This driver adds support for ACPI controlled removable drive bays such as the IBM ultrabay or the Dell Module Bay. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 6d932409aad..43cc43d7b59 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -200,6 +200,7 @@ struct ahci_port_priv { /* for NCQ spurious interrupt analysis */ unsigned int ncq_saw_d2h:1; unsigned int ncq_saw_dmas:1; + unsigned int ncq_saw_sdb:1; }; static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -218,10 +219,12 @@ 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); +#ifdef CONFIG_PM static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); static int ahci_port_resume(struct ata_port *ap); static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); +#endif static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, @@ -240,8 +243,10 @@ static struct scsi_host_template ahci_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations ahci_ops = { @@ -270,8 +275,10 @@ static const struct ata_port_operations ahci_ops = { .error_handler = ahci_error_handler, .post_internal_cmd = ahci_post_internal_cmd, +#ifdef CONFIG_PM .port_suspend = ahci_port_suspend, .port_resume = ahci_port_resume, +#endif .port_start = ahci_port_start, .port_stop = ahci_port_stop, @@ -303,8 +310,10 @@ static const struct ata_port_operations ahci_vt8251_ops = { .error_handler = ahci_vt8251_error_handler, .post_internal_cmd = ahci_post_internal_cmd, +#ifdef CONFIG_PM .port_suspend = ahci_port_suspend, .port_resume = ahci_port_resume, +#endif .port_start = ahci_port_start, .port_stop = ahci_port_stop, @@ -384,12 +393,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { 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 */ - { 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 */ + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ @@ -438,8 +444,10 @@ static struct pci_driver ahci_pci_driver = { .id_table = ahci_pci_tbl, .probe = ahci_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ahci_pci_device_suspend, .resume = ahci_pci_device_resume, +#endif }; @@ -579,6 +587,7 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap) writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); } +#ifdef CONFIG_PM static void ahci_power_down(void __iomem *port_mmio, u32 cap) { u32 cmd, scontrol; @@ -596,6 +605,7 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap) cmd &= ~PORT_CMD_SPIN_UP; writel(cmd, port_mmio + PORT_CMD); } +#endif static void ahci_init_port(void __iomem *port_mmio, u32 cap, dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) @@ -1160,23 +1170,31 @@ static void ahci_host_intr(struct ata_port *ap) } if (status & PORT_IRQ_SDB_FIS) { - /* SDB FIS containing spurious completions might be - * dangerous, whine and fail commands with HSM - * violation. EH will turn off NCQ after several such - * failures. - */ const __le32 *f = pp->rx_fis + RX_FIS_SDB; - ata_ehi_push_desc(ehi, "spurious completion during NCQ " - "issue=0x%x SAct=0x%x FIS=%08x:%08x", - readl(port_mmio + PORT_CMD_ISSUE), - readl(port_mmio + PORT_SCR_ACT), - le32_to_cpu(f[0]), le32_to_cpu(f[1])); - - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_SOFTRESET; - ata_port_freeze(ap); - + if (le32_to_cpu(f[1])) { + /* SDB FIS containing spurious completions + * might be dangerous, whine and fail commands + * with HSM violation. EH will turn off NCQ + * after several such failures. + */ + ata_ehi_push_desc(ehi, + "spurious completions during NCQ " + "issue=0x%x SAct=0x%x FIS=%08x:%08x", + readl(port_mmio + PORT_CMD_ISSUE), + readl(port_mmio + PORT_SCR_ACT), + le32_to_cpu(f[0]), le32_to_cpu(f[1])); + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + } else { + if (!pp->ncq_saw_sdb) + ata_port_printk(ap, KERN_INFO, + "spurious SDB FIS %08x:%08x during NCQ, " + "this message won't be printed again\n", + le32_to_cpu(f[0]), le32_to_cpu(f[1])); + pp->ncq_saw_sdb = 1; + } known_irq = 1; } @@ -1329,6 +1347,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) } } +#ifdef CONFIG_PM static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) { struct ahci_host_priv *hpriv = ap->host->private_data; @@ -1407,6 +1426,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) return 0; } +#endif static int ahci_port_start(struct ata_port *ap) { @@ -1665,13 +1685,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - if (pdev->vendor == PCI_VENDOR_ID_JMICRON) { - /* Function 1 is the PATA controller except on the 368, where - we are not AHCI anyway */ - if (PCI_FUNC(pdev->devfn)) - return -ENODEV; - } - rc = pcim_enable_device(pdev); if (rc) return rc; diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index f48b4883c93..d8e79882b88 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -119,8 +119,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations generic_port_ops = { @@ -230,8 +232,10 @@ static struct pci_driver ata_generic_pci_driver = { .id_table = ata_generic, .probe = ata_generic_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init ata_generic_init(void) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 61572d8c78a..dc42ba1b46f 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -253,8 +253,10 @@ static struct pci_driver piix_pci_driver = { .id_table = piix_pci_tbl, .probe = piix_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static struct scsi_host_template piix_sht = { @@ -273,8 +275,10 @@ static struct scsi_host_template piix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations piix_pata_ops = { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c8d44a7c403..dc362fa01ca 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1850,8 +1850,11 @@ int ata_bus_probe(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].pio_mode = XFER_PIO_0; - /* read IDENTIFY page and configure devices */ - for (i = 0; i < ATA_MAX_DEVICES; i++) { + /* read IDENTIFY page and configure devices. We have to do the identify + specific sequence bass-ackwards so that PDIAG- is released by + the slave device */ + + for (i = ATA_MAX_DEVICES - 1; i >= 0; i--) { dev = &ap->device[i]; if (tries[i]) @@ -1864,6 +1867,15 @@ int ata_bus_probe(struct ata_port *ap) dev->id); if (rc) goto fail; + } + + /* After the identify sequence we can now set up the devices. We do + this in the normal order so that the user doesn't get confused */ + + for(i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + if (!ata_dev_enabled(dev)) + continue; ap->eh_context.i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); @@ -2556,12 +2568,11 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) * host channels are not permitted to do so. */ if (used_dma && (ap->host->flags & ATA_HOST_SIMPLEX)) - ap->host->simplex_claimed = 1; + ap->host->simplex_claimed = ap; /* step5: chip specific finalisation */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); - out: if (rc) *r_failed_dev = dev; @@ -3346,6 +3357,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices where NCQ should be avoided */ /* NCQ is slow */ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, + /* http://thread.gmane.org/gmane.linux.ide/14907 */ + { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, /* Devices with NCQ limits */ @@ -3442,7 +3455,7 @@ static void ata_dev_xfermask(struct ata_device *dev) "device is on DMA blacklist, disabling DMA\n"); } - if ((host->flags & ATA_HOST_SIMPLEX) && host->simplex_claimed) { + if ((host->flags & ATA_HOST_SIMPLEX) && host->simplex_claimed != ap) { xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by " "other device, disabling DMA\n"); @@ -5341,6 +5354,7 @@ int ata_flush_cache(struct ata_device *dev) return 0; } +#ifdef CONFIG_PM static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, unsigned int action, unsigned int ehi_flags, int wait) @@ -5456,6 +5470,7 @@ void ata_host_resume(struct ata_host *host) ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); host->dev->power.power_state = PMSG_ON; } +#endif /** * ata_port_start - Set port up for dma. @@ -5680,6 +5695,8 @@ static void ata_host_release(struct device *gendev, void *res) if (host->ops->host_stop) host->ops->host_stop(host); + + dev_set_drvdata(gendev, NULL); } /** @@ -5902,7 +5919,6 @@ int ata_device_add(const struct ata_probe_ent *ent) err_out: devres_release_group(dev, ata_device_add); - dev_set_drvdata(dev, NULL); VPRINTK("EXIT, returning %d\n", rc); return 0; } @@ -6090,6 +6106,7 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits) return (tmp == bits->val) ? 1 : 0; } +#ifdef CONFIG_PM void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg) { pci_save_state(pdev); @@ -6141,6 +6158,8 @@ int ata_pci_device_resume(struct pci_dev *pdev) ata_host_resume(host); return rc; } +#endif /* CONFIG_PM */ + #endif /* CONFIG_PCI */ @@ -6349,8 +6368,10 @@ EXPORT_SYMBOL_GPL(sata_scr_write); EXPORT_SYMBOL_GPL(sata_scr_write_flush); EXPORT_SYMBOL_GPL(ata_port_online); EXPORT_SYMBOL_GPL(ata_port_offline); +#ifdef CONFIG_PM EXPORT_SYMBOL_GPL(ata_host_suspend); EXPORT_SYMBOL_GPL(ata_host_resume); +#endif /* CONFIG_PM */ EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_id_to_dma_mode); @@ -6366,16 +6387,20 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); +#ifdef CONFIG_PM EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend); EXPORT_SYMBOL_GPL(ata_pci_device_do_resume); EXPORT_SYMBOL_GPL(ata_pci_device_suspend); EXPORT_SYMBOL_GPL(ata_pci_device_resume); +#endif /* CONFIG_PM */ EXPORT_SYMBOL_GPL(ata_pci_default_filter); EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); #endif /* CONFIG_PCI */ +#ifdef CONFIG_PM EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); +#endif /* CONFIG_PM */ EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_port_schedule_eh); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index cad0d6db6df..7349c3dbf77 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -52,8 +52,33 @@ enum { static void __ata_port_freeze(struct ata_port *ap); static void ata_eh_finish(struct ata_port *ap); +#ifdef CONFIG_PM static void ata_eh_handle_port_suspend(struct ata_port *ap); static void ata_eh_handle_port_resume(struct ata_port *ap); +static int ata_eh_suspend(struct ata_port *ap, + struct ata_device **r_failed_dev); +static void ata_eh_prep_resume(struct ata_port *ap); +static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev); +#else /* CONFIG_PM */ +static void ata_eh_handle_port_suspend(struct ata_port *ap) +{ } + +static void ata_eh_handle_port_resume(struct ata_port *ap) +{ } + +static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) +{ + return 0; +} + +static void ata_eh_prep_resume(struct ata_port *ap) +{ } + +static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) +{ + return 0; +} +#endif /* CONFIG_PM */ static void ata_ering_record(struct ata_ering *ering, int is_io, unsigned int err_mask) @@ -1790,6 +1815,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, return rc; } +#ifdef CONFIG_PM /** * ata_eh_suspend - handle suspend EH action * @ap: target host port @@ -1947,6 +1973,7 @@ static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) DPRINTK("EXIT\n"); return 0; } +#endif /* CONFIG_PM */ static int ata_port_nr_enabled(struct ata_port *ap) { @@ -2249,6 +2276,7 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_finish(ap); } +#ifdef CONFIG_PM /** * ata_eh_handle_port_suspend - perform port suspend operation * @ap: port to suspend @@ -2364,3 +2392,4 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) } spin_unlock_irqrestore(ap->lock, flags); } +#endif /* CONFIG_PM */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 00a9a6c8f83..6cc817a1020 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -510,6 +510,7 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) } } +#ifdef CONFIG_PM /** * ata_scsi_device_suspend - suspend ATA device associated with sdev * @sdev: the SCSI device to suspend @@ -634,6 +635,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) sdev->sdev_gendev.power.power_state = PMSG_ON; return 0; } +#endif /* CONFIG_PM */ /** * ata_to_sense_error - convert ATA error to SCSI error diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index a90ed00c07e..11ea552a58c 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -345,8 +345,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; /* @@ -667,11 +669,13 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int ali_reinit_one(struct pci_dev *pdev) { ali_init_chipset(pdev); return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id ali[] = { { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), }, @@ -685,8 +689,10 @@ static struct pci_driver ali_pci_driver = { .id_table = ali, .probe = ali_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ali_reinit_one, +#endif }; static int __init ali_init(void) diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 3c760d0f471..18381762908 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -334,8 +334,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations amd33_port_ops = { @@ -663,6 +665,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int amd_reinit_one(struct pci_dev *pdev) { if (pdev->vendor == PCI_VENDOR_ID_AMD) { @@ -679,6 +682,7 @@ static int amd_reinit_one(struct pci_dev *pdev) } return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id amd[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 }, @@ -708,8 +712,10 @@ static struct pci_driver amd_pci_driver = { .id_table = amd, .probe = amd_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = amd_reinit_one, +#endif }; static int __init amd_init(void) diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index c3eb40c91c8..51d9923be02 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -224,8 +224,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations atiixp_port_ops = { @@ -290,8 +292,10 @@ static struct pci_driver atiixp_pci_driver = { .id_table = atiixp, .probe = atiixp_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .resume = ata_pci_device_resume, .suspend = ata_pci_device_suspend, +#endif }; static int __init atiixp_init(void) diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index da098282b5f..5b13bdd1edc 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -1,5 +1,5 @@ /* - * pata_cmd64x.c - ATI PATA for new ATA layer + * pata_cmd64x.c - CMD64x PATA for new ATA layer * (C) 2005 Red Hat Inc * Alan Cox <alan@redhat.com> * @@ -285,8 +285,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations cmd64x_port_ops = { @@ -479,6 +481,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int cmd64x_reinit_one(struct pci_dev *pdev) { u8 mrdmode; @@ -492,6 +495,7 @@ static int cmd64x_reinit_one(struct pci_dev *pdev) #endif return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id cmd64x[] = { { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, @@ -507,8 +511,10 @@ static struct pci_driver cmd64x_pci_driver = { .id_table = cmd64x, .probe = cmd64x_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = cmd64x_reinit_one, +#endif }; static int __init cmd64x_init(void) diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index c1334c6c415..7ef834250a4 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -167,8 +167,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations cs5520_port_ops = { @@ -306,9 +308,9 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); } +#ifdef CONFIG_PM /** * cs5520_reinit_one - device resume * @pdev: PCI device @@ -348,6 +350,7 @@ static int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) pci_save_state(pdev); return 0; } +#endif /* CONFIG_PM */ /* For now keep DMA off. We can set it for all but A rev CS5510 once the core ATA code can handle it */ @@ -364,8 +367,10 @@ static struct pci_driver cs5520_pci_driver = { .id_table = pata_cs5520, .probe = cs5520_init_one, .remove = cs5520_remove_one, +#ifdef CONFIG_PM .suspend = cs5520_pci_device_suspend, .resume = cs5520_reinit_one, +#endif }; static int __init cs5520_init(void) diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 78c7cdfff69..db63e80e608 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -188,8 +188,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations cs5530_port_ops = { @@ -376,6 +378,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int cs5530_reinit_one(struct pci_dev *pdev) { /* If we fail on resume we are doomed */ @@ -383,6 +386,7 @@ static int cs5530_reinit_one(struct pci_dev *pdev) BUG(); return ata_pci_device_resume(pdev); } +#endif /* CONFIG_PM */ static const struct pci_device_id cs5530[] = { { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, @@ -395,8 +399,10 @@ static struct pci_driver cs5530_pci_driver = { .id_table = cs5530, .probe = cs5530_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = cs5530_reinit_one, +#endif }; static int __init cs5530_init(void) diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 17bc693cc51..1572e5c9031 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -185,8 +185,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations cs5535_port_ops = { @@ -270,8 +272,10 @@ static struct pci_driver cs5535_pci_driver = { .id_table = cs5535, .probe = cs5535_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init cs5535_init(void) diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 63f48f08763..f69dde5f706 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -136,8 +136,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations cy82c693_port_ops = { @@ -206,8 +208,10 @@ static struct pci_driver cy82c693_pci_driver = { .id_table = cy82c693, .probe = cy82c693_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init cy82c693_init(void) diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index c19b6a8a7dc..dac7a6554f6 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -234,8 +234,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations efar_ops = { @@ -317,8 +319,10 @@ static struct pci_driver efar_pci_driver = { .id_table = efar_pci_tbl, .probe = efar_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init efar_init(void) diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index e7d33c628a6..baf35f87603 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -328,8 +328,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; /* @@ -457,12 +459,13 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) return ata_pci_init_one(dev, port_info, 2); } +#ifdef CONFIG_PM static int hpt36x_reinit_one(struct pci_dev *dev) { hpt36x_init_chipset(dev); return ata_pci_device_resume(dev); } - +#endif static const struct pci_device_id hpt36x[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, @@ -474,8 +477,10 @@ static struct pci_driver hpt36x_pci_driver = { .id_table = hpt36x, .probe = hpt36x_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = hpt36x_reinit_one, +#endif }; static int __init hpt36x_init(void) diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index 483ce7c12c9..813485c8526 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -119,8 +119,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations hpt3x3_port_ops = { @@ -206,11 +208,13 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) return ata_pci_init_one(dev, port_info, 2); } +#ifdef CONFIG_PM static int hpt3x3_reinit_one(struct pci_dev *dev) { hpt3x3_init_chipset(dev); return ata_pci_device_resume(dev); } +#endif static const struct pci_device_id hpt3x3[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), }, @@ -223,8 +227,10 @@ static struct pci_driver hpt3x3_pci_driver = { .id_table = hpt3x3, .probe = hpt3x3_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = hpt3x3_reinit_one, +#endif }; static int __init hpt3x3_init(void) diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index d5f2e85e28f..1a61cc89174 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -128,7 +128,6 @@ static void isapnp_remove_one(struct pnp_dev *idev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); } static struct pnp_device_id isapnp_devices[] = { diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index 7eac869dfcd..ea734701555 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c @@ -246,8 +246,10 @@ static struct scsi_host_template it8213_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations it8213_ops = { @@ -330,8 +332,10 @@ static struct pci_driver it8213_pci_driver = { .id_table = it8213_pci_tbl, .probe = it8213_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init it8213_init(void) diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 903137a6da5..35ecb2ba067 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -646,8 +646,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations it821x_smart_port_ops = { @@ -780,6 +782,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int it821x_reinit_one(struct pci_dev *pdev) { /* Resume - turn raid back off if need be */ @@ -787,6 +790,7 @@ static int it821x_reinit_one(struct pci_dev *pdev) it821x_disable_raid(pdev); return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id it821x[] = { { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), }, @@ -800,8 +804,10 @@ static struct pci_driver it821x_pci_driver = { .id_table = it821x, .probe = it821x_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = it821x_reinit_one, +#endif }; static int __init it821x_init(void) diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 7a635dd326f..43763c99ea0 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -137,6 +137,10 @@ static struct scsi_host_template jmicron_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations jmicron_ops = { @@ -202,49 +206,20 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i }; struct ata_port_info *port_info[2] = { &info, &info }; - u32 reg; - - /* PATA controller is fn 1, AHCI is fn 0 */ - if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - /* The 365/66 have two PATA channels, redirect the second */ - if (id->driver_data == 365 || id->driver_data == 366) { - pci_read_config_dword(pdev, 0x80, ®); - reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ - pci_write_config_dword(pdev, 0x80, reg); - } - 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}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 365}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 366}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 368}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 361 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 363 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 365 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 366 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 368 }, { } /* terminate list */ }; @@ -254,8 +229,10 @@ static struct pci_driver jmicron_pci_driver = { .id_table = jmicron_pci_tbl, .probe = jmicron_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, - .resume = jmicron_reinit_one, + .resume = ata_pci_device_resume, +#endif }; static int __init jmicron_init(void) diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 6ee61c67163..fc5b73d78e0 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -186,7 +186,10 @@ static struct ata_port_operations legacy_port_ops = { .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, @@ -298,7 +301,10 @@ static struct ata_port_operations pdc20230_port_ops = { .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, @@ -350,7 +356,10 @@ static struct ata_port_operations ht6560a_port_ops = { .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, @@ -413,7 +422,10 @@ static struct ata_port_operations ht6560b_port_ops = { .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, @@ -531,7 +543,10 @@ static struct ata_port_operations opti82c611a_port_ops = { .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, @@ -661,7 +676,10 @@ static struct ata_port_operations opti82c46x_port_ops = { .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 = opti82c46x_qc_issue_prot, diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 13a70ac6f1d..6dd7c4ef3e6 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -103,8 +103,10 @@ static struct scsi_host_template marvell_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations marvell_ops = { @@ -199,8 +201,10 @@ static struct pci_driver marvell_pci_driver = { .id_table = marvell_pci_tbl, .probe = marvell_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init marvell_init(void) diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 29e1809e5ec..f5d88729ca7 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -280,6 +280,10 @@ static struct scsi_host_template mpc52xx_ata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, +#endif }; static struct ata_port_operations mpc52xx_ata_port_ops = { diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index f2e7115f7ab..4abe45ac19a 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -165,8 +165,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations mpiix_port_ops = { @@ -270,8 +272,10 @@ static struct pci_driver mpiix_pci_driver = { .id_table = mpiix, .probe = mpiix_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init mpiix_init(void) diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index e8393e19be4..38f99b38a5e 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -63,8 +63,10 @@ static struct scsi_host_template netcell_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations netcell_ops = { @@ -153,8 +155,10 @@ static struct pci_driver netcell_pci_driver = { .id_table = netcell_pci_tbl, .probe = netcell_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init netcell_init(void) diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 3d1fa487c48..9944a28daa9 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -157,8 +157,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations ns87410_port_ops = { @@ -212,8 +214,10 @@ static struct pci_driver ns87410_pci_driver = { .id_table = ns87410, .probe = ns87410_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init ns87410_init(void) diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 2389107a200..da68cd19efd 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -233,8 +233,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations oldpiix_pata_ops = { @@ -316,8 +318,10 @@ static struct pci_driver oldpiix_pci_driver = { .id_table = oldpiix_pci_tbl, .probe = oldpiix_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init oldpiix_init(void) diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index 1b3cd5369f0..3fd3a35c224 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -179,8 +179,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations opti_port_ops = { @@ -244,8 +246,10 @@ static struct pci_driver opti_pci_driver = { .id_table = opti, .probe = opti_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init opti_init(void) diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index b76c976e505..9764907e8a1 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -360,8 +360,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations optidma_port_ops = { @@ -524,8 +526,10 @@ static struct pci_driver optidma_pci_driver = { .id_table = optidma, .probe = optidma_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init optidma_init(void) diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 80685388c2b..3fb41778016 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -267,8 +267,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations pdc2024x_port_ops = { @@ -399,8 +401,10 @@ static struct pci_driver pdc202xx_pci_driver = { .id_table = pdc202xx, .probe = pdc202xx_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init pdc202xx_init(void) diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 02ea95fcba6..4b82a5435a4 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -228,7 +228,6 @@ static int __devexit pata_platform_remove(struct platform_device *pdev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); return 0; } diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index c2f87da6033..c3810012f3f 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -363,7 +363,8 @@ static __init int qdi_init(void) release_region(port, 2); continue; } - ct += qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); + if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0) + ct++; } if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) { /* QD6580: dual channel */ @@ -375,11 +376,14 @@ static __init int qdi_init(void) res = inb(port + 3); if (res & 1) { /* Single channel mode */ - ct += qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); + if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04)) + ct++; } else { /* Dual channel mode */ - ct += qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04); - ct += qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04); + if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0) + ct++; + if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0) + ct++; } } } diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 0d1e571ef63..9a9132c9e33 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -228,8 +228,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations radisys_pata_ops = { @@ -312,8 +314,10 @@ static struct pci_driver radisys_pci_driver = { .id_table = radisys_pci_tbl, .probe = radisys_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init radisys_init(void) diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 60fc598f765..f522daa2a6a 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -94,8 +94,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations rz1000_port_ops = { @@ -178,6 +180,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en return -ENODEV; } +#ifdef CONFIG_PM static int rz1000_reinit_one(struct pci_dev *pdev) { /* If this fails on resume (which is a "cant happen" case), we @@ -186,6 +189,7 @@ static int rz1000_reinit_one(struct pci_dev *pdev) panic("rz1000 fifo"); return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id pata_rz1000[] = { { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, @@ -199,8 +203,10 @@ static struct pci_driver rz1000_pci_driver = { .id_table = pata_rz1000, .probe = rz1000_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = rz1000_reinit_one, +#endif }; static int __init rz1000_init(void) diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 58e42fbd14f..93b3ed0f9e8 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -194,8 +194,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations sc1200_port_ops = { @@ -210,7 +212,10 @@ static struct ata_port_operations sc1200_port_ops = { .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, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -266,8 +271,10 @@ static struct pci_driver sc1200_pci_driver = { .id_table = sc1200, .probe = sc1200_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init sc1200_init(void) diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 45866098fbf..f3ed141fdc0 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -984,8 +984,10 @@ static struct scsi_host_template scc_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations scc_pata_ops = { diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index dde7eb9f72b..598eef810a7 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -319,8 +319,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations serverworks_osb4_port_ops = { @@ -548,6 +550,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id return ata_pci_init_one(pdev, port_info, ports); } +#ifdef CONFIG_PM static int serverworks_reinit_one(struct pci_dev *pdev) { /* Force master latency timer to 64 PCI clocks */ @@ -571,6 +574,7 @@ static int serverworks_reinit_one(struct pci_dev *pdev) } return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id serverworks[] = { { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, @@ -587,8 +591,10 @@ static struct pci_driver serverworks_pci_driver = { .id_table = serverworks, .probe = serverworks_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = serverworks_reinit_one, +#endif }; static int __init serverworks_init(void) diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 1cb67b221c2..dab2889a556 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -236,6 +236,10 @@ static struct scsi_host_template sil680_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, +#endif }; static struct ata_port_operations sil680_port_ops = { @@ -377,11 +381,13 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM static int sil680_reinit_one(struct pci_dev *pdev) { sil680_init_chip(pdev); return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id sil680[] = { { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, @@ -394,8 +400,10 @@ static struct pci_driver sil680_pci_driver = { .id_table = sil680, .probe = sil680_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = sil680_reinit_one, +#endif }; static int __init sil680_init(void) diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index be300923b27..f4820786593 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -575,8 +575,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static const struct ata_port_operations sis_133_ops = { @@ -1032,8 +1034,10 @@ static struct pci_driver sis_pci_driver = { .id_table = sis_pci_tbl, .probe = sis_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init sis_init(void) diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 13e81f0ef1f..b681441cfcb 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -234,7 +234,10 @@ static struct ata_port_operations sl82c105_port_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, .error_handler = sl82c105_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .bmdma_setup = ata_bmdma_setup, .bmdma_start = sl82c105_bmdma_start, diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 453ab90b721..71418f2a0cd 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -193,8 +193,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations triflex_port_ops = { @@ -260,8 +262,10 @@ static struct pci_driver triflex_pci_driver = { .id_table = triflex, .probe = triflex_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, +#endif }; static int __init triflex_init(void) diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 20fc2d0dcfa..946ade0e1f1 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -305,8 +305,10 @@ 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, +#ifdef CONFIG_PM .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, +#endif }; static struct ata_port_operations via_port_ops = { @@ -560,6 +562,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ata_pci_init_one(pdev, port_info, 2); } +#ifdef CONFIG_PM /** * via_reinit_one - reinit after resume * @pdev; PCI device @@ -592,6 +595,7 @@ static int via_reinit_one(struct pci_dev *pdev) } return ata_pci_device_resume(pdev); } +#endif static const struct pci_device_id via[] = { { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, @@ -607,8 +611,10 @@ static struct pci_driver via_pci_driver = { .id_table = via, .probe = via_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = via_reinit_one, +#endif }; static int __init via_init(void) diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 31b636fac98..3193a603d1a 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -135,8 +135,10 @@ static struct scsi_host_template inic_sht = { .slave_configure = inic_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static const int scr_map[] = { @@ -632,6 +634,7 @@ static int init_controller(void __iomem *mmio_base, u16 hctl) return 0; } +#ifdef CONFIG_PM static int inic_pci_device_resume(struct pci_dev *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); @@ -642,7 +645,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev) ata_pci_device_do_resume(pdev); if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - printk("XXX\n"); rc = init_controller(mmio_base, hpriv->cached_hctl); if (rc) return rc; @@ -652,6 +654,7 @@ static int inic_pci_device_resume(struct pci_dev *pdev) return 0; } +#endif static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -755,8 +758,10 @@ static const struct pci_device_id inic_pci_tbl[] = { static struct pci_driver inic_pci_driver = { .name = DRV_NAME, .id_table = inic_pci_tbl, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = inic_pci_device_resume, +#endif .probe = inic_init_one, .remove = ata_pci_remove_one, }; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 30eed12b363..388d07fab5f 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -230,7 +230,9 @@ struct nv_host_priv { static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void nv_remove_one (struct pci_dev *pdev); +#ifdef CONFIG_PM static int nv_pci_device_resume(struct pci_dev *pdev); +#endif static void nv_ck804_host_stop(struct ata_host *host); static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); @@ -251,8 +253,10 @@ 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); +#ifdef CONFIG_PM static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); static int nv_adma_port_resume(struct ata_port *ap); +#endif static void nv_adma_error_handler(struct ata_port *ap); static void nv_adma_host_stop(struct ata_host *host); static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); @@ -295,8 +299,10 @@ static struct pci_driver nv_pci_driver = { .name = DRV_NAME, .id_table = nv_pci_tbl, .probe = nv_init_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = nv_pci_device_resume, +#endif .remove = nv_remove_one, }; @@ -316,8 +322,10 @@ static struct scsi_host_template nv_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static struct scsi_host_template nv_adma_sht = { @@ -336,8 +344,10 @@ static struct scsi_host_template nv_adma_sht = { .slave_configure = nv_adma_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations nv_generic_ops = { @@ -449,8 +459,10 @@ static const struct ata_port_operations nv_adma_ops = { .scr_write = nv_scr_write, .port_start = nv_adma_port_start, .port_stop = nv_adma_port_stop, +#ifdef CONFIG_PM .port_suspend = nv_adma_port_suspend, .port_resume = nv_adma_port_resume, +#endif .host_stop = nv_adma_host_stop, }; @@ -1003,6 +1015,7 @@ static void nv_adma_port_stop(struct ata_port *ap) writew(0, mmio + NV_ADMA_CTL); } +#ifdef CONFIG_PM static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg) { struct nv_adma_port_priv *pp = ap->private_data; @@ -1053,6 +1066,7 @@ static int nv_adma_port_resume(struct ata_port *ap) return 0; } +#endif static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) { @@ -1555,6 +1569,7 @@ static void nv_remove_one (struct pci_dev *pdev) kfree(hpriv); } +#ifdef CONFIG_PM static int nv_pci_device_resume(struct pci_dev *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); @@ -1602,6 +1617,7 @@ static int nv_pci_device_resume(struct pci_dev *pdev) return 0; } +#endif static void nv_ck804_host_stop(struct ata_host *host) { diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index f7179c646be..917b7ea4ef7 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -183,8 +183,10 @@ static struct scsi_host_template sil_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations sil_ops = { diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 5d083f43f90..75d96159965 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -380,8 +380,10 @@ static struct scsi_host_template sil24_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM .suspend = ata_scsi_device_suspend, .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations sil24_ops = { @@ -647,7 +649,6 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, struct sil24_sge *sge) { struct scatterlist *sg; - unsigned int idx = 0; ata_for_each_sg(sg, qc) { sge->addr = cpu_to_le64(sg_dma_address(sg)); @@ -656,9 +657,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, sge->flags = cpu_to_le32(SGE_TRM); else sge->flags = 0; - sge++; - idx++; } } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index cacb1c816e3..17ee97f3a99 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -406,22 +406,6 @@ config BLK_DEV_RAM_BLOCKSIZE setups function - apparently needed by the rd_load_image routine that supposes the filesystem in the image uses a 1024 blocksize. -config BLK_DEV_INITRD - bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" - depends on BROKEN || !FRV - help - The initial RAM filesystem is a ramfs which is loaded by the - boot loader (loadlin or lilo) and that is mounted as root - before the normal boot procedure. It is typically used to - load modules needed to mount the "real" root file system, - etc. See <file:Documentation/initrd.txt> for details. - - If RAM disk support (BLK_DEV_RAM) is also included, this - also enables initial RAM disk (initrd) support and adds - 15 Kbytes (more on some other architectures) to the kernel size. - - If unsure say Y. - config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index bb022ed4a86..8d17d8df366 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -530,7 +530,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) u16 aoemajor; hin = (struct aoe_hdr *) skb->mac.raw; - aoemajor = be16_to_cpu(hin->major); + aoemajor = be16_to_cpu(get_unaligned(&hin->major)); d = aoedev_by_aoeaddr(aoemajor, hin->minor); if (d == NULL) { snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " @@ -542,7 +542,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) spin_lock_irqsave(&d->lock, flags); - n = be32_to_cpu(hin->tag); + n = be32_to_cpu(get_unaligned(&hin->tag)); f = getframe(d, n); if (f == NULL) { calc_rttavg(d, -tsince(n)); @@ -550,9 +550,9 @@ aoecmd_ata_rsp(struct sk_buff *skb) snprintf(ebuf, sizeof ebuf, "%15s e%d.%d tag=%08x@%08lx\n", "unexpected rsp", - be16_to_cpu(hin->major), + be16_to_cpu(get_unaligned(&hin->major)), hin->minor, - be32_to_cpu(hin->tag), + be32_to_cpu(get_unaligned(&hin->tag)), jiffies); aoechr_error(ebuf); return; @@ -631,7 +631,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) printk(KERN_INFO "aoe: unrecognized ata command %2.2Xh for %d.%d\n", ahout->cmdstat, - be16_to_cpu(hin->major), + be16_to_cpu(get_unaligned(&hin->major)), hin->minor); } } @@ -733,7 +733,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) * Enough people have their dip switches set backwards to * warrant a loud message for this special case. */ - aoemajor = be16_to_cpu(h->major); + aoemajor = be16_to_cpu(get_unaligned(&h->major)); if (aoemajor == 0xfff) { printk(KERN_ERR "aoe: Warning: shelf address is all ones. " "Check shelf dip switches.\n"); diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 9626e0f5da9..aab6d91a2c2 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -8,6 +8,7 @@ #include <linux/blkdev.h> #include <linux/netdevice.h> #include <linux/moduleparam.h> +#include <asm/unaligned.h> #include "aoe.h" #define NECODES 5 @@ -123,7 +124,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb_push(skb, ETH_HLEN); /* (1) */ h = (struct aoe_hdr *) skb->mac.raw; - n = be32_to_cpu(h->tag); + n = be32_to_cpu(get_unaligned(&h->tag)); if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) goto exit; @@ -133,7 +134,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, n = 0; if (net_ratelimit()) printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", - be16_to_cpu(h->major), h->minor, + be16_to_cpu(get_unaligned(&h->major)), h->minor, h->err, aoe_errlist[n]); goto exit; } diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 05dfe357527..0c716ee905d 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1291,13 +1291,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index) if (inq_buff == NULL) goto mem_msg; + /* testing to see if 16-byte CDBs are already being used */ + if (h->cciss_read == CCISS_READ_16) { + cciss_read_capacity_16(h->ctlr, drv_index, 1, + &total_size, &block_size); + goto geo_inq; + } + cciss_read_capacity(ctlr, drv_index, 1, &total_size, &block_size); - /* total size = last LBA + 1 */ - /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */ - /* so we assume this volume this must be >2TB in size */ - if (total_size == (__u32) 0) { + /* if read_capacity returns all F's this volume is >2TB in size */ + /* so we switch to 16-byte CDB's for all read/write ops */ + if (total_size == 0xFFFFFFFFULL) { cciss_read_capacity_16(ctlr, drv_index, 1, &total_size, &block_size); h->cciss_read = CCISS_READ_16; @@ -1306,6 +1312,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index) h->cciss_read = CCISS_READ_10; h->cciss_write = CCISS_WRITE_10; } +geo_inq: cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, inq_buff, &h->drv[drv_index]); @@ -1917,13 +1924,14 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, drv->raid_level = inq_buff->data_byte[8]; } drv->block_size = block_size; - drv->nr_blocks = total_size; + drv->nr_blocks = total_size + 1; t = drv->heads * drv->sectors; if (t > 1) { - unsigned rem = sector_div(total_size, t); + sector_t real_size = total_size + 1; + unsigned long rem = sector_div(real_size, t); if (rem) - total_size++; - drv->cylinders = total_size; + real_size++; + drv->cylinders = real_size; } } else { /* Get geometry failed */ printk(KERN_WARNING "cciss: reading geometry failed\n"); @@ -1953,16 +1961,16 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, ctlr, buf, sizeof(ReadCapdata_struct), 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1; + *total_size = be32_to_cpu(*(__u32 *) buf->total_size); *block_size = be32_to_cpu(*(__u32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; *block_size = BLOCK_SIZE; } - if (*total_size != (__u32) 0) + if (*total_size != 0) printk(KERN_INFO " blocks= %llu block_size= %d\n", - (unsigned long long)*total_size, *block_size); + (unsigned long long)*total_size+1, *block_size); kfree(buf); return; } @@ -1989,7 +1997,7 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, 1, logvol, 0, NULL, TYPE_CMD); } if (return_code == IO_OK) { - *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1; + *total_size = be64_to_cpu(*(__u64 *) buf->total_size); *block_size = be32_to_cpu(*(__u32 *) buf->block_size); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); @@ -1997,7 +2005,7 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, *block_size = BLOCK_SIZE; } printk(KERN_INFO " blocks= %llu block_size= %d\n", - (unsigned long long)*total_size, *block_size); + (unsigned long long)*total_size+1, *block_size); kfree(buf); return; } @@ -3119,8 +3127,9 @@ static void cciss_getgeometry(int cntl_num) } cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size); - /* total_size = last LBA + 1 */ - if(total_size == (__u32) 0) { + /* If read_capacity returns all F's the logical is >2TB */ + /* so we switch to 16-byte CDBs for all read/write ops */ + if(total_size == 0xFFFFFFFFULL) { cciss_read_capacity_16(cntl_num, i, 0, &total_size, &block_size); hba[cntl_num]->cciss_read = CCISS_READ_16; @@ -3395,7 +3404,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, return -1; } -static void __devexit cciss_remove_one(struct pci_dev *pdev) +static void cciss_remove_one(struct pci_dev *pdev) { ctlr_info_t *tmp_ptr; int i, j; @@ -3419,9 +3428,10 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) memset(flush_buf, 0, 4); return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL, TYPE_CMD); - if (return_code != IO_OK) { - printk(KERN_WARNING "Error Flushing cache on controller %d\n", - i); + if (return_code == IO_OK) { + printk(KERN_INFO "Completed flushing cache on controller %d\n", i); + } else { + printk(KERN_WARNING "Error flushing cache on controller %d\n", i); } free_irq(hba[i]->intr[2], hba[i]); @@ -3472,6 +3482,7 @@ static struct pci_driver cciss_pci_driver = { .probe = cciss_init_one, .remove = __devexit_p(cciss_remove_one), .id_table = cciss_pci_device_id, /* id_table */ + .shutdown = cciss_remove_one, }; /* diff --git a/drivers/block/umem.c b/drivers/block/umem.c index dff3766f117..5872036e8ae 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1179,8 +1179,10 @@ static int __init mm_init(void) return -ENOMEM; err = major_nr = register_blkdev(0, "umem"); - if (err < 0) + if (err < 0) { + pci_unregister_driver(&mm_pci_driver); return -EIO; + } for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); @@ -1207,6 +1209,7 @@ static int __init mm_init(void) return 0; out: + pci_unregister_driver(&mm_pci_driver); unregister_blkdev(major_nr, "umem"); while (i--) put_disk(mm_gendisk[i]); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index dc13ebacedf..44cd7b2ddf0 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -376,6 +376,25 @@ static int send_request(struct request *req) return 0; } +static void viocd_end_request(struct request *req, int uptodate) +{ + int nsectors = req->hard_nr_sectors; + + /* + * Make sure it's fully ended, and ensure that we process + * at least one sector. + */ + if (blk_pc_request(req)) + nsectors = (req->data_len + 511) >> 9; + if (!nsectors) + nsectors = 1; + + if (end_that_request_first(req, uptodate, nsectors)) + BUG(); + add_disk_randomness(req->rq_disk); + blkdev_dequeue_request(req); + end_that_request_last(req, uptodate); +} static int rwreq; @@ -385,11 +404,11 @@ static void do_viocd_request(request_queue_t *q) while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) { if (!blk_fs_request(req)) - end_request(req, 0); + viocd_end_request(req, 0); else if (send_request(req) < 0) { printk(VIOCD_KERN_WARNING "unable to send message to OS/400!"); - end_request(req, 0); + viocd_end_request(req, 0); } else rwreq++; } @@ -601,9 +620,9 @@ return_complete: "with rc %d:0x%04X: %s\n", req, event->xRc, bevent->sub_result, err->msg); - end_request(req, 0); + viocd_end_request(req, 0); } else - end_request(req, 1); + viocd_end_request(req, 1); /* restart handling of incoming requests */ spin_unlock_irqrestore(&viocd_reqlock, flags); diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 54df35527bc..16dc5d1d3cb 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -3501,6 +3501,7 @@ get_serial_info(struct cyclades_port *info, tmp.irq = cinfo->irq; tmp.flags = info->flags; tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; tmp.baud_base = info->baud; tmp.custom_divisor = info->custom_divisor; tmp.hub6 = 0; /*!!! */ diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 88fc24fc439..de5be30484a 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -209,7 +209,6 @@ static void digi_send_break(struct channel *ch, int msec); static void setup_empty_event(struct tty_struct *tty, struct channel *ch); void epca_setup(char *, int *); -static int get_termio(struct tty_struct *, struct termio __user *); static int pc_write(struct tty_struct *, const unsigned char *, int); static int pc_init(void); static int init_PCI(void); @@ -2362,15 +2361,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, switch (cmd) { /* Begin switch cmd */ - -#if 0 /* Handled by calling layer properly */ - case TCGETS: - if (copy_to_user(argp, tty->termios, sizeof(struct ktermios))) - return -EFAULT; - return 0; - case TCGETA: - return get_termio(tty, argp); -#endif case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) @@ -2735,13 +2725,6 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch) memoff(ch); } /* End setup_empty_event */ -/* --------------------- Begin get_termio ----------------------- */ - -static int get_termio(struct tty_struct * tty, struct termio __user * termio) -{ /* Begin get_termio */ - return kernel_termios_to_user_termio(termio, tty->termios); -} /* End get_termio */ - /* ---------------------- Begin epca_setup -------------------------- */ void epca_setup(char *str, int *ints) { /* Begin epca_setup */ diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a7b33d2f599..e22146546ad 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2478,6 +2478,11 @@ static __devinit void default_find_bmc(void) if (!info) return; +#ifdef CONFIG_PPC_MERGE + if (check_legacy_ioport(ipmi_defaults[i].port)) + continue; +#endif + info->addr_source = NULL; info->si_type = ipmi_defaults[i].type; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f24c26d2dba..e4532685668 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1901,6 +1901,20 @@ static int init_dev(struct tty_driver *driver, int idx, /* check whether we're reopening an existing tty */ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { tty = devpts_get_tty(idx); + /* + * If we don't have a tty here on a slave open, it's because + * the master already started the close process and there's + * no relation between devpts file and tty anymore. + */ + if (!tty && driver->subtype == PTY_TYPE_SLAVE) { + retval = -EIO; + goto end_init; + } + /* + * It's safe from now on because init_dev() is called with + * tty_mutex held and release_dev() won't change tty->count + * or tty->flags without having to grab tty_mutex + */ if (tty && driver->subtype == PTY_TYPE_MASTER) tty = tty->link; } else { diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index ccaa6a39cb4..d42060ede93 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -214,4 +214,7 @@ pm_good: return clocksource_register(&clocksource_acpi_pm); } -module_init(init_acpi_pm_clocksource); +/* We use fs_initcall because we want the PCI fixups to have run + * but we still need to load before device_initcall + */ +fs_initcall(init_acpi_pm_clocksource); diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c index 4f3925ceb36..1bde303b970 100644 --- a/drivers/clocksource/cyclone.c +++ b/drivers/clocksource/cyclone.c @@ -116,4 +116,4 @@ static int __init init_cyclone_clocksource(void) return clocksource_register(&clocksource_cyclone); } -module_init(init_cyclone_clocksource); +arch_initcall(init_cyclone_clocksource); diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c index 0eb62841e9b..6d3840e629d 100644 --- a/drivers/crypto/geode-aes.c +++ b/drivers/crypto/geode-aes.c @@ -99,9 +99,8 @@ do_crypt(void *src, void *dst, int len, u32 flags) static unsigned int geode_aes_crypt(struct geode_aes_op *op) { - u32 flags = 0; - int iflags; + unsigned long iflags; if (op->len == 0 || op->src == op->dst) return 0; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7452399501b..f4ee1afe488 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -667,7 +667,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (item.format != HID_ITEM_FORMAT_SHORT) { dbg("unexpected long global item"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -676,7 +675,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (dispatch_type[item.type](parser, &item)) { dbg("item %u %u %u %u parsing failed\n", item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -685,14 +683,12 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (start == end) { if (parser->collection_stack_ptr) { dbg("unbalanced collection at end of report description"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; } if (parser->local.delimiter_depth) { dbg("unbalanced delimiter at end of report description"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -703,7 +699,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) } dbg("item fetching failed at offset %d\n", (int)(end - start)); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -880,7 +875,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data) /* make sure the unused bits in the last byte are zeros */ if (count > 0 && size > 0) - data[(count*size-1)/8] = 0; + data[(offset+count*size-1)/8] = 0; for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 89241be4ec9..83c4126b37c 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -29,6 +29,7 @@ */ #include <linux/hid.h> +#include <linux/hid-debug.h> struct hid_usage_entry { unsigned page; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 25d180a24fc..c8434023ba6 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -2,7 +2,7 @@ * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina * * HID to Linux Input mapping */ @@ -71,7 +71,6 @@ static const struct { #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) -#define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0) #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #ifdef CONFIG_USB_HIDINPUT_POWERBOOK @@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } } - map_key_clear(code); + map_key(code); break; @@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: if (field->flags & HID_MAIN_ITEM_RELATIVE) - map_rel_clear(usage->hid & 0xf); + map_rel(usage->hid & 0xf); else - map_abs_clear(usage->hid & 0xf); + map_abs(usage->hid & 0xf); break; case HID_GD_HATSWITCH: @@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x22f: map_key_clear(KEY_ZOOMRESET); break; case 0x233: map_key_clear(KEY_SCROLLUP); break; case 0x234: map_key_clear(KEY_SCROLLDOWN); break; - case 0x238: map_rel_clear(REL_HWHEEL); break; + case 0x238: map_rel(REL_HWHEEL); break; case 0x25f: map_key_clear(KEY_CANCEL); break; case 0x279: map_key_clear(KEY_REDO); break; @@ -532,6 +531,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x302: map_key_clear(KEY_PROG2); break; case 0x303: map_key_clear(KEY_PROG3); break; + /* Reported on Logitech S510 wireless keyboard */ + case 0x101f: map_key_clear(KEY_ZOOMIN); break; + case 0x1020: map_key_clear(KEY_ZOOMOUT); break; + case 0x1021: map_key_clear(KEY_ZOOMRESET); break; + /* this one is marked as 'Rotate' */ + case 0x1028: map_key_clear(KEY_ANGLE); break; + case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x1041: map_key_clear(KEY_BATTERY); break; + case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; + case 0x1043: map_key_clear(KEY_SPREADSHEET); break; + case 0x1044: map_key_clear(KEY_PRESENTATION); break; + case 0x1045: map_key_clear(KEY_UNDO); break; + case 0x1046: map_key_clear(KEY_REDO); break; + case 0x1047: map_key_clear(KEY_PRINT); break; + case 0x1048: map_key_clear(KEY_SAVE); break; + case 0x1049: map_key_clear(KEY_PROG1); break; + case 0x104a: map_key_clear(KEY_PROG2); break; + case 0x104b: map_key_clear(KEY_PROG3); break; + case 0x104c: map_key_clear(KEY_PROG4); break; + default: goto ignore; } break; @@ -647,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(usage->type, input->evbit); + if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && + (usage->type == EV_KEY || + usage->type == EV_REL || + usage->type == EV_ABS)) + clear_bit(usage->code, bit); + while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 4d44a2db29d..fb19dbb31e4 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -495,6 +495,16 @@ config I2C_VERSATILE This driver can also be built as a module. If so, the module will be called i2c-versatile. +config I2C_ACORN + bool "Acorn IOC/IOMD I2C bus support" + depends on I2C && ARCH_ACORN + default y + select I2C_ALGOBIT + help + Say yes if you want to support the I2C bus on Acorn platforms. + + If you don't know, say Y. + config I2C_VIA tristate "VIA 82C586B" depends on I2C && PCI && EXPERIMENTAL diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 03505aa44bb..290b5401835 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o +obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c new file mode 100644 index 00000000000..09bd7f40b90 --- /dev/null +++ b/drivers/i2c/busses/i2c-acorn.c @@ -0,0 +1,97 @@ +/* + * linux/drivers/acorn/char/i2c.c + * + * Copyright (C) 2000 Russell King + * + * 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. + * + * ARM IOC/IOMD i2c driver. + * + * On Acorn machines, the following i2c devices are on the bus: + * - PCF8583 real time clock & static RAM + */ +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/hardware/ioc.h> +#include <asm/system.h> + +#define FORCE_ONES 0xdc +#define SCL 0x02 +#define SDA 0x01 + +/* + * We must preserve all non-i2c output bits in IOC_CONTROL. + * Note also that we need to preserve the value of SCL and + * SDA outputs as well (which may be different from the + * values read back from IOC_CONTROL). + */ +static u_int force_ones; + +static void ioc_setscl(void *data, int state) +{ + u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); + u_int ones = force_ones; + + if (state) + ones |= SCL; + else + ones &= ~SCL; + + force_ones = ones; + + ioc_writeb(ioc_control | ones, IOC_CONTROL); +} + +static void ioc_setsda(void *data, int state) +{ + u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); + u_int ones = force_ones; + + if (state) + ones |= SDA; + else + ones &= ~SDA; + + force_ones = ones; + + ioc_writeb(ioc_control | ones, IOC_CONTROL); +} + +static int ioc_getscl(void *data) +{ + return (ioc_readb(IOC_CONTROL) & SCL) != 0; +} + +static int ioc_getsda(void *data) +{ + return (ioc_readb(IOC_CONTROL) & SDA) != 0; +} + +static struct i2c_algo_bit_data ioc_data = { + .setsda = ioc_setsda, + .setscl = ioc_setscl, + .getsda = ioc_getsda, + .getscl = ioc_getscl, + .udelay = 80, + .timeout = 100 +}; + +static struct i2c_adapter ioc_ops = { + .id = I2C_HW_B_IOC, + .algo_data = &ioc_data, +}; + +static int __init i2c_ioc_init(void) +{ + force_ones = FORCE_ONES | SCL | SDA; + + return i2c_bit_add_bus(&ioc_ops); +} + +__initcall(i2c_ioc_init); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 49234e32fd1..5d134bb75ba 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1023,7 +1023,7 @@ config BLK_DEV_4DRIVES config BLK_DEV_ALI14XX tristate "ALI M14xx support" help - This driver is enabled at runtime using the "ide0=ali14xx" kernel + This driver is enabled at runtime using the "ali14xx.probe" kernel boot parameter. It enables support for the secondary IDE interface of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster I/O speeds to be set as well. See the files @@ -1033,7 +1033,7 @@ config BLK_DEV_ALI14XX config BLK_DEV_DTC2278 tristate "DTC-2278 support" help - This driver is enabled at runtime using the "ide0=dtc2278" kernel + This driver is enabled at runtime using the "dtc2278.probe" kernel boot parameter. It enables support for the secondary IDE interface of the DTC-2278 card, and permits faster I/O speeds to be set as well. See the <file:Documentation/ide.txt> and @@ -1042,7 +1042,7 @@ config BLK_DEV_DTC2278 config BLK_DEV_HT6560B tristate "Holtek HT6560B support" help - This driver is enabled at runtime using the "ide0=ht6560b" kernel + This driver is enabled at runtime using the "ht6560b.probe" kernel boot parameter. It enables support for the secondary IDE interface of the Holtek card, and permits faster I/O speeds to be set as well. See the <file:Documentation/ide.txt> and @@ -1051,7 +1051,7 @@ config BLK_DEV_HT6560B config BLK_DEV_QD65XX tristate "QDI QD65xx support" help - This driver is enabled at runtime using the "ide0=qd65xx" kernel + This driver is enabled at runtime using the "qd65xx.probe" kernel boot parameter. It permits faster I/O speeds to be set. See the <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for more info. @@ -1059,7 +1059,7 @@ config BLK_DEV_QD65XX config BLK_DEV_UMC8672 tristate "UMC-8672 support" help - This driver is enabled at runtime using the "ide0=umc8672" kernel + This driver is enabled at runtime using the "umc8672.probe" kernel boot parameter. It enables support for the secondary IDE interface of the UMC-8672, and permits faster I/O speeds to be set as well. See the files <file:Documentation/ide.txt> and diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index 6b2d152351b..556455fbfa2 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -17,8 +17,6 @@ * device can't do DMA handshaking for some stupid reason. We don't need to do that. */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/types.h> #include <linux/kernel.h> #include <linux/timer.h> diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e2cea1889c4..37aa6ddd970 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -43,8 +43,6 @@ #define IDEDISK_VERSION "1.18" -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - //#define DEBUG #include <linux/module.h> diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index c67b3b1e6f4..bd513f5a232 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -583,6 +583,8 @@ u8 eighty_ninty_three (ide_drive_t *drive) if(!(drive->id->hw_config & 0x4000)) return 0; #endif /* CONFIG_IDEDMA_IVB */ + if (!(drive->id->hw_config & 0x2000)) + return 0; return 1; } diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 8afce4ceea3..68719314df3 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -345,16 +345,16 @@ static int ide_scan_pio_blacklist (char *model) /** * ide_get_best_pio_mode - get PIO mode from drive - * @driver: drive to consider + * @drive: drive to consider * @mode_wanted: preferred mode - * @max_mode: highest allowed - * @d: pio data + * @max_mode: highest allowed mode + * @d: PIO data * * This routine returns the recommended PIO settings for a given drive, * based on the drive->id information and the ide_pio_blacklist[]. - * This is used by most chipset support modules when "auto-tuning". * - * Drive PIO mode auto selection + * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. + * This is used by most chipset support modules when "auto-tuning". */ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_pio_data_t *d) @@ -367,6 +367,7 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p if (mode_wanted != 255) { pio_mode = mode_wanted; + use_iordy = (pio_mode > 2); } else if (!drive->id) { pio_mode = 0; } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { @@ -396,19 +397,12 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p } } -#if 0 - if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); -#endif - /* * Conservative "downgrade" for all pre-ATA2 drives */ if (pio_mode && pio_mode < 4) { pio_mode--; overridden = 1; -#if 0 - use_iordy = (pio_mode > 2); -#endif if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) cycle_time = 0; /* use standard timing */ } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 8afbd6cb94b..8f15c23aa70 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -31,8 +31,6 @@ * valid after probe time even with noprobe */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index b3c0818c5c6..dfbd7445852 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -126,8 +126,6 @@ #define REVISION "Revision: 7.00alpha2" #define VERSION "Id: ide.c 7.00a2 20020906" -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #define _IDE_C /* Tell ide.h it's really us */ #include <linux/module.h> @@ -1486,23 +1484,23 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m } #ifdef CONFIG_BLK_DEV_ALI14XX -static int __initdata probe_ali14xx; +extern int probe_ali14xx; extern int ali14xx_init(void); #endif #ifdef CONFIG_BLK_DEV_UMC8672 -static int __initdata probe_umc8672; +extern int probe_umc8672; extern int umc8672_init(void); #endif #ifdef CONFIG_BLK_DEV_DTC2278 -static int __initdata probe_dtc2278; +extern int probe_dtc2278; extern int dtc2278_init(void); #endif #ifdef CONFIG_BLK_DEV_HT6560B -static int __initdata probe_ht6560b; +extern int probe_ht6560b; extern int ht6560b_init(void); #endif #ifdef CONFIG_BLK_DEV_QD65XX -static int __initdata probe_qd65xx; +extern int probe_qd65xx; extern int qd65xx_init(void); #endif @@ -1580,7 +1578,7 @@ static int __init ide_setup(char *s) */ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { - "none", "noprobe", "nowerr", "cdrom", "serialize", + "none", "noprobe", "nowerr", "cdrom", "minus5", "autotune", "noautotune", "minus8", "swapdata", "bswap", "noflush", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; @@ -1608,9 +1606,6 @@ static int __init ide_setup(char *s) drive->ready_stat = 0; hwif->noprobe = 0; goto done; - case -5: /* "serialize" */ - printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); - goto do_serialize; case -6: /* "autotune" */ drive->autotune = IDE_TUNE_AUTO; goto obsolete_option; @@ -1671,7 +1666,7 @@ static int __init ide_setup(char *s) * (-8, -9, -10) are reserved to ease the hardcoding. */ static const char *ide_words[] = { - "noprobe", "serialize", "autotune", "noautotune", + "noprobe", "serialize", "minus3", "minus4", "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; @@ -1742,12 +1737,17 @@ static int __init ide_setup(char *s) hwif->chipset = mate->chipset = ide_4drives; mate->irq = hwif->irq; memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); - goto do_serialize; + hwif->mate = mate; + mate->mate = hwif; + hwif->serialized = mate->serialized = 1; + goto obsolete_option; } #endif /* CONFIG_BLK_DEV_4DRIVES */ case -10: /* minus10 */ case -9: /* minus9 */ case -8: /* minus8 */ + case -4: + case -3: goto bad_option; case -7: /* ata66 */ #ifdef CONFIG_BLK_DEV_IDEPCI @@ -1762,16 +1762,7 @@ static int __init ide_setup(char *s) case -5: /* "reset" */ hwif->reset = 1; goto obsolete_option; - case -4: /* "noautotune" */ - hwif->drives[0].autotune = IDE_TUNE_NOAUTO; - hwif->drives[1].autotune = IDE_TUNE_NOAUTO; - goto obsolete_option; - case -3: /* "autotune" */ - hwif->drives[0].autotune = IDE_TUNE_AUTO; - hwif->drives[1].autotune = IDE_TUNE_AUTO; - goto obsolete_option; case -2: /* "serialize" */ - do_serialize: hwif->mate = &ide_hwifs[hw^1]; hwif->mate->mate = hwif; hwif->serialized = hwif->mate->serialized = 1; @@ -1840,8 +1831,8 @@ static void __init probe_for_hwifs (void) #endif /* CONFIG_BLK_DEV_CMD640 */ #ifdef CONFIG_BLK_DEV_IDE_PMAC { - extern void pmac_ide_probe(void); - pmac_ide_probe(); + extern int pmac_ide_probe(void); + (void)pmac_ide_probe(); } #endif /* CONFIG_BLK_DEV_IDE_PMAC */ #ifdef CONFIG_BLK_DEV_GAYLE diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 9c544467cb7..91961aa0304 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -37,8 +37,6 @@ * mode 4 for a while now with no trouble.) -Derek */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -230,9 +228,17 @@ static int __init ali14xx_probe(void) return 0; } +int probe_ali14xx = 0; + +module_param_named(probe, probe_ali14xx, bool, 0); +MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets"); + /* Can be called directly from ide.c. */ int __init ali14xx_init(void) { + if (probe_ali14xx == 0) + goto out; + /* auto-detect IDE controller port */ if (findPort()) { if (ali14xx_probe()) @@ -240,6 +246,7 @@ int __init ali14xx_init(void) return 0; } printk(KERN_ERR "ali14xx: not found.\n"); +out: return -ENODEV; } diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index 3b1d33baaa2..0219ffa64db 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -4,8 +4,6 @@ * Copyright (C) 1996 Linus Torvalds & author (see below) */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -94,7 +92,7 @@ static void tune_dtc2278 (ide_drive_t *drive, u8 pio) HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; } -static int __init probe_dtc2278(void) +static int __init dtc2278_probe(void) { unsigned long flags; ide_hwif_t *hwif, *mate; @@ -145,10 +143,18 @@ static int __init probe_dtc2278(void) return 0; } +int probe_dtc2278 = 0; + +module_param_named(probe, probe_dtc2278, bool, 0); +MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); + /* Can be called directly from ide.c. */ int __init dtc2278_init(void) { - if (probe_dtc2278()) { + if (probe_dtc2278 == 0) + return -ENODEV; + + if (dtc2278_probe()) { printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); return -EBUSY; } diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 19ccd006f20..a2832643c52 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -36,8 +36,6 @@ #define HT6560B_VERSION "v0.07" -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -303,12 +301,20 @@ static void tune_ht6560b (ide_drive_t *drive, u8 pio) #endif } +int probe_ht6560b = 0; + +module_param_named(probe, probe_ht6560b, bool, 0); +MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); + /* Can be called directly from ide.c. */ int __init ht6560b_init(void) { ide_hwif_t *hwif, *mate; int t; + if (probe_ht6560b == 0) + return -ENODEV; + hwif = &ide_hwifs[0]; mate = &ide_hwifs[1]; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index a5023cdbdc5..b08c37c9f95 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -359,14 +359,17 @@ void ide_release(struct pcmcia_device *link) static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_FUNC_ID(4), PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ + PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ + PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), + PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */ + PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */ + PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */ PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index d3c3bc2640e..2fb8f50f129 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -16,8 +16,8 @@ * Please set local bus speed using kernel parameter idebus * for example, "idebus=33" stands for 33Mhz VLbus * To activate controller support, use "ide0=qd65xx" - * To enable tuning, use "ide0=autotune" - * To enable second channel tuning (qd6580 only), use "ide1=autotune" + * To enable tuning, use "hda=autotune hdb=autotune" + * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune" */ /* @@ -25,8 +25,6 @@ * Samuel Thibault <samuel.thibault@fnac.net> */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -490,9 +488,17 @@ static int __init qd_probe(int base) return 1; } +int probe_qd65xx = 0; + +module_param_named(probe, probe_qd65xx, bool, 0); +MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); + /* Can be called directly from ide.c. */ int __init qd65xx_init(void) { + if (probe_qd65xx == 0) + return -ENODEV; + if (qd_probe(0x30)) qd_probe(0xb0); if (ide_hwifs[0].chipset != ide_qd65xx && diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 6e2c58c5f6a..ca797445557 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -165,12 +165,21 @@ static int __init umc8672_probe(void) return 0; } +int probe_umc8672 = 0; + +module_param_named(probe, probe_umc8672, bool, 0); +MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); + /* Can be called directly from ide.c. */ int __init umc8672_init(void) { - if (umc8672_probe()) - return -ENODEV; - return 0; + if (probe_umc8672 == 0) + goto out; + + if (umc8672_probe() == 0) + return 0;; +out: + return -ENODEV;; } #ifdef MODULE diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 0a59d5ef159..b2dc028dc8c 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -29,8 +29,6 @@ * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE * Interface and Linux Device Driver" Application Note. */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 4debd18d52f..83e0aa65a43 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 + * linux/drivers/ide/pci/alim15x3.c Version 0.21 2007/02/03 * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer @@ -9,6 +9,7 @@ * May be copied or modified under the terms of the GNU General Public License * Copyright (C) 2002 Alan Cox <alan@redhat.com> * ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw> + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> * * (U)DMA capable version of ali 1533/1543(C), 1535(D) * @@ -280,15 +281,17 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count) #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ /** - * ali15x3_tune_drive - set up a drive + * ali15x3_tune_pio - set up chipset for PIO mode * @drive: drive to tune - * @pio: unused + * @pio: desired mode * - * Select the best PIO timing for the drive in question. Then - * program the controller for this drive set up + * Select the best PIO mode for the drive in question. + * Then program the controller for this mode. + * + * Returns the PIO mode programmed. */ -static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) +static u8 ali15x3_tune_pio (ide_drive_t *drive, u8 pio) { ide_pio_data_t d; ide_hwif_t *hwif = HWIF(drive); @@ -356,6 +359,22 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) */ + return pio; +} + +/** + * ali15x3_tune_drive - set up drive for PIO mode + * @drive: drive to tune + * @pio: desired mode + * + * Program the controller with the best PIO timing for the given drive. + * Then set up the drive itself. + */ + +static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) +{ + pio = ali15x3_tune_pio(drive, pio); + (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); } /** @@ -430,7 +449,7 @@ static u8 ali15x3_ratemask (ide_drive_t *drive) } /** - * ali15x3_tune_chipset - set up chiset for new speed + * ali15x3_tune_chipset - set up chipset/drive for new speed * @drive: drive to configure for * @xferspeed: desired speed * @@ -461,7 +480,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) pci_write_config_byte(dev, m5229_udma, tmpbyte); if (speed < XFER_SW_DMA_0) - ali15x3_tune_drive(drive, speed); + (void) ali15x3_tune_pio(drive, speed - XFER_PIO_0); } else { pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= (0x0f << ((1-unit) << 2)); diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 61b5f9c0b2f..dc43f009aca 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -98,7 +98,6 @@ * (patch courtesy of Zoltan Hidvegi) */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ #define CMD640_PREFETCH_MASKS 1 //#define CMD640_DUMP_REGS diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 49df27513da..b0d4825c56a 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -1,6 +1,6 @@ /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 * - * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 + * linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because @@ -12,6 +12,7 @@ * Copyright (C) 1998 David S. Miller (davem@redhat.com) * * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> */ #include <linux/module.h> @@ -262,43 +263,25 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ } /* - * Attempts to set the interface PIO mode. - * The preferred method of selecting PIO modes (e.g. mode 4) is - * "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are - * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. - * Called with 255 at boot time. + * This routine selects drive's best PIO mode, calculates setup/active/recovery + * counts, and then writes them into the chipset registers. */ - -static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted) +static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted) { int setup_time, active_time, recovery_time; int clock_time, pio_mode, cycle_time; u8 recovery_count2, cycle_count; int setup_count, active_count, recovery_count; int bus_speed = system_bus_clock(); - /*byte b;*/ ide_pio_data_t d; - switch (mode_wanted) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - /*set_prefetch_mode(index, mode_wanted);*/ - cmdprintk("%s: %sabled cmd640 prefetch\n", - drive->name, mode_wanted ? "en" : "dis"); - return; - } - - mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d); - pio_mode = d.pio_mode; + pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d); cycle_time = d.cycle_time; /* * I copied all this complicated stuff from cmd640.c and made a few * minor changes. For now I am just going to pray that it is correct. */ - if (pio_mode > 5) - pio_mode = 5; setup_time = ide_pio_timings[pio_mode].setup_time; active_time = ide_pio_timings[pio_mode].active_time; recovery_time = cycle_time - (setup_time + active_time); @@ -320,22 +303,33 @@ static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted) if (active_count > 16) active_count = 16; /* maximum allowed by cmd646 */ - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it - * (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ program_drive_counts (drive, setup_count, active_count, recovery_count); - cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, " + cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, " "clocks=%d/%d/%d\n", - drive->name, pio_mode, mode_wanted, cycle_time, + drive->name, mode_wanted, pio_mode, cycle_time, d.overridden ? " (overriding vendor mode)" : "", setup_count, active_count, recovery_count); + + return pio_mode; +} + +/* + * Attempts to set drive's PIO mode. + * Special cases are 8: prefetch off, 9: prefetch on (both never worked), + * and 255: auto-select best mode (used at boot time). + */ +static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio) +{ + /* + * Filter out the prefetch control values + * to prevent PIO5 from being programmed + */ + if (pio == 8 || pio == 9) + return; + + pio = cmd64x_tune_pio(drive, pio); + (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); } static u8 cmd64x_ratemask (ide_drive_t *drive) @@ -387,22 +381,6 @@ static u8 cmd64x_ratemask (ide_drive_t *drive) return mode; } -static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, u8 set_speed) -{ - u8 speed = 0x00; - u8 set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); - - cmd64x_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} - -static void config_chipset_for_pio (ide_drive_t *drive, u8 set_speed) -{ - config_cmd64x_chipset_for_pio(drive, set_speed); -} - static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -414,7 +392,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); - if (speed > XFER_PIO_4) { + if (speed >= XFER_SW_DMA_0) { (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); regD &= ~(unit ? 0x40 : 0x20); @@ -438,17 +416,20 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; - case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; - case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; - case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; - case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; - case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; + case XFER_PIO_5: + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + (void) cmd64x_tune_pio(drive, speed - XFER_PIO_0); + break; default: return 1; } - if (speed > XFER_PIO_4) { + if (speed >= XFER_SW_DMA_0) { (void) pci_write_config_byte(dev, pciU, regU); regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); @@ -461,8 +442,6 @@ static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); - config_chipset_for_pio(drive, !speed); - if (!speed) return 0; @@ -478,7 +457,7 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive) return 0; if (ide_use_fast_pio(drive)) - config_chipset_for_pio(drive, 1); + cmd64x_tune_drive(drive, 255); return -1; } @@ -679,14 +658,13 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - hwif->tuneproc = &cmd64x_tuneproc; + hwif->tuneproc = &cmd64x_tune_drive; hwif->speedproc = &cmd64x_tune_chipset; - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) return; - } hwif->atapi_dma = 1; diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index e2672fc65d3..d4b753e7011 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -122,7 +122,7 @@ static struct pci_driver driver = { static int delkin_cb_init (void) { - return pci_module_init(&driver); + return pci_register_driver(&driver); } static void diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index b408c6c517e..f2c5a141ca1 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -21,8 +21,6 @@ * are deemed to be part of the source code. */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 9ca60dd2185..aede7eee924 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -57,7 +57,7 @@ * There is a 25/33MHz switch in configuration * register, but driver is written for use at any frequency which get * (use idebus=xx to select PCI bus speed). - * Use ide0=autotune for automatical tune of the PIO modes. + * Use hda=autotune and hdb=autotune for automatical tune of the PIO modes. * If you get strange results, do not use this and set PIO manually * by hdparm. * @@ -87,7 +87,6 @@ * 0.5 doesn't work. */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ #define OPTI621_DEBUG /* define for debug messages */ #include <linux/types.h> diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 569822f4cf5..061d300ab8b 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -1,10 +1,10 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.46 December 3, 2006 + * linux/drivers/ide/pci/piix.c Version 0.47 February 8, 2007 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat Inc <alan@redhat.com> - * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com> + * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> * * May be copied or modified under the terms of the GNU General Public License * @@ -205,14 +205,13 @@ static u8 piix_dma_2_pio (u8 xfer_rate) { } /** - * piix_tune_drive - tune a drive attached to a PIIX + * piix_tune_pio - tune PIIX for PIO mode * @drive: drive to tune * @pio: desired PIO mode * - * Set the interface PIO mode based upon the settings done by AMI BIOS - * (might be useful if drive is not registered in CMOS for any reason). + * Set the interface PIO mode based upon the settings done by AMI BIOS. */ -static void piix_tune_drive (ide_drive_t *drive, u8 pio) +static void piix_tune_pio (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; @@ -233,8 +232,6 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { 2, 1 }, { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - /* * Master vs slave is synchronized above us but the slave register is * shared by the two hwifs so the corner case of two slave timeouts in @@ -253,19 +250,20 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) master_data |= 0x4000; master_data &= ~0x0070; if (pio > 1) { - /* enable PPE, IE and TIME */ - master_data = master_data | (control << 4); + /* Set PPE, IE and TIME */ + master_data |= control << 4; } pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); + slave_data &= hwif->channel ? 0x0f : 0xf0; + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << + (hwif->channel ? 4 : 0); } else { master_data &= ~0x3307; if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | control; + master_data |= control; } - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); } pci_write_config_word(dev, master_port, master_data); if (is_slave) @@ -274,6 +272,21 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) } /** + * piix_tune_drive - tune a drive attached to PIIX + * @drive: drive to tune + * @pio: desired PIO mode + * + * Set the drive's PIO mode (might be useful if drive is not registered + * in CMOS for any reason). + */ +static void piix_tune_drive (ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + piix_tune_pio(drive, pio); + (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); +} + +/** * piix_tune_chipset - tune a PIIX interface * @drive: IDE drive to tune * @xferspeed: speed to configure @@ -348,8 +361,8 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } - piix_tune_drive(drive, piix_dma_2_pio(speed)); - return (ide_config_drive_speed(drive, speed)); + piix_tune_pio(drive, piix_dma_2_pio(speed)); + return ide_config_drive_speed(drive, speed); } /** @@ -392,9 +405,7 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) return 0; if (ide_use_fast_pio(drive)) - /* Find best PIO mode. */ - piix_tune_chipset(drive, XFER_PIO_0 + - ide_get_best_pio_mode(drive, 255, 4, NULL)); + piix_tune_drive(drive, 255); return -1; } diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index c1855311052..f8c95469014 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -15,8 +15,6 @@ * Dunno if this fixes both ports, or only the primary port (?). */ -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 7b4c189a9d9..71eccdf5f81 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -26,6 +26,11 @@ * If you have strange problems with nVidia chipset systems please * see the SI support documentation and update your system BIOS * if neccessary + * + * The Dell DRAC4 has some interesting features including effectively hot + * unplugging/replugging the virtual CD interface when the DRAC is reset. + * This often causes drivers/ide/siimage to panic but is ok with the rather + * smarter code in libata. */ #include <linux/types.h> diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index ae7eb58d961..852ccb36da1 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,8 +1,8 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.13 December 30, 2006 + * linux/drivers/ide/pci/slc90e66.c Version 0.14 February 8, 2007 * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com> + * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> * * This is a look-alike variation of the ICH0 PIIX4 Ultra-66, * but this keeps the ISA-Bridge and slots alive. @@ -57,11 +57,7 @@ static u8 slc90e66_dma_2_pio (u8 xfer_rate) { } } -/* - * Based on settings done by AMI BIOS - * (might be useful if drive is not registered in CMOS for any reason). - */ -static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) +static void slc90e66_tune_pio (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; @@ -80,7 +76,6 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) { 2, 1 }, { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); spin_lock_irqsave(&ide_lock, flags); pci_read_config_word(dev, master_port, &master_data); @@ -94,19 +89,20 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) master_data |= 0x4000; master_data &= ~0x0070; if (pio > 1) { - /* enable PPE, IE and TIME */ - master_data = master_data | (control << 4); + /* Set PPE, IE and TIME */ + master_data |= control << 4; } pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); + slave_data &= hwif->channel ? 0x0f : 0xf0; + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << + (hwif->channel ? 4 : 0); } else { master_data &= ~0x3307; if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | control; + master_data |= control; } - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); } pci_write_config_word(dev, master_port, master_data); if (is_slave) @@ -114,6 +110,13 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) spin_unlock_irqrestore(&ide_lock, flags); } +static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + slc90e66_tune_pio(drive, pio); + (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); +} + static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -162,8 +165,8 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); } - slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed)); - return (ide_config_drive_speed(drive, speed)); + slc90e66_tune_pio(drive, slc90e66_dma_2_pio(speed)); + return ide_config_drive_speed(drive, speed); } static int slc90e66_config_drive_for_dma (ide_drive_t *drive) @@ -185,8 +188,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) return 0; if (ide_use_fast_pio(drive)) - (void)slc90e66_tune_chipset(drive, XFER_PIO_0 + - ide_get_best_pio_mode(drive, 255, 4, NULL)); + slc90e66_tune_drive(drive, 255); return -1; } diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 395d35253d5..071a030ec26 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -48,7 +48,7 @@ #include <asm/mediabay.h> #endif -#include "ide-timing.h" +#include "../ide-timing.h" #undef IDE_PMAC_DEBUG @@ -1551,19 +1551,34 @@ static struct pci_driver pmac_ide_pci_driver = { }; MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); -void __init -pmac_ide_probe(void) +int __init pmac_ide_probe(void) { + int error; + if (!machine_is(powermac)) - return; + return -ENODEV; #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST - pci_register_driver(&pmac_ide_pci_driver); - macio_register_driver(&pmac_ide_macio_driver); + error = pci_register_driver(&pmac_ide_pci_driver); + if (error) + goto out; + error = macio_register_driver(&pmac_ide_macio_driver); + if (error) { + pci_unregister_driver(&pmac_ide_pci_driver); + goto out; + } #else - macio_register_driver(&pmac_ide_macio_driver); - pci_register_driver(&pmac_ide_pci_driver); + error = macio_register_driver(&pmac_ide_macio_driver); + if (error) + goto out; + error = pci_register_driver(&pmac_ide_pci_driver); + if (error) { + macio_unregister_driver(&pmac_ide_macio_driver); + goto out; + } #endif +out: + return error; } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC @@ -1983,7 +1998,7 @@ static void pmac_ide_dma_host_off(ide_drive_t *drive) { } -static int pmac_ide_dma_host_on(ide_drive_t *drive) +static void pmac_ide_dma_host_on(ide_drive_t *drive) { } diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/ppc/scc_pata.c index de64b022478..f84bf791f72 100644 --- a/drivers/ide/ppc/scc_pata.c +++ b/drivers/ide/ppc/scc_pata.c @@ -509,6 +509,32 @@ static int scc_ide_dma_end(ide_drive_t * drive) return __ide_dma_end(drive); } +/* returns 1 if dma irq issued, 0 otherwise */ +static int scc_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = hwif->INB(hwif->dma_status); + + /* return 1 if INTR asserted */ + if ((dma_stat & 4) == 4) + return 1; + + /* Workaround for PTERADD: emulate DMA_INTR when + * - IDE_STATUS[ERR] = 1 + * - INT_STATUS[INTRQ] = 1 + * - DMA_STATUS[IORACTA] = 1 + */ + if (in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT && + in_be32((void __iomem *)(hwif->dma_base + 0x014)) & INTSTS_INTRQ && + dma_stat & 1) + return 1; + + if (!drive->waiting_for_dma) + printk(KERN_WARNING "%s: (%s) called while not waiting\n", + drive->name, __FUNCTION__); + return 0; +} + /** * setup_mmio_scc - map CTRL/BMID region * @dev: PCI device we are configuring @@ -712,6 +738,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) hwif->speedproc = scc_tune_chipset; hwif->tuneproc = scc_tuneproc; hwif->ide_dma_check = scc_config_drive_for_dma; + hwif->ide_dma_test_irq = scc_dma_test_irq; hwif->drives[0].autotune = IDE_TUNE_AUTO; hwif->drives[1].autotune = IDE_TUNE_AUTO; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64509689fa6..f17e9c7d4b3 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -215,14 +215,16 @@ config KEYBOARD_AAED2000 module will be called aaed2000_kbd. config KEYBOARD_GPIO - tristate "Buttons on CPU GPIOs (PXA)" - depends on (ARCH_SA1100 || ARCH_PXA || ARCH_S3C2410) + tristate "GPIO Buttons" + depends on GENERIC_GPIO help This driver implements support for buttons connected - directly to GPIO pins of SA1100, PXA or S3C24xx CPUs. + to GPIO pins of various CPUs (and some other chips). Say Y here if your device has buttons connected - directly to GPIO pins of the CPU. + directly to such GPIO pins. Your board-specific + setup logic must also provide a platform device, + with configuration data saying which GPIOs are used. To compile this driver as a module, choose M here: the module will be called gpio-keys. diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index fa03a00b4c6..ccf6df387b6 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -23,11 +23,9 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/irq.h> +#include <linux/gpio_keys.h> #include <asm/gpio.h> -#include <asm/arch/hardware.h> - -#include <asm/hardware/gpio_keys.h> static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 8b6c9a431ff..c921d6c522f 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -2,13 +2,25 @@ # Config.in for the CAPI subsystem # config ISDN_DRV_AVMB1_VERBOSE_REASON - bool "Verbose reason code reporting (kernel size +=7K)" + bool "Verbose reason code reporting" depends on ISDN_CAPI + default y help - If you say Y here, the AVM B1 driver will give verbose reasons for + If you say Y here, the CAPI drivers will give verbose reasons for disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. +config CAPI_TRACE + bool "CAPI trace support" + depends on ISDN_CAPI + default y + help + If you say Y here, the kernelcapi driver can make verbose traces + of CAPI messages. This feature can be enabled/disabled via IOCTL for + every controler (default disabled). + This will increase the size of the kernelcapi module by 20 KB. + If unsure, say Y. + config ISDN_CAPI_MIDDLEWARE bool "CAPI2.0 Middleware support (EXPERIMENTAL)" depends on ISDN_CAPI && EXPERIMENTAL diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 2a49cea0a22..23b6f7bc16b 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -990,6 +990,7 @@ static void handle_plci(_cmsg * cmsg) capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); capidrv_plci *plcip; isdn_ctrl cmd; + _cdebbuf *cdb; if (!card) { printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", @@ -1122,8 +1123,15 @@ static void handle_plci(_cmsg * cmsg) break; } } - printk(KERN_ERR "capidrv-%d: %s\n", - card->contrnr, capi_cmsg2str(cmsg)); + cdb = capi_cmsg2str(cmsg); + if (cdb) { + printk(KERN_WARNING "capidrv-%d: %s\n", + card->contrnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n", + card->contrnr, cmsg->InfoNumber); + break; case CAPI_CONNECT_ACTIVE_CONF: /* plci */ @@ -1371,10 +1379,18 @@ static _cmsg s_cmsg; static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 3) - printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", - ap->applid, capi_cmsg2str(&s_cmsg)); - + if (debugmode > 3) { + _cdebbuf *cdb = capi_cmsg2str(&s_cmsg); + + if (cdb) { + printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__, + ap->applid, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "%s: applid=%d %s not traced\n", + __FUNCTION__, ap->applid, + capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand)); + } if (s_cmsg.Command == CAPI_DATA_B3 && s_cmsg.Subcommand == CAPI_IND) { handle_data(&s_cmsg, skb); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index c1b21552fc0..ad1e2702c2d 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd) /*-------------------------------------------------------*/ + +#ifdef CONFIG_CAPI_TRACE + /*-------------------------------------------------------*/ static char *pnames[] = @@ -703,44 +706,77 @@ static char *pnames[] = }; -static char buf[8192]; -static char *p = NULL; #include <stdarg.h> /*-------------------------------------------------------*/ -static void bufprint(char *fmt,...) +static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...) { va_list f; + size_t n,r; + + if (!cdb) + return NULL; va_start(f, fmt); - vsprintf(p, fmt, f); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); va_end(f); - p += strlen(p); + if (n >= r) { + /* truncated, need bigger buffer */ + size_t ns = 2 * cdb->size; + u_char *nb; + + while ((ns - cdb->pos) <= n) + ns *= 2; + nb = kmalloc(ns, GFP_ATOMIC); + if (!nb) { + cdebbuf_free(cdb); + return NULL; + } + memcpy(nb, cdb->buf, cdb->pos); + kfree(cdb->buf); + nb[cdb->pos] = 0; + cdb->buf = nb; + cdb->p = cdb->buf + cdb->pos; + cdb->size = ns; + va_start(f, fmt); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); + va_end(f); + } + cdb->p += n; + cdb->pos += n; + return cdb; } -static void printstructlen(u8 * m, unsigned len) +static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len) { unsigned hex = 0; + + if (!cdb) + return NULL; for (; len; len--, m++) if (isalnum(*m) || *m == ' ') { if (hex) - bufprint(">"); - bufprint("%c", *m); + cdb = bufprint(cdb, ">"); + cdb = bufprint(cdb, "%c", *m); hex = 0; } else { if (!hex) - bufprint("<%02x", *m); + cdb = bufprint(cdb, "<%02x", *m); else - bufprint(" %02x", *m); + cdb = bufprint(cdb, " %02x", *m); hex = 1; } if (hex) - bufprint(">"); + cdb = bufprint(cdb, ">"); + return cdb; } -static void printstruct(u8 * m) +static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m) { unsigned len; + if (m[0] != 0xff) { len = m[0]; m += 1; @@ -748,42 +784,45 @@ static void printstruct(u8 * m) len = ((u16 *) (m + 1))[0]; m += 3; } - printstructlen(m, len); + cdb = printstructlen(cdb, m, len); + return cdb; } /*-------------------------------------------------------*/ #define NAME (pnames[cmsg->par[cmsg->p]]) -static void protocol_message_2_pars(_cmsg * cmsg, int level) +static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level) { for (; TYP != _CEND; cmsg->p++) { int slen = 29 + 3 - level; int i; - bufprint(" "); + if (!cdb) + return NULL; + cdb = bufprint(cdb, " "); for (i = 0; i < level - 1; i++) - bufprint(" "); + cdb = bufprint(cdb, " "); switch (TYP) { case _CBYTE: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); cmsg->l++; break; case _CWORD: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); cmsg->l += 2; break; case _CDWORD: - bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); cmsg->l += 4; break; case _CSTRUCT: - bufprint("%-*s = ", slen, NAME); + cdb = bufprint(cdb, "%-*s = ", slen, NAME); if (cmsg->m[cmsg->l] == '\0') - bufprint("default"); + cdb = bufprint(cdb, "default"); else - printstruct(cmsg->m + cmsg->l); - bufprint("\n"); + cdb = printstruct(cdb, cmsg->m + cmsg->l); + cdb = bufprint(cdb, "\n"); if (cmsg->m[cmsg->l] != 0xff) cmsg->l += 1 + cmsg->m[cmsg->l]; else @@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level) case _CMSTRUCT: /*----- Metastruktur 0 -----*/ if (cmsg->m[cmsg->l] == '\0') { - bufprint("%-*s = default\n", slen, NAME); + cdb = bufprint(cdb, "%-*s = default\n", slen, NAME); cmsg->l++; jumpcstruct(cmsg); } else { char *name = NAME; unsigned _l = cmsg->l; - bufprint("%-*s\n", slen, name); + cdb = bufprint(cdb, "%-*s\n", slen, name); cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; cmsg->p++; - protocol_message_2_pars(cmsg, level + 1); + cdb = protocol_message_2_pars(cdb, cmsg, level + 1); } break; } } + return cdb; } /*-------------------------------------------------------*/ -char *capi_message2str(u8 * msg) + +static _cdebbuf *g_debbuf; +static u_long g_debbuf_lock; +static _cmsg *g_cmsg; + +_cdebbuf *cdebbuf_alloc(void) { + _cdebbuf *cdb; + + if (likely(!test_and_set_bit(1, &g_debbuf_lock))) { + cdb = g_debbuf; + goto init; + } else + cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC); + if (!cdb) + return NULL; + cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC); + if (!cdb->buf) { + kfree(cdb); + return NULL; + } + cdb->size = CDEBUG_SIZE; +init: + cdb->buf[0] = 0; + cdb->p = cdb->buf; + cdb->pos = 0; + return cdb; +} - _cmsg cmsg; - p = buf; - p[0] = 0; +void cdebbuf_free(_cdebbuf *cdb) +{ + if (likely(cdb == g_debbuf)) { + test_and_clear_bit(1, &g_debbuf_lock); + return; + } + if (likely(cdb)) + kfree(cdb->buf); + kfree(cdb); +} - cmsg.m = msg; - cmsg.l = 8; - cmsg.p = 0; - byteTRcpy(cmsg.m + 4, &cmsg.Command); - byteTRcpy(cmsg.m + 5, &cmsg.Subcommand); - cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)]; - bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", - mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], +_cdebbuf *capi_message2str(u8 * msg) +{ + _cdebbuf *cdb; + _cmsg *cmsg; + + cdb = cdebbuf_alloc(); + if (unlikely(!cdb)) + return NULL; + if (likely(cdb == g_debbuf)) + cmsg = g_cmsg; + else + cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC); + if (unlikely(!cmsg)) { + cdebbuf_free(cdb); + return NULL; + } + cmsg->m = msg; + cmsg->l = 8; + cmsg->p = 0; + byteTRcpy(cmsg->m + 4, &cmsg->Command); + byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); + cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; + + cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n", + mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((unsigned short *) msg)[1], ((unsigned short *) msg)[3], ((unsigned short *) msg)[0]); - protocol_message_2_pars(&cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + if (unlikely(cmsg != g_cmsg)) + kfree(cmsg); + return cdb; } -char *capi_cmsg2str(_cmsg * cmsg) +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) { - p = buf; - p[0] = 0; + _cdebbuf *cdb; + + cdb = cdebbuf_alloc(); + if (!cdb) + return NULL; cmsg->l = 8; cmsg->p = 0; - bufprint("%s ID=%03d #0x%04x LEN=%04d\n", + cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((u16 *) cmsg->m)[1], ((u16 *) cmsg->m)[3], ((u16 *) cmsg->m)[0]); - protocol_message_2_pars(cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + return cdb; } +int __init cdebug_init(void) +{ + g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL); + if (!g_cmsg) + return ENOMEM; + g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL); + if (!g_debbuf) { + kfree(g_cmsg); + return ENOMEM; + } + g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL); + if (!g_debbuf->buf) { + kfree(g_cmsg); + kfree(g_debbuf); + return ENOMEM;; + } + g_debbuf->size = CDEBUG_GSIZE; + g_debbuf->buf[0] = 0; + g_debbuf->p = g_debbuf->buf; + g_debbuf->pos = 0; + return 0; +} + +void __exit cdebug_exit(void) +{ + if (g_debbuf) + kfree(g_debbuf->buf); + kfree(g_debbuf); + kfree(g_cmsg); +} + +#else /* !CONFIG_CAPI_TRACE */ + +static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0}; + +_cdebbuf *capi_message2str(u8 * msg) +{ + return &g_debbuf; +} + +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) +{ + return &g_debbuf; +} + +_cdebbuf *cdebbuf_alloc(void) +{ + return &g_debbuf; +} + +void cdebbuf_free(_cdebbuf *cdb) +{ +} + +int __init cdebug_init(void) +{ + return 0; +} + +void __exit cdebug_exit(void) +{ +} + +#endif + +EXPORT_SYMBOL(cdebbuf_alloc); +EXPORT_SYMBOL(cdebbuf_free); EXPORT_SYMBOL(capi_cmsg2message); EXPORT_SYMBOL(capi_message2cmsg); EXPORT_SYMBOL(capi_cmsg_header); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 783a2552631..3ed34f7a1c4 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -276,10 +276,17 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s int showctl = 0; u8 cmd, subcmd; unsigned long flags; + _cdebbuf *cdb; if (card->cardstate != CARD_RUNNING) { - printk(KERN_INFO "kcapi: controller %d not active, got: %s", - card->cnr, capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", + card->cnr); goto error; } @@ -295,15 +302,21 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", - (unsigned long) card->cnr, - CAPIMSG_APPID(skb->data), + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", + card->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", - (unsigned long) card->cnr, - capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: got [%03d] %s\n", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", + card->cnr, CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } } @@ -312,8 +325,15 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); if ((!ap) || (ap->release_in_progress)) { read_unlock_irqrestore(&application_lock, flags); - printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", - CAPIMSG_APPID(skb->data), capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", + CAPIMSG_APPID(skb->data), cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n", + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd)); goto error; } skb_queue_tail(&ap->recv_queue, skb); @@ -332,7 +352,7 @@ void capi_ctr_ready(struct capi_ctr * card) { card->cardstate = CARD_RUNNING; - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", + printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", card->cnr, card->name); notify_push(KCI_CONTRUP, card->cnr, 0, 0); @@ -364,7 +384,7 @@ void capi_ctr_reseted(struct capi_ctr * card) capi_ctr_put(card); } - printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr); + printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); } @@ -374,7 +394,7 @@ EXPORT_SYMBOL(capi_ctr_reseted); void capi_ctr_suspend_output(struct capi_ctr *card) { if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); card->blocked = 1; } } @@ -384,7 +404,7 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); void capi_ctr_resume_output(struct capi_ctr *card) { if (card->blocked) { - printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); card->blocked = 0; } } @@ -432,7 +452,7 @@ attach_capi_ctr(struct capi_ctr *card) } ncards++; - printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", card->cnr, card->name); return 0; } @@ -451,7 +471,7 @@ int detach_capi_ctr(struct capi_ctr *card) card->procent = NULL; } capi_cards[card->cnr - 1] = NULL; - printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", card->cnr, card->name); return 0; @@ -623,17 +643,25 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n", + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", CAPIMSG_CONTROLLER(skb->data), CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: put [%#x] %s\n", - CAPIMSG_CONTROLLER(skb->data), - capi_message2str(skb->data)); + _cdebbuf *cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: put [%03d] %s\n", + CAPIMSG_CONTROLLER(skb->data), + cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n", + CAPIMSG_CONTROLLER(skb->data), + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } - } return card->send_message(card, skb); } @@ -894,7 +922,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) return -ESRCH; card->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr %d set trace=%d\n", + printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", card->cnr, card->traceflag); return 0; } @@ -967,7 +995,11 @@ static int __init kcapi_init(void) { char *p; char rev[32]; + int ret; + ret = cdebug_init(); + if (ret) + return ret; kcapi_proc_init(); if ((p = strchr(revision, ':')) != 0 && p[1]) { @@ -988,6 +1020,7 @@ static void __exit kcapi_exit(void) /* make sure all notifiers are finished */ flush_scheduled_work(); + cdebug_exit(); } module_init(kcapi_init); diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index 5158be0b7ab..e9d3189f56b 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,8 +1,9 @@ gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o usb_gigaset-y := usb-gigaset.o -bas_gigaset-y := bas-gigaset.o isocdata.o ser_gigaset-y := ser-gigaset.o +bas_gigaset-y := bas-gigaset.o isocdata.o -obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o +obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o +obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o +obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o +obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index f2f108fcec4..00a3be5b862 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -13,11 +13,6 @@ * ===================================================================== */ -/* not set by Kbuild when building both ser_gigaset and usb_gigaset */ -#ifndef KBUILD_MODNAME -#define KBUILD_MODNAME "asy_gigaset" -#endif - #include "gigaset.h" #include <linux/crc-ccitt.h> #include <linux/bitrev.h> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 04574a9d443..0d122bf889d 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -14,6 +14,7 @@ #include "vmx.h" #include <linux/kvm.h> +#include <linux/kvm_para.h> #define CR0_PE_MASK (1ULL << 0) #define CR0_TS_MASK (1ULL << 3) @@ -237,6 +238,9 @@ struct kvm_vcpu { unsigned long cr0; unsigned long cr2; unsigned long cr3; + gpa_t para_state_gpa; + struct page *para_state_page; + gpa_t hypercall_gpa; unsigned long cr4; unsigned long cr8; u64 pdptrs[4]; /* pae */ @@ -305,6 +309,7 @@ struct kvm { int busy; unsigned long rmap_overflow; struct list_head vm_list; + struct file *filp; }; struct kvm_stat { @@ -339,7 +344,7 @@ struct kvm_arch_ops { int (*vcpu_create)(struct kvm_vcpu *vcpu); void (*vcpu_free)(struct kvm_vcpu *vcpu); - struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); + void (*vcpu_load)(struct kvm_vcpu *vcpu); void (*vcpu_put)(struct kvm_vcpu *vcpu); void (*vcpu_decache)(struct kvm_vcpu *vcpu); @@ -382,6 +387,8 @@ struct kvm_arch_ops { int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run); int (*vcpu_setup)(struct kvm_vcpu *vcpu); void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); + void (*patch_hypercall)(struct kvm_vcpu *vcpu, + unsigned char *hypercall_addr); }; extern struct kvm_stat kvm_stat; @@ -476,6 +483,8 @@ void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes); int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu); +int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run); + static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code) { @@ -523,7 +532,7 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) { struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); - return (struct kvm_mmu_page *)page->private; + return (struct kvm_mmu_page *)page_private(page); } static inline u16 read_fs(void) diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index af866147ff2..a163bca3897 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -20,6 +20,7 @@ #include <linux/kvm.h> #include <linux/module.h> #include <linux/errno.h> +#include <linux/magic.h> #include <asm/processor.h> #include <linux/percpu.h> #include <linux/gfp.h> @@ -36,6 +37,9 @@ #include <asm/desc.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/mount.h> #include "x86_emulate.h" #include "segment_descriptor.h" @@ -72,6 +76,8 @@ static struct kvm_stats_debugfs_item { static struct dentry *debugfs_dir; +struct vfsmount *kvmfs_mnt; + #define MAX_IO_MSRS 256 #define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL @@ -90,6 +96,58 @@ struct segment_descriptor_64 { #endif +static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, + unsigned long arg); + +static struct inode *kvmfs_inode(struct file_operations *fops) +{ + int error = -ENOMEM; + struct inode *inode = new_inode(kvmfs_mnt->mnt_sb); + + if (!inode) + goto eexit_1; + + inode->i_fop = fops; + + /* + * Mark the inode dirty from the very beginning, + * that way it will never be moved to the dirty + * list because mark_inode_dirty() will think + * that it already _is_ on the dirty list. + */ + inode->i_state = I_DIRTY; + inode->i_mode = S_IRUSR | S_IWUSR; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + return inode; + +eexit_1: + return ERR_PTR(error); +} + +static struct file *kvmfs_file(struct inode *inode, void *private_data) +{ + struct file *file = get_empty_filp(); + + if (!file) + return ERR_PTR(-ENFILE); + + file->f_path.mnt = mntget(kvmfs_mnt); + file->f_path.dentry = d_alloc_anon(inode); + if (!file->f_path.dentry) + return ERR_PTR(-ENOMEM); + file->f_mapping = inode->i_mapping; + + file->f_pos = 0; + file->f_flags = O_RDWR; + file->f_op = inode->i_fop; + file->f_mode = FMODE_READ | FMODE_WRITE; + file->f_version = 0; + file->private_data = private_data; + return file; +} + unsigned long segment_base(u16 selector) { struct descriptor_table gdt; @@ -126,10 +184,8 @@ static inline int valid_vcpu(int n) return likely(n >= 0 && n < KVM_MAX_VCPUS); } -int kvm_read_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *dest) +int kvm_read_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, + void *dest) { unsigned char *host_buf = dest; unsigned long req_size = size; @@ -161,10 +217,8 @@ int kvm_read_guest(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(kvm_read_guest); -int kvm_write_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *data) +int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, + void *data) { unsigned char *host_buf = data; unsigned long req_size = size; @@ -174,12 +228,15 @@ int kvm_write_guest(struct kvm_vcpu *vcpu, unsigned now; unsigned offset; hva_t guest_buf; + gfn_t gfn; paddr = gva_to_hpa(vcpu, addr); if (is_error_hpa(paddr)) break; + gfn = vcpu->mmu.gva_to_gpa(vcpu, addr) >> PAGE_SHIFT; + mark_page_dirty(vcpu->kvm, gfn); guest_buf = (hva_t)kmap_atomic( pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0); offset = addr & ~PAGE_MASK; @@ -195,24 +252,30 @@ int kvm_write_guest(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(kvm_write_guest); -static int vcpu_slot(struct kvm_vcpu *vcpu) +/* + * Switches to specified vcpu, until a matching vcpu_put() + */ +static void vcpu_load(struct kvm_vcpu *vcpu) { - return vcpu - vcpu->kvm->vcpus; + mutex_lock(&vcpu->mutex); + kvm_arch_ops->vcpu_load(vcpu); } /* - * Switches to specified vcpu, until a matching vcpu_put() + * Switches to specified vcpu, until a matching vcpu_put(). Will return NULL + * if the slot is not populated. */ -static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot) +static struct kvm_vcpu *vcpu_load_slot(struct kvm *kvm, int slot) { - struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot]; + struct kvm_vcpu *vcpu = &kvm->vcpus[slot]; mutex_lock(&vcpu->mutex); - if (unlikely(!vcpu->vmcs)) { + if (!vcpu->vmcs) { mutex_unlock(&vcpu->mutex); return NULL; } - return kvm_arch_ops->vcpu_load(vcpu); + kvm_arch_ops->vcpu_load(vcpu); + return vcpu; } static void vcpu_put(struct kvm_vcpu *vcpu) @@ -221,13 +284,13 @@ static void vcpu_put(struct kvm_vcpu *vcpu) mutex_unlock(&vcpu->mutex); } -static int kvm_dev_open(struct inode *inode, struct file *filp) +static struct kvm *kvm_create_vm(void) { struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); int i; if (!kvm) - return -ENOMEM; + return ERR_PTR(-ENOMEM); spin_lock_init(&kvm->lock); INIT_LIST_HEAD(&kvm->active_mmu_pages); @@ -243,7 +306,11 @@ static int kvm_dev_open(struct inode *inode, struct file *filp) list_add(&kvm->vm_list, &vm_list); spin_unlock(&kvm_lock); } - filp->private_data = kvm; + return kvm; +} + +static int kvm_dev_open(struct inode *inode, struct file *filp) +{ return 0; } @@ -281,9 +348,10 @@ static void kvm_free_physmem(struct kvm *kvm) static void kvm_free_vcpu(struct kvm_vcpu *vcpu) { - if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu))) + if (!vcpu->vmcs) return; + vcpu_load(vcpu); kvm_mmu_destroy(vcpu); vcpu_put(vcpu); kvm_arch_ops->vcpu_free(vcpu); @@ -299,14 +367,24 @@ static void kvm_free_vcpus(struct kvm *kvm) static int kvm_dev_release(struct inode *inode, struct file *filp) { - struct kvm *kvm = filp->private_data; + return 0; +} +static void kvm_destroy_vm(struct kvm *kvm) +{ spin_lock(&kvm_lock); list_del(&kvm->vm_list); spin_unlock(&kvm_lock); kvm_free_vcpus(kvm); kvm_free_physmem(kvm); kfree(kvm); +} + +static int kvm_vm_release(struct inode *inode, struct file *filp) +{ + struct kvm *kvm = filp->private_data; + + kvm_destroy_vm(kvm); return 0; } @@ -457,7 +535,7 @@ EXPORT_SYMBOL_GPL(set_cr4); void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) { if (is_long_mode(vcpu)) { - if ( cr3 & CR3_L_MODE_RESEVED_BITS) { + if (cr3 & CR3_L_MODE_RESEVED_BITS) { printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); inject_gp(vcpu); return; @@ -533,55 +611,11 @@ void fx_init(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(fx_init); -/* - * Creates some virtual cpus. Good luck creating more than one. - */ -static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n) +static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot) { - int r; - struct kvm_vcpu *vcpu; - - r = -EINVAL; - if (!valid_vcpu(n)) - goto out; - - vcpu = &kvm->vcpus[n]; - - mutex_lock(&vcpu->mutex); - - if (vcpu->vmcs) { - mutex_unlock(&vcpu->mutex); - return -EEXIST; - } - - vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf, - FX_IMAGE_ALIGN); - vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; - - r = kvm_arch_ops->vcpu_create(vcpu); - if (r < 0) - goto out_free_vcpus; - - r = kvm_mmu_create(vcpu); - if (r < 0) - goto out_free_vcpus; - - kvm_arch_ops->vcpu_load(vcpu); - r = kvm_mmu_setup(vcpu); - if (r >= 0) - r = kvm_arch_ops->vcpu_setup(vcpu); - vcpu_put(vcpu); - - if (r < 0) - goto out_free_vcpus; - - return 0; - -out_free_vcpus: - kvm_free_vcpu(vcpu); - mutex_unlock(&vcpu->mutex); -out: - return r; + spin_lock(&vcpu->kvm->lock); + kvm_mmu_slot_remove_write_access(vcpu, slot); + spin_unlock(&vcpu->kvm->lock); } /* @@ -590,8 +624,8 @@ out: * * Discontiguous memory is allowed, mostly for framebuffers. */ -static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm, - struct kvm_memory_region *mem) +static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, + struct kvm_memory_region *mem) { int r; gfn_t base_gfn; @@ -674,7 +708,7 @@ raced: | __GFP_ZERO); if (!new.phys_mem[i]) goto out_free; - new.phys_mem[i]->private = 0; + set_page_private(new.phys_mem[i],0); } } @@ -711,9 +745,11 @@ raced: for (i = 0; i < KVM_MAX_VCPUS; ++i) { struct kvm_vcpu *vcpu; - vcpu = vcpu_load(kvm, i); + vcpu = vcpu_load_slot(kvm, i); if (!vcpu) continue; + if (new.flags & KVM_MEM_LOG_DIRTY_PAGES) + do_remove_write_access(vcpu, mem->slot); kvm_mmu_reset_context(vcpu); vcpu_put(vcpu); } @@ -729,18 +765,11 @@ out: return r; } -static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot) -{ - spin_lock(&vcpu->kvm->lock); - kvm_mmu_slot_remove_write_access(vcpu, slot); - spin_unlock(&vcpu->kvm->lock); -} - /* * Get (and clear) the dirty memory log for a memory slot. */ -static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log) +static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, + struct kvm_dirty_log *log) { struct kvm_memory_slot *memslot; int r, i; @@ -765,21 +794,21 @@ static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm, if (!memslot->dirty_bitmap) goto out; - n = ALIGN(memslot->npages, 8) / 8; + n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; - for (i = 0; !any && i < n; ++i) + for (i = 0; !any && i < n/sizeof(long); ++i) any = memslot->dirty_bitmap[i]; r = -EFAULT; if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n)) goto out; - if (any) { cleared = 0; for (i = 0; i < KVM_MAX_VCPUS; ++i) { - struct kvm_vcpu *vcpu = vcpu_load(kvm, i); + struct kvm_vcpu *vcpu; + vcpu = vcpu_load_slot(kvm, i); if (!vcpu) continue; if (!cleared) { @@ -903,8 +932,9 @@ static int emulator_read_emulated(unsigned long addr, return X86EMUL_CONTINUE; else { gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); + if (gpa == UNMAPPED_GVA) - return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT; + return X86EMUL_PROPAGATE_FAULT; vcpu->mmio_needed = 1; vcpu->mmio_phys_addr = gpa; vcpu->mmio_size = bytes; @@ -928,6 +958,7 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, return 0; page = gfn_to_page(m, gpa >> PAGE_SHIFT); kvm_mmu_pre_write(vcpu, gpa, bytes); + mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT); virt = kmap_atomic(page, KM_USER0); memcpy(virt + offset_in_page(gpa), &val, bytes); kunmap_atomic(virt, KM_USER0); @@ -1142,6 +1173,42 @@ int emulate_instruction(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(emulate_instruction); +int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned long nr, a0, a1, a2, a3, a4, a5, ret; + + kvm_arch_ops->decache_regs(vcpu); + ret = -KVM_EINVAL; +#ifdef CONFIG_X86_64 + if (is_long_mode(vcpu)) { + nr = vcpu->regs[VCPU_REGS_RAX]; + a0 = vcpu->regs[VCPU_REGS_RDI]; + a1 = vcpu->regs[VCPU_REGS_RSI]; + a2 = vcpu->regs[VCPU_REGS_RDX]; + a3 = vcpu->regs[VCPU_REGS_RCX]; + a4 = vcpu->regs[VCPU_REGS_R8]; + a5 = vcpu->regs[VCPU_REGS_R9]; + } else +#endif + { + nr = vcpu->regs[VCPU_REGS_RBX] & -1u; + a0 = vcpu->regs[VCPU_REGS_RAX] & -1u; + a1 = vcpu->regs[VCPU_REGS_RCX] & -1u; + a2 = vcpu->regs[VCPU_REGS_RDX] & -1u; + a3 = vcpu->regs[VCPU_REGS_RSI] & -1u; + a4 = vcpu->regs[VCPU_REGS_RDI] & -1u; + a5 = vcpu->regs[VCPU_REGS_RBP] & -1u; + } + switch (nr) { + default: + ; + } + vcpu->regs[VCPU_REGS_RAX] = ret; + kvm_arch_ops->cache_regs(vcpu); + return 1; +} +EXPORT_SYMBOL_GPL(kvm_hypercall); + static u64 mk_cr_64(u64 curr_cr, u32 new_val) { return (curr_cr & ~((1ULL << 32) - 1)) | new_val; @@ -1208,6 +1275,75 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, } } +/* + * Register the para guest with the host: + */ +static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa) +{ + struct kvm_vcpu_para_state *para_state; + hpa_t para_state_hpa, hypercall_hpa; + struct page *para_state_page; + unsigned char *hypercall; + gpa_t hypercall_gpa; + + printk(KERN_DEBUG "kvm: guest trying to enter paravirtual mode\n"); + printk(KERN_DEBUG ".... para_state_gpa: %08Lx\n", para_state_gpa); + + /* + * Needs to be page aligned: + */ + if (para_state_gpa != PAGE_ALIGN(para_state_gpa)) + goto err_gp; + + para_state_hpa = gpa_to_hpa(vcpu, para_state_gpa); + printk(KERN_DEBUG ".... para_state_hpa: %08Lx\n", para_state_hpa); + if (is_error_hpa(para_state_hpa)) + goto err_gp; + + mark_page_dirty(vcpu->kvm, para_state_gpa >> PAGE_SHIFT); + para_state_page = pfn_to_page(para_state_hpa >> PAGE_SHIFT); + para_state = kmap_atomic(para_state_page, KM_USER0); + + printk(KERN_DEBUG ".... guest version: %d\n", para_state->guest_version); + printk(KERN_DEBUG ".... size: %d\n", para_state->size); + + para_state->host_version = KVM_PARA_API_VERSION; + /* + * We cannot support guests that try to register themselves + * with a newer API version than the host supports: + */ + if (para_state->guest_version > KVM_PARA_API_VERSION) { + para_state->ret = -KVM_EINVAL; + goto err_kunmap_skip; + } + + hypercall_gpa = para_state->hypercall_gpa; + hypercall_hpa = gpa_to_hpa(vcpu, hypercall_gpa); + printk(KERN_DEBUG ".... hypercall_hpa: %08Lx\n", hypercall_hpa); + if (is_error_hpa(hypercall_hpa)) { + para_state->ret = -KVM_EINVAL; + goto err_kunmap_skip; + } + + printk(KERN_DEBUG "kvm: para guest successfully registered.\n"); + vcpu->para_state_page = para_state_page; + vcpu->para_state_gpa = para_state_gpa; + vcpu->hypercall_gpa = hypercall_gpa; + + mark_page_dirty(vcpu->kvm, hypercall_gpa >> PAGE_SHIFT); + hypercall = kmap_atomic(pfn_to_page(hypercall_hpa >> PAGE_SHIFT), + KM_USER1) + (hypercall_hpa & ~PAGE_MASK); + kvm_arch_ops->patch_hypercall(vcpu, hypercall); + kunmap_atomic(hypercall, KM_USER1); + + para_state->ret = 0; +err_kunmap_skip: + kunmap_atomic(para_state, KM_USER0); + return 0; +err_gp: + return 1; +} + int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) { u64 data; @@ -1316,6 +1452,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) case MSR_IA32_MISC_ENABLE: vcpu->ia32_misc_enable_msr = data; break; + /* + * This is the 'probe whether the host is KVM' logic: + */ + case MSR_KVM_API_MAGIC: + return vcpu_register_para(vcpu, data); + default: printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); return 1; @@ -1338,8 +1480,7 @@ void kvm_resched(struct kvm_vcpu *vcpu) { vcpu_put(vcpu); cond_resched(); - /* Cannot fail - no vcpu unplug yet. */ - vcpu_load(vcpu->kvm, vcpu_slot(vcpu)); + vcpu_load(vcpu); } EXPORT_SYMBOL_GPL(kvm_resched); @@ -1361,17 +1502,11 @@ void save_msrs(struct vmx_msr_entry *e, int n) } EXPORT_SYMBOL_GPL(save_msrs); -static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run) +static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { - struct kvm_vcpu *vcpu; int r; - if (!valid_vcpu(kvm_run->vcpu)) - return -EINVAL; - - vcpu = vcpu_load(kvm, kvm_run->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); /* re-sync apic's tpr */ vcpu->cr8 = kvm_run->cr8; @@ -1394,16 +1529,10 @@ static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run) return r; } -static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs) +static int kvm_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, + struct kvm_regs *regs) { - struct kvm_vcpu *vcpu; - - if (!valid_vcpu(regs->vcpu)) - return -EINVAL; - - vcpu = vcpu_load(kvm, regs->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); kvm_arch_ops->cache_regs(vcpu); @@ -1440,16 +1569,10 @@ static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs) return 0; } -static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs) +static int kvm_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, + struct kvm_regs *regs) { - struct kvm_vcpu *vcpu; - - if (!valid_vcpu(regs->vcpu)) - return -EINVAL; - - vcpu = vcpu_load(kvm, regs->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); vcpu->regs[VCPU_REGS_RAX] = regs->rax; vcpu->regs[VCPU_REGS_RBX] = regs->rbx; @@ -1486,16 +1609,12 @@ static void get_segment(struct kvm_vcpu *vcpu, return kvm_arch_ops->get_segment(vcpu, var, seg); } -static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs) +static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) { - struct kvm_vcpu *vcpu; struct descriptor_table dt; - if (!valid_vcpu(sregs->vcpu)) - return -EINVAL; - vcpu = vcpu_load(kvm, sregs->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); get_segment(vcpu, &sregs->cs, VCPU_SREG_CS); get_segment(vcpu, &sregs->ds, VCPU_SREG_DS); @@ -1537,18 +1656,14 @@ static void set_segment(struct kvm_vcpu *vcpu, return kvm_arch_ops->set_segment(vcpu, var, seg); } -static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs) +static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) { - struct kvm_vcpu *vcpu; int mmu_reset_needed = 0; int i; struct descriptor_table dt; - if (!valid_vcpu(sregs->vcpu)) - return -EINVAL; - vcpu = vcpu_load(kvm, sregs->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); set_segment(vcpu, &sregs->ds, VCPU_SREG_DS); @@ -1654,20 +1769,14 @@ static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) * * @return number of msrs set successfully. */ -static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs, +static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs, struct kvm_msr_entry *entries, int (*do_msr)(struct kvm_vcpu *vcpu, unsigned index, u64 *data)) { - struct kvm_vcpu *vcpu; int i; - if (!valid_vcpu(msrs->vcpu)) - return -EINVAL; - - vcpu = vcpu_load(kvm, msrs->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); for (i = 0; i < msrs->nmsrs; ++i) if (do_msr(vcpu, entries[i].index, &entries[i].data)) @@ -1683,7 +1792,7 @@ static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs, * * @return number of msrs set successfully. */ -static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs, +static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs, int (*do_msr)(struct kvm_vcpu *vcpu, unsigned index, u64 *data), int writeback) @@ -1711,7 +1820,7 @@ static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs, if (copy_from_user(entries, user_msrs->entries, size)) goto out_free; - r = n = __msr_io(kvm, &msrs, entries, do_msr); + r = n = __msr_io(vcpu, &msrs, entries, do_msr); if (r < 0) goto out_free; @@ -1730,38 +1839,31 @@ out: /* * Translate a guest virtual address to a guest physical address. */ -static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr) +static int kvm_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, + struct kvm_translation *tr) { unsigned long vaddr = tr->linear_address; - struct kvm_vcpu *vcpu; gpa_t gpa; - vcpu = vcpu_load(kvm, tr->vcpu); - if (!vcpu) - return -ENOENT; - spin_lock(&kvm->lock); + vcpu_load(vcpu); + spin_lock(&vcpu->kvm->lock); gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr); tr->physical_address = gpa; tr->valid = gpa != UNMAPPED_GVA; tr->writeable = 1; tr->usermode = 0; - spin_unlock(&kvm->lock); + spin_unlock(&vcpu->kvm->lock); vcpu_put(vcpu); return 0; } -static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq) +static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, + struct kvm_interrupt *irq) { - struct kvm_vcpu *vcpu; - - if (!valid_vcpu(irq->vcpu)) - return -EINVAL; if (irq->irq < 0 || irq->irq >= 256) return -EINVAL; - vcpu = vcpu_load(kvm, irq->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); set_bit(irq->irq, vcpu->irq_pending); set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary); @@ -1771,17 +1873,12 @@ static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq) return 0; } -static int kvm_dev_ioctl_debug_guest(struct kvm *kvm, - struct kvm_debug_guest *dbg) +static int kvm_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, + struct kvm_debug_guest *dbg) { - struct kvm_vcpu *vcpu; int r; - if (!valid_vcpu(dbg->vcpu)) - return -EINVAL; - vcpu = vcpu_load(kvm, dbg->vcpu); - if (!vcpu) - return -ENOENT; + vcpu_load(vcpu); r = kvm_arch_ops->set_guest_debug(vcpu, dbg); @@ -1790,30 +1887,129 @@ static int kvm_dev_ioctl_debug_guest(struct kvm *kvm, return r; } -static long kvm_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) +static int kvm_vcpu_release(struct inode *inode, struct file *filp) { - struct kvm *kvm = filp->private_data; + struct kvm_vcpu *vcpu = filp->private_data; + + fput(vcpu->kvm->filp); + return 0; +} + +static struct file_operations kvm_vcpu_fops = { + .release = kvm_vcpu_release, + .unlocked_ioctl = kvm_vcpu_ioctl, + .compat_ioctl = kvm_vcpu_ioctl, +}; + +/* + * Allocates an inode for the vcpu. + */ +static int create_vcpu_fd(struct kvm_vcpu *vcpu) +{ + int fd, r; + struct inode *inode; + struct file *file; + + atomic_inc(&vcpu->kvm->filp->f_count); + inode = kvmfs_inode(&kvm_vcpu_fops); + if (IS_ERR(inode)) { + r = PTR_ERR(inode); + goto out1; + } + + file = kvmfs_file(inode, vcpu); + if (IS_ERR(file)) { + r = PTR_ERR(file); + goto out2; + } + + r = get_unused_fd(); + if (r < 0) + goto out3; + fd = r; + fd_install(fd, file); + + return fd; + +out3: + fput(file); +out2: + iput(inode); +out1: + fput(vcpu->kvm->filp); + return r; +} + +/* + * Creates some virtual cpus. Good luck creating more than one. + */ +static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) +{ + int r; + struct kvm_vcpu *vcpu; + + r = -EINVAL; + if (!valid_vcpu(n)) + goto out; + + vcpu = &kvm->vcpus[n]; + + mutex_lock(&vcpu->mutex); + + if (vcpu->vmcs) { + mutex_unlock(&vcpu->mutex); + return -EEXIST; + } + + vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf, + FX_IMAGE_ALIGN); + vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; + + r = kvm_arch_ops->vcpu_create(vcpu); + if (r < 0) + goto out_free_vcpus; + + r = kvm_mmu_create(vcpu); + if (r < 0) + goto out_free_vcpus; + + kvm_arch_ops->vcpu_load(vcpu); + r = kvm_mmu_setup(vcpu); + if (r >= 0) + r = kvm_arch_ops->vcpu_setup(vcpu); + vcpu_put(vcpu); + + if (r < 0) + goto out_free_vcpus; + + r = create_vcpu_fd(vcpu); + if (r < 0) + goto out_free_vcpus; + + return r; + +out_free_vcpus: + kvm_free_vcpu(vcpu); + mutex_unlock(&vcpu->mutex); +out: + return r; +} + +static long kvm_vcpu_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + struct kvm_vcpu *vcpu = filp->private_data; void __user *argp = (void __user *)arg; int r = -EINVAL; switch (ioctl) { - case KVM_GET_API_VERSION: - r = KVM_API_VERSION; - break; - case KVM_CREATE_VCPU: { - r = kvm_dev_ioctl_create_vcpu(kvm, arg); - if (r) - goto out; - break; - } case KVM_RUN: { struct kvm_run kvm_run; r = -EFAULT; if (copy_from_user(&kvm_run, argp, sizeof kvm_run)) goto out; - r = kvm_dev_ioctl_run(kvm, &kvm_run); + r = kvm_vcpu_ioctl_run(vcpu, &kvm_run); if (r < 0 && r != -EINTR) goto out; if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) { @@ -1825,10 +2021,8 @@ static long kvm_dev_ioctl(struct file *filp, case KVM_GET_REGS: { struct kvm_regs kvm_regs; - r = -EFAULT; - if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs)) - goto out; - r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs); + memset(&kvm_regs, 0, sizeof kvm_regs); + r = kvm_vcpu_ioctl_get_regs(vcpu, &kvm_regs); if (r) goto out; r = -EFAULT; @@ -1843,7 +2037,7 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs)) goto out; - r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs); + r = kvm_vcpu_ioctl_set_regs(vcpu, &kvm_regs); if (r) goto out; r = 0; @@ -1852,10 +2046,8 @@ static long kvm_dev_ioctl(struct file *filp, case KVM_GET_SREGS: { struct kvm_sregs kvm_sregs; - r = -EFAULT; - if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs)) - goto out; - r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs); + memset(&kvm_sregs, 0, sizeof kvm_sregs); + r = kvm_vcpu_ioctl_get_sregs(vcpu, &kvm_sregs); if (r) goto out; r = -EFAULT; @@ -1870,7 +2062,7 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs)) goto out; - r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs); + r = kvm_vcpu_ioctl_set_sregs(vcpu, &kvm_sregs); if (r) goto out; r = 0; @@ -1882,7 +2074,7 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&tr, argp, sizeof tr)) goto out; - r = kvm_dev_ioctl_translate(kvm, &tr); + r = kvm_vcpu_ioctl_translate(vcpu, &tr); if (r) goto out; r = -EFAULT; @@ -1897,7 +2089,7 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&irq, argp, sizeof irq)) goto out; - r = kvm_dev_ioctl_interrupt(kvm, &irq); + r = kvm_vcpu_ioctl_interrupt(vcpu, &irq); if (r) goto out; r = 0; @@ -1909,19 +2101,45 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&dbg, argp, sizeof dbg)) goto out; - r = kvm_dev_ioctl_debug_guest(kvm, &dbg); + r = kvm_vcpu_ioctl_debug_guest(vcpu, &dbg); if (r) goto out; r = 0; break; } + case KVM_GET_MSRS: + r = msr_io(vcpu, argp, get_msr, 1); + break; + case KVM_SET_MSRS: + r = msr_io(vcpu, argp, do_set_msr, 0); + break; + default: + ; + } +out: + return r; +} + +static long kvm_vm_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + struct kvm *kvm = filp->private_data; + void __user *argp = (void __user *)arg; + int r = -EINVAL; + + switch (ioctl) { + case KVM_CREATE_VCPU: + r = kvm_vm_ioctl_create_vcpu(kvm, arg); + if (r < 0) + goto out; + break; case KVM_SET_MEMORY_REGION: { struct kvm_memory_region kvm_mem; r = -EFAULT; if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem)) goto out; - r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem); + r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_mem); if (r) goto out; break; @@ -1932,16 +2150,112 @@ static long kvm_dev_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&log, argp, sizeof log)) goto out; - r = kvm_dev_ioctl_get_dirty_log(kvm, &log); + r = kvm_vm_ioctl_get_dirty_log(kvm, &log); if (r) goto out; break; } - case KVM_GET_MSRS: - r = msr_io(kvm, argp, get_msr, 1); + default: + ; + } +out: + return r; +} + +static struct page *kvm_vm_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type) +{ + struct kvm *kvm = vma->vm_file->private_data; + unsigned long pgoff; + struct kvm_memory_slot *slot; + struct page *page; + + *type = VM_FAULT_MINOR; + pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + slot = gfn_to_memslot(kvm, pgoff); + if (!slot) + return NOPAGE_SIGBUS; + page = gfn_to_page(slot, pgoff); + if (!page) + return NOPAGE_SIGBUS; + get_page(page); + return page; +} + +static struct vm_operations_struct kvm_vm_vm_ops = { + .nopage = kvm_vm_nopage, +}; + +static int kvm_vm_mmap(struct file *file, struct vm_area_struct *vma) +{ + vma->vm_ops = &kvm_vm_vm_ops; + return 0; +} + +static struct file_operations kvm_vm_fops = { + .release = kvm_vm_release, + .unlocked_ioctl = kvm_vm_ioctl, + .compat_ioctl = kvm_vm_ioctl, + .mmap = kvm_vm_mmap, +}; + +static int kvm_dev_ioctl_create_vm(void) +{ + int fd, r; + struct inode *inode; + struct file *file; + struct kvm *kvm; + + inode = kvmfs_inode(&kvm_vm_fops); + if (IS_ERR(inode)) { + r = PTR_ERR(inode); + goto out1; + } + + kvm = kvm_create_vm(); + if (IS_ERR(kvm)) { + r = PTR_ERR(kvm); + goto out2; + } + + file = kvmfs_file(inode, kvm); + if (IS_ERR(file)) { + r = PTR_ERR(file); + goto out3; + } + kvm->filp = file; + + r = get_unused_fd(); + if (r < 0) + goto out4; + fd = r; + fd_install(fd, file); + + return fd; + +out4: + fput(file); +out3: + kvm_destroy_vm(kvm); +out2: + iput(inode); +out1: + return r; +} + +static long kvm_dev_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int r = -EINVAL; + + switch (ioctl) { + case KVM_GET_API_VERSION: + r = KVM_API_VERSION; break; - case KVM_SET_MSRS: - r = msr_io(kvm, argp, do_set_msr, 0); + case KVM_CREATE_VM: + r = kvm_dev_ioctl_create_vm(); break; case KVM_GET_MSR_INDEX_LIST: { struct kvm_msr_list __user *user_msr_list = argp; @@ -1977,43 +2291,11 @@ out: return r; } -static struct page *kvm_dev_nopage(struct vm_area_struct *vma, - unsigned long address, - int *type) -{ - struct kvm *kvm = vma->vm_file->private_data; - unsigned long pgoff; - struct kvm_memory_slot *slot; - struct page *page; - - *type = VM_FAULT_MINOR; - pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; - slot = gfn_to_memslot(kvm, pgoff); - if (!slot) - return NOPAGE_SIGBUS; - page = gfn_to_page(slot, pgoff); - if (!page) - return NOPAGE_SIGBUS; - get_page(page); - return page; -} - -static struct vm_operations_struct kvm_dev_vm_ops = { - .nopage = kvm_dev_nopage, -}; - -static int kvm_dev_mmap(struct file *file, struct vm_area_struct *vma) -{ - vma->vm_ops = &kvm_dev_vm_ops; - return 0; -} - static struct file_operations kvm_chardev_ops = { .open = kvm_dev_open, .release = kvm_dev_release, .unlocked_ioctl = kvm_dev_ioctl, .compat_ioctl = kvm_dev_ioctl, - .mmap = kvm_dev_mmap, }; static struct miscdevice kvm_dev = { @@ -2080,13 +2362,17 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, int cpu = (long)v; switch (val) { - case CPU_DEAD: + case CPU_DOWN_PREPARE: case CPU_UP_CANCELED: + printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", + cpu); decache_vcpus_on_cpu(cpu); smp_call_function_single(cpu, kvm_arch_ops->hardware_disable, NULL, 0, 1); break; - case CPU_UP_PREPARE: + case CPU_ONLINE: + printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", + cpu); smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, NULL, 0, 1); break; @@ -2121,13 +2407,13 @@ static void kvm_exit_debug(void) static int kvm_suspend(struct sys_device *dev, pm_message_t state) { decache_vcpus_on_cpu(raw_smp_processor_id()); - on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); + on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); return 0; } static int kvm_resume(struct sys_device *dev) { - on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); + on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); return 0; } @@ -2144,6 +2430,18 @@ static struct sys_device kvm_sysdev = { hpa_t bad_page_address; +static int kvmfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "kvm:", NULL, KVMFS_SUPER_MAGIC, mnt); +} + +static struct file_system_type kvm_fs_type = { + .name = "kvmfs", + .get_sb = kvmfs_get_sb, + .kill_sb = kill_anon_super, +}; + int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) { int r; @@ -2220,8 +2518,16 @@ void kvm_exit_arch(void) static __init int kvm_init(void) { static struct page *bad_page; - int r = 0; + int r; + + r = register_filesystem(&kvm_fs_type); + if (r) + goto out3; + kvmfs_mnt = kern_mount(&kvm_fs_type); + r = PTR_ERR(kvmfs_mnt); + if (IS_ERR(kvmfs_mnt)) + goto out2; kvm_init_debug(); kvm_init_msr_list(); @@ -2234,10 +2540,14 @@ static __init int kvm_init(void) bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT; memset(__va(bad_page_address), 0, PAGE_SIZE); - return r; + return 0; out: kvm_exit_debug(); + mntput(kvmfs_mnt); +out2: + unregister_filesystem(&kvm_fs_type); +out3: return r; } @@ -2245,6 +2555,8 @@ static __exit void kvm_exit(void) { kvm_exit_debug(); __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT)); + mntput(kvmfs_mnt); + unregister_filesystem(&kvm_fs_type); } module_init(kvm_init) diff --git a/drivers/kvm/kvm_svm.h b/drivers/kvm/kvm_svm.h index 74cc862f493..624f1ca4865 100644 --- a/drivers/kvm/kvm_svm.h +++ b/drivers/kvm/kvm_svm.h @@ -1,6 +1,7 @@ #ifndef __KVM_SVM_H #define __KVM_SVM_H +#include <linux/kernel.h> #include <linux/types.h> #include <linux/list.h> #include <asm/msr.h> @@ -18,7 +19,7 @@ static const u32 host_save_msrs[] = { MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/ }; -#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs)) +#define NR_HOST_SAVE_MSRS ARRAY_SIZE(host_save_msrs) #define NUM_DB_REGS 4 struct vcpu_svm { diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index be793770f31..a1a93368f31 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c @@ -298,18 +298,18 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte) if (!is_rmap_pte(*spte)) return; page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); - if (!page->private) { + if (!page_private(page)) { rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte); - page->private = (unsigned long)spte; - } else if (!(page->private & 1)) { + set_page_private(page,(unsigned long)spte); + } else if (!(page_private(page) & 1)) { rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte); desc = mmu_alloc_rmap_desc(vcpu); - desc->shadow_ptes[0] = (u64 *)page->private; + desc->shadow_ptes[0] = (u64 *)page_private(page); desc->shadow_ptes[1] = spte; - page->private = (unsigned long)desc | 1; + set_page_private(page,(unsigned long)desc | 1); } else { rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte); - desc = (struct kvm_rmap_desc *)(page->private & ~1ul); + desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul); while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) desc = desc->more; if (desc->shadow_ptes[RMAP_EXT-1]) { @@ -337,12 +337,12 @@ static void rmap_desc_remove_entry(struct kvm_vcpu *vcpu, if (j != 0) return; if (!prev_desc && !desc->more) - page->private = (unsigned long)desc->shadow_ptes[0]; + set_page_private(page,(unsigned long)desc->shadow_ptes[0]); else if (prev_desc) prev_desc->more = desc->more; else - page->private = (unsigned long)desc->more | 1; + set_page_private(page,(unsigned long)desc->more | 1); mmu_free_rmap_desc(vcpu, desc); } @@ -356,20 +356,20 @@ static void rmap_remove(struct kvm_vcpu *vcpu, u64 *spte) if (!is_rmap_pte(*spte)) return; page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); - if (!page->private) { + if (!page_private(page)) { printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte); BUG(); - } else if (!(page->private & 1)) { + } else if (!(page_private(page) & 1)) { rmap_printk("rmap_remove: %p %llx 1->0\n", spte, *spte); - if ((u64 *)page->private != spte) { + if ((u64 *)page_private(page) != spte) { printk(KERN_ERR "rmap_remove: %p %llx 1->BUG\n", spte, *spte); BUG(); } - page->private = 0; + set_page_private(page,0); } else { rmap_printk("rmap_remove: %p %llx many->many\n", spte, *spte); - desc = (struct kvm_rmap_desc *)(page->private & ~1ul); + desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul); prev_desc = NULL; while (desc) { for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i) @@ -398,11 +398,11 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn) BUG_ON(!slot); page = gfn_to_page(slot, gfn); - while (page->private) { - if (!(page->private & 1)) - spte = (u64 *)page->private; + while (page_private(page)) { + if (!(page_private(page) & 1)) + spte = (u64 *)page_private(page); else { - desc = (struct kvm_rmap_desc *)(page->private & ~1ul); + desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul); spte = desc->shadow_ptes[0]; } BUG_ON(!spte); @@ -1218,7 +1218,7 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu) INIT_LIST_HEAD(&page_header->link); if ((page = alloc_page(GFP_KERNEL)) == NULL) goto error_1; - page->private = (unsigned long)page_header; + set_page_private(page, (unsigned long)page_header); page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT; memset(__va(page_header->page_hpa), 0, PAGE_SIZE); list_add(&page_header->link, &vcpu->free_pages); diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index b6b90e9e130..f3bcee90465 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h @@ -128,8 +128,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker, goto access_error; #endif - if (!(*ptep & PT_ACCESSED_MASK)) - *ptep |= PT_ACCESSED_MASK; /* avoid rmw */ + if (!(*ptep & PT_ACCESSED_MASK)) { + mark_page_dirty(vcpu->kvm, table_gfn); + *ptep |= PT_ACCESSED_MASK; + } if (walker->level == PT_PAGE_TABLE_LEVEL) { walker->gfn = (*ptep & PT_BASE_ADDR_MASK) @@ -185,6 +187,12 @@ static void FNAME(release_walker)(struct guest_walker *walker) kunmap_atomic(walker->table, KM_USER0); } +static void FNAME(mark_pagetable_dirty)(struct kvm *kvm, + struct guest_walker *walker) +{ + mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]); +} + static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte, u64 *shadow_pte, u64 access_bits, gfn_t gfn) { @@ -348,12 +356,15 @@ static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu, } else if (kvm_mmu_lookup_page(vcpu, gfn)) { pgprintk("%s: found shadow page for %lx, marking ro\n", __FUNCTION__, gfn); + mark_page_dirty(vcpu->kvm, gfn); + FNAME(mark_pagetable_dirty)(vcpu->kvm, walker); *guest_ent |= PT_DIRTY_MASK; *write_pt = 1; return 0; } mark_page_dirty(vcpu->kvm, gfn); *shadow_ent |= PT_WRITABLE_MASK; + FNAME(mark_pagetable_dirty)(vcpu->kvm, walker); *guest_ent |= PT_DIRTY_MASK; rmap_add(vcpu, shadow_ent); @@ -430,9 +441,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, /* * mmio: emulate if accessible, otherwise its a guest fault. */ - if (is_io_pte(*shadow_pte)) { + if (is_io_pte(*shadow_pte)) return 1; - } ++kvm_stat.pf_fixed; kvm_mmu_audit(vcpu, "post page fault (fixed)"); diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 83da4ea150a..3d8ea7ac2ec 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -15,6 +15,7 @@ */ #include <linux/module.h> +#include <linux/kernel.h> #include <linux/vmalloc.h> #include <linux/highmem.h> #include <linux/profile.h> @@ -75,7 +76,7 @@ struct svm_init_data { static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000}; -#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges)) +#define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges) #define MSRS_RANGE_SIZE 2048 #define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2) @@ -485,6 +486,7 @@ static void init_vmcb(struct vmcb *vmcb) control->intercept = (1ULL << INTERCEPT_INTR) | (1ULL << INTERCEPT_NMI) | + (1ULL << INTERCEPT_SMI) | /* * selective cr0 intercept bug? * 0: 0f 22 d8 mov %eax,%cr3 @@ -553,7 +555,7 @@ static void init_vmcb(struct vmcb *vmcb) * cr0 val on cpu init should be 0x60000010, we enable cpu * cache by default. the orderly way is to enable cache in bios. */ - save->cr0 = 0x00000010 | CR0_PG_MASK; + save->cr0 = 0x00000010 | CR0_PG_MASK | CR0_WP_MASK; save->cr4 = CR4_PAE_MASK; /* rdx = ?? */ } @@ -598,10 +600,9 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) kfree(vcpu->svm); } -static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu) +static void svm_vcpu_load(struct kvm_vcpu *vcpu) { get_cpu(); - return vcpu; } static void svm_vcpu_put(struct kvm_vcpu *vcpu) @@ -1042,22 +1043,22 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) addr_mask = io_adress(vcpu, _in, &kvm_run->io.address); if (!addr_mask) { - printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__); + printk(KERN_DEBUG "%s: get io address failed\n", + __FUNCTION__); return 1; } if (kvm_run->io.rep) { - kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & addr_mask; + kvm_run->io.count + = vcpu->regs[VCPU_REGS_RCX] & addr_mask; kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0; } - } else { + } else kvm_run->io.value = vcpu->svm->vmcb->save.rax; - } return 0; } - static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { return 1; @@ -1075,6 +1076,12 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 0; } +static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +{ + vcpu->svm->vmcb->save.rip += 3; + return kvm_hypercall(vcpu, kvm_run); +} + static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { inject_ud(vcpu); @@ -1275,7 +1282,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, [SVM_EXIT_TASK_SWITCH] = task_switch_interception, [SVM_EXIT_SHUTDOWN] = shutdown_interception, [SVM_EXIT_VMRUN] = invalid_op_interception, - [SVM_EXIT_VMMCALL] = invalid_op_interception, + [SVM_EXIT_VMMCALL] = vmmcall_interception, [SVM_EXIT_VMLOAD] = invalid_op_interception, [SVM_EXIT_VMSAVE] = invalid_op_interception, [SVM_EXIT_STGI] = invalid_op_interception, @@ -1297,7 +1304,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info, exit_code); - if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers) + if (exit_code >= ARRAY_SIZE(svm_exit_handlers) || svm_exit_handlers[exit_code] == 0) { kvm_run->exit_reason = KVM_EXIT_UNKNOWN; printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n", @@ -1668,6 +1675,18 @@ static int is_disabled(void) return 0; } +static void +svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) +{ + /* + * Patch in the VMMCALL instruction: + */ + hypercall[0] = 0x0f; + hypercall[1] = 0x01; + hypercall[2] = 0xd9; + hypercall[3] = 0xc3; +} + static struct kvm_arch_ops svm_arch_ops = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled, @@ -1716,6 +1735,7 @@ static struct kvm_arch_ops svm_arch_ops = { .run = svm_vcpu_run, .skip_emulated_instruction = skip_emulated_instruction, .vcpu_setup = svm_vcpu_setup, + .patch_hypercall = svm_patch_hypercall, }; static int __init svm_init(void) diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index fd4e9173438..c07178e6112 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -19,6 +19,7 @@ #include "vmx.h" #include "kvm_vmx.h" #include <linux/module.h> +#include <linux/kernel.h> #include <linux/mm.h> #include <linux/highmem.h> #include <linux/profile.h> @@ -27,7 +28,6 @@ #include "segment_descriptor.h" - MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); @@ -76,7 +76,7 @@ static const u32 vmx_msr_index[] = { #endif MSR_EFER, MSR_K6_STAR, }; -#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index)) +#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index) static inline int is_page_fault(u32 intr_info) { @@ -204,7 +204,7 @@ static void vmcs_write64(unsigned long field, u64 value) * Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken. */ -static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) +static void vmx_vcpu_load(struct kvm_vcpu *vcpu) { u64 phys_addr = __pa(vcpu->vmcs); int cpu; @@ -242,7 +242,6 @@ static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ } - return vcpu; } static void vmx_vcpu_put(struct kvm_vcpu *vcpu) @@ -418,10 +417,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) case MSR_IA32_SYSENTER_ESP: vmcs_write32(GUEST_SYSENTER_ESP, data); break; - case MSR_IA32_TIME_STAMP_COUNTER: { + case MSR_IA32_TIME_STAMP_COUNTER: guest_write_tsc(data); break; - } default: msr = find_msr_entry(vcpu, msr_index); if (msr) { @@ -793,6 +791,9 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) */ static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0) { + if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK)) + enter_rmode(vcpu); + vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0); update_exception_bitmap(vcpu); vmcs_writel(CR0_READ_SHADOW, cr0); @@ -1467,6 +1468,18 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 0; } +static void +vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) +{ + /* + * Patch in the VMCALL instruction: + */ + hypercall[0] = 0x0f; + hypercall[1] = 0x01; + hypercall[2] = 0xc1; + hypercall[3] = 0xc3; +} + static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { u64 exit_qualification; @@ -1643,6 +1656,12 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 0; } +static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +{ + vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3); + return kvm_hypercall(vcpu, kvm_run); +} + /* * The exit handlers return 1 if the exit was handled fully and guest execution * may resume. Otherwise they set the kvm_run parameter to indicate what needs @@ -1661,6 +1680,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu, [EXIT_REASON_MSR_WRITE] = handle_wrmsr, [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window, [EXIT_REASON_HLT] = handle_halt, + [EXIT_REASON_VMCALL] = handle_vmcall, }; static const int kvm_vmx_max_exit_handlers = @@ -2062,6 +2082,7 @@ static struct kvm_arch_ops vmx_arch_ops = { .run = vmx_vcpu_run, .skip_emulated_instruction = skip_emulated_instruction, .vcpu_setup = vmx_vcpu_setup, + .patch_hypercall = vmx_patch_hypercall, }; static int __init vmx_init(void) diff --git a/drivers/md/md.c b/drivers/md/md.c index 05febfd9f07..6c06e825cff 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1296,27 +1296,17 @@ static struct super_type super_types[] = { .sync_super = super_1_sync, }, }; - -static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev) -{ - struct list_head *tmp; - mdk_rdev_t *rdev; - - ITERATE_RDEV(mddev,rdev,tmp) - if (rdev->bdev->bd_contains == dev->bdev->bd_contains) - return rdev; - - return NULL; -} static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) { - struct list_head *tmp; - mdk_rdev_t *rdev; + struct list_head *tmp, *tmp2; + mdk_rdev_t *rdev, *rdev2; ITERATE_RDEV(mddev1,rdev,tmp) - if (match_dev_unit(mddev2, rdev)) - return 1; + ITERATE_RDEV(mddev2, rdev2, tmp2) + if (rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) + return 1; return 0; } @@ -1325,8 +1315,7 @@ static LIST_HEAD(pending_raid_disks); static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) { - mdk_rdev_t *same_pdev; - char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + char b[BDEVNAME_SIZE]; struct kobject *ko; char *s; @@ -1342,14 +1331,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) else mddev->size = rdev->size; } - same_pdev = match_dev_unit(mddev, rdev); - if (same_pdev) - printk(KERN_WARNING - "%s: WARNING: %s appears to be on the same physical" - " disk as %s. True\n protection against single-disk" - " failure might be compromised.\n", - mdname(mddev), bdevname(rdev->bdev,b), - bdevname(same_pdev->bdev,b2)); /* Verify rdev->desc_nr is unique. * If it is -1, assign a free number, else @@ -3109,6 +3090,36 @@ static int do_md_run(mddev_t * mddev) return -EINVAL; } + if (pers->sync_request) { + /* Warn if this is a potentially silly + * configuration. + */ + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + mdk_rdev_t *rdev2; + struct list_head *tmp2; + int warned = 0; + ITERATE_RDEV(mddev, rdev, tmp) { + ITERATE_RDEV(mddev, rdev2, tmp2) { + if (rdev < rdev2 && + rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) { + printk(KERN_WARNING + "%s: WARNING: %s appears to be" + " on the same physical disk as" + " %s.\n", + mdname(mddev), + bdevname(rdev->bdev,b), + bdevname(rdev2->bdev,b2)); + warned = 1; + } + } + } + if (warned) + printk(KERN_WARNING + "True protection against single-disk" + " failure might be compromised.\n"); + } + mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; @@ -3311,6 +3322,9 @@ static int do_md_stop(mddev_t * mddev, int mode) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); mddev->pers->stop(mddev); + mddev->queue->merge_bvec_fn = NULL; + mddev->queue->unplug_fn = NULL; + mddev->queue->issue_flush_fn = NULL; if (mddev->pers->sync_request) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); @@ -5343,6 +5357,44 @@ void md_do_sync(mddev_t *mddev) EXPORT_SYMBOL_GPL(md_do_sync); +static int remove_and_add_spares(mddev_t *mddev) +{ + mdk_rdev_t *rdev; + struct list_head *rtmp; + int spares = 0; + + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + (test_bit(Faulty, &rdev->flags) || + ! test_bit(In_sync, &rdev->flags)) && + atomic_read(&rdev->nr_pending)==0) { + if (mddev->pers->hot_remove_disk( + mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + rdev->raid_disk = -1; + } + } + + if (mddev->degraded) { + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk < 0 + && !test_bit(Faulty, &rdev->flags)) { + rdev->recovery_offset = 0; + if (mddev->pers->hot_add_disk(mddev,rdev)) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm); + spares++; + md_new_event(mddev); + } else + break; + } + } + return spares; +} /* * This routine is regularly called by all per-raid-array threads to * deal with generic issues like resync and super-block update. @@ -5397,7 +5449,7 @@ void md_check_recovery(mddev_t *mddev) return; if (mddev_trylock(mddev)) { - int spares =0; + int spares = 0; spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && @@ -5460,35 +5512,13 @@ void md_check_recovery(mddev_t *mddev) * Spare are also removed and re-added, to allow * the personality to fail the re-add. */ - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk >= 0 && - (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && - atomic_read(&rdev->nr_pending)==0) { - if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { - char nm[20]; - sprintf(nm,"rd%d", rdev->raid_disk); - sysfs_remove_link(&mddev->kobj, nm); - rdev->raid_disk = -1; - } - } - - if (mddev->degraded) { - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk < 0 - && !test_bit(Faulty, &rdev->flags)) { - rdev->recovery_offset = 0; - if (mddev->pers->hot_add_disk(mddev,rdev)) { - char nm[20]; - sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); - spares++; - md_new_event(mddev); - } else - break; - } - } - if (spares) { + if (mddev->reshape_position != MaxSector) { + if (mddev->pers->check_reshape(mddev) != 0) + /* Cannot proceed */ + goto unlock; + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + } else if ((spares = remove_and_add_spares(mddev))) { clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); } else if (mddev->recovery_cp < MaxSector) { diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a9401c017e3..82249a69014 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -429,7 +429,7 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev) if (dev < 0) dev += conf->raid_disks; } else { - while (sector > conf->stride) { + while (sector >= conf->stride) { sector -= conf->stride; if (dev < conf->near_copies) dev += conf->raid_disks - conf->near_copies; @@ -1801,6 +1801,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (k=0; k<conf->copies; k++) if (r10_bio->devs[k].devnum == i) break; + BUG_ON(k == conf->copies); bio = r10_bio->devs[1].bio; bio->bi_next = biolist; biolist = bio; @@ -2021,19 +2022,30 @@ static int run(mddev_t *mddev) if (!conf->tmppage) goto out_free_conf; + conf->mddev = mddev; + conf->raid_disks = mddev->raid_disks; conf->near_copies = nc; conf->far_copies = fc; conf->copies = nc*fc; conf->far_offset = fo; conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1; conf->chunk_shift = ffz(~mddev->chunk_size) - 9; + size = mddev->size >> (conf->chunk_shift-1); + sector_div(size, fc); + size = size * conf->raid_disks; + sector_div(size, nc); + /* 'size' is now the number of chunks in the array */ + /* calculate "used chunks per device" in 'stride' */ + stride = size * conf->copies; + sector_div(stride, conf->raid_disks); + mddev->size = stride << (conf->chunk_shift-1); + if (fo) - conf->stride = 1 << conf->chunk_shift; - else { - stride = mddev->size >> (conf->chunk_shift-1); + stride = 1; + else sector_div(stride, fc); - conf->stride = stride << conf->chunk_shift; - } + conf->stride = stride << conf->chunk_shift; + conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, r10bio_pool_free, conf); if (!conf->r10bio_pool) { @@ -2063,8 +2075,6 @@ static int run(mddev_t *mddev) disk->head_position = 0; } - conf->raid_disks = mddev->raid_disks; - conf->mddev = mddev; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -2106,16 +2116,8 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - if (conf->far_offset) { - size = mddev->size >> (conf->chunk_shift-1); - size *= conf->raid_disks; - size <<= conf->chunk_shift; - sector_div(size, conf->far_copies); - } else - size = conf->stride * conf->raid_disks; - sector_div(size, conf->near_copies); - mddev->array_size = size/2; - mddev->resync_max_sectors = size; + mddev->array_size = size << (conf->chunk_shift-1); + mddev->resync_max_sectors = size << conf->chunk_shift; mddev->queue->unplug_fn = raid10_unplug; mddev->queue->issue_flush_fn = raid10_issue_flush; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 11c3d7bfa79..54a1ad5eef4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1050,7 +1050,7 @@ static void compute_parity5(struct stripe_head *sh, int method) static void compute_parity6(struct stripe_head *sh, int method) { raid6_conf_t *conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count; + int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count; struct bio *chosen; /**** FIX THIS: This could be very bad if disks is close to 256 ****/ void *ptrs[disks]; @@ -1131,8 +1131,7 @@ static void compute_parity6(struct stripe_head *sh, int method) /* Compute one missing block */ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; void *ptr[MAX_XOR_BLOCKS], *p; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); @@ -1170,8 +1169,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) /* Compute two missing blocks */ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); int d0_idx = raid6_next_disk(qd_idx, disks); @@ -1887,11 +1885,11 @@ static void handle_stripe5(struct stripe_head *sh) static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) { raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks; + int disks = sh->disks; struct bio *return_bi= NULL; struct bio *bi; int i; - int syncing; + int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; int non_overwrite = 0; int failed_num[2] = {0, 0}; @@ -1909,6 +1907,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) clear_bit(STRIPE_DELAYED, &sh->state); syncing = test_bit(STRIPE_SYNCING, &sh->state); + expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); + expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ rcu_read_lock(); @@ -2114,13 +2114,15 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { + if (to_read || non_overwrite || (to_write && failed) || + (syncing && (uptodate < disks)) || expanding) { for (i=disks; i--;) { dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread || (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || syncing || + expanding || (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) ) @@ -2355,6 +2357,79 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) } } } + + if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { + /* Need to write out all blocks after computing P&Q */ + sh->disks = conf->raid_disks; + sh->pd_idx = stripe_to_pdidx(sh->sector, conf, + conf->raid_disks); + compute_parity6(sh, RECONSTRUCT_WRITE); + for (i = conf->raid_disks ; i-- ; ) { + set_bit(R5_LOCKED, &sh->dev[i].flags); + locked++; + set_bit(R5_Wantwrite, &sh->dev[i].flags); + } + clear_bit(STRIPE_EXPANDING, &sh->state); + } else if (expanded) { + clear_bit(STRIPE_EXPAND_READY, &sh->state); + atomic_dec(&conf->reshape_stripes); + wake_up(&conf->wait_for_overlap); + md_done_sync(conf->mddev, STRIPE_SECTORS, 1); + } + + if (expanding && locked == 0) { + /* We have read all the blocks in this stripe and now we need to + * copy some of them into a target stripe for expand. + */ + clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); + for (i = 0; i < sh->disks ; i++) + if (i != pd_idx && i != qd_idx) { + int dd_idx2, pd_idx2, j; + struct stripe_head *sh2; + + sector_t bn = compute_blocknr(sh, i); + sector_t s = raid5_compute_sector( + bn, conf->raid_disks, + conf->raid_disks - conf->max_degraded, + &dd_idx2, &pd_idx2, conf); + sh2 = get_active_stripe(conf, s, + conf->raid_disks, + pd_idx2, 1); + if (sh2 == NULL) + /* so for only the early blocks of + * this stripe have been requests. + * When later blocks get requests, we + * will try again + */ + continue; + if (!test_bit(STRIPE_EXPANDING, &sh2->state) || + test_bit(R5_Expanded, + &sh2->dev[dd_idx2].flags)) { + /* must have already done this block */ + release_stripe(sh2); + continue; + } + memcpy(page_address(sh2->dev[dd_idx2].page), + page_address(sh->dev[i].page), + STRIPE_SIZE); + set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags); + set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags); + for (j = 0 ; j < conf->raid_disks ; j++) + if (j != sh2->pd_idx && + j != raid6_next_disk(sh2->pd_idx, + sh2->disks) && + !test_bit(R5_Expanded, + &sh2->dev[j].flags)) + break; + if (j == conf->raid_disks) { + set_bit(STRIPE_EXPAND_READY, + &sh2->state); + set_bit(STRIPE_HANDLE, &sh2->state); + } + release_stripe(sh2); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { @@ -2395,7 +2470,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) rcu_read_unlock(); if (rdev) { - if (syncing) + if (syncing || expanding || expanded) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -2915,8 +2990,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped struct stripe_head *sh; int pd_idx; sector_t first_sector, last_sector; - int raid_disks; - int data_disks; + int raid_disks = conf->previous_raid_disks; + int data_disks = raid_disks - conf->max_degraded; + int new_data_disks = conf->raid_disks - conf->max_degraded; int i; int dd_idx; sector_t writepos, safepos, gap; @@ -2925,7 +3001,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped conf->expand_progress != 0) { /* restarting in the middle, skip the initial sectors */ sector_nr = conf->expand_progress; - sector_div(sector_nr, conf->raid_disks-1); + sector_div(sector_nr, new_data_disks); *skipped = 1; return sector_nr; } @@ -2939,14 +3015,14 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * to after where expand_lo old_maps to */ writepos = conf->expand_progress + - conf->chunk_size/512*(conf->raid_disks-1); - sector_div(writepos, conf->raid_disks-1); + conf->chunk_size/512*(new_data_disks); + sector_div(writepos, new_data_disks); safepos = conf->expand_lo; - sector_div(safepos, conf->previous_raid_disks-1); + sector_div(safepos, data_disks); gap = conf->expand_progress - conf->expand_lo; if (writepos >= safepos || - gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { + gap > (new_data_disks)*3000*2 /*3Meg*/) { /* Cannot proceed until we've updated the superblock... */ wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes)==0); @@ -2976,6 +3052,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped sector_t s; if (j == sh->pd_idx) continue; + if (conf->level == 6 && + j == raid6_next_disk(sh->pd_idx, sh->disks)) + continue; s = compute_blocknr(sh, j); if (s < (mddev->array_size<<1)) { skipped = 1; @@ -2992,28 +3071,27 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped release_stripe(sh); } spin_lock_irq(&conf->device_lock); - conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1); + conf->expand_progress = (sector_nr + i) * new_data_disks; spin_unlock_irq(&conf->device_lock); /* Ok, those stripe are ready. We can start scheduling * reads on the source stripes. * The source stripes are determined by mapping the first and last * block on the destination stripes. */ - raid_disks = conf->previous_raid_disks; - data_disks = raid_disks - 1; first_sector = - raid5_compute_sector(sector_nr*(conf->raid_disks-1), + raid5_compute_sector(sector_nr*(new_data_disks), raid_disks, data_disks, &dd_idx, &pd_idx, conf); last_sector = raid5_compute_sector((sector_nr+conf->chunk_size/512) - *(conf->raid_disks-1) -1, + *(new_data_disks) -1, raid_disks, data_disks, &dd_idx, &pd_idx, conf); if (last_sector >= (mddev->size<<1)) last_sector = (mddev->size<<1)-1; while (first_sector <= last_sector) { - pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); + pd_idx = stripe_to_pdidx(first_sector, conf, + conf->previous_raid_disks); sh = get_active_stripe(conf, first_sector, conf->previous_raid_disks, pd_idx, 0); set_bit(STRIPE_EXPAND_SOURCE, &sh->state); @@ -3348,35 +3426,44 @@ static int run(mddev_t *mddev) */ sector_t here_new, here_old; int old_disks; + int max_degraded = (mddev->level == 5 ? 1 : 2); if (mddev->new_level != mddev->level || mddev->new_layout != mddev->layout || mddev->new_chunk != mddev->chunk_size) { - printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "required - aborting.\n", mdname(mddev)); return -EINVAL; } if (mddev->delta_disks <= 0) { - printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "(reduce disks) required - aborting.\n", mdname(mddev)); return -EINVAL; } old_disks = mddev->raid_disks - mddev->delta_disks; /* reshape_position must be on a new-stripe boundary, and one - * further up in new geometry must map after here in old geometry. + * further up in new geometry must map after here in old + * geometry. */ here_new = mddev->reshape_position; - if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) { - printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n"); + if (sector_div(here_new, (mddev->chunk_size>>9)* + (mddev->raid_disks - max_degraded))) { + printk(KERN_ERR "raid5: reshape_position not " + "on a stripe boundary\n"); return -EINVAL; } /* here_new is the stripe we will write to */ here_old = mddev->reshape_position; - sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1)); - /* here_old is the first stripe that we might need to read from */ + sector_div(here_old, (mddev->chunk_size>>9)* + (old_disks-max_degraded)); + /* here_old is the first stripe that we might need to read + * from */ if (here_new >= here_old) { /* Reading from the same stripe as writing to - bad */ - printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n"); + printk(KERN_ERR "raid5: reshape_position too early for " + "auto-recovery - aborting.\n"); return -EINVAL; } printk(KERN_INFO "raid5: reshape will continue\n"); @@ -3814,6 +3901,8 @@ static int raid5_check_reshape(mddev_t *mddev) if (err) return err; + if (mddev->degraded > conf->max_degraded) + return -EINVAL; /* looks like we might be able to manage this */ return 0; } @@ -3827,8 +3916,7 @@ static int raid5_start_reshape(mddev_t *mddev) int added_devices = 0; unsigned long flags; - if (mddev->degraded || - test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; ITERATE_RDEV(mddev, rdev, rtmp) @@ -3836,7 +3924,7 @@ static int raid5_start_reshape(mddev_t *mddev) !test_bit(Faulty, &rdev->flags)) spares++; - if (spares < mddev->delta_disks-1) + if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded) /* Not enough devices even to make a degraded array * of that size */ @@ -3899,7 +3987,8 @@ static void end_reshape(raid5_conf_t *conf) struct block_device *bdev; if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { - conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1); + conf->mddev->array_size = conf->mddev->size * + (conf->raid_disks - conf->max_degraded); set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); conf->mddev->changed = 1; @@ -3972,6 +4061,10 @@ static struct mdk_personality raid6_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, +#ifdef CONFIG_MD_RAID5_RESHAPE + .check_reshape = raid5_check_reshape, + .start_reshape = raid5_start_reshape, +#endif .quiesce = raid5_quiesce, }; static struct mdk_personality raid5_personality = diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 359157aaf9e..6181a5a3365 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -30,14 +30,8 @@ const struct raid6_mmx_constants { static int raid6_have_mmx(void) { -#ifdef __KERNEL__ /* Not really "boot_cpu" but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (1<<23)) == (1<<23) ); -#endif } /* @@ -48,13 +42,12 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -78,7 +71,7 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %mm4,%mm4"); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx1 = { @@ -96,13 +89,12 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -137,7 +129,7 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx2 = { diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f7e7859f71a..f0a1ba8f40b 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -33,16 +33,10 @@ extern const struct raid6_mmx_constants { static int raid6_have_sse1_or_mmxext(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && (boot_cpu_has(X86_FEATURE_XMM) || boot_cpu_has(X86_FEATURE_MMXEXT)); -#else - /* User space test code - this incorrectly breaks on some Athlons */ - u32 features = cpuid_features(); - return ( (features & (5<<23)) == (5<<23) ); -#endif } /* @@ -53,14 +47,12 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - /* This is really MMX code, not SSE */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -94,8 +86,8 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm4,%0" : "=m" (q[d])); } - raid6_after_mmx(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x1 = { @@ -113,13 +105,12 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -157,8 +148,8 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); asm volatile("sfence" : :: "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x2 = { diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index b3aa7fe0877..0f019762a7c 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -30,17 +30,11 @@ static const struct raid6_sse_constants { static int raid6_have_sse2(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && boot_cpu_has(X86_FEATURE_FXSR) && boot_cpu_has(X86_FEATURE_XMM) && boot_cpu_has(X86_FEATURE_XMM2); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (15<<23)) == (15<<23) ); -#endif } /* @@ -51,13 +45,12 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -93,8 +86,8 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %xmm4,%xmm4"); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x1 = { @@ -112,13 +105,12 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -156,8 +148,8 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm6,%0" : "=m" (q[d+16])); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x2 = { @@ -179,13 +171,12 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse16_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse16(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" :: "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm2,%xmm2"); /* P[0] */ @@ -256,8 +247,9 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm14,%0" : "=m" (q[d+48])); asm volatile("pxor %xmm14,%xmm14"); } + asm volatile("sfence" : : : "memory"); - raid6_after_sse16(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x4 = { diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 4cf20534fe4..9111950414f 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -21,224 +21,40 @@ #if defined(__i386__) || defined(__x86_64__) -#ifdef __x86_64__ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t __attribute__((aligned(16))); - -/* N.B.: For SSE we only save %xmm0-%xmm7 even for x86-64, since - the code doesn't know about the additional x86-64 registers */ -typedef struct { - unsigned int sarea[8*4+2]; - unsigned long cr0; -} raid6_sse_save_t __attribute__((aligned(16))); - -/* This is for x86-64-specific code which uses all 16 XMM registers */ -typedef struct { - unsigned int sarea[16*4+2]; - unsigned long cr0; -} raid6_sse16_save_t __attribute__((aligned(16))); - -/* On x86-64 the stack *SHOULD* be 16-byte aligned, but currently this - is buggy in the kernel and it's only 8-byte aligned in places, so - we need to do this anyway. Sigh. */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#else /* __i386__ */ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t; - -/* On i386, the stack is only 8-byte aligned, but SSE requires 16-byte - alignment. The +3 is so we have the slack space to manually align - a properly-sized area correctly. */ -typedef struct { - unsigned int sarea[8*4+3]; - unsigned long cr0; -} raid6_sse_save_t; - -/* Find the 16-byte aligned save area */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#endif - #ifdef __KERNEL__ /* Real code */ -/* Note: %cr0 is 32 bits on i386 and 64 bits on x86-64 */ - -static inline unsigned long raid6_get_fpu(void) -{ - unsigned long cr0; - - preempt_disable(); - asm volatile("mov %%cr0,%0 ; clts" : "=r" (cr0)); - return cr0; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - asm volatile("mov %0,%%cr0" : : "r" (cr0)); - preempt_enable(); -} +#include <asm/i387.h> #else /* Dummy code for user space testing */ -static inline unsigned long raid6_get_fpu(void) -{ - return 0xf00ba6; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - (void)cr0; -} - -#endif - -static inline void raid6_before_mmx(raid6_mmx_save_t *s) -{ - s->cr0 = raid6_get_fpu(); - asm volatile("fsave %0 ; fwait" : "=m" (s->fsave[0])); -} - -static inline void raid6_after_mmx(raid6_mmx_save_t *s) -{ - asm volatile("frstor %0" : : "m" (s->fsave[0])); - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movaps %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movaps %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movaps %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movaps %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movaps %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movaps %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movaps %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movaps %%xmm7,%0" : "=m" (rsa[28])); -} - -static inline void raid6_after_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - asm volatile("movaps %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movaps %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movaps %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movaps %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movaps %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movaps %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movaps %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movaps %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_begin(void) { - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); } -static inline void raid6_after_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_end(void) { - unsigned int *rsa = SAREA(s); - - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); } -#ifdef __x86_64__ - -static inline void raid6_before_sse16(raid6_sse16_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions + * (fast save and restore) */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); - asm volatile("movdqa %%xmm8,%0" : "=m" (rsa[32])); - asm volatile("movdqa %%xmm9,%0" : "=m" (rsa[36])); - asm volatile("movdqa %%xmm10,%0" : "=m" (rsa[40])); - asm volatile("movdqa %%xmm11,%0" : "=m" (rsa[44])); - asm volatile("movdqa %%xmm12,%0" : "=m" (rsa[48])); - asm volatile("movdqa %%xmm13,%0" : "=m" (rsa[52])); - asm volatile("movdqa %%xmm14,%0" : "=m" (rsa[56])); - asm volatile("movdqa %%xmm15,%0" : "=m" (rsa[60])); -} - -static inline void raid6_after_sse16(raid6_sse16_save_t *s) +/* Should work well enough on modern CPUs for testing */ +static inline int boot_cpu_has(int flag) { - unsigned int *rsa = SAREA(s); + u32 eax = (flag >> 5) ? 0x80000001 : 1; + u32 edx; - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - asm volatile("movdqa %0,%%xmm8" : : "m" (rsa[32])); - asm volatile("movdqa %0,%%xmm9" : : "m" (rsa[36])); - asm volatile("movdqa %0,%%xmm10" : : "m" (rsa[40])); - asm volatile("movdqa %0,%%xmm11" : : "m" (rsa[44])); - asm volatile("movdqa %0,%%xmm12" : : "m" (rsa[48])); - asm volatile("movdqa %0,%%xmm13" : : "m" (rsa[52])); - asm volatile("movdqa %0,%%xmm14" : : "m" (rsa[56])); - asm volatile("movdqa %0,%%xmm15" : : "m" (rsa[60])); + asm volatile("cpuid" + : "+a" (eax), "=d" (edx) + : : "ecx", "ebx"); - raid6_put_fpu(s->cr0); + return (edx >> (flag & 31)) & 1; } -#endif /* __x86_64__ */ - -/* User space test hack */ -#ifndef __KERNEL__ -static inline int cpuid_features(void) -{ - u32 eax = 1; - u32 ebx, ecx, edx; - - asm volatile("cpuid" : - "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)); - - return edx; -} #endif /* ndef __KERNEL__ */ #endif diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 15d12fce34d..127a94b9a1b 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -469,9 +469,9 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { fw->data[BLUEBIRD_01_ID_OFFSET + 2] = - udev->descriptor.idProduct + 1; + le16_to_cpu(udev->descriptor.idProduct) + 1; fw->data[BLUEBIRD_01_ID_OFFSET + 3] = - udev->descriptor.idProduct >> 8; + le16_to_cpu(udev->descriptor.idProduct) >> 8; return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); } diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 4a198d4755b..b5acb11c0bc 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -119,6 +119,8 @@ static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_f struct dvb_usb_adapter *adap = fe->dvb->priv; u8 b[5]; dvb_usb_tuner_calc_regs(fe,fep,b, 5); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0); } diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 682dc7ce48d..710c11a6829 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1022,7 +1022,7 @@ static ssize_t cafe_v4l_read(struct file *filp, char __user *buffer, size_t len, loff_t *pos) { struct cafe_camera *cam = filp->private_data; - int ret; + int ret = 0; /* * Perhaps we're in speculative read mode and already @@ -1251,8 +1251,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, if (cam->n_sbufs == 0) /* no luck at all - ret already set */ kfree(cam->sb_bufs); - else - ret = 0; req->count = cam->n_sbufs; /* In case of partial success */ out: diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index cc535ca713d..774d2536555 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -633,7 +633,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_CX25840) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -903,13 +903,13 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->vbi_line_offset = 8; state->id = id; + i2c_attach_client(client); + if (state->is_cx25836) cx25836_initialize(client); else cx25840_initialize(client, 1); - i2c_attach_client(client); - return 0; } diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1958d4016ea..0e86b9d033a 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -37,7 +37,7 @@ */ #define FWSEND 48 -#define FWDEV(x) &((x)->adapter->dev) +#define FWDEV(x) &((x)->dev) static char *firmware = FWFILE; diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a1be1e279df..b0466b88f52 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -56,7 +56,8 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); /* ------------------------------------------------------------------ */ -#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 +#define OLD_BLACKBIRD_FIRM_IMAGE_SIZE 262144 +#define BLACKBIRD_FIRM_IMAGE_SIZE 376836 /* defines below are from ivtv-driver.h */ @@ -404,7 +405,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev) u32 value; int i; - for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) { + for (i = 0; i < dev->fw_size; i++) { memory_read(dev->core, i, &value); if (value == signature[signaturecnt]) signaturecnt++; @@ -452,12 +453,15 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) return -1; } - if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { - dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", - firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); + if ((firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) && + (firmware->size != OLD_BLACKBIRD_FIRM_IMAGE_SIZE)) { + dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d or %d)\n", + firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE, + OLD_BLACKBIRD_FIRM_IMAGE_SIZE); release_firmware(firmware); return -1; } + dev->fw_size = firmware->size; if (0 != memcmp(firmware->data, magic, 8)) { dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a97be1bdc31..bdfe2af7012 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1389,7 +1389,7 @@ static int vidioc_g_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* cx2388x has a 24-bit register space */ reg->val = cx_read(reg->reg&0xffffff); @@ -1401,7 +1401,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx_write(reg->reg&0xffffff, reg->val); return 0; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index d2ecfba9bb4..a4f7befda5b 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -463,6 +463,7 @@ struct cx8802_dev { u32 mailbox; int width; int height; + int fw_size; #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) /* for dvb only */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a1ca0f5007e..1ff5138e4bb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1268,7 +1268,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) if (fw_len % sizeof(u32)) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "size of %s firmware" - " must be a multiple of %u bytes", + " must be a multiple of %zu bytes", fw_files[fwidx],sizeof(u32)); release_firmware(fw_entry); return -1; @@ -3256,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 chip_id, u64 reg_id, - int setFl,u32 *val_ptr) + u32 match_type, u32 match_chip, u64 reg_id, + int setFl,u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct list_head *item; @@ -3268,13 +3268,16 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.i2c_id = chip_id; + req.match_type = match_type; + req.match_chip = match_chip; req.reg = reg_id; if (setFl) req.val = *val_ptr; mutex_lock(&hdw->i2c_list_lock); do { list_for_each(item,&hdw->i2c_clients) { cp = list_entry(item,struct pvr2_i2c_client,list); - if (cp->client->driver->id != chip_id) continue; + if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) { + continue; + } stat = pvr2_i2c_client_cmd( cp,(setFl ? VIDIOC_DBG_S_REGISTER : VIDIOC_DBG_G_REGISTER),&req); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 566a8ef7e12..0c9cca43ff8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -217,13 +217,14 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); /* Direct read/write access to chip's registers: - chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) + match_type - how to interpret match_chip (e.g. driver ID, i2c address) + match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) reg_id - register number to access setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 chip_id,u64 reg_id, - int setFl,u32 *val_ptr); + u32 match_type, u32 match_chip,u64 reg_id, + int setFl,u64 *val_ptr); /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4fe4136204c..5313d342666 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -740,11 +740,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: { - u32 val; + u64 val; struct v4l2_register *req = (struct v4l2_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( - hdw,req->i2c_id,req->reg, + hdw,req->match_type,req->match_chip,req->reg, cmd == VIDIOC_DBG_S_REGISTER,&val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c4f066d6668..7735b675892 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1425,7 +1425,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA711X) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bd9c4f3ad02..654863db159 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -619,7 +619,7 @@ static int saa7127_command(struct i2c_client *client, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA7127) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 886b5df7c9d..d5ec05f56ad 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -955,7 +955,7 @@ static int tvp5150_command(struct i2c_client *c, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_TVP5150) + if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index b3b5fd536dc..28d1133a3b7 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -167,7 +167,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 8852903e7a9..fe38224150d 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -144,7 +144,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64083) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index ae5f42562c0..6fc14557d62 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -521,7 +521,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_register *reg = arg; int errCode; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -540,7 +540,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, reg->val); + (unsigned int)reg->reg, (unsigned int)reg->val); return 0; } #endif diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index ddfd80c5618..54747606eae 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -51,6 +51,7 @@ #include <linux/mm.h> #include <linux/string.h> #include <linux/errno.h> +#include <linux/i2c.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/pgtable.h> @@ -365,13 +366,21 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", -#if 1 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", -#endif [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", - [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS" + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", +#if 1 + [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES", + [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", + [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", +#endif }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -395,9 +404,6 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", - [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", - [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", @@ -947,6 +953,28 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) return **ctrl_classes; } +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + return (c != NULL && c->driver != NULL && c->driver->id == match_chip); + case V4L2_CHIP_MATCH_I2C_ADDR: + return (c != NULL && c->addr == match_chip); + default: + return 0; + } +} + +int v4l2_chip_match_host(u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_HOST: + return match_chip == 0; + default: + return 0; + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_norm_to_name); @@ -970,6 +998,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); EXPORT_SYMBOL(v4l2_ctrl_query_fill); EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); +EXPORT_SYMBOL(v4l2_chip_match_i2c_client); +EXPORT_SYMBOL(v4l2_chip_match_host); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index dc9b1ef678a..011938fb7e0 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1342,6 +1342,42 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_s_jpegcomp(file, fh, p); break; } + case VIDIOC_G_ENC_INDEX: + { + struct v4l2_enc_idx *p=arg; + + if (!vfd->vidioc_g_enc_index) + break; + ret=vfd->vidioc_g_enc_index(file, fh, p); + if (!ret) + dbgarg (cmd, "entries=%d, entries_cap=%d\n", + p->entries,p->entries_cap); + break; + } + case VIDIOC_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_encoder_cmd) + break; + ret=vfd->vidioc_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } + case VIDIOC_TRY_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_try_encoder_cmd) + break; + ret=vfd->vidioc_try_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } case VIDIOC_G_PARM: { struct v4l2_streamparm *p=arg; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 5046a166134..4a73e8b2428 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -376,10 +376,11 @@ static inline void mmc_set_ios(struct mmc_host *host) { struct mmc_ios *ios = &host->ios; - pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", + pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u " + "width %u timing %u\n", mmc_hostname(host), ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, ios->vdd, - ios->bus_width); + ios->bus_width, ios->timing); host->ops->set_ios(host, ios); } @@ -809,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host) host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_UP; host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); mmc_delay(1); @@ -828,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host) host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_OFF; host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); } @@ -1112,46 +1115,50 @@ static void mmc_process_ext_csds(struct mmc_host *host) 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; + if (host->caps & MMC_CAP_MMC_HIGHSPEED) { + /* 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; - } + 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); + mmc_card_set_highspeed(card); - /* Check for host support for wide-bus modes. */ - if (!(host->caps & MMC_CAP_4_BIT_DATA)) { - continue; + host->ios.timing = MMC_TIMING_SD_HS; + mmc_set_ios(host); } - /* 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; + /* Check for host support for wide-bus modes. */ + if (host->caps & MMC_CAP_4_BIT_DATA) { + /* 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; - } + 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; + host->ios.bus_width = MMC_BUS_WIDTH_4; + mmc_set_ios(host); + } } kfree(ext_csd); @@ -1241,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) unsigned char *status; struct scatterlist sg; + if (!(host->caps & MMC_CAP_SD_HIGHSPEED)) + return; + status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_WARNING "%s: Unable to allocate buffer for " @@ -1332,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) } mmc_card_set_highspeed(card); + + host->ios.timing = MMC_TIMING_SD_HS; + mmc_set_ios(host); } kfree(status); diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 7522f76b15e..d749f08601b 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -606,7 +606,6 @@ 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; @@ -615,13 +614,6 @@ 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; @@ -761,10 +753,17 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) sdhci_set_power(host, ios->vdd); ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + if (ios->bus_width == MMC_BUS_WIDTH_4) ctrl |= SDHCI_CTRL_4BITBUS; else ctrl &= ~SDHCI_CTRL_4BITBUS; + + if (ios->timing == MMC_TIMING_SD_HS) + ctrl |= SDHCI_CTRL_HISPD; + else + ctrl &= ~SDHCI_CTRL_HISPD; + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); mmiowb(); @@ -994,7 +993,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask = readl(host->ioaddr + SDHCI_INT_STATUS); - if (!intmask) { + if (!intmask || intmask == 0xffffffff) { result = IRQ_NONE; goto out; } @@ -1080,6 +1079,13 @@ static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state) pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + + for (i = 0;i < chip->num_slots;i++) { + if (!chip->hosts[i]) + continue; + free_irq(chip->hosts[i]->irq, chip->hosts[i]); + } + pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1108,6 +1114,11 @@ static int sdhci_resume (struct pci_dev *pdev) continue; if (chip->hosts[i]->flags & SDHCI_USE_DMA) pci_set_master(pdev); + ret = request_irq(chip->hosts[i]->irq, sdhci_irq, + IRQF_SHARED, chip->hosts[i]->slot_descr, + chip->hosts[i]); + if (ret) + return ret; sdhci_init(chip->hosts[i]); mmiowb(); ret = mmc_resume_host(chip->hosts[i]->mmc); @@ -1274,6 +1285,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) mmc->f_max = host->max_clk; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; + if (caps & SDHCI_CAN_DO_HISPD) + mmc->caps |= MMC_CAP_SD_HIGHSPEED; + mmc->ocr_avail = 0; if (caps & SDHCI_CAN_VDD_330) mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; @@ -1282,13 +1296,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) 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/net/3c59x.c b/drivers/net/3c59x.c index 716a47210aa..72995777f80 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -822,11 +822,17 @@ static int vortex_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct vortex_private *vp = netdev_priv(dev); + int err; if (dev && vp) { pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_WARNING "%s: Could not enable device \n", + dev->name); + return err; + } pci_set_master(pdev); if (request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) { diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 6f93a765e56..12c8453f44b 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -448,8 +448,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) spin_lock_irqsave(&cp->lock, flags); cp->cpcmd &= ~RxVlanOn; cpw16(CpCmd, cp->cpcmd); - if (cp->vlgrp) - cp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(cp->vlgrp, vid, NULL); spin_unlock_irqrestore(&cp->lock, flags); } #endif /* CP_VLAN_TAG_USED */ diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 33c6645455a..7138e0e025b 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2293,10 +2293,7 @@ static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) local_irq_save(flags); ace_mask_irq(dev); - - if (ap->vlgrp) - ap->vlgrp->vlan_devices[vid] = NULL; - + vlan_group_set_device(ap->vlgrp, vid, NULL); ace_unmask_irq(dev); local_irq_restore(flags); } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 9c399aaefbd..962c954c2d5 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1737,8 +1737,7 @@ static void amd8111e_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid { struct amd8111e_priv *lp = netdev_priv(dev); spin_lock_irq(&lp->lock); - if (lp->vlgrp) - lp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(lp->vlgrp, vid, NULL); spin_unlock_irq(&lp->lock); } #endif diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index 65673485bb6..88d4f70035b 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -1252,8 +1252,7 @@ static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) spin_lock_irqsave(&adapter->lock, flags); /* atl1_irq_disable(adapter); */ - if (adapter->vlgrp) - adapter->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(adapter->vlgrp, vid, NULL); /* atl1_irq_enable(adapter); */ spin_unlock_irqrestore(&adapter->lock, flags); /* We don't do Vlan filtering */ @@ -1266,7 +1265,7 @@ static void atl1_restore_vlan(struct atl1_adapter *adapter) if (adapter->vlgrp) { u16 vid; for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if (!adapter->vlgrp->vlan_devices[vid]) + if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; atl1_vlan_rx_add_vid(adapter->netdev, vid); } diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5a96d7611af..c12e5ea6181 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4467,9 +4467,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) struct bnx2 *bp = netdev_priv(dev); bnx2_netif_stop(bp); - - if (bp->vlgrp) - bp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(bp->vlgrp, vid, NULL); bnx2_set_rx_mode(dev); bnx2_netif_start(bp); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a7c8f98a890..e4724d874e7 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -60,6 +60,7 @@ #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/inetdevice.h> +#include <linux/igmp.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <net/sock.h> @@ -488,9 +489,9 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) /* Save and then restore vlan_dev in the grp array, * since the slave's driver might clear it. */ - vlan_dev = bond->vlgrp->vlan_devices[vid]; + vlan_dev = vlan_group_get_device(bond->vlgrp, vid); slave_dev->vlan_rx_kill_vid(slave_dev, vid); - bond->vlgrp->vlan_devices[vid] = vlan_dev; + vlan_group_set_device(bond->vlgrp, vid, vlan_dev); } } @@ -550,9 +551,9 @@ static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *s /* Save and then restore vlan_dev in the grp array, * since the slave's driver might clear it. */ - vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id); - bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev; + vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev); } unreg: @@ -861,6 +862,28 @@ static void bond_mc_delete(struct bonding *bond, void *addr, int alen) } } + +/* + * Retrieve the list of registered multicast addresses for the bonding + * device and retransmit an IGMP JOIN request to the current active + * slave. + */ +static void bond_resend_igmp_join_requests(struct bonding *bond) +{ + struct in_device *in_dev; + struct ip_mc_list *im; + + rcu_read_lock(); + in_dev = __in_dev_get_rcu(bond->dev); + if (in_dev) { + for (im = in_dev->mc_list; im; im = im->next) { + ip_mc_rejoin_group(im); + } + } + + rcu_read_unlock(); +} + /* * Totally destroys the mc_list in bond */ @@ -874,6 +897,7 @@ static void bond_mc_list_destroy(struct bonding *bond) kfree(dmi); dmi = bond->mc_list; } + bond->mc_list = NULL; } /* @@ -967,6 +991,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } + bond_resend_igmp_join_requests(bond); } } @@ -2397,7 +2422,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) vlan_id = 0; list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, vlan_list) { - vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan_dev == rt->u.dst.dev) { vlan_id = vlan->vlan_id; dprintk("basa: vlan match on %s %d\n", @@ -2444,7 +2469,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond) } list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan->vlan_ip) { bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip, vlan->vlan_ip, vlan->vlan_id); @@ -3371,7 +3396,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, vlan_list) { - vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); if (vlan_dev == event_dev) { switch (event) { case NETDEV_UP: @@ -3423,15 +3448,21 @@ void bond_register_arp(struct bonding *bond) { struct packet_type *pt = &bond->arp_mon_pt; + if (pt->type) + return; + pt->type = htons(ETH_P_ARP); - pt->dev = NULL; /*bond->dev;XXX*/ + pt->dev = bond->dev; pt->func = bond_arp_rcv; dev_add_pack(pt); } void bond_unregister_arp(struct bonding *bond) { - dev_remove_pack(&bond->arp_mon_pt); + struct packet_type *pt = &bond->arp_mon_pt; + + dev_remove_pack(pt); + pt->type = 0; } /*---------------------------- Hashing Policies -----------------------------*/ @@ -4011,42 +4042,6 @@ out: return 0; } -static void bond_activebackup_xmit_copy(struct sk_buff *skb, - struct bonding *bond, - struct slave *slave) -{ - struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); - struct ethhdr *eth_data; - u8 *hwaddr; - int res; - - if (!skb2) { - printk(KERN_ERR DRV_NAME ": Error: " - "bond_activebackup_xmit_copy(): skb_copy() failed\n"); - return; - } - - skb2->mac.raw = (unsigned char *)skb2->data; - eth_data = eth_hdr(skb2); - - /* Pick an appropriate source MAC address - * -- use slave's perm MAC addr, unless used by bond - * -- otherwise, borrow active slave's perm MAC addr - * since that will not be used - */ - hwaddr = slave->perm_hwaddr; - if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN)) - hwaddr = bond->curr_active_slave->perm_hwaddr; - - /* Set source MAC address appropriately */ - memcpy(eth_data->h_source, hwaddr, ETH_ALEN); - - res = bond_dev_queue_xmit(bond, skb2, slave->dev); - if (res) - dev_kfree_skb(skb2); - - return; -} /* * in active-backup mode, we know that bond->curr_active_slave is always valid if @@ -4067,21 +4062,6 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d if (!bond->curr_active_slave) goto out; - /* Xmit IGMP frames on all slaves to ensure rapid fail-over - for multicast traffic on snooping switches */ - if (skb->protocol == __constant_htons(ETH_P_IP) && - skb->nh.iph->protocol == IPPROTO_IGMP) { - struct slave *slave, *active_slave; - int i; - - active_slave = bond->curr_active_slave; - bond_for_each_slave_from_to(bond, slave, i, active_slave->next, - active_slave->prev) - if (IS_UP(slave->dev) && - (slave->link == BOND_LINK_UP)) - bond_activebackup_xmit_copy(skb, bond, slave); - } - res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); out: diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 7d0f24f6977..125c9b10586 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -889,8 +889,7 @@ static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) struct adapter *adapter = dev->priv; spin_lock_irq(&adapter->async_lock); - if (adapter->vlan_grp) - adapter->vlan_grp->vlan_devices[vid] = NULL; + vlan_group_set_device(adapter->vlan_grp, vid, NULL); spin_unlock_irq(&adapter->async_lock); } #endif diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index b2cf5f6feb4..f6ed033efb5 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -160,14 +160,16 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter, int i; for_each_port(adapter, i) { - const struct vlan_group *grp; + struct vlan_group *grp; struct net_device *dev = adapter->port[i]; const struct port_info *p = netdev_priv(dev); if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) { if (vlan && vlan != VLAN_VID_MASK) { grp = p->vlan_grp; - dev = grp ? grp->vlan_devices[vlan] : NULL; + dev = NULL; + if (grp) + dev = vlan_group_get_device(grp, vlan); } else while (dev->master) dev = dev->master; diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 782a6cf158a..82278f85025 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -35,7 +35,7 @@ #define DRV_DESC "Chelsio T3 Network Driver" #define DRV_NAME "cxgb3" /* Driver version */ -#define DRV_VERSION "1.0" +#define DRV_VERSION "1.0-ko" #define FW_VERSION_MAJOR 3 #define FW_VERSION_MINOR 2 #endif /* __CHELSIO_VERSION_H */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 98215fdd7d1..1d08e937af8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -376,7 +376,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter) uint16_t vid = adapter->hw.mng_cookie.vlan_id; uint16_t old_vid = adapter->mng_vlan_id; if (adapter->vlgrp) { - if (!adapter->vlgrp->vlan_devices[vid]) { + if (!vlan_group_get_device(adapter->vlgrp, vid)) { if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { e1000_vlan_rx_add_vid(netdev, vid); @@ -386,7 +386,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter) if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && (vid != old_vid) && - !adapter->vlgrp->vlan_devices[old_vid]) + !vlan_group_get_device(adapter->vlgrp, old_vid)) e1000_vlan_rx_kill_vid(netdev, old_vid); } else adapter->mng_vlan_id = vid; @@ -1482,7 +1482,7 @@ e1000_close(struct net_device *netdev) if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && !(adapter->vlgrp && - adapter->vlgrp->vlan_devices[adapter->mng_vlan_id])) { + vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) { e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); } @@ -4998,10 +4998,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) uint32_t vfta, index; e1000_irq_disable(adapter); - - if (adapter->vlgrp) - adapter->vlgrp->vlan_devices[vid] = NULL; - + vlan_group_set_device(adapter->vlgrp, vid, NULL); e1000_irq_enable(adapter); if ((adapter->hw.mng_cookie.status & @@ -5027,7 +5024,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter) if (adapter->vlgrp) { uint16_t vid; for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if (!adapter->vlgrp->vlan_devices[vid]) + if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; e1000_vlan_rx_add_vid(adapter->netdev, vid); } diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 88ad1c8bcee..0e4042bc0a4 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1939,8 +1939,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) int index; u64 hret; - if (port->vgrp) - port->vgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(port->vgrp, vid, NULL); cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb1) { diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1f83988a6a6..02b61b85b62 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1132,8 +1132,7 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) spin_lock_irqsave(&priv->rxlock, flags); - if (priv->vlgrp) - priv->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(priv->vgrp, vid, NULL); spin_unlock_irqrestore(&priv->rxlock, flags); } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 0c368288934..afc2ec72529 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -2213,8 +2213,7 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ixgb_irq_disable(adapter); - if(adapter->vlgrp) - adapter->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(adapter->vlgrp, vid, NULL); ixgb_irq_enable(adapter); @@ -2234,7 +2233,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter) if(adapter->vlgrp) { uint16_t vid; for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if(!adapter->vlgrp->vlan_devices[vid]) + if(!vlan_group_get_device(adapter->vlgrp, vid)) continue; ixgb_vlan_rx_add_vid(adapter->netdev, vid); } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 3e045a695db..9ba21e0f27c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1309,7 +1309,7 @@ static void mv643xx_init_ethtool_cmd(struct net_device *dev, int phy_address, static int mv643xx_eth_probe(struct platform_device *pdev) { struct mv643xx_eth_platform_data *pd; - int port_num = pdev->id; + int port_num; struct mv643xx_private *mp; struct net_device *dev; u8 *p; @@ -1319,6 +1319,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev) int duplex = DUPLEX_HALF; int speed = 0; /* default to auto-negotiation */ + pd = pdev->dev.platform_data; + if (pd == NULL) { + printk(KERN_ERR "No mv643xx_eth_platform_data\n"); + return -ENODEV; + } + dev = alloc_etherdev(sizeof(struct mv643xx_private)); if (!dev) return -ENOMEM; @@ -1331,8 +1337,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) BUG_ON(!res); dev->irq = res->start; - mp->port_num = port_num; - dev->open = mv643xx_eth_open; dev->stop = mv643xx_eth_stop; dev->hard_start_xmit = mv643xx_eth_start_xmit; @@ -1373,39 +1377,40 @@ static int mv643xx_eth_probe(struct platform_device *pdev) spin_lock_init(&mp->lock); + port_num = pd->port_number; + /* set default config values */ eth_port_uc_addr_get(dev, dev->dev_addr); mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE; mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE; - pd = pdev->dev.platform_data; - if (pd) { - if (pd->mac_addr) - memcpy(dev->dev_addr, pd->mac_addr, 6); + if (is_valid_ether_addr(pd->mac_addr)) + memcpy(dev->dev_addr, pd->mac_addr, 6); - if (pd->phy_addr || pd->force_phy_addr) - ethernet_phy_set(port_num, pd->phy_addr); + if (pd->phy_addr || pd->force_phy_addr) + ethernet_phy_set(port_num, pd->phy_addr); - if (pd->rx_queue_size) - mp->rx_ring_size = pd->rx_queue_size; + if (pd->rx_queue_size) + mp->rx_ring_size = pd->rx_queue_size; - if (pd->tx_queue_size) - mp->tx_ring_size = pd->tx_queue_size; + if (pd->tx_queue_size) + mp->tx_ring_size = pd->tx_queue_size; - if (pd->tx_sram_size) { - mp->tx_sram_size = pd->tx_sram_size; - mp->tx_sram_addr = pd->tx_sram_addr; - } - - if (pd->rx_sram_size) { - mp->rx_sram_size = pd->rx_sram_size; - mp->rx_sram_addr = pd->rx_sram_addr; - } + if (pd->tx_sram_size) { + mp->tx_sram_size = pd->tx_sram_size; + mp->tx_sram_addr = pd->tx_sram_addr; + } - duplex = pd->duplex; - speed = pd->speed; + if (pd->rx_sram_size) { + mp->rx_sram_size = pd->rx_sram_size; + mp->rx_sram_addr = pd->rx_sram_addr; } + duplex = pd->duplex; + speed = pd->speed; + + mp->port_num = port_num; + /* Hook up MII support for ethtool */ mp->mii.dev = dev; mp->mii.mdio_read = mv643xx_mdio_read; diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 7cb0a41c5cb..7d4e90cf49e 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -9,6 +9,8 @@ #include <linux/mv643xx.h> +#include <asm/dma-mapping.h> + /* Checksum offload for Tx works for most packets, but * fails if previous packet sent did not use hw csum */ @@ -47,7 +49,7 @@ #define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ #define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \ ETH_VLAN_HLEN + ETH_FCS_LEN) -#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + ETH_DMA_ALIGN) +#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + dma_get_cache_alignment()) #define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ #define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 954842e85ab..b05dc6ed7fb 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1,7 +1,7 @@ /************************************************************************* * myri10ge.c: Myricom Myri-10G Ethernet driver. * - * Copyright (C) 2005, 2006 Myricom, Inc. + * Copyright (C) 2005 - 2007 Myricom, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -16,17 +16,17 @@ * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * * * If the eeprom on your board is not recent enough, you will need to get a diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 5c57433cb30..c6172a77a6d 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2024,6 +2024,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) struct netdev_private *np = netdev_priv(dev); void __iomem * ioaddr = ns_ioaddr(dev); unsigned entry; + unsigned long flags; /* Note: Ordering is important here, set the field with the "ownership" bit last, and only then increment cur_tx. */ @@ -2037,7 +2038,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]); - spin_lock_irq(&np->lock); + spin_lock_irqsave(&np->lock, flags); if (!np->hands_off) { np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len); @@ -2056,7 +2057,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb_irq(skb); np->stats.tx_dropped++; } - spin_unlock_irq(&np->lock); + spin_unlock_irqrestore(&np->lock, flags); dev->trans_start = jiffies; @@ -2222,6 +2223,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) pkt_len = (desc_status & DescSizeMask) - 4; if ((desc_status&(DescMore|DescPktOK|DescRxLong)) != DescPktOK){ if (desc_status & DescMore) { + unsigned long flags; + if (netif_msg_rx_err(np)) printk(KERN_WARNING "%s: Oversized(?) Ethernet " @@ -2236,12 +2239,12 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) * reset procedure documented in * AN-1287. */ - spin_lock_irq(&np->lock); + spin_lock_irqsave(&np->lock, flags); reset_rx(dev); reinit_rx(dev); writel(np->ring_dma, ioaddr + RxRingPtr); check_link(dev); - spin_unlock_irq(&np->lock); + spin_unlock_irqrestore(&np->lock, flags); /* We'll enable RX on exit from this * function. */ @@ -2396,8 +2399,19 @@ static struct net_device_stats *get_stats(struct net_device *dev) #ifdef CONFIG_NET_POLL_CONTROLLER static void natsemi_poll_controller(struct net_device *dev) { + struct netdev_private *np = netdev_priv(dev); + disable_irq(dev->irq); - intr_handler(dev->irq, dev); + + /* + * A real interrupt might have already reached us at this point + * but NAPI might still haven't called us back. As the interrupt + * status register is cleared by reading, we should prevent an + * interrupt loss in this case... + */ + if (!np->intr_status) + intr_handler(dev->irq, dev); + enable_irq(dev->irq); } #endif diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 2807ef400fb..81742e4e561 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -72,6 +72,8 @@ #define FLASH_SECTOR_SIZE (64 * 1024) #define FLASH_TOTAL_SIZE (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE) +#define PHAN_VENDOR_ID 0x4040 + #define RCV_DESC_RINGSIZE \ (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) #define STATUS_DESC_RINGSIZE \ @@ -82,7 +84,7 @@ (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 find_diff_among(a,b,range) ((a)<=(b)?((b)-(a)):((b)+(range)-(a))) #define NETXEN_NETDEV_STATUS 0x1 #define NETXEN_RCV_PRODUCER_OFFSET 0 diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 6252e9a8727..986ef98db22 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -82,8 +82,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { #define NETXEN_NIC_STATS_LEN ARRAY_SIZE(netxen_nic_gstrings_stats) static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = { - "Register_Test_offline", "EEPROM_Test_offline", - "Interrupt_Test_offline", "Loopback_Test_offline", + "Register_Test_on_offline", "Link_Test_on_offline" }; @@ -394,19 +393,12 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) } } -static void -netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; - /* options can be added depending upon the mode */ - wol->wolopts = 0; -} - static u32 netxen_nic_test_link(struct net_device *dev) { struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; __u32 status; + int val; /* read which mode */ if (adapter->ahw.board_type == NETXEN_NIC_GBE) { @@ -415,11 +407,13 @@ static u32 netxen_nic_test_link(struct net_device *dev) NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status) != 0) return -EIO; - else - return (netxen_get_phy_link(status)); + else { + val = netxen_get_phy_link(status); + return !val; + } } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { - int val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); - return val == XG_LINK_UP; + val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); + return (val == XG_LINK_UP) ? 0 : 1; } return -EIO; } @@ -606,100 +600,21 @@ netxen_nic_set_pauseparam(struct net_device *dev, 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; - __u32 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 & NETXEN_NIC_INVALID_DATA; - else - data_written = NETXEN_NIC_INVALID_DATA; - 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 & NETXEN_NIC_INVALID_DATA; - else - data_written = NETXEN_NIC_INVALID_DATA; - 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; - } + struct netxen_adapter *adapter = netdev_priv(dev); + u32 data_read, data_written; - /* netxen_niu_gb_interface_status is read only */ - netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_INTERFACE_STATUS(port-> - portnum), - &data_read); + netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read); + if ((data_read & 0xffff) != PHAN_VENDOR_ID) + return 1; - save = data_read; - if (data_read) - data_written = data_read & NETXEN_NIC_INVALID_DATA; - else - data_written = NETXEN_NIC_INVALID_DATA; - netxen_nic_write_w0(adapter, - NETXEN_NIU_GB_INTERFACE_STATUS(port-> - portnum), - data_written); + data_written = (u32)0xa5a5a5a5; - netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_INTERFACE_STATUS(port-> - portnum), - &data_read); + netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written); + data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST)); + if (data_written != data_read) + return 1; - if (data_written == data_read) { - netxen_nic_write_w0(adapter, - NETXEN_NIU_GB_INTERFACE_STATUS - (port->portnum), save); - - return 0; - } - } /* GB Mode */ - return 1; + return 0; } static int netxen_nic_diag_test_count(struct net_device *dev) @@ -713,26 +628,20 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, { if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* offline tests */ /* link test */ - if (!(data[4] = (u64) netxen_nic_test_link(dev))) + if ((data[1] = (u64) netxen_nic_test_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))) + 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_test_link(dev))) + /* register tests */ + if((data[0] = netxen_nic_reg_test(dev))) eth_test->flags |= ETH_TEST_FL_FAILED; - /* other tests pass by default */ - data[0] = data[1] = data[2] = data[3] = 1; + /* link test */ + if ((data[1] = (u64) netxen_nic_test_link(dev))) + eth_test->flags |= ETH_TEST_FL_FAILED; } } @@ -783,7 +692,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .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 = ethtool_op_get_link, .get_eeprom_len = netxen_nic_get_eeprom_len, .get_eeprom = netxen_nic_get_eeprom, diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index deec796f90d..a2877f33fa8 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -508,8 +508,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 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; + u32 data, size = 0; + u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE; u64 off; void __iomem *addr; @@ -951,6 +951,7 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) netxen_nic_driver_name); return; } + *ptr32 = le32_to_cpu(*ptr32); ptr32++; addr += sizeof(u32); } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 2f965701a95..586d32b676a 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -38,13 +38,13 @@ #include "netxen_nic_phan_reg.h" struct crb_addr_pair { - long addr; - long data; + u32 addr; + u32 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 NETXEN_ADDR_ERROR (0xffffffff) #define crb_addr_transform(name) \ crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \ @@ -252,10 +252,10 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) * 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) +u32 netxen_decode_crb_addr(u32 addr) { int i; - unsigned long base_addr, offset, pci_base; + u32 base_addr, offset, pci_base; crb_addr_transform_setup(); @@ -756,7 +756,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) int n, i; int init_delay = 0; struct crb_addr_pair *buf; - unsigned long off; + u32 off; /* resetall */ status = netxen_nic_get_board_info(adapter); @@ -813,14 +813,13 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) if (verbose) printk("%s: PCI: 0x%08x == 0x%08x\n", netxen_nic_driver_name, (unsigned int) - netxen_decode_crb_addr((unsigned long) - addr), val); + netxen_decode_crb_addr(addr), val); } for (i = 0; i < n; i++) { - off = netxen_decode_crb_addr((unsigned long)buf[i].addr); + off = netxen_decode_crb_addr(buf[i].addr); if (off == NETXEN_ADDR_ERROR) { - printk(KERN_ERR"CRB init value out of range %lx\n", + printk(KERN_ERR"CRB init value out of range %x\n", buf[i].addr); continue; } @@ -927,6 +926,10 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) void netxen_free_adapter_offload(struct netxen_adapter *adapter) { if (adapter->dummy_dma.addr) { + writel(0, NETXEN_CRB_NORMALIZE(adapter, + CRB_HOST_DUMMY_BUF_ADDR_HI)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, + CRB_HOST_DUMMY_BUF_ADDR_LO)); pci_free_consistent(adapter->ahw.pdev, NETXEN_HOST_DUMMY_DMA_SIZE, adapter->dummy_dma.addr, diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 1bf3d494b92..7d2525e76ab 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -42,8 +42,6 @@ #include <linux/dma-mapping.h> #include <linux/vmalloc.h> -#define PHAN_VENDOR_ID 0x4040 - MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); @@ -379,6 +377,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->tx_timeout = netxen_tx_timeout; netdev->watchdog_timeo = HZ; + netxen_nic_change_mtu(netdev, netdev->mtu); + SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); netdev->poll = netxen_nic_poll; netdev->weight = NETXEN_NETDEV_WEIGHT; @@ -434,13 +434,11 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->port_count++; adapter->port[i] = port; } -#ifndef CONFIG_PPC64 writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); netxen_pinit_from_rom(adapter, 0); udelay(500); netxen_load_firmware(adapter); netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); -#endif /* * delay a while to ensure that the Pegs are up & running. * Otherwise, we might see some flaky behaviour. @@ -529,12 +527,13 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) free_irq(adapter->irq, adapter); netxen_nic_stop_all_ports(adapter); /* leave the hw in the same state as reboot */ - netxen_pinit_from_rom(adapter, 0); writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + netxen_pinit_from_rom(adapter, 0); + udelay(500); netxen_load_firmware(adapter); netxen_free_adapter_offload(adapter); - udelay(500); /* Delay for a while to drain the DMA engines */ + mdelay(1000); /* 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)) { @@ -545,7 +544,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) 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); @@ -556,6 +554,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { recv_ctx = &adapter->recv_ctx[ctxid]; diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 7879f855af0..0c7c94328b7 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -102,6 +102,9 @@ #define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0) #define CRB_TEMP_STATE NETXEN_NIC_REG(0x1b4) +/* used for ethtool tests */ +#define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) + /* * 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 diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 568daeb3e9d..9ec6e9e54f4 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -514,8 +514,7 @@ static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid spin_lock_irq(&dev->misc_lock); spin_lock(&dev->tx_lock); - if (dev->vlgrp) - dev->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(dev->vlgrp, vid, NULL); spin_unlock(&dev->tx_lock); spin_unlock_irq(&dev->misc_lock); } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 36f9d988278..4d94ba7899b 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1234,14 +1234,14 @@ static void pcnet32_rx_entry(struct net_device *dev, skb_put(skb, pkt_len); /* Make room */ pci_dma_sync_single_for_cpu(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ - 2, + pkt_len, PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, (unsigned char *)(lp->rx_skbuff[entry]->data), pkt_len, 0); pci_dma_sync_single_for_device(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ - 2, + pkt_len, PCI_DMA_FROMDEVICE); } lp->stats.rx_bytes += skb->len; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 860bb0f60f6..86e56f1f2f0 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -7,6 +7,12 @@ * * Version: 0.7.0 * + * 070228 : Fix to allow multiple sessions with same remote MAC and same + * session id by including the local device ifindex in the + * tuple identifying a session. This also ensures packets can't + * be injected into a session from interfaces other than the one + * specified by userspace. Florian Zumbiehl <florz@florz.de> + * (Oh, BTW, this one is YYMMDD, in case you were wondering ...) * 220102 : Fix module use count on failure in pppoe_create, pppox_sk -acme * 030700 : Fixed connect logic to allow for disconnect. * 270700 : Fixed potential SMP problems; we must protect against @@ -127,14 +133,14 @@ static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE]; * Set/get/delete/rehash items (internal versions) * **********************************************************************/ -static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr) +static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr, int ifindex) { int hash = hash_item(sid, addr); struct pppox_sock *ret; ret = item_hash_table[hash]; - while (ret && !cmp_addr(&ret->pppoe_pa, sid, addr)) + while (ret && !(cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_dev->ifindex == ifindex)) ret = ret->next; return ret; @@ -147,21 +153,19 @@ static int __set_item(struct pppox_sock *po) ret = item_hash_table[hash]; while (ret) { - if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa)) + if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_dev->ifindex == po->pppoe_dev->ifindex) return -EALREADY; ret = ret->next; } - if (!ret) { - po->next = item_hash_table[hash]; - item_hash_table[hash] = po; - } + po->next = item_hash_table[hash]; + item_hash_table[hash] = po; return 0; } -static struct pppox_sock *__delete_item(unsigned long sid, char *addr) +static struct pppox_sock *__delete_item(unsigned long sid, char *addr, int ifindex) { int hash = hash_item(sid, addr); struct pppox_sock *ret, **src; @@ -170,7 +174,7 @@ static struct pppox_sock *__delete_item(unsigned long sid, char *addr) src = &item_hash_table[hash]; while (ret) { - if (cmp_addr(&ret->pppoe_pa, sid, addr)) { + if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_dev->ifindex == ifindex) { *src = ret->next; break; } @@ -188,12 +192,12 @@ static struct pppox_sock *__delete_item(unsigned long sid, char *addr) * **********************************************************************/ static inline struct pppox_sock *get_item(unsigned long sid, - unsigned char *addr) + unsigned char *addr, int ifindex) { struct pppox_sock *po; read_lock_bh(&pppoe_hash_lock); - po = __get_item(sid, addr); + po = __get_item(sid, addr, ifindex); if (po) sock_hold(sk_pppox(po)); read_unlock_bh(&pppoe_hash_lock); @@ -203,7 +207,15 @@ static inline struct pppox_sock *get_item(unsigned long sid, static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) { - return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote); + struct net_device *dev = NULL; + int ifindex; + + dev = dev_get_by_name(sp->sa_addr.pppoe.dev); + if(!dev) + return NULL; + ifindex = dev->ifindex; + dev_put(dev); + return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex); } static inline int set_item(struct pppox_sock *po) @@ -220,12 +232,12 @@ static inline int set_item(struct pppox_sock *po) return i; } -static inline struct pppox_sock *delete_item(unsigned long sid, char *addr) +static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int ifindex) { struct pppox_sock *ret; write_lock_bh(&pppoe_hash_lock); - ret = __delete_item(sid, addr); + ret = __delete_item(sid, addr, ifindex); write_unlock_bh(&pppoe_hash_lock); return ret; @@ -391,7 +403,7 @@ static int pppoe_rcv(struct sk_buff *skb, ph = (struct pppoe_hdr *) skb->nh.raw; - po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); if (po != NULL) return sk_receive_skb(sk_pppox(po), skb, 0); drop: @@ -425,7 +437,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (ph->code != PADT_CODE) goto abort; - po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); if (po) { struct sock *sk = sk_pppox(po); @@ -517,7 +529,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); if (po->pppoe_pa.sid) { - delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote); + delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_dev->ifindex); } if (po->pppoe_dev) @@ -539,7 +551,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len, int flags) { struct sock *sk = sock->sk; - struct net_device *dev = NULL; + struct net_device *dev; struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; struct pppox_sock *po = pppox_sk(sk); int error; @@ -565,7 +577,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, pppox_unbind_sock(sk); /* Delete the old binding */ - delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote); + delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote,po->pppoe_dev->ifindex); if(po->pppoe_dev) dev_put(po->pppoe_dev); @@ -705,7 +717,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, break; /* PPPoE address from the user specifies an outbound - PPPoE address to which frames are forwarded to */ + PPPoE address which frames are forwarded to */ err = -EFAULT; if (copy_from_user(&po->pppoe_relay, (void __user *)arg, diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 3a14d19b72b..d3f65dab306 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2210,7 +2210,7 @@ static int ql_send_map(struct ql3_adapter *qdev, { struct oal *oal; struct oal_entry *oal_entry; - int len = skb->len; + int len = skb_headlen(skb); dma_addr_t map; int err; int completed_segs, i; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 13cf06ee97f..15d954e50ca 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -890,8 +890,7 @@ static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) unsigned long flags; spin_lock_irqsave(&tp->lock, flags); - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(tp->vlgrp, vid, NULL); spin_unlock_irqrestore(&tp->lock, flags); } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 44bb2395af8..46ebf141ee5 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -325,8 +325,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) unsigned long flags; spin_lock_irqsave(&nic->tx_lock, flags); - if (nic->vlgrp) - nic->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(nic->vlgrp, vid, NULL); spin_unlock_irqrestore(&nic->tx_lock, flags); } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index fb2b5305163..b3750f28427 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -968,10 +968,10 @@ static void mdio_write(struct net_device *net_dev, int phy_id, int location, static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr) { - int i = 0; + int i; u16 status; - while (i++ < 2) + for (i = 0; i < 2; i++) status = mdio_read(net_dev, phy_addr, MII_STATUS); mdio_write( net_dev, phy_addr, MII_CONTROL, MII_CNTL_RESET ); @@ -1430,7 +1430,7 @@ static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr) int i = 0; u32 status; - while (i++ < 2) + for (i = 0; i < 2; i++) status = mdio_read(net_dev, phy_addr, MII_STATUS); if (!(status & MII_STAT_LINK)){ @@ -1466,9 +1466,9 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex int phy_addr = sis_priv->cur_phy; u32 status; u16 autoadv, autorec; - int i = 0; + int i; - while (i++ < 2) + for (i = 0; i < 2; i++) status = mdio_read(net_dev, phy_addr, MII_STATUS); if (!(status & MII_STAT_LINK)) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 52edbd7ac17..53839979cfb 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1053,8 +1053,7 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); - if (sky2->vlgrp) - sky2->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(sky2->vlgrp, vid, NULL); netif_tx_unlock_bh(dev); } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index bf873ea2579..8bba2e3da7e 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -677,8 +677,7 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) spin_lock(&np->lock); if (debug > 1) printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid); - if (np->vlgrp) - np->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(np->vlgrp, vid, NULL); set_rx_mode(dev); spin_unlock(&np->lock); } @@ -1738,7 +1737,7 @@ static void set_rx_mode(struct net_device *dev) int vlan_count = 0; void __iomem *filter_addr = ioaddr + HashTable + 8; for (i = 0; i < VLAN_VID_MASK; i++) { - if (np->vlgrp->vlan_devices[i]) { + if (vlan_group_get_device(np->vlgrp, i)) { if (vlan_count >= 32) break; writew(cpu_to_be16(i), filter_addr); diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index eae2b63951f..e3a7e3ceab7 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1703,19 +1703,6 @@ static void tc35815_chip_init(struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); } -/* XXX */ -void -tc35815_killall(void) -{ - struct net_device *dev; - - for (dev = root_tc35815_dev; dev; dev = ((struct tc35815_local *)dev->priv)->next_module) { - if (dev->flags&IFF_UP){ - dev->stop(dev); - } - } -} - static struct pci_driver tc35815_driver = { .name = TC35815_MODULE_NAME, .probe = tc35815_probe, diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 26c6ac48288..8c8f9f4d47a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9114,8 +9114,7 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) tg3_netif_stop(tp); tg3_full_lock(tp, 0); - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(tp->vlgrp, vid, NULL); tg3_full_unlock(tp); if (netif_running(dev)) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 9d67f11422e..c82befa209a 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC (debug, "de2104x bitmapped message enable number"); /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ - || defined(__sparc_) || defined(__ia64__) \ + || defined(__sparc__) || defined(__ia64__) \ || defined(__sh__) || defined(__mips__) static int rx_copybreak = 1518; #else @@ -1685,7 +1685,7 @@ static const struct ethtool_ops de_ethtool_ops = { .get_regs = de_get_regs, }; -static void __init de21040_get_mac_address (struct de_private *de) +static void __devinit de21040_get_mac_address (struct de_private *de) { unsigned i; @@ -1703,7 +1703,7 @@ static void __init de21040_get_mac_address (struct de_private *de) } } -static void __init de21040_get_media_info(struct de_private *de) +static void __devinit de21040_get_media_info(struct de_private *de) { unsigned int i; @@ -1765,7 +1765,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in return retval; } -static void __init de21041_get_srom_info (struct de_private *de) +static void __devinit de21041_get_srom_info (struct de_private *de) { unsigned i, sa_offset = 0, ofs; u8 ee_data[DE_EEPROM_SIZE + 6] = {}; diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 7f59a3d4fda..24a29c99ba9 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -143,9 +143,16 @@ #define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */ #define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */ -#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value)) +#define DMFE_DBUG(dbug_now, msg, value) \ + do { \ + if (dmfe_debug || (dbug_now)) \ + printk(KERN_ERR DRV_NAME ": %s %lx\n",\ + (msg), (long) (value)); \ + } while (0) -#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half"); +#define SHOW_MEDIA_TYPE(mode) \ + printk (KERN_INFO DRV_NAME ": Change Speed to %sMhz %s duplex\n" , \ + (mode & 1) ? "100":"10", (mode & 4) ? "full":"half"); /* CR9 definition: SROM/MII */ @@ -163,10 +170,20 @@ #define SROM_V41_CODE 0x14 -#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5); +#define SROM_CLK_WRITE(data, ioaddr) \ + outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \ + udelay(5); \ + outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \ + udelay(5); \ + outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \ + udelay(5); + +#define __CHK_IO_SIZE(pci_id, dev_rev) \ + (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \ + DM9102A_IO_SIZE: DM9102_IO_SIZE) -#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE -#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev) +#define CHK_IO_SIZE(pci_dev, dev_rev) \ + (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)) /* Sten Check */ #define DEVICE net_device @@ -187,7 +204,7 @@ struct rx_desc { struct dmfe_board_info { u32 chip_id; /* Chip vendor/Device ID */ u32 chip_revision; /* Chip revision */ - struct DEVICE *dev; /* net device */ + struct DEVICE *next_dev; /* next device */ struct pci_dev *pdev; /* PCI device */ spinlock_t lock; @@ -231,7 +248,6 @@ struct dmfe_board_info { u8 media_mode; /* user specify media mode */ u8 op_mode; /* real work media mode */ u8 phy_addr; - u8 link_failed; /* Ever link failed */ u8 wait_reset; /* Hardware failed, need to reset */ u8 dm910x_chk_mode; /* Operating mode check */ u8 first_in_callback; /* Flag to record state */ @@ -329,7 +345,7 @@ static void dmfe_program_DM9802(struct dmfe_board_info *); static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * ); static void dmfe_set_phyxcer(struct dmfe_board_info *); -/* DM910X network baord routine ---------------------------- */ +/* DM910X network board routine ---------------------------- */ /* * Search DM910X board ,allocate space and register it @@ -356,7 +372,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n"); + printk(KERN_WARNING DRV_NAME + ": 32-bit PCI DMA not available.\n"); err = -ENODEV; goto err_out_free; } @@ -399,11 +416,12 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* Init system & device */ db = netdev_priv(dev); - db->dev = dev; - /* Allocate Tx/Rx descriptor memory */ - db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr); - db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr); + db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * + DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr); + + db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * + TX_DESC_CNT + 4, &db->buf_pool_dma_ptr); db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr; db->first_tx_desc_dma = db->desc_pool_dma_ptr; @@ -428,7 +446,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, dev->poll_controller = &poll_dmfe; #endif dev->ethtool_ops = &netdev_ethtool_ops; - netif_carrier_off(db->dev); + netif_carrier_off(dev); spin_lock_init(&db->lock); pci_read_config_dword(pdev, 0x50, &pci_pmr); @@ -440,7 +458,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* read 64 word srom data */ for (i = 0; i < 64; i++) - ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i)); + ((u16 *) db->srom)[i] = + cpu_to_le16(read_srom_word(db->ioaddr, i)); /* Set Node address */ for (i = 0; i < 6; i++) @@ -482,14 +501,17 @@ static void __devexit dmfe_remove_one (struct pci_dev *pdev) DMFE_DBUG(0, "dmfe_remove_one()", 0); if (dev) { + + unregister_netdev(dev); + pci_free_consistent(db->pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, db->desc_pool_ptr, db->desc_pool_dma_ptr); pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, db->buf_pool_ptr, db->buf_pool_dma_ptr); - unregister_netdev(dev); pci_release_regions(pdev); free_netdev(dev); /* free board information */ + pci_set_drvdata(pdev, NULL); } @@ -509,7 +531,8 @@ static int dmfe_open(struct DEVICE *dev) DMFE_DBUG(0, "dmfe_open", 0); - ret = request_irq(dev->irq, &dmfe_interrupt, IRQF_SHARED, dev->name, dev); + ret = request_irq(dev->irq, &dmfe_interrupt, + IRQF_SHARED, dev->name, dev); if (ret) return ret; @@ -518,7 +541,6 @@ static int dmfe_open(struct DEVICE *dev) db->tx_packet_cnt = 0; db->tx_queue_cnt = 0; db->rx_avail_cnt = 0; - db->link_failed = 1; db->wait_reset = 0; db->first_in_callback = 0; @@ -650,7 +672,8 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev) /* No Tx resource check, it never happen nromally */ if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); - printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_queue_cnt); + printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", + db->tx_queue_cnt); return 1; } @@ -722,7 +745,8 @@ static int dmfe_stop(struct DEVICE *dev) #if 0 /* show statistic counter */ - printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n", + printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx" + " LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n", db->tx_fifo_underrun, db->tx_excessive_collision, db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier, db->tx_jabber_timeout, db->reset_count, db->reset_cr8, @@ -905,7 +929,7 @@ static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) { struct rx_desc *rxptr; - struct sk_buff *skb; + struct sk_buff *skb, *newskb; int rxlen; u32 rdes0; @@ -919,7 +943,9 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) db->rx_avail_cnt--; db->interval_rx_cnt++; - pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE); + pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), + RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE); + if ( (rdes0 & 0x300) != 0x300) { /* A packet without First/Last flag */ /* reuse this SKB */ @@ -956,9 +982,11 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) } else { /* Good packet, send to upper layer */ /* Shorst packet used new SKB */ - if ( (rxlen < RX_COPY_SIZE) && - ( (skb = dev_alloc_skb(rxlen + 2) ) - != NULL) ) { + if ((rxlen < RX_COPY_SIZE) && + ((newskb = dev_alloc_skb(rxlen + 2)) + != NULL)) { + + skb = newskb; /* size less than COPY_SIZE, allocate a rxlen SKB */ skb->dev = dev; skb_reserve(skb, 2); /* 16byte align */ @@ -1069,6 +1097,8 @@ static void dmfe_timer(unsigned long data) struct dmfe_board_info *db = netdev_priv(dev); unsigned long flags; + int link_ok, link_ok_phy; + DMFE_DBUG(0, "dmfe_timer()", 0); spin_lock_irqsave(&db->lock, flags); @@ -1078,7 +1108,8 @@ static void dmfe_timer(unsigned long data) if (db->chip_type && (db->chip_id==PCI_DM9102_ID)) { db->cr6_data &= ~0x40000; update_cr6(db->cr6_data, db->ioaddr); - phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id); + phy_write(db->ioaddr, + db->phy_addr, 0, 0x1000, db->chip_id); db->cr6_data |= 0x40000; update_cr6(db->cr6_data, db->ioaddr); db->timer.expires = DMFE_TIMER_WUT + HZ * 2; @@ -1139,21 +1170,41 @@ static void dmfe_timer(unsigned long data) (db->chip_revision == 0x02000010)) ) { /* DM9102A Chip */ if (tmp_cr12 & 2) - tmp_cr12 = 0x0; /* Link failed */ + link_ok = 0; else - tmp_cr12 = 0x3; /* Link OK */ + link_ok = 1; } + else + /*0x43 is used instead of 0x3 because bit 6 should represent + link status of external PHY */ + link_ok = (tmp_cr12 & 0x43) ? 1 : 0; + + + /* If chip reports that link is failed it could be because external + PHY link status pin is not conected correctly to chip + To be sure ask PHY too. + */ + + /* need a dummy read because of PHY's register latch*/ + phy_read (db->ioaddr, db->phy_addr, 1, db->chip_id); + link_ok_phy = (phy_read (db->ioaddr, + db->phy_addr, 1, db->chip_id) & 0x4) ? 1 : 0; - if ( !(tmp_cr12 & 0x3) && !db->link_failed ) { + if (link_ok_phy != link_ok) { + DMFE_DBUG (0, "PHY and chip report different link status", 0); + link_ok = link_ok | link_ok_phy; + } + + if ( !link_ok && netif_carrier_ok(dev)) { /* Link Failed */ DMFE_DBUG(0, "Link Failed", tmp_cr12); - db->link_failed = 1; - netif_carrier_off(db->dev); + netif_carrier_off(dev); /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */ /* AUTO or force 1M Homerun/Longrun don't need */ if ( !(db->media_mode & 0x38) ) - phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id); + phy_write(db->ioaddr, db->phy_addr, + 0, 0x1000, db->chip_id); /* AUTO mode, if INT phyxcer link failed, select EXT device */ if (db->media_mode & DMFE_AUTO) { @@ -1162,21 +1213,19 @@ static void dmfe_timer(unsigned long data) db->cr6_data&=~0x00000200; /* bit9=0, HD mode */ update_cr6(db->cr6_data, db->ioaddr); } - } else - if ((tmp_cr12 & 0x3) && db->link_failed) { - DMFE_DBUG(0, "Link link OK", tmp_cr12); - db->link_failed = 0; - - /* Auto Sense Speed */ - if ( (db->media_mode & DMFE_AUTO) && - dmfe_sense_speed(db) ) - db->link_failed = 1; - else - netif_carrier_on(db->dev); - dmfe_process_mode(db); - /* SHOW_MEDIA_TYPE(db->op_mode); */ + } else if (!netif_carrier_ok(dev)) { + + DMFE_DBUG(0, "Link link OK", tmp_cr12); + + /* Auto Sense Speed */ + if ( !(db->media_mode & DMFE_AUTO) || !dmfe_sense_speed(db)) { + netif_carrier_on(dev); + SHOW_MEDIA_TYPE(db->op_mode); } + dmfe_process_mode(db); + } + /* HPNA remote command check */ if (db->HPNA_command & 0xf00) { db->HPNA_timer--; @@ -1221,7 +1270,7 @@ static void dmfe_dynamic_reset(struct DEVICE *dev) db->tx_packet_cnt = 0; db->tx_queue_cnt = 0; db->rx_avail_cnt = 0; - db->link_failed = 1; + netif_carrier_off(dev); db->wait_reset = 0; /* Re-initilize DM910X board */ @@ -1259,7 +1308,8 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb) if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) { rxptr->rx_skb_ptr = skb; - rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); + rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, + skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); wmb(); rxptr->rdes0 = cpu_to_le32(0x80000000); db->rx_avail_cnt++; @@ -1291,8 +1341,11 @@ static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioadd outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */ /* rx descriptor start pointer */ - db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT; - db->first_rx_desc_dma = db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT; + db->first_rx_desc = (void *)db->first_tx_desc + + sizeof(struct tx_desc) * TX_DESC_CNT; + + db->first_rx_desc_dma = db->first_tx_desc_dma + + sizeof(struct tx_desc) * TX_DESC_CNT; db->rx_insert_ptr = db->first_rx_desc; db->rx_ready_ptr = db->first_rx_desc; outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */ @@ -1470,7 +1523,8 @@ static void allocate_rx_buffer(struct dmfe_board_info *db) if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL ) break; rxptr->rx_skb_ptr = skb; /* FIXME (?) */ - rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); + rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, + RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); wmb(); rxptr->rdes0 = cpu_to_le32(0x80000000); rxptr = rxptr->next_rx_desc; @@ -1510,7 +1564,8 @@ static u16 read_srom_word(long ioaddr, int offset) for (i = 16; i > 0; i--) { outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr); udelay(5); - srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0); + srom_data = (srom_data << 1) | + ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0); outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); udelay(5); } @@ -1537,9 +1592,11 @@ static u8 dmfe_sense_speed(struct dmfe_board_info * db) if ( (phy_mode & 0x24) == 0x24 ) { if (db->chip_id == PCI_DM9132_ID) /* DM9132 */ - phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000; + phy_mode = phy_read(db->ioaddr, + db->phy_addr, 7, db->chip_id) & 0xf000; else /* DM9102/DM9102A */ - phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000; + phy_mode = phy_read(db->ioaddr, + db->phy_addr, 17, db->chip_id) & 0xf000; /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */ switch (phy_mode) { case 0x1000: db->op_mode = DMFE_10MHF; break; @@ -1576,8 +1633,11 @@ static void dmfe_set_phyxcer(struct dmfe_board_info *db) /* DM9009 Chip: Phyxcer reg18 bit12=0 */ if (db->chip_id == PCI_DM9009_ID) { - phy_reg = phy_read(db->ioaddr, db->phy_addr, 18, db->chip_id) & ~0x1000; - phy_write(db->ioaddr, db->phy_addr, 18, phy_reg, db->chip_id); + phy_reg = phy_read(db->ioaddr, + db->phy_addr, 18, db->chip_id) & ~0x1000; + + phy_write(db->ioaddr, + db->phy_addr, 18, phy_reg, db->chip_id); } /* Phyxcer capability setting */ @@ -1650,10 +1710,12 @@ static void dmfe_process_mode(struct dmfe_board_info *db) case DMFE_100MHF: phy_reg = 0x2000; break; case DMFE_100MFD: phy_reg = 0x2100; break; } - phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id); + phy_write(db->ioaddr, + db->phy_addr, 0, phy_reg, db->chip_id); if ( db->chip_type && (db->chip_id == PCI_DM9102_ID) ) mdelay(20); - phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id); + phy_write(db->ioaddr, + db->phy_addr, 0, phy_reg, db->chip_id); } } } @@ -1663,7 +1725,8 @@ static void dmfe_process_mode(struct dmfe_board_info *db) * Write a word to Phy register */ -static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id) +static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, + u16 phy_data, u32 chip_id) { u16 i; unsigned long ioaddr; @@ -1689,11 +1752,13 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); + phy_write_1bit(ioaddr, + phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0); + phy_write_1bit(ioaddr, + offset & i ? PHY_DATA_1 : PHY_DATA_0); /* written trasnition */ phy_write_1bit(ioaddr, PHY_DATA_1); @@ -1701,7 +1766,8 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data /* Write a word data to PHY controller */ for ( i = 0x8000; i > 0; i >>= 1) - phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0); + phy_write_1bit(ioaddr, + phy_data & i ? PHY_DATA_1 : PHY_DATA_0); } } @@ -1738,11 +1804,13 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id) /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); + phy_write_1bit(ioaddr, + phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0); + phy_write_1bit(ioaddr, + offset & i ? PHY_DATA_1 : PHY_DATA_0); /* Skip transition state */ phy_read_1bit(ioaddr); @@ -1963,7 +2031,8 @@ static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db) /* Check remote device status match our setting ot not */ if ( phy_reg != (db->HPNA_command & 0x0f00) ) { - phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id); + phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, + db->chip_id); db->HPNA_timer=8; } else db->HPNA_timer=600; /* Match, every 10 minutes, check */ @@ -2003,8 +2072,11 @@ module_param(HPNA_tx_cmd, byte, 0); module_param(HPNA_NoiseFloor, byte, 0); module_param(SF_mode, byte, 0); MODULE_PARM_DESC(debug, "Davicom DM9xxx enable debugging (0-1)"); -MODULE_PARM_DESC(mode, "Davicom DM9xxx: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); -MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function (bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)"); +MODULE_PARM_DESC(mode, "Davicom DM9xxx: " + "Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); + +MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function " + "(bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)"); /* Description: * when user used insmod to add module, system invoked init_module() diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 5a35354aa52..e3774a52237 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -67,7 +67,7 @@ const char * const medianame[32] = { /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ - || defined(__sparc_) || defined(__ia64__) \ + || defined(__sparc__) || defined(__ia64__) \ || defined(__sh__) || defined(__mips__) static int rx_copybreak = 1518; #else diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 9781b16bb8b..0d91d094edd 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -746,8 +746,7 @@ typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct typhoon *tp = netdev_priv(dev); spin_lock_bh(&tp->state_lock); - if(tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(tp->vlgrp, vid, NULL); spin_unlock_bh(&tp->state_lock); } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 885e73d731c..dab88b958d6 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3598,17 +3598,20 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Move to next BD in the ring */ if (!(bd_status & T_W)) - ugeth->txBd[txQ] = bd + sizeof(struct qe_bd); + bd += sizeof(struct qe_bd); else - ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ]; + bd = ugeth->p_tx_bd_ring[txQ]; /* If the next BD still needs to be cleaned up, then the bds are full. We need to tell the kernel to stop sending us stuff. */ if (bd == ugeth->confBd[txQ]) { if (!netif_queue_stopped(dev)) netif_stop_queue(dev); + return NETDEV_TX_BUSY; } + ugeth->txBd[txQ] = bd; + if (ugeth->p_scheduler) { ugeth->cpucount[txQ]++; /* Indicate to QE that there are more Tx bds ready for @@ -3620,7 +3623,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&ugeth->lock); - return 0; + return NETDEV_TX_OK; } static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) @@ -3722,7 +3725,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Handle the transmitted buffer and release */ /* the BD to be used with the current frame */ - if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) + if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) break; ugeth->stats.tx_packets++; @@ -3741,10 +3744,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Advance the confirmation BD pointer */ if (!(bd_status & T_W)) - ugeth->confBd[txQ] += sizeof(struct qe_bd); + bd += sizeof(struct qe_bd); else - ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ]; + bd = ugeth->p_tx_bd_ring[txQ]; + bd_status = in_be32((u32 *)bd); } + ugeth->confBd[txQ] = bd; return 0; } diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 9040d7cf651..65ad2e24caf 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -38,7 +38,7 @@ #include <linux/hdlc.h> -static const char* version = "HDLC support module revision 1.20"; +static const char* version = "HDLC support module revision 1.21"; #undef DEBUG_LINK @@ -222,19 +222,31 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; } +static void hdlc_setup_dev(struct net_device *dev) +{ + /* Re-init all variables changed by HDLC protocol drivers, + * including ether_setup() called from hdlc_raw_eth.c. + */ + dev->get_stats = hdlc_get_stats; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->mtu = HDLC_MAX_MTU; + dev->type = ARPHRD_RAWHDLC; + dev->hard_header_len = 16; + dev->addr_len = 0; + dev->hard_header = NULL; + dev->rebuild_header = NULL; + dev->set_mac_address = NULL; + dev->hard_header_cache = NULL; + dev->header_cache_update = NULL; + dev->change_mtu = hdlc_change_mtu; + dev->hard_header_parse = NULL; +} + static void hdlc_setup(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - dev->get_stats = hdlc_get_stats; - dev->change_mtu = hdlc_change_mtu; - dev->mtu = HDLC_MAX_MTU; - - dev->type = ARPHRD_RAWHDLC; - dev->hard_header_len = 16; - - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - + hdlc_setup_dev(dev); hdlc->carrier = 1; hdlc->open = 0; spin_lock_init(&hdlc->state_lock); @@ -294,6 +306,7 @@ void detach_hdlc_protocol(struct net_device *dev) } kfree(hdlc->state); hdlc->state = NULL; + hdlc_setup_dev(dev); } diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index b0bc5ddcf1b..c9664fd8a91 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -365,10 +365,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) memcpy(&state(hdlc)->settings, &new_settings, size); dev->hard_start_xmit = hdlc->xmit; dev->hard_header = cisco_hard_header; - dev->hard_header_cache = NULL; dev->type = ARPHRD_CISCO; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; netif_dormant_on(dev); return 0; } diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index b45ab680d2d..c6c3c757d6f 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1289,10 +1289,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) memcpy(&state(hdlc)->settings, &new_settings, size); dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; dev->type = ARPHRD_FRAD; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; return 0; case IF_PROTO_FR_ADD_PVC: diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index e9f717070fd..4591437dd2f 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -127,9 +127,7 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; dev->type = ARPHRD_PPP; - dev->addr_len = 0; netif_dormant_off(dev); return 0; } diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index fe3cae5c6b9..e23bc665626 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -88,10 +88,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) return result; memcpy(hdlc->state, &new_settings, size); dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; dev->type = ARPHRD_RAWHDLC; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; netif_dormant_off(dev); return 0; } diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index e4bb9f8ad43..cd7b22f50ed 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -215,9 +215,7 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) x25_rx, 0)) != 0) return result; dev->hard_start_xmit = x25_xmit; - dev->hard_header = NULL; dev->type = ARPHRD_X25; - dev->addr_len = 0; netif_dormant_off(dev); return 0; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 73c831a3b74..e594af46ff0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2733,8 +2733,9 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) * dangling pins on the second core. Be careful * and ignore these cores here. */ - if (bcm->pci_dev->device != 0x4324) { - dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n"); + if (1 /*bcm->pci_dev->device != 0x4324*/ ) { + /* TODO: A PHY */ + dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n"); continue; } } diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 68555c11f55..01869b1782e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -38,6 +38,36 @@ static int msi_cache_init(void) return 0; } +static void msi_set_enable(struct pci_dev *dev, int enable) +{ + int pos; + u16 control; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos) { + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + control &= ~PCI_MSI_FLAGS_ENABLE; + if (enable) + control |= PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} + +static void msix_set_enable(struct pci_dev *dev, int enable) +{ + int pos; + u16 control; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); + control &= ~PCI_MSIX_FLAGS_ENABLE; + if (enable) + control |= PCI_MSIX_FLAGS_ENABLE; + pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + } +} + static void msi_set_mask_bit(unsigned int irq, int flag) { struct msi_desc *entry; @@ -55,6 +85,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag) mask_bits &= ~(1); mask_bits |= flag; pci_write_config_dword(entry->dev, pos, mask_bits); + } else { + msi_set_enable(entry->dev, !flag); } break; case PCI_CAP_ID_MSIX: @@ -192,44 +224,6 @@ static struct msi_desc* alloc_msi_entry(void) return entry; } -static void enable_msi_mode(struct pci_dev *dev, int pos, int type) -{ - u16 control; - - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (type == PCI_CAP_ID_MSI) { - /* Set enabled bits to single MSI & enable MSI_enable bit */ - msi_enable(control, 1); - pci_write_config_word(dev, msi_control_reg(pos), control); - dev->msi_enabled = 1; - } else { - msix_enable(control); - pci_write_config_word(dev, msi_control_reg(pos), control); - dev->msix_enabled = 1; - } - - pci_intx(dev, 0); /* disable intx */ -} - -void disable_msi_mode(struct pci_dev *dev, int pos, int type) -{ - u16 control; - - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (type == PCI_CAP_ID_MSI) { - /* Set enabled bits to single MSI & enable MSI_enable bit */ - msi_disable(control); - pci_write_config_word(dev, msi_control_reg(pos), control); - dev->msi_enabled = 0; - } else { - msix_disable(control); - pci_write_config_word(dev, msi_control_reg(pos), control); - dev->msix_enabled = 0; - } - - pci_intx(dev, 1); /* enable intx */ -} - #ifdef CONFIG_PM static int __pci_save_msi_state(struct pci_dev *dev) { @@ -238,12 +232,11 @@ static int __pci_save_msi_state(struct pci_dev *dev) struct pci_cap_saved_state *save_state; u32 *cap; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (pos <= 0 || dev->no_msi) + if (!dev->msi_enabled) return 0; - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (!(control & PCI_MSI_FLAGS_ENABLE)) + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos <= 0) return 0; save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5, @@ -276,13 +269,18 @@ static void __pci_restore_msi_state(struct pci_dev *dev) struct pci_cap_saved_state *save_state; u32 *cap; + if (!dev->msi_enabled) + return; + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI); pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (!save_state || pos <= 0) return; cap = &save_state->data[0]; + pci_intx(dev, 0); /* disable intx */ control = cap[i++] >> 16; + msi_set_enable(dev, 0); pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]); if (control & PCI_MSI_FLAGS_64BIT) { pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]); @@ -292,7 +290,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev) if (control & PCI_MSI_FLAGS_MASKBIT) pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]); pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); - enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); pci_remove_saved_cap(save_state); kfree(save_state); } @@ -308,13 +305,11 @@ static int __pci_save_msix_state(struct pci_dev *dev) return 0; pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos <= 0 || dev->no_msi) + if (pos <= 0) return 0; /* save the capability */ pci_read_config_word(dev, msi_control_reg(pos), &control); - if (!(control & PCI_MSIX_FLAGS_ENABLE)) - return 0; save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), GFP_KERNEL); if (!save_state) { @@ -376,6 +371,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev) return; /* route the table */ + pci_intx(dev, 0); /* disable intx */ + msix_set_enable(dev, 0); irq = head = dev->first_msi_irq; while (head != tail) { entry = get_irq_msi(irq); @@ -386,7 +383,6 @@ static void __pci_restore_msix_state(struct pci_dev *dev) } pci_write_config_word(dev, msi_control_reg(pos), save); - enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); } void pci_restore_msi_state(struct pci_dev *dev) @@ -411,6 +407,8 @@ static int msi_capability_init(struct pci_dev *dev) int pos, irq; u16 control; + msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ @@ -454,7 +452,9 @@ static int msi_capability_init(struct pci_dev *dev) set_irq_msi(irq, entry); /* Set MSI enabled bits */ - enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + pci_intx(dev, 0); /* disable intx */ + msi_set_enable(dev, 1); + dev->msi_enabled = 1; dev->irq = irq; return 0; @@ -481,6 +481,8 @@ static int msix_capability_init(struct pci_dev *dev, u8 bir; void __iomem *base; + msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */ + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); /* Request & Map MSI-X table region */ pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -549,7 +551,9 @@ static int msix_capability_init(struct pci_dev *dev, } dev->first_msi_irq = entries[0].vector; /* Set MSI-X enabled bits */ - enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); + pci_intx(dev, 0); /* disable intx */ + msix_set_enable(dev, 1); + dev->msix_enabled = 1; return 0; } @@ -611,12 +615,11 @@ int pci_enable_msi(struct pci_dev* dev) WARN_ON(!!dev->msi_enabled); /* Check whether driver already requested for MSI-X irqs */ - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos > 0 && dev->msix_enabled) { - printk(KERN_INFO "PCI: %s: Can't enable MSI. " - "Device already has MSI-X enabled\n", - pci_name(dev)); - return -EINVAL; + if (dev->msix_enabled) { + printk(KERN_INFO "PCI: %s: Can't enable MSI. " + "Device already has MSI-X enabled\n", + pci_name(dev)); + return -EINVAL; } status = msi_capability_init(dev); return status; @@ -625,8 +628,7 @@ int pci_enable_msi(struct pci_dev* dev) void pci_disable_msi(struct pci_dev* dev) { struct msi_desc *entry; - int pos, default_irq; - u16 control; + int default_irq; if (!pci_msi_enable) return; @@ -636,16 +638,9 @@ void pci_disable_msi(struct pci_dev* dev) if (!dev->msi_enabled) return; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (!pos) - return; - - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (!(control & PCI_MSI_FLAGS_ENABLE)) - return; - - - disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + msi_set_enable(dev, 0); + pci_intx(dev, 1); /* enable intx */ + dev->msi_enabled = 0; entry = get_irq_msi(dev->first_msi_irq); if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { @@ -746,8 +741,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) WARN_ON(!!dev->msix_enabled); /* Check whether driver already requested for MSI irq */ - if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && - dev->msi_enabled) { + if (dev->msi_enabled) { printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " "Device already has an MSI irq assigned\n", pci_name(dev)); @@ -760,8 +754,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) void pci_disable_msix(struct pci_dev* dev) { int irq, head, tail = 0, warning = 0; - int pos; - u16 control; if (!pci_msi_enable) return; @@ -771,15 +763,9 @@ void pci_disable_msix(struct pci_dev* dev) if (!dev->msix_enabled) return; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (!pos) - return; - - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (!(control & PCI_MSIX_FLAGS_ENABLE)) - return; - - disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); + msix_set_enable(dev, 0); + pci_intx(dev, 1); /* enable intx */ + dev->msix_enabled = 0; irq = head = dev->first_msi_irq; while (head != tail) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1e74e1ee8bd..df495300ce3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -881,13 +881,6 @@ pci_disable_device(struct pci_dev *dev) 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); - if (dev->msix_enabled) - disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), - PCI_CAP_ID_MSIX); - pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; @@ -1277,6 +1270,33 @@ pci_intx(struct pci_dev *pdev, int enable) } } +/** + * pci_msi_off - disables any msi or msix capabilities + * @pdev: the PCI device to operate on + * + * If you want to use msi see pci_enable_msi and friends. + * This is a lower level primitive that allows us to disable + * msi operation at the device level. + */ +void pci_msi_off(struct pci_dev *dev) +{ + int pos; + u16 control; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos) { + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + control &= ~PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); + control &= ~PCI_MSIX_FLAGS_ENABLE; + pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + } +} + #ifndef HAVE_ARCH_PCI_SET_DMA_MASK /* * These can be overridden by arch-specific implementations diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a4f2d580625..ae7a975995a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -46,10 +46,8 @@ extern struct rw_semaphore pci_bus_sem; extern unsigned int pci_pm_d3_delay; #ifdef CONFIG_PCI_MSI -void disable_msi_mode(struct pci_dev *dev, int pos, int type); void pci_no_msi(void); #else -static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } static inline void pci_no_msi(void) { } #endif diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2fe1d690eb1..a4a96826d9e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -682,7 +682,34 @@ static void pci_read_irq(struct pci_dev *dev) dev->irq = irq; } -#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) +static void change_legacy_io_resource(struct pci_dev * dev, unsigned index, + unsigned start, unsigned end) +{ + unsigned base = start & PCI_BASE_ADDRESS_IO_MASK; + unsigned len = (end | ~PCI_BASE_ADDRESS_IO_MASK) - base + 1; + + /* + * Some X versions get confused when the BARs reported through + * /sys or /proc differ from those seen in config space, thus + * try to update the config space values, too. + */ + if (!(pci_resource_flags(dev, index) & IORESOURCE_IO)) + printk(KERN_WARNING "%s: cannot adjust BAR%u (not I/O)\n", + pci_name(dev), index); + else if (pci_resource_len(dev, index) != len) + printk(KERN_WARNING "%s: cannot adjust BAR%u (size %04X)\n", + pci_name(dev), index, (unsigned)pci_resource_len(dev, index)); + else { + printk(KERN_INFO "%s: trying to change BAR%u from %04X to %04X\n", + pci_name(dev), index, + (unsigned)pci_resource_start(dev, index), base); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + index * 4, base); + } + pci_resource_start(dev, index) = start; + pci_resource_end(dev, index) = end; + pci_resource_flags(dev, index) = + IORESOURCE_IO | IORESOURCE_PCI_FIXED | PCI_BASE_ADDRESS_SPACE_IO; +} /** * pci_setup_device - fill in class and map information of a device @@ -735,20 +762,12 @@ static int pci_setup_device(struct pci_dev * dev) 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 = LEGACY_IO_RESOURCE; - dev->resource[1].start = 0x3F6; - dev->resource[1].end = 0x3F6; - dev->resource[1].flags = LEGACY_IO_RESOURCE; + change_legacy_io_resource(dev, 0, 0x1F0, 0x1F7); + change_legacy_io_resource(dev, 1, 0x3F6, 0x3F6); } if ((progif & 4) == 0) { - dev->resource[2].start = 0x170; - dev->resource[2].end = 0x177; - dev->resource[2].flags = LEGACY_IO_RESOURCE; - dev->resource[3].start = 0x376; - dev->resource[3].end = 0x376; - dev->resource[3].flags = LEGACY_IO_RESOURCE; + change_legacy_io_resource(dev, 2, 0x170, 0x177); + change_legacy_io_resource(dev, 3, 0x376, 0x376); } } break; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1e6eda25c0d..7f94fc098cd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1218,45 +1218,68 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_a * do this early on to make the additional device appear during * the PCI scanning. */ - -static void quirk_jmicron_dualfn(struct pci_dev *pdev) +static void quirk_jmicron_ata(struct pci_dev *pdev) { - u32 conf; + u32 conf1, conf5, class; u8 hdr; /* Only poke fn 0 */ if (PCI_FUNC(pdev->devfn)) return; - switch(pdev->device) { - case PCI_DEVICE_ID_JMICRON_JMB365: - case PCI_DEVICE_ID_JMICRON_JMB366: - /* Redirect IDE second PATA port to the right spot */ - pci_read_config_dword(pdev, 0x80, &conf); - conf |= (1 << 24); - /* Fall through */ - pci_write_config_dword(pdev, 0x80, conf); - case PCI_DEVICE_ID_JMICRON_JMB361: - case PCI_DEVICE_ID_JMICRON_JMB363: - pci_read_config_dword(pdev, 0x40, &conf); - /* Enable dual function mode, AHCI on fn 0, IDE fn1 */ - /* Set the class codes correctly and then direct IDE 0 */ - conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */ - conf |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */ - pci_write_config_dword(pdev, 0x40, conf); - - /* Reconfigure so that the PCI scanner discovers the - device is now multifunction */ - - pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr); - pdev->hdr_type = hdr & 0x7f; - pdev->multifunction = !!(hdr & 0x80); + pci_read_config_dword(pdev, 0x40, &conf1); + pci_read_config_dword(pdev, 0x80, &conf5); - break; + conf1 &= ~0x00CFF302; /* Clear bit 1, 8, 9, 12-19, 22, 23 */ + conf5 &= ~(1 << 24); /* Clear bit 24 */ + + switch (pdev->device) { + case PCI_DEVICE_ID_JMICRON_JMB360: + /* The controller should be in single function ahci mode */ + conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */ + break; + + case PCI_DEVICE_ID_JMICRON_JMB365: + case PCI_DEVICE_ID_JMICRON_JMB366: + /* Redirect IDE second PATA port to the right spot */ + conf5 |= (1 << 24); + /* Fall through */ + case PCI_DEVICE_ID_JMICRON_JMB361: + case PCI_DEVICE_ID_JMICRON_JMB363: + /* Enable dual function mode, AHCI on fn 0, IDE fn1 */ + /* Set the class codes correctly and then direct IDE 0 */ + conf1 |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */ + break; + + case PCI_DEVICE_ID_JMICRON_JMB368: + /* The controller should be in single function IDE mode */ + conf1 |= 0x00C00000; /* Set 22, 23 */ + break; } -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); + + pci_write_config_dword(pdev, 0x40, conf1); + pci_write_config_dword(pdev, 0x80, conf5); + + /* Update pdev accordingly */ + pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr); + pdev->hdr_type = hdr & 0x7f; + pdev->multifunction = !!(hdr & 0x80); + + pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class); + pdev->class = class >> 8; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); #endif @@ -1415,8 +1438,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quir */ static void __devinit quirk_pcie_pxh(struct pci_dev *dev) { - disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), - PCI_CAP_ID_MSI); + pci_msi_off(dev); + dev->no_msi = 1; printk(KERN_WARNING "PCI: PXH quirk detected, " diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index deef29646e0..95826b92ca4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -207,10 +207,12 @@ config RTC_DRV_PCF8563 config RTC_DRV_PCF8583 tristate "Philips PCF8583" - depends on RTC_CLASS && I2C + depends on RTC_CLASS && I2C && ARCH_RPC help - If you say yes here you get support for the - Philips PCF8583 RTC chip. + If you say yes here you get support for the Philips PCF8583 + RTC chip found on Acorn RiscPCs. This driver supports the + platform specific method of retrieving the current year from + the RTC's SRAM. This driver can also be built as a module. If so, the module will be called rtc-pcf8583. diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 7a0d8ee2de9..04aaa634723 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -113,10 +113,16 @@ EXPORT_SYMBOL_GPL(rtc_device_register); */ void rtc_device_unregister(struct rtc_device *rtc) { - mutex_lock(&rtc->ops_lock); - rtc->ops = NULL; - mutex_unlock(&rtc->ops_lock); - class_device_unregister(&rtc->class_dev); + if (class_device_get(&rtc->class_dev) != NULL) { + mutex_lock(&rtc->ops_lock); + /* remove innards of this RTC, then disable it, before + * letting any rtc_class_open() users access it again + */ + class_device_unregister(&rtc->class_dev); + rtc->ops = NULL; + mutex_unlock(&rtc->ops_lock); + class_device_put(&rtc->class_dev); + } } EXPORT_SYMBOL_GPL(rtc_device_unregister); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 6f11f6dfdd9..ef40df0f169 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -179,7 +179,7 @@ struct class_device *rtc_class_open(char *name) down(&rtc_class->sem); list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { - class_dev = class_dev_tmp; + class_dev = class_device_get(class_dev_tmp); break; } } @@ -197,6 +197,7 @@ EXPORT_SYMBOL_GPL(rtc_class_open); void rtc_class_close(struct class_device *class_dev) { module_put(to_rtc_device(class_dev)->owner); + class_device_put(class_dev); } EXPORT_SYMBOL_GPL(rtc_class_close); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 5875ebb8c79..d48b0337458 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -40,7 +40,7 @@ struct pcf8583 { #define CTRL_ALARM 0x02 #define CTRL_TIMER 0x01 -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; /* Module parameters */ I2C_CLIENT_INSMOD; @@ -81,11 +81,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt) buf[4] &= 0x3f; buf[5] &= 0x1f; - dt->tm_sec = BCD_TO_BIN(buf[1]); - dt->tm_min = BCD_TO_BIN(buf[2]); - dt->tm_hour = BCD_TO_BIN(buf[3]); - dt->tm_mday = BCD_TO_BIN(buf[4]); - dt->tm_mon = BCD_TO_BIN(buf[5]); + dt->tm_sec = BCD2BIN(buf[1]); + dt->tm_min = BCD2BIN(buf[2]); + dt->tm_hour = BCD2BIN(buf[3]); + dt->tm_mday = BCD2BIN(buf[4]); + dt->tm_mon = BCD2BIN(buf[5]) - 1; } return ret == 2 ? 0 : -EIO; @@ -99,14 +99,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, buf[0] = 0; buf[1] = get_ctrl(client) | 0x80; buf[2] = 0; - buf[3] = BIN_TO_BCD(dt->tm_sec); - buf[4] = BIN_TO_BCD(dt->tm_min); - buf[5] = BIN_TO_BCD(dt->tm_hour); + buf[3] = BIN2BCD(dt->tm_sec); + buf[4] = BIN2BCD(dt->tm_min); + buf[5] = BIN2BCD(dt->tm_hour); if (datetoo) { len = 8; - buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6); - buf[7] = BIN_TO_BCD(dt->tm_mon) | (dt->tm_wday << 5); + buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6); + buf[7] = BIN2BCD(dt->tm_mon + 1) | (dt->tm_wday << 5); } ret = i2c_master_send(client, (char *)buf, len); @@ -226,7 +226,7 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) */ year_offset += 4; - tm->tm_year = real_year + year_offset + year[1] * 100; + tm->tm_year = (real_year + year_offset + year[1] * 100) - 1900; return 0; } @@ -237,6 +237,7 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char year[2], chk; struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + unsigned int proper_year = tm->tm_year + 1900; int ret; /* @@ -258,8 +259,8 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) chk -= year[1] + year[0]; - year[1] = tm->tm_year / 100; - year[0] = tm->tm_year % 100; + year[1] = proper_year / 100; + year[0] = proper_year % 100; chk += year[1] + year[0]; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 2257e45594b..d8a86f5af37 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -3654,7 +3654,7 @@ qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card) return rc; for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){ - if (vg->vlan_devices[i] == dev){ + if (vlan_group_get_device(vg, i) == dev){ rc = QETH_VLAN_CARD; break; } @@ -5261,7 +5261,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) QETH_DBF_TEXT(trace, 4, "frvaddr4"); rcu_read_lock(); - in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); + in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid)); if (!in_dev) goto out; for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { @@ -5288,7 +5288,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) QETH_DBF_TEXT(trace, 4, "frvaddr6"); - in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); + in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid)); if (!in6_dev) return; for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){ @@ -5360,7 +5360,7 @@ qeth_layer2_process_vlans(struct qeth_card *card, int clear) if (!card->vlangrp) return; for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { - if (card->vlangrp->vlan_devices[i] == NULL) + if (vlan_group_get_device(card->vlangrp, i) == NULL) continue; if (clear) qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN); @@ -5398,8 +5398,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) spin_lock_irqsave(&card->vlanlock, flags); /* unregister IP addresses of vlan device */ qeth_free_vlan_addresses(card, vid); - if (card->vlangrp) - card->vlangrp->vlan_devices[vid] = NULL; + vlan_group_set_device(card->vlangrp, vid, NULL); spin_unlock_irqrestore(&card->vlanlock, flags); if (card->options.layer2) qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); @@ -5662,10 +5661,11 @@ qeth_add_vlan_mc(struct qeth_card *card) vg = card->vlangrp; for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { - if (vg->vlan_devices[i] == NULL || - !(vg->vlan_devices[i]->flags & IFF_UP)) + struct net_device *netdev = vlan_group_get_device(vg, i); + if (netdev == NULL || + !(netdev->flags & IFF_UP)) continue; - in_dev = in_dev_get(vg->vlan_devices[i]); + in_dev = in_dev_get(netdev); if (!in_dev) continue; read_lock(&in_dev->mc_list_lock); @@ -5749,10 +5749,11 @@ qeth_add_vlan_mc6(struct qeth_card *card) vg = card->vlangrp; for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { - if (vg->vlan_devices[i] == NULL || - !(vg->vlan_devices[i]->flags & IFF_UP)) + struct net_device *netdev = vlan_group_get_device(vg, i); + if (netdev == NULL || + !(netdev->flags & IFF_UP)) continue; - in_dev = in6_dev_get(vg->vlan_devices[i]); + in_dev = in6_dev_get(netdev); if (!in_dev) continue; read_lock(&in_dev->lock); diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index d2d51dc51ab..82add77ad13 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -178,10 +178,10 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp, dma_dir = DMA_MODE_READ, alatch_dir = ALATCH_DMA_IN; - dma_map_sg(dev, info->sg, bufs + 1, map_dir); + dma_map_sg(dev, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH); set_dma_mode(dmach, dma_dir); enable_dma(dmach); diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index d4136524fc4..ed06a8c19ad 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -175,10 +175,10 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp, map_dir = DMA_FROM_DEVICE, dma_dir = DMA_MODE_READ; - dma_map_sg(dev, info->sg, bufs + 1, map_dir); + dma_map_sg(dev, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); set_dma_mode(dmach, dma_dir); enable_dma(dmach); return fasdma_real_all; diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 2969cc0ff25..fb5f2028438 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -633,7 +633,7 @@ static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) BUG_ON(bytes_transferred < 0); - info->SCpnt->request_bufflen -= bytes_transferred; + SCp->phase -= bytes_transferred; while (bytes_transferred != 0) { if (SCp->this_residual > bytes_transferred) @@ -715,7 +715,7 @@ static void fas216_cleanuptransfer(FAS216_Info *info) return; if (dmatype == fasdma_real_all) - total = info->SCpnt->request_bufflen; + total = info->scsi.SCp.phase; else total = info->scsi.SCp.this_residual; @@ -753,7 +753,7 @@ static void fas216_transfer(FAS216_Info *info) fas216_log(info, LOG_BUFFER, "starttransfer: buffer %p length 0x%06x reqlen 0x%06x", info->scsi.SCp.ptr, info->scsi.SCp.this_residual, - info->SCpnt->request_bufflen); + info->scsi.SCp.phase); if (!info->scsi.SCp.ptr) { fas216_log(info, LOG_ERROR, "null buffer passed to " @@ -784,7 +784,7 @@ static void fas216_transfer(FAS216_Info *info) info->dma.transfer_type = dmatype; if (dmatype == fasdma_real_all) - fas216_set_stc(info, info->SCpnt->request_bufflen); + fas216_set_stc(info, info->scsi.SCp.phase); else fas216_set_stc(info, info->scsi.SCp.this_residual); @@ -2114,6 +2114,7 @@ request_sense: SCpnt->SCp.buffers_residual = 0; SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer; SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); + SCpnt->SCp.phase = sizeof(SCpnt->sense_buffer); SCpnt->SCp.Message = 0; SCpnt->SCp.Status = 0; SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index f9cd20bfb95..159047a3499 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -148,10 +148,10 @@ powertecscsi_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp, map_dir = DMA_FROM_DEVICE, dma_dir = DMA_MODE_READ; - dma_map_sg(dev, info->sg, bufs + 1, map_dir); + dma_map_sg(dev, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); set_dma_mode(dmach, dma_dir); enable_dma(dmach); return fasdma_real_all; @@ -342,6 +342,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id) info->base = base; powertecscsi_terminator_ctl(host, term[ec->slot_no]); + info->ec = ec; info->info.scsi.io_base = base + POWERTEC_FAS216_OFFSET; info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT; info->info.scsi.irq = ec->irq; diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h index 3a39579bd08..21ba57155be 100644 --- a/drivers/scsi/arm/scsi.h +++ b/drivers/scsi/arm/scsi.h @@ -80,6 +80,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt) (page_address(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset); SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; + SCpnt->SCp.phase = SCpnt->request_bufflen; #ifdef BELT_AND_BRACES /* @@ -98,6 +99,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt) } else { SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; SCpnt->SCp.this_residual = SCpnt->request_bufflen; + SCpnt->SCp.phase = SCpnt->request_bufflen; } /* diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 587d87b9eb3..d31721f2744 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -170,8 +170,7 @@ static void dz_enable_ms(struct uart_port *port) * This routine deals with inputs from any lines. * ------------------------------------------------------------ */ -static inline void dz_receive_chars(struct dz_port *dport_in, - struct pt_regs *regs) +static inline void dz_receive_chars(struct dz_port *dport_in) { struct dz_port *dport; struct tty_struct *tty = NULL; @@ -226,7 +225,7 @@ static inline void dz_receive_chars(struct dz_port *dport_in, break; } - if (uart_handle_sysrq_char(&dport->port, ch, regs)) + if (uart_handle_sysrq_char(&dport->port, ch)) continue; if ((status & dport->port.ignore_status_mask) == 0) { @@ -332,7 +331,7 @@ static irqreturn_t dz_interrupt(int irq, void *dev) status = dz_in(dport, DZ_CSR); if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) - dz_receive_chars(dport, regs); + dz_receive_chars(dport); if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) dz_transmit_chars(dport); diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 8e86c3c6dc0..827a75a186b 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -4,7 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina */ /* @@ -27,9 +27,6 @@ #include <linux/input.h> #include <linux/wait.h> -#undef DEBUG -#undef DEBUG_DATA - #include <linux/usb.h> #include <linux/hid.h> @@ -756,6 +753,8 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 +#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 +#define USB_DEVICE_ID_DINOVO_EDGE 0xc714 #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 @@ -776,6 +775,8 @@ static const struct hid_blacklist { unsigned quirks; } hid_blacklist[] = { + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, @@ -938,6 +939,7 @@ static const struct hid_blacklist { { 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 }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR }, { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, @@ -1035,6 +1037,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) kfree(buf); } +/* + * Logitech S510 keyboard sends in report #3 keys which are far + * above the logical maximum described in descriptor. This extends + * the original value of 0x28c of logical maximum to 0x104d + */ +static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize) +{ + if (rsize >= 90 && rdesc[83] == 0x26 + && rdesc[84] == 0x8c + && rdesc[85] == 0x02) { + info("Fixing up Logitech S510 report descriptor"); + rdesc[84] = rdesc[89] = 0x4d; + rdesc[85] = rdesc[90] = 0x10; + } +} + static struct hid_device *usb_hid_configure(struct usb_interface *intf) { struct usb_host_interface *interface = intf->cur_altsetting; @@ -1108,7 +1126,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if ((quirks & HID_QUIRK_CYMOTION)) hid_fixup_cymotion_descriptor(rdesc, rsize); -#ifdef DEBUG_DATA + if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR) + hid_fixup_s510_descriptor(rdesc, rsize); + +#ifdef CONFIG_HID_DEBUG printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); for (n = 0; n < rsize; n++) printk(" %02x", (unsigned char) rdesc[n]); @@ -1224,8 +1245,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) le16_to_cpu(dev->descriptor.idProduct)); hid->bus = BUS_USB; - hid->vendor = dev->descriptor.idVendor; - hid->product = dev->descriptor.idProduct; + hid->vendor = le16_to_cpu(dev->descriptor.idVendor); + hid->product = le16_to_cpu(dev->descriptor.idProduct); usb_make_path(dev, hid->phys, sizeof(hid->phys)); strlcat(hid->phys, "/input", sizeof(hid->phys)); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 7e7ec29782f..8e898e3d861 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -55,7 +55,7 @@ #include <linux/slab.h> #include <linux/kthread.h> #include <linux/mutex.h> -#include <linux/utsrelease.h> +#include <linux/utsname.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -547,7 +547,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) idesc->bInterfaceSubClass, idesc->bInterfaceProtocol, msgs[msg], - UTS_RELEASE); + utsname()->release); } return 0; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index c1536d78555..7f5a5983681 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -677,8 +677,6 @@ config FB_S1D13XXX config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI - select I2C_ALGOBIT if FB_NVIDIA_I2C - select I2C if FB_NVIDIA_I2C select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT select FB_MODE_HELPERS select FB_CFB_FILLRECT @@ -697,6 +695,7 @@ config FB_NVIDIA config FB_NVIDIA_I2C bool "Enable DDC Support" depends on FB_NVIDIA + select FB_DDC help This enables I2C support for nVidia Chipsets. This is used only for getting EDID information from the attached display @@ -716,7 +715,6 @@ config FB_NVIDIA_BACKLIGHT config FB_RIVA tristate "nVidia Riva support" depends on FB && PCI - select FB_DDC if FB_RIVA_I2C select FB_BACKLIGHT if FB_RIVA_BACKLIGHT select FB_MODE_HELPERS select FB_CFB_FILLRECT @@ -734,6 +732,7 @@ config FB_RIVA config FB_RIVA_I2C bool "Enable DDC Support" depends on FB_RIVA + select FB_DDC help This enables I2C support for nVidia Chipsets. This is used only for getting EDID information from the attached display @@ -812,8 +811,6 @@ config FB_INTEL depends on FB && EXPERIMENTAL && PCI && X86 select AGP select AGP_INTEL - select I2C_ALGOBIT if FB_INTEL_I2C - select I2C if FB_INTEL_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -846,6 +843,7 @@ config FB_INTEL_DEBUG config FB_INTEL_I2C bool "DDC/I2C for Intel framebuffer support" depends on FB_INTEL + select FB_DDC default y help Say Y here if you want DDC/I2C support for your on-board Intel graphics. @@ -924,8 +922,8 @@ config FB_MATROX_G config FB_MATROX_I2C tristate "Matrox I2C support" - depends on FB_MATROX && I2C - select I2C_ALGOBIT + depends on FB_MATROX + select FB_DDC ---help--- This drivers creates I2C buses which are needed for accessing the DDC (I2C) bus present on all Matroxes, an I2C bus which @@ -993,7 +991,6 @@ config FB_MATROX_MULTIHEAD config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI - select FB_DDC if FB_RADEON_I2C select FB_BACKLIGHT if FB_RADEON_BACKLIGHT select FB_MODE_HELPERS select FB_CFB_FILLRECT @@ -1018,6 +1015,7 @@ config FB_RADEON config FB_RADEON_I2C bool "DDC/I2C for ATI Radeon support" depends on FB_RADEON + select FB_DDC default y help Say Y here if you want DDC/I2C support for your Radeon board. @@ -1125,7 +1123,6 @@ config FB_S3 config FB_SAVAGE tristate "S3 Savage support" depends on FB && PCI && EXPERIMENTAL - select FB_DDC if FB_SAVAGE_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -1142,6 +1139,7 @@ config FB_SAVAGE config FB_SAVAGE_I2C bool "Enable DDC2 Support" depends on FB_SAVAGE + select FB_DDC help This enables I2C support for S3 Savage Chipsets. This is used only for getting EDID information from the attached display @@ -1618,8 +1616,7 @@ config FB_IBM_GXT4500 config FB_PS3 bool "PS3 GPU framebuffer driver" - depends on FB && PPC_PS3 - select PS3_PS3AV + depends on FB && PS3_PS3AV select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 8726c366971..e86d7e0c982 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -357,6 +357,12 @@ static int default_lcd_on __devinitdata = 1; static int mtrr = 1; #endif +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight __devinitdata = 1; +#else +static int backlight __devinitdata = 0; +#endif + /* PLL constants */ struct aty128_constants { u32 ref_clk; @@ -1652,6 +1658,9 @@ static int __devinit aty128fb_setup(char *options) } else if (!strncmp(this_opt, "crt:", 4)) { default_crt_on = simple_strtoul(this_opt+4, NULL, 0); continue; + } else if (!strncmp(this_opt, "backlight:", 10)) { + backlight = simple_strtoul(this_opt+10, NULL, 0); + continue; } #ifdef CONFIG_MTRR if(!strncmp(this_opt, "nomtrr", 6)) { @@ -1985,7 +1994,8 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i par->lock_blank = 0; #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_init(par); + if (backlight) + aty128_bl_init(par); #endif if (register_framebuffer(info) < 0) diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index f72faff33c0..dc62f8e282b 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -284,7 +284,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par) #endif } -#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) +#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ +defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT) extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); #endif diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index a7e0062233f..d7627fc4f11 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -131,7 +131,8 @@ #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args) #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) -#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) +#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ +defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) static const u32 lt_lcd_regs[] = { CONFIG_PANEL_LG, LCD_GEN_CNTL_LG, @@ -308,6 +309,12 @@ static int xclk; static int comp_sync __devinitdata = -1; static char *mode; +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight __devinitdata = 1; +#else +static int backlight __devinitdata = 0; +#endif + #ifdef CONFIG_PPC static int default_vmode __devinitdata = VMODE_CHOOSE; static int default_cmode __devinitdata = CMODE_CHOOSE; @@ -2575,7 +2582,7 @@ static int __devinit aty_init(struct fb_info *info) | (USE_F32KHZ | TRISTATE_MEM_EN), par); } else #endif - if (M64_HAS(MOBIL_BUS)) { + if (M64_HAS(MOBIL_BUS) && backlight) { #ifdef CONFIG_FB_ATY_BACKLIGHT aty_bl_init (par); #endif @@ -3757,6 +3764,8 @@ static int __init atyfb_setup(char *options) xclk = simple_strtoul(this_opt+5, NULL, 0); else if (!strncmp(this_opt, "comp_sync:", 10)) comp_sync = simple_strtoul(this_opt+10, NULL, 0); + else if (!strncmp(this_opt, "backlight:", 10)) + backlight = simple_strtoul(this_opt+10, NULL, 0); #ifdef CONFIG_PPC else if (!strncmp(this_opt, "vmode:", 6)) { unsigned int vmode = diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index f3b487b8710..1fdcfdbf669 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -598,7 +598,6 @@ static void aty_resume_pll_ct(const struct fb_info *info, struct atyfb_par *par = info->par; if (par->mclk_per != par->xclk_per) { - int i; /* * This disables the sclk, crashes the computer as reported: * aty_st_pll_ct(SPLL_CNTL2, 3, info); @@ -614,7 +613,7 @@ static void aty_resume_pll_ct(const struct fb_info *info, * helps for Rage Mobilities that sometimes crash when * we switch to sclk. (Daniel Mantione, 13-05-2003) */ - for (i=0;i<=0x1ffff;i++); + udelay(500); } aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 7e228aded4c..1bf6f42eb40 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -268,6 +268,11 @@ static int nomtrr = 0; #endif static int force_sleep; static int ignore_devlist; +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight = 1; +#else +static int backlight = 0; +#endif /* * prototypes @@ -1026,8 +1031,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) break; } - /* let fbcon do a soft blank for us */ - return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0; + return 0; } static int radeonfb_blank (int blank, struct fb_info *info) @@ -2349,7 +2353,8 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, MTRR_TYPE_WRCOMB, 1); #endif - radeonfb_bl_init(rinfo); + if (backlight) + radeonfb_bl_init(rinfo); printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); @@ -2470,6 +2475,8 @@ static int __init radeonfb_setup (char *options) force_dfp = 1; } else if (!strncmp(this_opt, "panel_yres:", 11)) { panel_yres = simple_strtoul((this_opt+11), NULL, 0); + } else if (!strncmp(this_opt, "backlight:", 10)) { + backlight = simple_strtoul(this_opt+10, NULL, 0); #ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index b7016e9b9e1..43f62d8ee41 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c @@ -12,6 +12,11 @@ #include <linux/backlight.h> #include <linux/fb.h> #include <linux/pci.h> + +#ifdef CONFIG_PMAC_BACKLIGHT +#include <asm/backlight.h> +#endif + #include "nv_local.h" #include "nv_type.h" #include "nv_proto.h" @@ -23,8 +28,6 @@ #define MAX_LEVEL 0x534 #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) -static struct backlight_properties nvidia_bl_data; - static int nvidia_bl_get_level_brightness(struct nvidia_par *par, int level) { @@ -119,7 +122,7 @@ void nvidia_bl_init(struct nvidia_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; - bd->props.brightness = nvidia_bl_data.max_brightness; + bd->props.brightness = bd->props.max_brightness; bd->props.power = FB_BLANK_UNBLANK; backlight_update_status(bd); diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index c18e9557ca3..b97ec690126 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -83,6 +83,11 @@ static int bpp __devinitdata = 8; #ifdef CONFIG_MTRR static int nomtrr __devinitdata = 0; #endif +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight __devinitdata = 1; +#else +static int backlight __devinitdata = 0; +#endif static char *mode_option __devinitdata = NULL; @@ -1311,7 +1316,10 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, nvidia_save_vga(par, &par->SavedReg); pci_set_drvdata(pd, info); - nvidia_bl_init(par); + + if (backlight) + nvidia_bl_init(par); + if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering nVidia framebuffer\n"); goto err_out_iounmap_fb; @@ -1408,6 +1416,8 @@ static int __devinit nvidiafb_setup(char *options) paneltweak = simple_strtoul(this_opt+11, NULL, 0); } else if (!strncmp(this_opt, "vram:", 5)) { vram = simple_strtoul(this_opt+5, NULL, 0); + } else if (!strncmp(this_opt, "backlight:", 10)) { + backlight = simple_strtoul(this_opt+10, NULL, 0); #ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index f8a3d608b20..1d1c7c624d7 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -215,6 +215,11 @@ static int noaccel __devinitdata = 0; #ifdef CONFIG_MTRR static int nomtrr __devinitdata = 0; #endif +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight __devinitdata = 1; +#else +static int backlight __devinitdata = 0; +#endif static char *mode_option __devinitdata = NULL; static int strictmode = 0; @@ -2059,7 +2064,10 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->monspecs.modedb = NULL; pci_set_drvdata(pd, info); - riva_bl_init(info->par); + + if (backlight) + riva_bl_init(info->par); + ret = register_framebuffer(info); if (ret < 0) { printk(KERN_ERR PFX @@ -2157,6 +2165,8 @@ static int __init rivafb_setup(char *options) forceCRTC = -1; } else if (!strncmp(this_opt, "flatpanel", 9)) { flatpanel = 1; + } else if (!strncmp(this_opt, "backlight:", 10)) { + backlight = simple_strtoul(this_opt+10, NULL, 0); #ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 02b290ca01e..0a44c44672c 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -136,8 +136,8 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) #define SM501_MEMF_CRT (4) #define SM501_MEMF_ACCEL (8) -int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, - unsigned int why, size_t size) +static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, + unsigned int why, size_t size) { unsigned int ptr = 0; @@ -926,7 +926,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) * set or change the hardware cursor parameters */ -int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; @@ -1074,9 +1074,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, if (len < 1) return -EINVAL; - if (strnicmp(buf, "crt", sizeof("crt")) == 0) + if (strnicmp(buf, "crt", 3) == 0) head = HEAD_CRT; - else if (strnicmp(buf, "panel", sizeof("panel")) == 0) + else if (strnicmp(buf, "panel", 5) == 0) head = HEAD_PANEL; else return -EINVAL; @@ -1098,7 +1098,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); sm501fb_sync_regs(info); - return (head == HEAD_CRT) ? 3 : 5; + return len; } /* Prepare the device_attr for registration with sysfs later */ @@ -1225,7 +1225,7 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt, * initialise hw cursor parameters */ -int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) +static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) { struct sm501fb_par *par = fbi->par; struct sm501fb_info *info = par->info; @@ -1768,7 +1768,7 @@ static struct platform_driver sm501fb_driver = { }, }; -int __devinit sm501fb_init(void) +static int __devinit sm501fb_init(void) { return platform_driver_register(&sm501fb_driver); } |