diff --git a/[refs] b/[refs] index 8790a38072f0..1ecf412808e2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: fba956c46a72f9e7503fd464ffee43c632307e31 +refs/heads/master: dec18810c52ed564c1aedc7f93dbf278b7fdf6d5 diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index fb8258ebc577..63df2262d41a 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -205,6 +205,20 @@ Who: Len Brown --------------------------- +What: Compaq touchscreen device emulation +When: Oct 2007 +Files: drivers/input/tsdev.c +Why: The code says it was obsolete when it was written in 2001. + tslib is a userspace library which does anything tsdev can do and + much more besides in userspace where this code belongs. There is no + longer any need for tsdev and applications should have converted to + use tslib by now. + The name "tsdev" is also extremely confusing and lots of people have + it loaded when they don't need/use it. +Who: Richard Purdie + +--------------------------- + What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers When: September 2007 Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 085e4a095eaa..fdd6dbcf864e 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1890,6 +1890,9 @@ and is between 256 and 4096 characters. It is defined in the file Format: ,,,,,,,, + tsdev.xres= [TS] Horizontal screen resolution. + tsdev.yres= [TS] Vertical screen resolution. + turbografx.map[2|3]= [HW,JOY] TurboGraFX parallel port interface Format: diff --git a/trunk/Documentation/networking/bonding.txt b/trunk/Documentation/networking/bonding.txt index 11340625e363..1da566630831 100644 --- a/trunk/Documentation/networking/bonding.txt +++ b/trunk/Documentation/networking/bonding.txt @@ -281,39 +281,6 @@ downdelay will be rounded down to the nearest multiple. The default value is 0. -fail_over_mac - - Specifies whether active-backup mode should set all slaves to - the same MAC address (the traditional behavior), or, when - enabled, change the bond's MAC address when changing the - active interface (i.e., fail over the MAC address itself). - - Fail over MAC is useful for devices that cannot ever alter - their MAC address, or for devices that refuse incoming - broadcasts with their own source MAC (which interferes with - the ARP monitor). - - The down side of fail over MAC is that every device on the - network must be updated via gratuitous ARP, vs. just updating - a switch or set of switches (which often takes place for any - traffic, not just ARP traffic, if the switch snoops incoming - traffic to update its tables) for the traditional method. If - the gratuitous ARP is lost, communication may be disrupted. - - When fail over MAC is used in conjuction with the mii monitor, - devices which assert link up prior to being able to actually - transmit and receive are particularly susecptible to loss of - the gratuitous ARP, and an appropriate updelay setting may be - required. - - A value of 0 disables fail over MAC, and is the default. A - value of 1 enables fail over MAC. This option is enabled - automatically if the first slave added cannot change its MAC - address. This option may be modified via sysfs only when no - slaves are present in the bond. - - This option was added in bonding version 3.2.0. - lacp_rate Option specifying the rate in which we'll ask our link partner diff --git a/trunk/arch/blackfin/mach-bf548/boards/ezkit.c b/trunk/arch/blackfin/mach-bf548/boards/ezkit.c index 046e6d84bbfc..2c47db494f7d 100644 --- a/trunk/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/trunk/arch/blackfin/mach-bf548/boards/ezkit.c @@ -88,7 +88,7 @@ static struct platform_device bf54x_lq043_device = { #endif #if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE) -static const unsigned int bf548_keymap[] = { +static int bf548_keymap[] = { KEYVAL(0, 0, KEY_ENTER), KEYVAL(0, 1, KEY_HELP), KEYVAL(0, 2, KEY_0), @@ -110,8 +110,8 @@ static const unsigned int bf548_keymap[] = { static struct bfin_kpad_platform_data bf54x_kpad_data = { .rows = 4, .cols = 4, - .keymap = bf548_keymap, - .keymapsize = ARRAY_SIZE(bf548_keymap), + .keymap = bf548_keymap, + .keymapsize = ARRAY_SIZE(bf548_keymap), .repeat = 0, .debounce_time = 5000, /* ns (5ms) */ .coldrive_time = 1000, /* ns (1ms) */ diff --git a/trunk/arch/m68k/atari/atakeyb.c b/trunk/arch/m68k/atari/atakeyb.c index 880add120eb3..fbbccb5e7511 100644 --- a/trunk/arch/m68k/atari/atakeyb.c +++ b/trunk/arch/m68k/atari/atakeyb.c @@ -1,4 +1,6 @@ /* + * linux/arch/m68k/atari/atakeyb.c + * * Atari Keyboard driver for 680x0 Linux * * This file is subject to the terms and conditions of the GNU General Public diff --git a/trunk/arch/mips/au1000/common/prom.c b/trunk/arch/mips/au1000/common/prom.c index 90d70695aa60..a8637cdb5b4b 100644 --- a/trunk/arch/mips/au1000/common/prom.c +++ b/trunk/arch/mips/au1000/common/prom.c @@ -33,6 +33,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include @@ -40,16 +41,18 @@ #include -int prom_argc; -char **prom_argv; -char **prom_envp; +/* #define DEBUG_CMDLINE */ + +extern int prom_argc; +extern char **prom_argv, **prom_envp; + char * __init_or_module prom_getcmdline(void) { return &(arcs_cmdline[0]); } -void prom_init_cmdline(void) +void prom_init_cmdline(void) { char *cp; int actr; @@ -58,7 +61,7 @@ void prom_init_cmdline(void) cp = &(arcs_cmdline[0]); while(actr < prom_argc) { - strcpy(cp, prom_argv[actr]); + strcpy(cp, prom_argv[actr]); cp += strlen(prom_argv[actr]); *cp++ = ' '; actr++; @@ -67,8 +70,10 @@ void prom_init_cmdline(void) --cp; if (prom_argc > 1) *cp = '\0'; + } + char *prom_getenv(char *envname) { /* @@ -90,23 +95,21 @@ char *prom_getenv(char *envname) } env++; } - return NULL; } -static inline unsigned char str2hexnum(unsigned char c) +inline unsigned char str2hexnum(unsigned char c) { - if (c >= '0' && c <= '9') + if(c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') + if(c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') + if(c >= 'A' && c <= 'F') return c - 'A' + 10; - return 0; /* foo */ } -static inline void str2eaddr(unsigned char *ea, unsigned char *str) +inline void str2eaddr(unsigned char *ea, unsigned char *str) { int i; @@ -121,29 +124,35 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str) } } -int prom_get_ethernet_addr(char *ethernet_addr) +int get_ethernet_addr(char *ethernet_addr) { - char *ethaddr_str; - char *argptr; + char *ethaddr_str; - /* Check the environment variables first */ - ethaddr_str = prom_getenv("ethaddr"); + ethaddr_str = prom_getenv("ethaddr"); if (!ethaddr_str) { - /* Check command line */ - argptr = prom_getcmdline(); - ethaddr_str = strstr(argptr, "ethaddr="); - if (!ethaddr_str) - return -1; - - ethaddr_str += strlen("ethaddr="); + printk("ethaddr not set in boot prom\n"); + return -1; } - str2eaddr(ethernet_addr, ethaddr_str); +#if 0 + { + int i; + + printk("get_ethernet_addr: "); + for (i=0; i<5; i++) + printk("%02x:", (unsigned char)*(ethernet_addr+i)); + printk("%02x\n", *(ethernet_addr+i)); + } +#endif + return 0; } -EXPORT_SYMBOL(prom_get_ethernet_addr); void __init prom_free_prom_memory(void) { } + +EXPORT_SYMBOL(prom_getcmdline); +EXPORT_SYMBOL(get_ethernet_addr); +EXPORT_SYMBOL(str2eaddr); diff --git a/trunk/arch/mips/au1000/common/setup.c b/trunk/arch/mips/au1000/common/setup.c index a90d425d4651..b212c0726125 100644 --- a/trunk/arch/mips/au1000/common/setup.c +++ b/trunk/arch/mips/au1000/common/setup.c @@ -40,11 +40,10 @@ #include #include #include +#include #include -#include -#include - +extern char * prom_getcmdline(void); extern void __init board_setup(void); extern void au1000_restart(char *); extern void au1000_halt(void); diff --git a/trunk/arch/mips/au1000/db1x00/init.c b/trunk/arch/mips/au1000/db1x00/init.c index 43298fd9459c..4d7bcfc8cf73 100644 --- a/trunk/arch/mips/au1000/db1x00/init.c +++ b/trunk/arch/mips/au1000/db1x00/init.c @@ -31,13 +31,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/mtx-1/init.c b/trunk/arch/mips/au1000/mtx-1/init.c index cdeae3212a2d..2aa7b2ed6a8c 100644 --- a/trunk/arch/mips/au1000/mtx-1/init.c +++ b/trunk/arch/mips/au1000/mtx-1/init.c @@ -34,11 +34,13 @@ #include #include #include - #include #include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/pb1000/init.c b/trunk/arch/mips/au1000/pb1000/init.c index ddccaf6997d0..4535f7208e18 100644 --- a/trunk/arch/mips/au1000/pb1000/init.c +++ b/trunk/arch/mips/au1000/pb1000/init.c @@ -30,13 +30,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/pb1100/init.c b/trunk/arch/mips/au1000/pb1100/init.c index c93fd39b4aba..7ba6852de7cd 100644 --- a/trunk/arch/mips/au1000/pb1100/init.c +++ b/trunk/arch/mips/au1000/pb1100/init.c @@ -31,13 +31,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/pb1200/board_setup.c b/trunk/arch/mips/au1000/pb1200/board_setup.c index 5dbc9868f598..2122515f79d7 100644 --- a/trunk/arch/mips/au1000/pb1200/board_setup.c +++ b/trunk/arch/mips/au1000/pb1200/board_setup.c @@ -41,10 +41,8 @@ #include #include #include - -#include -#include -#include +#include +#include #ifdef CONFIG_MIPS_PB1200 #include diff --git a/trunk/arch/mips/au1000/pb1200/init.c b/trunk/arch/mips/au1000/pb1200/init.c index c251570749ee..5a70029d5388 100644 --- a/trunk/arch/mips/au1000/pb1200/init.c +++ b/trunk/arch/mips/au1000/pb1200/init.c @@ -31,13 +31,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/pb1500/init.c b/trunk/arch/mips/au1000/pb1500/init.c index 507d4b204161..e58a9d6c5021 100644 --- a/trunk/arch/mips/au1000/pb1500/init.c +++ b/trunk/arch/mips/au1000/pb1500/init.c @@ -31,13 +31,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/pb1550/init.c b/trunk/arch/mips/au1000/pb1550/init.c index b03eee601e36..fad53bf5aad1 100644 --- a/trunk/arch/mips/au1000/pb1550/init.c +++ b/trunk/arch/mips/au1000/pb1550/init.c @@ -31,13 +31,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/mips/au1000/xxs1500/init.c b/trunk/arch/mips/au1000/xxs1500/init.c index 6532939f377a..9f839c36f69e 100644 --- a/trunk/arch/mips/au1000/xxs1500/init.c +++ b/trunk/arch/mips/au1000/xxs1500/init.c @@ -30,13 +30,15 @@ #include #include #include -#include -#include - #include #include +#include +#include -#include +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); const char *get_system_type(void) { diff --git a/trunk/arch/powerpc/platforms/cell/axon_msi.c b/trunk/arch/powerpc/platforms/cell/axon_msi.c index 095988f13bf4..1245b2f517bb 100644 --- a/trunk/arch/powerpc/platforms/cell/axon_msi.c +++ b/trunk/arch/powerpc/platforms/cell/axon_msi.c @@ -77,7 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) { pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); - dcr_write(msic->dcr_host, dcr_n, val); + dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val); +} + +static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n) +{ + return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n); } static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) @@ -86,7 +91,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) u32 write_offset, msi; int idx; - write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG); + write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG); pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); /* write_offset doesn't wrap properly, so we have to mask it */ @@ -301,7 +306,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb, list_for_each_entry(msic, &axon_msic_list, list) { pr_debug("axon_msi: disabling %s\n", msic->irq_host->of_node->full_name); - tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); + tmp = msic_dcr_read(msic, MSIC_CTRL_REG); tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; msic_dcr_write(msic, MSIC_CTRL_REG, tmp); } diff --git a/trunk/arch/powerpc/sysdev/dcr.c b/trunk/arch/powerpc/sysdev/dcr.c index 427027c7ea0f..ab11c0b29024 100644 --- a/trunk/arch/powerpc/sysdev/dcr.c +++ b/trunk/arch/powerpc/sysdev/dcr.c @@ -126,13 +126,13 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, } EXPORT_SYMBOL_GPL(dcr_map); -void dcr_unmap(dcr_host_t host, unsigned int dcr_c) +void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) { dcr_host_t h = host; if (h.token == NULL) return; - h.token += host.base * h.stride; + h.token += dcr_n * h.stride; iounmap(h.token); h.token = NULL; } diff --git a/trunk/arch/powerpc/sysdev/mpic.c b/trunk/arch/powerpc/sysdev/mpic.c index e47938899a92..893e65439e85 100644 --- a/trunk/arch/powerpc/sysdev/mpic.c +++ b/trunk/arch/powerpc/sysdev/mpic.c @@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type, switch(type) { #ifdef CONFIG_PPC_DCR case mpic_access_dcr: - return dcr_read(rb->dhost, reg); + return dcr_read(rb->dhost, rb->dhost.base + reg); #endif case mpic_access_mmio_be: return in_be32(rb->base + (reg >> 2)); @@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type, switch(type) { #ifdef CONFIG_PPC_DCR case mpic_access_dcr: - return dcr_write(rb->dhost, reg, value); + return dcr_write(rb->dhost, rb->dhost.base + reg, value); #endif case mpic_access_mmio_be: return out_be32(rb->base + (reg >> 2), value); diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index 33f5eb038773..4672066167e3 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -272,15 +272,6 @@ config PATA_CS5535 If unsure, say N. -config PATA_CS5536 - tristate "CS5536 PATA support (Experimental)" - depends on PCI && X86 && !X86_64 && EXPERIMENTAL - help - This option enables support for the AMD CS5536 - companion chip used with the Geode LX processor family. - - If unsure, say N. - config PATA_CYPRESS tristate "Cypress CY82C693 PATA support (Very Experimental)" depends on PCI && EXPERIMENTAL diff --git a/trunk/drivers/ata/Makefile b/trunk/drivers/ata/Makefile index 6bdc307649e6..2a63645003eb 100644 --- a/trunk/drivers/ata/Makefile +++ b/trunk/drivers/ata/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o -obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o obj-$(CONFIG_PATA_EFAR) += pata_efar.o obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 3c6f43e381f4..9ce4aa9c2f25 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -130,7 +130,6 @@ enum { ich8_sata_ahci = 9, piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ tolapai_sata_ahci = 11, - ich9_2port_sata = 12, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -239,19 +238,19 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller 1 IDE (ICH8) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller 2 IDE (ICH8) */ - { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* Mobile SATA Controller IDE (ICH8M) */ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9) */ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9M) */ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (Tolapai) */ @@ -449,18 +448,6 @@ static const struct piix_map_db tolapai_map_db = { }, }; -static const struct piix_map_db ich9_2port_map_db = { - .mask = 0x3, - .port_enable = 0x3, - .map = { - /* PM PS SM SS MAP */ - { P0, NA, P1, NA }, /* 00b */ - { RV, RV, RV, RV }, /* 01b */ - { RV, RV, RV, RV }, /* 10b */ - { RV, RV, RV, RV }, - }, -}; - static const struct piix_map_db *piix_map_db_table[] = { [ich5_sata] = &ich5_map_db, [ich6_sata] = &ich6_map_db, @@ -468,7 +455,6 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6m_sata_ahci] = &ich6m_map_db, [ich8_sata_ahci] = &ich8_map_db, [tolapai_sata_ahci] = &tolapai_map_db, - [ich9_2port_sata] = &ich9_2port_map_db, }; static struct ata_port_info piix_port_info[] = { @@ -584,17 +570,6 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, - - [ich9_2port_sata] = - { - .sht = &piix_sht, - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | - PIIX_FLAG_AHCI, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, }; static struct pci_bits piix_enable_bits[] = { diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 68699b3e7998..b05384a8c326 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -3984,7 +3984,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, - { "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, }, { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, @@ -4014,14 +4013,8 @@ int strn_pattern_cmp(const char *patt, const char *name, int wildchar) p = strchr(patt, wildchar); if (p && ((*(p + 1)) == 0)) len = p - patt; - else { + else len = strlen(name); - if (!len) { - if (!*patt) - return 0; - return -1; - } - } return strncmp(patt, name, len); } diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index d63c81ed084f..ea53e6a570b4 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -1363,7 +1363,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct ata_eh_info *ehi = &qc->dev->link->eh_info; struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); @@ -1377,14 +1376,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) case ATA_CMD_SET_FEATURES: if ((qc->tf.feature == SETFEATURES_WC_ON) || (qc->tf.feature == SETFEATURES_WC_OFF)) { - ehi->action |= ATA_EH_REVALIDATE; + ap->link.eh_info.action |= ATA_EH_REVALIDATE; ata_port_schedule_eh(ap); } break; case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ case ATA_CMD_SET_MULTI: /* multi_count changed */ - ehi->action |= ATA_EH_REVALIDATE; + ap->link.eh_info.action |= ATA_EH_REVALIDATE; ata_port_schedule_eh(ap); break; } diff --git a/trunk/drivers/ata/pata_cs5536.c b/trunk/drivers/ata/pata_cs5536.c deleted file mode 100644 index 21405bf14837..000000000000 --- a/trunk/drivers/ata/pata_cs5536.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * pata_cs5536.c - CS5536 PATA for new ATA layer - * (C) 2007 Martin K. Petersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Documentation: - * Available from AMD web site. - * - * The IDE timing registers for the CS5536 live in the Geode Machine - * Specific Register file and not PCI config space. Most BIOSes - * virtualize the PCI registers so the chip looks like a standard IDE - * controller. Unfortunately not all implementations get this right. - * In particular some have problems with unaligned accesses to the - * virtualized PCI registers. This driver always does full dword - * writes to work around the issue. Also, in case of a bad BIOS this - * driver can be loaded with the "msr=1" parameter which forces using - * the Machine Specific Registers to configure the device. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pata_cs5536" -#define DRV_VERSION "0.0.5" - -enum { - CFG = 0, - DTC = 1, - CAST = 2, - ETC = 3, - - MSR_IDE_BASE = 0x51300000, - MSR_IDE_CFG = (MSR_IDE_BASE + 0x10), - MSR_IDE_DTC = (MSR_IDE_BASE + 0x12), - MSR_IDE_CAST = (MSR_IDE_BASE + 0x13), - MSR_IDE_ETC = (MSR_IDE_BASE + 0x14), - - PCI_IDE_CFG = 0x40, - PCI_IDE_DTC = 0x48, - PCI_IDE_CAST = 0x4c, - PCI_IDE_ETC = 0x50, - - IDE_CFG_CHANEN = 0x2, - IDE_CFG_CABLE = 0x10000, - - IDE_D0_SHIFT = 24, - IDE_D1_SHIFT = 16, - IDE_DRV_MASK = 0xff, - - IDE_CAST_D0_SHIFT = 6, - IDE_CAST_D1_SHIFT = 4, - IDE_CAST_DRV_MASK = 0x3, - IDE_CAST_CMD_MASK = 0xff, - IDE_CAST_CMD_SHIFT = 24, - - IDE_ETC_NODMA = 0x03, -}; - -static int use_msr; - -static const u32 msr_reg[4] = { - MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC, -}; - -static const u8 pci_reg[4] = { - PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC, -}; - -static inline int cs5536_read(struct pci_dev *pdev, int reg, int *val) -{ - if (unlikely(use_msr)) { - u32 dummy; - - rdmsr(msr_reg[reg], *val, dummy); - return 0; - } - - return pci_read_config_dword(pdev, pci_reg[reg], val); -} - -static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) -{ - if (unlikely(use_msr)) { - wrmsr(msr_reg[reg], val, 0); - return 0; - } - - return pci_write_config_dword(pdev, pci_reg[reg], val); -} - -/** - * cs5536_cable_detect - detect cable type - * @ap: Port to detect on - * @deadline: deadline jiffies for the operation - * - * Perform cable detection for ATA66 capable cable. Return a libata - * cable type. - */ - -static int cs5536_cable_detect(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 cfg; - - cs5536_read(pdev, CFG, &cfg); - - if (cfg & (IDE_CFG_CABLE << ap->port_no)) - return ATA_CBL_PATA80; - else - return ATA_CBL_PATA40; -} - -/** - * cs5536_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - */ - -static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static const u8 drv_timings[5] = { - 0x98, 0x55, 0x32, 0x21, 0x20, - }; - - static const u8 addr_timings[5] = { - 0x2, 0x1, 0x0, 0x0, 0x0, - }; - - static const u8 cmd_timings[5] = { - 0x99, 0x92, 0x90, 0x22, 0x20, - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_device *pair = ata_dev_pair(adev); - int mode = adev->pio_mode - XFER_PIO_0; - int cmdmode = mode; - int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; - int cshift = ap->port_no ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; - u32 dtc, cast, etc; - - if (pair) - cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); - - cs5536_read(pdev, DTC, &dtc); - cs5536_read(pdev, CAST, &cast); - cs5536_read(pdev, ETC, &etc); - - dtc &= ~(IDE_DRV_MASK << dshift); - dtc |= drv_timings[mode] << dshift; - - cast &= ~(IDE_CAST_DRV_MASK << cshift); - cast |= addr_timings[mode] << cshift; - - cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); - cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; - - etc &= ~(IDE_DRV_MASK << dshift); - etc |= IDE_ETC_NODMA << dshift; - - cs5536_write(pdev, DTC, dtc); - cs5536_write(pdev, CAST, cast); - cs5536_write(pdev, ETC, etc); -} - -/** - * cs5536_set_dmamode - DMA timing setup - * @ap: ATA interface - * @adev: Device being configured - * - */ - -static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static const u8 udma_timings[6] = { - 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, - }; - - static const u8 mwdma_timings[3] = { - 0x67, 0x21, 0x20, - }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 dtc, etc; - int mode = adev->dma_mode; - int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; - - if (mode >= XFER_UDMA_0) { - cs5536_read(pdev, ETC, &etc); - - etc &= ~(IDE_DRV_MASK << dshift); - etc |= udma_timings[mode - XFER_UDMA_0] << dshift; - - cs5536_write(pdev, ETC, etc); - } else { /* MWDMA */ - cs5536_read(pdev, DTC, &dtc); - - dtc &= ~(IDE_DRV_MASK << dshift); - dtc |= mwdma_timings[mode] << dshift; - - cs5536_write(pdev, DTC, dtc); - } -} - -static struct scsi_host_template cs5536_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations cs5536_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = cs5536_set_piomode, - .set_dmamode = cs5536_set_dmamode, - .mode_filter = ata_pci_default_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .cable_detect = cs5536_cable_detect, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .data_xfer = ata_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, - - .port_start = ata_port_start, -}; - -/** - * cs5536_init_one - * @dev: PCI device - * @id: Entry in match table - * - */ - -static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - static const struct ata_port_info info = { - .sht = &cs5536_sht, - .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, - .port_ops = &cs5536_port_ops, - }; - - const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; - u32 cfg; - - if (use_msr) - printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); - - cs5536_read(dev, CFG, &cfg); - - if ((cfg & IDE_CFG_CHANEN) == 0) { - printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); - return -ENODEV; - } - - return ata_pci_init_one(dev, ppi); -} - -static const struct pci_device_id cs5536[] = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, - { }, -}; - -static struct pci_driver cs5536_pci_driver = { - .name = DRV_NAME, - .id_table = cs5536, - .probe = cs5536_init_one, - .remove = ata_pci_remove_one, -#ifdef CONFIG_PM - .suspend = ata_pci_device_suspend, - .resume = ata_pci_device_resume, -#endif -}; - -static int __init cs5536_init(void) -{ - return pci_register_driver(&cs5536_pci_driver); -} - -static void __exit cs5536_exit(void) -{ - pci_unregister_driver(&cs5536_pci_driver); -} - -MODULE_AUTHOR("Martin K. Petersen"); -MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, cs5536); -MODULE_VERSION(DRV_VERSION); -module_param_named(msr, use_msr, int, 0644); -MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); - -module_init(cs5536_init); -module_exit(cs5536_exit); diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c index 5db2013230b3..782ff4ada9d1 100644 --- a/trunk/drivers/ata/pata_pcmcia.c +++ b/trunk/drivers/ata/pata_pcmcia.c @@ -353,7 +353,6 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev) static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_FUNC_ID(4), - PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ 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 */ @@ -379,7 +378,6 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), - PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), diff --git a/trunk/drivers/ata/pata_sil680.c b/trunk/drivers/ata/pata_sil680.c index 4dc2e73298fd..2eb75cd74a96 100644 --- a/trunk/drivers/ata/pata_sil680.c +++ b/trunk/drivers/ata/pata_sil680.c @@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = { * Returns the final clock settings. */ -static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) +static u8 sil680_init_chip(struct pci_dev *pdev) { u32 class_rev = 0; u8 tmpbyte = 0; @@ -297,8 +297,6 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", tmpbyte & 1, tmpbyte & 0x30); - *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); - switch(tmpbyte & 0x30) { case 0x00: /* 133 clock attempt to force it on */ @@ -363,76 +361,25 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, }; const struct ata_port_info *ppi[] = { &info, NULL }; static int printed_version; - struct ata_host *host; - void __iomem *mmio_base; - int rc, try_mmio; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - switch (sil680_init_chip(pdev, &try_mmio)) { + switch(sil680_init_chip(pdev)) + { case 0: ppi[0] = &info_slow; break; case 0x30: return -ENODEV; } - - if (!try_mmio) - goto use_ioports; - - /* Try to acquire MMIO resources and fallback to PIO if - * that fails - */ - rc = pcim_enable_device(pdev); - if (rc) - return rc; - rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME); - if (rc) - goto use_ioports; - - /* Allocate host and set it up */ - host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); - if (!host) - return -ENOMEM; - host->iomap = pcim_iomap_table(pdev); - - /* Setup DMA masks */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - return rc; - pci_set_master(pdev); - - /* Get MMIO base and initialize port addresses */ - mmio_base = host->iomap[SIL680_MMIO_BAR]; - host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00; - host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80; - host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a; - host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a; - ata_std_ports(&host->ports[0]->ioaddr); - host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08; - host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0; - host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca; - host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca; - ata_std_ports(&host->ports[1]->ioaddr); - - /* Register & activate */ - return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, - &sil680_sht); - -use_ioports: return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM static int sil680_reinit_one(struct pci_dev *pdev) { - int try_mmio; - - sil680_init_chip(pdev, &try_mmio); + sil680_init_chip(pdev); return ata_pci_device_resume(pdev); } #endif diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c index 240a8920d0bd..40557fe2ffdf 100644 --- a/trunk/drivers/ata/sata_nv.c +++ b/trunk/drivers/ata/sata_nv.c @@ -169,35 +169,6 @@ enum { NV_ADMA_PORT_REGISTER_MODE = (1 << 0), NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1), - /* MCP55 reg offset */ - NV_CTL_MCP55 = 0x400, - NV_INT_STATUS_MCP55 = 0x440, - NV_INT_ENABLE_MCP55 = 0x444, - NV_NCQ_REG_MCP55 = 0x448, - - /* MCP55 */ - NV_INT_ALL_MCP55 = 0xffff, - NV_INT_PORT_SHIFT_MCP55 = 16, /* each port occupies 16 bits */ - NV_INT_MASK_MCP55 = NV_INT_ALL_MCP55 & 0xfffd, - - /* SWNCQ ENABLE BITS*/ - NV_CTL_PRI_SWNCQ = 0x02, - NV_CTL_SEC_SWNCQ = 0x04, - - /* SW NCQ status bits*/ - NV_SWNCQ_IRQ_DEV = (1 << 0), - NV_SWNCQ_IRQ_PM = (1 << 1), - NV_SWNCQ_IRQ_ADDED = (1 << 2), - NV_SWNCQ_IRQ_REMOVED = (1 << 3), - - NV_SWNCQ_IRQ_BACKOUT = (1 << 4), - NV_SWNCQ_IRQ_SDBFIS = (1 << 5), - NV_SWNCQ_IRQ_DHREGFIS = (1 << 6), - NV_SWNCQ_IRQ_DMASETUP = (1 << 7), - - NV_SWNCQ_IRQ_HOTPLUG = NV_SWNCQ_IRQ_ADDED | - NV_SWNCQ_IRQ_REMOVED, - }; /* ADMA Physical Region Descriptor - one SG segment */ @@ -255,42 +226,6 @@ struct nv_host_priv { unsigned long type; }; -struct defer_queue { - u32 defer_bits; - unsigned int head; - unsigned int tail; - unsigned int tag[ATA_MAX_QUEUE]; -}; - -enum ncq_saw_flag_list { - ncq_saw_d2h = (1U << 0), - ncq_saw_dmas = (1U << 1), - ncq_saw_sdb = (1U << 2), - ncq_saw_backout = (1U << 3), -}; - -struct nv_swncq_port_priv { - struct ata_prd *prd; /* our SG list */ - dma_addr_t prd_dma; /* and its DMA mapping */ - void __iomem *sactive_block; - void __iomem *irq_block; - void __iomem *tag_block; - u32 qc_active; - - unsigned int last_issue_tag; - - /* fifo circular queue to store deferral command */ - struct defer_queue defer_queue; - - /* for NCQ interrupt analysis */ - u32 dhfis_bits; - u32 dmafis_bits; - u32 sdbfis_bits; - - unsigned int ncq_flags; -}; - - #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); @@ -328,29 +263,13 @@ static void nv_adma_host_stop(struct ata_host *host); static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf); -static void nv_mcp55_thaw(struct ata_port *ap); -static void nv_mcp55_freeze(struct ata_port *ap); -static void nv_swncq_error_handler(struct ata_port *ap); -static int nv_swncq_slave_config(struct scsi_device *sdev); -static int nv_swncq_port_start(struct ata_port *ap); -static void nv_swncq_qc_prep(struct ata_queued_cmd *qc); -static void nv_swncq_fill_sg(struct ata_queued_cmd *qc); -static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc); -static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis); -static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance); -#ifdef CONFIG_PM -static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg); -static int nv_swncq_port_resume(struct ata_port *ap); -#endif - enum nv_host_type { GENERIC, NFORCE2, NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ CK804, - ADMA, - SWNCQ, + ADMA }; static const struct pci_device_id nv_pci_tbl[] = { @@ -361,13 +280,13 @@ static const struct pci_device_id nv_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), SWNCQ }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), SWNCQ }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, { } /* terminate list */ }; @@ -420,25 +339,6 @@ static struct scsi_host_template nv_adma_sht = { .bios_param = ata_std_bios_param, }; -static struct scsi_host_template nv_swncq_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .change_queue_depth = ata_scsi_change_queue_depth, - .can_queue = ATA_MAX_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = nv_swncq_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, -}; - static const struct ata_port_operations nv_generic_ops = { .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -544,35 +444,6 @@ static const struct ata_port_operations nv_adma_ops = { .host_stop = nv_adma_host_stop, }; -static const struct ata_port_operations nv_swncq_ops = { - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_defer = ata_std_qc_defer, - .qc_prep = nv_swncq_qc_prep, - .qc_issue = nv_swncq_qc_issue, - .freeze = nv_mcp55_freeze, - .thaw = nv_mcp55_thaw, - .error_handler = nv_swncq_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .data_xfer = ata_data_xfer, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .scr_read = nv_scr_read, - .scr_write = nv_scr_write, -#ifdef CONFIG_PM - .port_suspend = nv_swncq_port_suspend, - .port_resume = nv_swncq_port_resume, -#endif - .port_start = nv_swncq_port_start, -}; - static const struct ata_port_info nv_port_info[] = { /* generic */ { @@ -619,18 +490,6 @@ static const struct ata_port_info nv_port_info[] = { .port_ops = &nv_adma_ops, .irq_handler = nv_adma_interrupt, }, - /* SWNCQ */ - { - .sht = &nv_swncq_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_NCQ, - .link_flags = ATA_LFLAG_HRST_TO_RESUME, - .pio_mask = NV_PIO_MASK, - .mwdma_mask = NV_MWDMA_MASK, - .udma_mask = NV_UDMA_MASK, - .port_ops = &nv_swncq_ops, - .irq_handler = nv_swncq_interrupt, - }, }; MODULE_AUTHOR("NVIDIA"); @@ -640,7 +499,6 @@ MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); static int adma_enabled = 1; -static int swncq_enabled; static void nv_adma_register_mode(struct ata_port *ap) { @@ -1594,34 +1452,6 @@ static void nv_ck804_thaw(struct ata_port *ap) writeb(mask, mmio_base + NV_INT_ENABLE_CK804); } -static void nv_mcp55_freeze(struct ata_port *ap) -{ - void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; - int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55; - u32 mask; - - writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55); - - mask = readl(mmio_base + NV_INT_ENABLE_MCP55); - mask &= ~(NV_INT_ALL_MCP55 << shift); - writel(mask, mmio_base + NV_INT_ENABLE_MCP55); - ata_bmdma_freeze(ap); -} - -static void nv_mcp55_thaw(struct ata_port *ap) -{ - void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; - int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55; - u32 mask; - - writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55); - - mask = readl(mmio_base + NV_INT_ENABLE_MCP55); - mask |= (NV_INT_MASK_MCP55 << shift); - writel(mask, mmio_base + NV_INT_ENABLE_MCP55); - ata_bmdma_thaw(ap); -} - static int nv_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { @@ -1695,663 +1525,6 @@ static void nv_adma_error_handler(struct ata_port *ap) nv_hardreset, ata_std_postreset); } -static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - struct defer_queue *dq = &pp->defer_queue; - - /* queue is full */ - WARN_ON(dq->tail - dq->head == ATA_MAX_QUEUE); - dq->defer_bits |= (1 << qc->tag); - dq->tag[dq->tail++ & (ATA_MAX_QUEUE - 1)] = qc->tag; -} - -static struct ata_queued_cmd *nv_swncq_qc_from_dq(struct ata_port *ap) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - struct defer_queue *dq = &pp->defer_queue; - unsigned int tag; - - if (dq->head == dq->tail) /* null queue */ - return NULL; - - tag = dq->tag[dq->head & (ATA_MAX_QUEUE - 1)]; - dq->tag[dq->head++ & (ATA_MAX_QUEUE - 1)] = ATA_TAG_POISON; - WARN_ON(!(dq->defer_bits & (1 << tag))); - dq->defer_bits &= ~(1 << tag); - - return ata_qc_from_tag(ap, tag); -} - -static void nv_swncq_fis_reinit(struct ata_port *ap) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - - pp->dhfis_bits = 0; - pp->dmafis_bits = 0; - pp->sdbfis_bits = 0; - pp->ncq_flags = 0; -} - -static void nv_swncq_pp_reinit(struct ata_port *ap) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - struct defer_queue *dq = &pp->defer_queue; - - dq->head = 0; - dq->tail = 0; - dq->defer_bits = 0; - pp->qc_active = 0; - pp->last_issue_tag = ATA_TAG_POISON; - nv_swncq_fis_reinit(ap); -} - -static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - - writew(fis, pp->irq_block); -} - -static void __ata_bmdma_stop(struct ata_port *ap) -{ - struct ata_queued_cmd qc; - - qc.ap = ap; - ata_bmdma_stop(&qc); -} - -static void nv_swncq_ncq_stop(struct ata_port *ap) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - unsigned int i; - u32 sactive; - u32 done_mask; - - ata_port_printk(ap, KERN_ERR, - "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n", - ap->qc_active, ap->link.sactive); - ata_port_printk(ap, KERN_ERR, - "SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n " - "dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n", - pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag, - pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits); - - ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n", - ap->ops->check_status(ap), - ioread8(ap->ioaddr.error_addr)); - - sactive = readl(pp->sactive_block); - done_mask = pp->qc_active ^ sactive; - - ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n"); - for (i = 0; i < ATA_MAX_QUEUE; i++) { - u8 err = 0; - if (pp->qc_active & (1 << i)) - err = 0; - else if (done_mask & (1 << i)) - err = 1; - else - continue; - - ata_port_printk(ap, KERN_ERR, - "tag 0x%x: %01x %01x %01x %01x %s\n", i, - (pp->dhfis_bits >> i) & 0x1, - (pp->dmafis_bits >> i) & 0x1, - (pp->sdbfis_bits >> i) & 0x1, - (sactive >> i) & 0x1, - (err ? "error! tag doesn't exit" : " ")); - } - - nv_swncq_pp_reinit(ap); - ap->ops->irq_clear(ap); - __ata_bmdma_stop(ap); - nv_swncq_irq_clear(ap, 0xffff); -} - -static void nv_swncq_error_handler(struct ata_port *ap) -{ - struct ata_eh_context *ehc = &ap->link.eh_context; - - if (ap->link.sactive) { - nv_swncq_ncq_stop(ap); - ehc->i.action |= ATA_EH_HARDRESET; - } - - ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, - nv_hardreset, ata_std_postreset); -} - -#ifdef CONFIG_PM -static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg) -{ - void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; - u32 tmp; - - /* clear irq */ - writel(~0, mmio + NV_INT_STATUS_MCP55); - - /* disable irq */ - writel(0, mmio + NV_INT_ENABLE_MCP55); - - /* disable swncq */ - tmp = readl(mmio + NV_CTL_MCP55); - tmp &= ~(NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ); - writel(tmp, mmio + NV_CTL_MCP55); - - return 0; -} - -static int nv_swncq_port_resume(struct ata_port *ap) -{ - void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; - u32 tmp; - - /* clear irq */ - writel(~0, mmio + NV_INT_STATUS_MCP55); - - /* enable irq */ - writel(0x00fd00fd, mmio + NV_INT_ENABLE_MCP55); - - /* enable swncq */ - tmp = readl(mmio + NV_CTL_MCP55); - writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55); - - return 0; -} -#endif - -static void nv_swncq_host_init(struct ata_host *host) -{ - u32 tmp; - void __iomem *mmio = host->iomap[NV_MMIO_BAR]; - struct pci_dev *pdev = to_pci_dev(host->dev); - u8 regval; - - /* disable ECO 398 */ - pci_read_config_byte(pdev, 0x7f, ®val); - regval &= ~(1 << 7); - pci_write_config_byte(pdev, 0x7f, regval); - - /* enable swncq */ - tmp = readl(mmio + NV_CTL_MCP55); - VPRINTK("HOST_CTL:0x%X\n", tmp); - writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55); - - /* enable irq intr */ - tmp = readl(mmio + NV_INT_ENABLE_MCP55); - VPRINTK("HOST_ENABLE:0x%X\n", tmp); - writel(tmp | 0x00fd00fd, mmio + NV_INT_ENABLE_MCP55); - - /* clear port irq */ - writel(~0x0, mmio + NV_INT_STATUS_MCP55); -} - -static int nv_swncq_slave_config(struct scsi_device *sdev) -{ - struct ata_port *ap = ata_shost_to_port(sdev->host); - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct ata_device *dev; - int rc; - u8 rev; - u8 check_maxtor = 0; - unsigned char model_num[ATA_ID_PROD_LEN + 1]; - - rc = ata_scsi_slave_config(sdev); - if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun) - /* Not a proper libata device, ignore */ - return rc; - - dev = &ap->link.device[sdev->id]; - if (!(ap->flags & ATA_FLAG_NCQ) || dev->class == ATA_DEV_ATAPI) - return rc; - - /* if MCP51 and Maxtor, then disable ncq */ - if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA || - pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2) - check_maxtor = 1; - - /* if MCP55 and rev <= a2 and Maxtor, then disable ncq */ - if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA || - pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2) { - pci_read_config_byte(pdev, 0x8, &rev); - if (rev <= 0xa2) - check_maxtor = 1; - } - - if (!check_maxtor) - return rc; - - ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - - if (strncmp(model_num, "Maxtor", 6) == 0) { - ata_scsi_change_queue_depth(sdev, 1); - ata_dev_printk(dev, KERN_NOTICE, - "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth); - } - - return rc; -} - -static int nv_swncq_port_start(struct ata_port *ap) -{ - struct device *dev = ap->host->dev; - void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; - struct nv_swncq_port_priv *pp; - int rc; - - rc = ata_port_start(ap); - if (rc) - return rc; - - pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); - if (!pp) - return -ENOMEM; - - pp->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE, - &pp->prd_dma, GFP_KERNEL); - if (!pp->prd) - return -ENOMEM; - memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE); - - ap->private_data = pp; - pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE; - pp->irq_block = mmio + NV_INT_STATUS_MCP55 + ap->port_no * 2; - pp->tag_block = mmio + NV_NCQ_REG_MCP55 + ap->port_no * 2; - - return 0; -} - -static void nv_swncq_qc_prep(struct ata_queued_cmd *qc) -{ - if (qc->tf.protocol != ATA_PROT_NCQ) { - ata_qc_prep(qc); - return; - } - - if (!(qc->flags & ATA_QCFLAG_DMAMAP)) - return; - - nv_swncq_fill_sg(qc); -} - -static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct scatterlist *sg; - unsigned int idx; - struct nv_swncq_port_priv *pp = ap->private_data; - struct ata_prd *prd; - - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); - - prd = pp->prd + ATA_MAX_PRD * qc->tag; - - idx = 0; - ata_for_each_sg(sg, qc) { - u32 addr, offset; - u32 sg_len, len; - - addr = (u32)sg_dma_address(sg); - sg_len = sg_dma_len(sg); - - while (sg_len) { - offset = addr & 0xffff; - len = sg_len; - if ((offset + sg_len) > 0x10000) - len = 0x10000 - offset; - - prd[idx].addr = cpu_to_le32(addr); - prd[idx].flags_len = cpu_to_le32(len & 0xffff); - - idx++; - sg_len -= len; - addr += len; - } - } - - if (idx) - prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); -} - -static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap, - struct ata_queued_cmd *qc) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - - if (qc == NULL) - return 0; - - DPRINTK("Enter\n"); - - writel((1 << qc->tag), pp->sactive_block); - pp->last_issue_tag = qc->tag; - pp->dhfis_bits &= ~(1 << qc->tag); - pp->dmafis_bits &= ~(1 << qc->tag); - pp->qc_active |= (0x1 << qc->tag); - - ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ - ap->ops->exec_command(ap, &qc->tf); - - DPRINTK("Issued tag %u\n", qc->tag); - - return 0; -} - -static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct nv_swncq_port_priv *pp = ap->private_data; - - if (qc->tf.protocol != ATA_PROT_NCQ) - return ata_qc_issue_prot(qc); - - DPRINTK("Enter\n"); - - if (!pp->qc_active) - nv_swncq_issue_atacmd(ap, qc); - else - nv_swncq_qc_to_dq(ap, qc); /* add qc to defer queue */ - - return 0; -} - -static void nv_swncq_hotplug(struct ata_port *ap, u32 fis) -{ - u32 serror; - struct ata_eh_info *ehi = &ap->link.eh_info; - - ata_ehi_clear_desc(ehi); - - /* AHCI needs SError cleared; otherwise, it might lock up */ - sata_scr_read(&ap->link, SCR_ERROR, &serror); - sata_scr_write(&ap->link, SCR_ERROR, serror); - - /* analyze @irq_stat */ - if (fis & NV_SWNCQ_IRQ_ADDED) - ata_ehi_push_desc(ehi, "hot plug"); - else if (fis & NV_SWNCQ_IRQ_REMOVED) - ata_ehi_push_desc(ehi, "hot unplug"); - - ata_ehi_hotplugged(ehi); - - /* okay, let's hand over to EH */ - ehi->serror |= serror; - - ata_port_freeze(ap); -} - -static int nv_swncq_sdbfis(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - struct nv_swncq_port_priv *pp = ap->private_data; - struct ata_eh_info *ehi = &ap->link.eh_info; - u32 sactive; - int nr_done = 0; - u32 done_mask; - int i; - u8 host_stat; - u8 lack_dhfis = 0; - - host_stat = ap->ops->bmdma_status(ap); - if (unlikely(host_stat & ATA_DMA_ERR)) { - /* error when transfering data to/from memory */ - ata_ehi_clear_desc(ehi); - ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); - ehi->err_mask |= AC_ERR_HOST_BUS; - ehi->action |= ATA_EH_SOFTRESET; - return -EINVAL; - } - - ap->ops->irq_clear(ap); - __ata_bmdma_stop(ap); - - sactive = readl(pp->sactive_block); - done_mask = pp->qc_active ^ sactive; - - if (unlikely(done_mask & sactive)) { - ata_ehi_clear_desc(ehi); - ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition" - "(%08x->%08x)", pp->qc_active, sactive); - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_HARDRESET; - return -EINVAL; - } - for (i = 0; i < ATA_MAX_QUEUE; i++) { - if (!(done_mask & (1 << i))) - continue; - - qc = ata_qc_from_tag(ap, i); - if (qc) { - ata_qc_complete(qc); - pp->qc_active &= ~(1 << i); - pp->dhfis_bits &= ~(1 << i); - pp->dmafis_bits &= ~(1 << i); - pp->sdbfis_bits |= (1 << i); - nr_done++; - } - } - - if (!ap->qc_active) { - DPRINTK("over\n"); - nv_swncq_pp_reinit(ap); - return nr_done; - } - - if (pp->qc_active & pp->dhfis_bits) - return nr_done; - - if ((pp->ncq_flags & ncq_saw_backout) || - (pp->qc_active ^ pp->dhfis_bits)) - /* if the controller cann't get a device to host register FIS, - * The driver needs to reissue the new command. - */ - lack_dhfis = 1; - - DPRINTK("id 0x%x QC: qc_active 0x%x," - "SWNCQ:qc_active 0x%X defer_bits %X " - "dhfis 0x%X dmafis 0x%X last_issue_tag %x\n", - ap->print_id, ap->qc_active, pp->qc_active, - pp->defer_queue.defer_bits, pp->dhfis_bits, - pp->dmafis_bits, pp->last_issue_tag); - - nv_swncq_fis_reinit(ap); - - if (lack_dhfis) { - qc = ata_qc_from_tag(ap, pp->last_issue_tag); - nv_swncq_issue_atacmd(ap, qc); - return nr_done; - } - - if (pp->defer_queue.defer_bits) { - /* send deferral queue command */ - qc = nv_swncq_qc_from_dq(ap); - WARN_ON(qc == NULL); - nv_swncq_issue_atacmd(ap, qc); - } - - return nr_done; -} - -static inline u32 nv_swncq_tag(struct ata_port *ap) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - u32 tag; - - tag = readb(pp->tag_block) >> 2; - return (tag & 0x1f); -} - -static int nv_swncq_dmafis(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - unsigned int rw; - u8 dmactl; - u32 tag; - struct nv_swncq_port_priv *pp = ap->private_data; - - __ata_bmdma_stop(ap); - tag = nv_swncq_tag(ap); - - DPRINTK("dma setup tag 0x%x\n", tag); - qc = ata_qc_from_tag(ap, tag); - - if (unlikely(!qc)) - return 0; - - rw = qc->tf.flags & ATA_TFLAG_WRITE; - - /* load PRD table addr. */ - iowrite32(pp->prd_dma + ATA_PRD_TBL_SZ * qc->tag, - ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); - - /* specify data direction, triple-check start bit is clear */ - dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - dmactl &= ~ATA_DMA_WR; - if (!rw) - dmactl |= ATA_DMA_WR; - - iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - return 1; -} - -static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) -{ - struct nv_swncq_port_priv *pp = ap->private_data; - struct ata_queued_cmd *qc; - struct ata_eh_info *ehi = &ap->link.eh_info; - u32 serror; - u8 ata_stat; - int rc = 0; - - ata_stat = ap->ops->check_status(ap); - nv_swncq_irq_clear(ap, fis); - if (!fis) - return; - - if (ap->pflags & ATA_PFLAG_FROZEN) - return; - - if (fis & NV_SWNCQ_IRQ_HOTPLUG) { - nv_swncq_hotplug(ap, fis); - return; - } - - if (!pp->qc_active) - return; - - if (ap->ops->scr_read(ap, SCR_ERROR, &serror)) - return; - ap->ops->scr_write(ap, SCR_ERROR, serror); - - if (ata_stat & ATA_ERR) { - ata_ehi_clear_desc(ehi); - ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis); - ehi->err_mask |= AC_ERR_DEV; - ehi->serror |= serror; - ehi->action |= ATA_EH_SOFTRESET; - ata_port_freeze(ap); - return; - } - - if (fis & NV_SWNCQ_IRQ_BACKOUT) { - /* If the IRQ is backout, driver must issue - * the new command again some time later. - */ - pp->ncq_flags |= ncq_saw_backout; - } - - if (fis & NV_SWNCQ_IRQ_SDBFIS) { - pp->ncq_flags |= ncq_saw_sdb; - DPRINTK("id 0x%x SWNCQ: qc_active 0x%X " - "dhfis 0x%X dmafis 0x%X sactive 0x%X\n", - ap->print_id, pp->qc_active, pp->dhfis_bits, - pp->dmafis_bits, readl(pp->sactive_block)); - rc = nv_swncq_sdbfis(ap); - if (rc < 0) - goto irq_error; - } - - if (fis & NV_SWNCQ_IRQ_DHREGFIS) { - /* The interrupt indicates the new command - * was transmitted correctly to the drive. - */ - pp->dhfis_bits |= (0x1 << pp->last_issue_tag); - pp->ncq_flags |= ncq_saw_d2h; - if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) { - ata_ehi_push_desc(ehi, "illegal fis transaction"); - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_HARDRESET; - goto irq_error; - } - - if (!(fis & NV_SWNCQ_IRQ_DMASETUP) && - !(pp->ncq_flags & ncq_saw_dmas)) { - ata_stat = ap->ops->check_status(ap); - if (ata_stat & ATA_BUSY) - goto irq_exit; - - if (pp->defer_queue.defer_bits) { - DPRINTK("send next command\n"); - qc = nv_swncq_qc_from_dq(ap); - nv_swncq_issue_atacmd(ap, qc); - } - } - } - - if (fis & NV_SWNCQ_IRQ_DMASETUP) { - /* program the dma controller with appropriate PRD buffers - * and start the DMA transfer for requested command. - */ - pp->dmafis_bits |= (0x1 << nv_swncq_tag(ap)); - pp->ncq_flags |= ncq_saw_dmas; - rc = nv_swncq_dmafis(ap); - } - -irq_exit: - return; -irq_error: - ata_ehi_push_desc(ehi, "fis:0x%x", fis); - ata_port_freeze(ap); - return; -} - -static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance) -{ - struct ata_host *host = dev_instance; - unsigned int i; - unsigned int handled = 0; - unsigned long flags; - u32 irq_stat; - - spin_lock_irqsave(&host->lock, flags); - - irq_stat = readl(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_MCP55); - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { - if (ap->link.sactive) { - nv_swncq_host_interrupt(ap, (u16)irq_stat); - handled = 1; - } else { - if (irq_stat) /* reserve Hotplug */ - nv_swncq_irq_clear(ap, 0xfff0); - - handled += nv_host_intr(ap, (u8)irq_stat); - } - } - irq_stat >>= NV_INT_PORT_SHIFT_MCP55; - } - - spin_unlock_irqrestore(&host->lock, flags); - - return IRQ_RETVAL(handled); -} - static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; @@ -2378,7 +1551,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return rc; /* determine type and allocate host */ - if (type == CK804 && adma_enabled) { + if (type >= CK804 && adma_enabled) { dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); type = ADMA; } @@ -2424,9 +1597,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = nv_adma_host_init(host); if (rc) return rc; - } else if (type == SWNCQ && swncq_enabled) { - dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); - nv_swncq_host_init(host); } pci_set_master(pdev); @@ -2526,6 +1696,3 @@ module_init(nv_init); module_exit(nv_exit); module_param_named(adma, adma_enabled, bool, 0444); MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); -module_param_named(swncq, swncq_enabled, bool, 0444); -MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)"); - diff --git a/trunk/drivers/char/ec3104_keyb.c b/trunk/drivers/char/ec3104_keyb.c new file mode 100644 index 000000000000..020011495d91 --- /dev/null +++ b/trunk/drivers/char/ec3104_keyb.c @@ -0,0 +1,457 @@ +/* + * linux/drivers/char/ec3104_keyb.c + * + * Copyright (C) 2000 Philipp Rumpf + * + * based on linux/drivers/char/pc_keyb.c, which had the following comments: + * + * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 + * See keyboard.c for the whole history. + * + * Major cleanup by Martin Mares, May 1997 + * + * Combined the keyboard and PS/2 mouse handling into one file, + * because they share the same hardware. + * Johan Myreen 1998-10-08. + * + * Code fixes to handle mouse ACKs properly. + * C. Scott Ananian 1999-01-29. + */ +/* EC3104 note: + * This code was written without any documentation about the EC3104 chip. While + * I hope I got most of the basic functionality right, the register names I use + * are most likely completely different from those in the chip documentation. + * + * If you have any further information about the EC3104, please tell me + * (prumpf@tux.org). + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* Some configuration switches are present in the include file... */ + +#include + +#define MSR_CTS 0x10 +#define MCR_RTS 0x02 +#define LSR_DR 0x01 +#define LSR_BOTH_EMPTY 0x60 + +static struct e5_struct { + u8 packet[8]; + int pos; + int length; + + u8 cached_mcr; + u8 last_msr; +} ec3104_keyb; + +/* Simple translation table for the SysRq keys */ + + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char ec3104_kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +static void kbd_write_command_w(int data); +static void kbd_write_output_w(int data); +#ifdef CONFIG_PSMOUSE +static void aux_write_ack(int val); +static void __aux_write_ack(int val); +#endif + +static DEFINE_SPINLOCK(kbd_controller_lock); +static unsigned char handle_kbd_event(void); + +/* used only by send_data - set by keyboard_interrupt */ +static volatile unsigned char reply_expected; +static volatile unsigned char acknowledge; +static volatile unsigned char resend; + + +int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return 0; +} + +int ec3104_kbd_getkeycode(unsigned int scancode) +{ + return 0; +} + + +/* yes, it probably would be faster to use an array. I don't care. */ + +static inline unsigned char ec3104_scan2key(unsigned char scancode) +{ + switch (scancode) { + case 1: /* '`' */ + return 41; + + case 2 ... 27: + return scancode; + + case 28: /* '\\' */ + return 43; + + case 29 ... 39: + return scancode + 1; + + case 40: /* '\r' */ + return 28; + + case 41 ... 50: + return scancode + 3; + + case 51: /* ' ' */ + return 57; + + case 52: /* escape */ + return 1; + + case 54: /* insert/delete (labelled delete) */ + /* this should arguably be 110, but I'd like to have ctrl-alt-del + * working with a standard keymap */ + return 111; + + case 55: /* left */ + return 105; + case 56: /* home */ + return 102; + case 57: /* end */ + return 107; + case 58: /* up */ + return 103; + case 59: /* down */ + return 108; + case 60: /* pgup */ + return 104; + case 61: /* pgdown */ + return 109; + case 62: /* right */ + return 106; + + case 79 ... 88: /* f1 - f10 */ + return scancode - 20; + + case 89 ... 90: /* f11 - f12 */ + return scancode - 2; + + case 91: /* left shift */ + return 42; + + case 92: /* right shift */ + return 54; + + case 93: /* left alt */ + return 56; + case 94: /* right alt */ + return 100; + case 95: /* left ctrl */ + return 29; + case 96: /* right ctrl */ + return 97; + + case 97: /* caps lock */ + return 58; + case 102: /* left windows */ + return 125; + case 103: /* right windows */ + return 126; + + case 106: /* Fn */ + /* this is wrong. */ + return 84; + + default: + return 0; + } +} + +int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + scancode &= 0x7f; + + *keycode = ec3104_scan2key(scancode); + + return 1; +} + +char ec3104_kbd_unexpected_up(unsigned char keycode) +{ + return 0200; +} + +static inline void handle_keyboard_event(unsigned char scancode) +{ +#ifdef CONFIG_VT + handle_scancode(scancode, !(scancode & 0x80)); +#endif + tasklet_schedule(&keyboard_tasklet); +} + +void ec3104_kbd_leds(unsigned char leds) +{ +} + +static u8 e5_checksum(u8 *packet, int count) +{ + int i; + u8 sum = 0; + + for (i=0; i", byte); + + ctrl_outb(byte, EC3104_SER4_DATA); + + do { + status = ctrl_inb(EC3104_SER4_LSR); + } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY); + +} + +static int e5_send_packet(u8 *packet, int count, struct e5_struct *k) +{ + int i; + + disable_irq(EC3104_IRQ_SER4); + + if (k->cached_mcr & MCR_RTS) { + printk("e5_send_packet: too slow\n"); + enable_irq(EC3104_IRQ_SER4); + return -EAGAIN; + } + + k->cached_mcr |= MCR_RTS; + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + + e5_wait_for_cts(k); + + printk("p: "); + + for(i=0; icached_mcr &= ~MCR_RTS; + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + + set_current_state(TASK_UNINTERRUPTIBLE); + + + + enable_irq(EC3104_IRQ_SER4); + + + + return 0; +} + +/* + * E5 packets we know about: + * E5->host 0x80 0x05 - resend packet + * host->E5 0x83 0x43 - set LCD contrast + * host->E5 0x85 0x41 0x02 0x02 - set LCD backlight + * E5->host 0x87 0x00 - external PS2 + * E5->host 0x88 - key press + */ + +static void e5_receive(struct e5_struct *k) +{ + k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA); + + if (k->pos == 1) { + switch(k->packet[0]) { + case 0x80: + k->length = 3; + break; + + case 0x87: /* PS2 ext */ + k->length = 6; + break; + + case 0x88: /* keyboard */ + k->length = 3; + break; + + default: + k->length = 1; + printk(KERN_WARNING "unknown E5 packet %02x\n", + k->packet[0]); + } + } + + if (k->pos == k->length) { + int i; + + if (e5_checksum(k->packet, k->length) != 0) + printk(KERN_WARNING "E5: wrong checksum\n"); + +#if 0 + printk("E5 packet ["); + for(i=0; ilength; i++) { + printk("%02x ", k->packet[i]); + } + + printk("(%02x)]\n", e5_checksum(k->packet, k->length-1)); +#endif + + switch(k->packet[0]) { + case 0x80: + case 0x88: + handle_keyboard_event(k->packet[1]); + break; + } + + k->pos = k->length = 0; + } +} + +static void ec3104_keyb_interrupt(int irq, void *data) +{ + struct e5_struct *k = &ec3104_keyb; + u8 msr, lsr; + + msr = ctrl_inb(EC3104_SER4_MSR); + + if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) { + if (k->cached_mcr & MCR_RTS) + printk("confused: RTS already high\n"); + /* CTS went high. Send RTS. */ + k->cached_mcr |= MCR_RTS; + + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) { + /* CTS went low. */ + if (!(k->cached_mcr & MCR_RTS)) + printk("confused: RTS already low\n"); + + k->cached_mcr &= ~MCR_RTS; + + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + } + + k->last_msr = msr; + + lsr = ctrl_inb(EC3104_SER4_LSR); + + if (lsr & LSR_DR) + e5_receive(k); +} + +static void ec3104_keyb_clear_state(void) +{ + struct e5_struct *k = &ec3104_keyb; + u8 msr, lsr; + + /* we want CTS to be low */ + k->last_msr = 0; + + for (;;) { + msleep(100); + + msr = ctrl_inb(EC3104_SER4_MSR); + + lsr = ctrl_inb(EC3104_SER4_LSR); + + if (lsr & LSR_DR) { + e5_receive(k); + continue; + } + + if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) { + if (k->cached_mcr & MCR_RTS) + printk("confused: RTS already high\n"); + /* CTS went high. Send RTS. */ + k->cached_mcr |= MCR_RTS; + + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) { + /* CTS went low. */ + if (!(k->cached_mcr & MCR_RTS)) + printk("confused: RTS already low\n"); + + k->cached_mcr &= ~MCR_RTS; + + ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); + } else + break; + + k->last_msr = msr; + + continue; + } +} + +void __init ec3104_kbd_init_hw(void) +{ + ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR); + ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR); + + ec3104_keyb_clear_state(); + + /* Ok, finally allocate the IRQ, and off we go.. */ + request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL); +} diff --git a/trunk/drivers/hwmon/Kconfig b/trunk/drivers/hwmon/Kconfig index 700a1657554f..e47f88170806 100644 --- a/trunk/drivers/hwmon/Kconfig +++ b/trunk/drivers/hwmon/Kconfig @@ -158,7 +158,6 @@ config SENSORS_K8TEMP config SENSORS_AMS tristate "Apple Motion Sensor driver" depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL - select INPUT_POLLDEV help Support for the motion sensor included in PowerBooks. Includes implementations for PMU and I2C. @@ -702,7 +701,6 @@ config SENSORS_W83627EHF config SENSORS_HDAPS tristate "IBM Hard Drive Active Protection System (hdaps)" depends on INPUT && X86 - select INPUT_POLLDEV default n help This driver provides support for the IBM Hard Drive Active Protection @@ -724,7 +722,6 @@ config SENSORS_APPLESMC depends on INPUT && X86 select NEW_LEDS select LEDS_CLASS - select INPUT_POLLDEV default n help This driver provides support for the Apple System Management diff --git a/trunk/drivers/hwmon/ams/ams-input.c b/trunk/drivers/hwmon/ams/ams-input.c index 7b81e0c2c2d9..ca7095d96ad0 100644 --- a/trunk/drivers/hwmon/ams/ams-input.c +++ b/trunk/drivers/hwmon/ams/ams-input.c @@ -27,32 +27,47 @@ static unsigned int invert; module_param(invert, bool, 0644); MODULE_PARM_DESC(invert, "Invert input data on X and Y axis"); -static void ams_idev_poll(struct input_polled_dev *dev) +static int ams_input_kthread(void *data) { - struct input_dev *idev = dev->input; s8 x, y, z; - mutex_lock(&ams_info.lock); + while (!kthread_should_stop()) { + mutex_lock(&ams_info.lock); - ams_sensors(&x, &y, &z); + ams_sensors(&x, &y, &z); - x -= ams_info.xcalib; - y -= ams_info.ycalib; - z -= ams_info.zcalib; + x -= ams_info.xcalib; + y -= ams_info.ycalib; + z -= ams_info.zcalib; - input_report_abs(idev, ABS_X, invert ? -x : x); - input_report_abs(idev, ABS_Y, invert ? -y : y); - input_report_abs(idev, ABS_Z, z); + input_report_abs(ams_info.idev, ABS_X, invert ? -x : x); + input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y); + input_report_abs(ams_info.idev, ABS_Z, z); - input_sync(idev); + input_sync(ams_info.idev); - mutex_unlock(&ams_info.lock); + mutex_unlock(&ams_info.lock); + + msleep(25); + } + + return 0; +} + +static int ams_input_open(struct input_dev *dev) +{ + ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams"); + return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0; +} + +static void ams_input_close(struct input_dev *dev) +{ + kthread_stop(ams_info.kthread); } /* Call with ams_info.lock held! */ static void ams_input_enable(void) { - struct input_dev *input; s8 x, y, z; if (ams_info.idev) @@ -63,29 +78,27 @@ static void ams_input_enable(void) ams_info.ycalib = y; ams_info.zcalib = z; - ams_info.idev = input_allocate_polled_device(); + ams_info.idev = input_allocate_device(); if (!ams_info.idev) return; - ams_info.idev->poll = ams_idev_poll; - ams_info.idev->poll_interval = 25; - - input = ams_info.idev->input; - input->name = "Apple Motion Sensor"; - input->id.bustype = ams_info.bustype; - input->id.vendor = 0; - input->dev.parent = &ams_info.of_dev->dev; + ams_info.idev->name = "Apple Motion Sensor"; + ams_info.idev->id.bustype = ams_info.bustype; + ams_info.idev->id.vendor = 0; + ams_info.idev->open = ams_input_open; + ams_info.idev->close = ams_input_close; + ams_info.idev->dev.parent = &ams_info.of_dev->dev; - input_set_abs_params(input, ABS_X, -50, 50, 3, 0); - input_set_abs_params(input, ABS_Y, -50, 50, 3, 0); - input_set_abs_params(input, ABS_Z, -50, 50, 3, 0); + input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0); + input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0); + input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0); - set_bit(EV_ABS, input->evbit); - set_bit(EV_KEY, input->evbit); - set_bit(BTN_TOUCH, input->keybit); + set_bit(EV_ABS, ams_info.idev->evbit); + set_bit(EV_KEY, ams_info.idev->evbit); + set_bit(BTN_TOUCH, ams_info.idev->keybit); - if (input_register_polled_device(ams_info.idev)) { - input_free_polled_device(ams_info.idev); + if (input_register_device(ams_info.idev)) { + input_free_device(ams_info.idev); ams_info.idev = NULL; return; } @@ -95,8 +108,7 @@ static void ams_input_enable(void) static void ams_input_disable(void) { if (ams_info.idev) { - input_unregister_polled_device(ams_info.idev); - input_free_polled_device(ams_info.idev); + input_unregister_device(ams_info.idev); ams_info.idev = NULL; } } diff --git a/trunk/drivers/hwmon/ams/ams.h b/trunk/drivers/hwmon/ams/ams.h index a6221e5dd984..240730e6bcde 100644 --- a/trunk/drivers/hwmon/ams/ams.h +++ b/trunk/drivers/hwmon/ams/ams.h @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -52,7 +52,8 @@ struct ams { #endif /* Joystick emulation */ - struct input_polled_dev *idev; + struct task_struct *kthread; + struct input_dev *idev; __u16 bustype; /* calibrated null values */ diff --git a/trunk/drivers/hwmon/applesmc.c b/trunk/drivers/hwmon/applesmc.c index 4879125b4cdc..f37fd7ebf65a 100644 --- a/trunk/drivers/hwmon/applesmc.c +++ b/trunk/drivers/hwmon/applesmc.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -59,9 +59,9 @@ #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */ #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */ -#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ +#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ -#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ +#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ #define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */ #define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */ @@ -103,7 +103,7 @@ static const char* fan_speed_keys[] = { #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ -#define APPLESMC_POLL_INTERVAL 50 /* msecs */ +#define APPLESMC_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ #define APPLESMC_INPUT_FLAT 4 @@ -125,8 +125,9 @@ static const int debug; static struct platform_device *pdev; static s16 rest_x; static s16 rest_y; +static struct timer_list applesmc_timer; +static struct input_dev *applesmc_idev; static struct device *hwmon_dev; -static struct input_polled_dev *applesmc_idev; /* Indicates whether this computer has an accelerometer. */ static unsigned int applesmc_accelerometer; @@ -137,7 +138,7 @@ static unsigned int applesmc_light; /* Indicates which temperature sensors set to use. */ static unsigned int applesmc_temperature_set; -static DEFINE_MUTEX(applesmc_lock); +static struct mutex applesmc_lock; /* * Last index written to key_at_index sysfs file, and value to use for all other @@ -454,12 +455,27 @@ static void applesmc_calibrate(void) rest_x = -rest_x; } -static void applesmc_idev_poll(struct input_polled_dev *dev) +static int applesmc_idev_open(struct input_dev *dev) +{ + add_timer(&applesmc_timer); + + return 0; +} + +static void applesmc_idev_close(struct input_dev *dev) +{ + del_timer_sync(&applesmc_timer); +} + +static void applesmc_idev_poll(unsigned long unused) { - struct input_dev *idev = dev->input; s16 x, y; - mutex_lock(&applesmc_lock); + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ + if (!mutex_trylock(&applesmc_lock)) { + mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD); + return; + } if (applesmc_read_motion_sensor(SENSOR_X, &x)) goto out; @@ -467,11 +483,13 @@ static void applesmc_idev_poll(struct input_polled_dev *dev) goto out; x = -x; - input_report_abs(idev, ABS_X, x - rest_x); - input_report_abs(idev, ABS_Y, y - rest_y); - input_sync(idev); + input_report_abs(applesmc_idev, ABS_X, x - rest_x); + input_report_abs(applesmc_idev, ABS_Y, y - rest_y); + input_sync(applesmc_idev); out: + mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD); + mutex_unlock(&applesmc_lock); } @@ -803,7 +821,8 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev, if (!ret) { return info[0]; - } else { + } + else { return ret; } } @@ -1074,7 +1093,6 @@ static int applesmc_dmi_match(const struct dmi_system_id *id) /* Create accelerometer ressources */ static int applesmc_create_accelerometer(void) { - struct input_dev *idev; int ret; ret = sysfs_create_group(&pdev->dev.kobj, @@ -1082,37 +1100,40 @@ static int applesmc_create_accelerometer(void) if (ret) goto out; - applesmc_idev = input_allocate_polled_device(); + applesmc_idev = input_allocate_device(); if (!applesmc_idev) { ret = -ENOMEM; goto out_sysfs; } - applesmc_idev->poll = applesmc_idev_poll; - applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL; - /* initial calibrate for the input device */ applesmc_calibrate(); - /* initialize the input device */ - idev = applesmc_idev->input; - idev->name = "applesmc"; - idev->id.bustype = BUS_HOST; - idev->dev.parent = &pdev->dev; - idev->evbit[0] = BIT(EV_ABS); - input_set_abs_params(idev, ABS_X, + /* initialize the input class */ + applesmc_idev->name = "applesmc"; + applesmc_idev->id.bustype = BUS_HOST; + applesmc_idev->dev.parent = &pdev->dev; + applesmc_idev->evbit[0] = BIT(EV_ABS); + applesmc_idev->open = applesmc_idev_open; + applesmc_idev->close = applesmc_idev_close; + input_set_abs_params(applesmc_idev, ABS_X, -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); - input_set_abs_params(idev, ABS_Y, + input_set_abs_params(applesmc_idev, ABS_Y, -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); - ret = input_register_polled_device(applesmc_idev); + ret = input_register_device(applesmc_idev); if (ret) goto out_idev; + /* start up our timer for the input device */ + init_timer(&applesmc_timer); + applesmc_timer.function = applesmc_idev_poll; + applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD; + return 0; out_idev: - input_free_polled_device(applesmc_idev); + input_free_device(applesmc_idev); out_sysfs: sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); @@ -1125,8 +1146,8 @@ static int applesmc_create_accelerometer(void) /* Release all ressources used by the accelerometer */ static void applesmc_release_accelerometer(void) { - input_unregister_polled_device(applesmc_idev); - input_free_polled_device(applesmc_idev); + del_timer_sync(&applesmc_timer); + input_unregister_device(applesmc_idev); sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); } @@ -1163,6 +1184,8 @@ static int __init applesmc_init(void) int count; int i; + mutex_init(&applesmc_lock); + if (!dmi_check_system(applesmc_whitelist)) { printk(KERN_WARNING "applesmc: supported laptop not found!\n"); ret = -ENODEV; diff --git a/trunk/drivers/hwmon/hdaps.c b/trunk/drivers/hwmon/hdaps.c index 8a7ae03aeee4..a7c6d407572b 100644 --- a/trunk/drivers/hwmon/hdaps.c +++ b/trunk/drivers/hwmon/hdaps.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -61,12 +61,13 @@ #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ -#define HDAPS_POLL_INTERVAL 50 /* poll for input every 1/20s (50 ms)*/ +#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ #define HDAPS_INPUT_FLAT 4 +static struct timer_list hdaps_timer; static struct platform_device *pdev; -static struct input_polled_dev *hdaps_idev; +static struct input_dev *hdaps_idev; static unsigned int hdaps_invert; static u8 km_activity; static int rest_x; @@ -322,19 +323,24 @@ static void hdaps_calibrate(void) __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); } -static void hdaps_mousedev_poll(struct input_polled_dev *dev) +static void hdaps_mousedev_poll(unsigned long unused) { - struct input_dev *input_dev = dev->input; int x, y; - mutex_lock(&hdaps_mtx); + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ + if (mutex_trylock(&hdaps_mtx)) { + mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); + return; + } if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) goto out; - input_report_abs(input_dev, ABS_X, x - rest_x); - input_report_abs(input_dev, ABS_Y, y - rest_y); - input_sync(input_dev); + input_report_abs(hdaps_idev, ABS_X, x - rest_x); + input_report_abs(hdaps_idev, ABS_Y, y - rest_y); + input_sync(hdaps_idev); + + mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); out: mutex_unlock(&hdaps_mtx); @@ -530,7 +536,6 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { static int __init hdaps_init(void) { - struct input_dev *idev; int ret; if (!dmi_check_system(hdaps_whitelist)) { @@ -558,37 +563,39 @@ static int __init hdaps_init(void) if (ret) goto out_device; - hdaps_idev = input_allocate_polled_device(); + hdaps_idev = input_allocate_device(); if (!hdaps_idev) { ret = -ENOMEM; goto out_group; } - hdaps_idev->poll = hdaps_mousedev_poll; - hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL; - /* initial calibrate for the input device */ hdaps_calibrate(); /* initialize the input class */ - idev = hdaps_idev->input; - idev->name = "hdaps"; - idev->dev.parent = &pdev->dev; - idev->evbit[0] = BIT(EV_ABS); - input_set_abs_params(idev, ABS_X, + hdaps_idev->name = "hdaps"; + hdaps_idev->dev.parent = &pdev->dev; + hdaps_idev->evbit[0] = BIT(EV_ABS); + input_set_abs_params(hdaps_idev, ABS_X, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); - input_set_abs_params(idev, ABS_Y, + input_set_abs_params(hdaps_idev, ABS_Y, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); - ret = input_register_polled_device(hdaps_idev); + ret = input_register_device(hdaps_idev); if (ret) goto out_idev; + /* start up our timer for the input device */ + init_timer(&hdaps_timer); + hdaps_timer.function = hdaps_mousedev_poll; + hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; + add_timer(&hdaps_timer); + printk(KERN_INFO "hdaps: driver successfully loaded.\n"); return 0; out_idev: - input_free_polled_device(hdaps_idev); + input_free_device(hdaps_idev); out_group: sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); out_device: @@ -604,8 +611,8 @@ static int __init hdaps_init(void) static void __exit hdaps_exit(void) { - input_unregister_polled_device(hdaps_idev); - input_free_polled_device(hdaps_idev); + del_timer_sync(&hdaps_timer); + input_unregister_device(hdaps_idev); sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); platform_device_unregister(pdev); platform_driver_unregister(&hdaps_driver); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index 1b3327ad6bc4..6545fa798b12 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -349,7 +349,6 @@ struct ipoib_neigh { struct sk_buff_head queue; struct neighbour *neighbour; - struct net_device *dev; struct list_head list; }; @@ -366,8 +365,7 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh) INFINIBAND_ALEN, sizeof(void *)); } -struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh, - struct net_device *dev); +struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh); void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh); extern struct workqueue_struct *ipoib_workqueue; diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 362610d870e4..e072f3c32ce6 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -517,7 +517,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) struct ipoib_path *path; struct ipoib_neigh *neigh; - neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); + neigh = ipoib_neigh_alloc(skb->dst->neighbour); if (!neigh) { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -692,10 +692,9 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } } else if (neigh->ah) { - if (unlikely((memcmp(&neigh->dgid.raw, + if (unlikely(memcmp(&neigh->dgid.raw, skb->dst->neighbour->ha + 4, - sizeof(union ib_gid))) || - (neigh->dev != dev))) { + sizeof(union ib_gid)))) { spin_lock(&priv->lock); /* * It's safe to call ipoib_put_ah() inside @@ -818,13 +817,6 @@ static void ipoib_neigh_cleanup(struct neighbour *n) unsigned long flags; struct ipoib_ah *ah = NULL; - neigh = *to_ipoib_neigh(n); - if (neigh) { - priv = netdev_priv(neigh->dev); - ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n", - n->dev->name); - } else - return; ipoib_dbg(priv, "neigh_cleanup for %06x " IPOIB_GID_FMT "\n", IPOIB_QPN(n->ha), @@ -832,10 +824,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n) spin_lock_irqsave(&priv->lock, flags); - if (neigh->ah) - ah = neigh->ah; - list_del(&neigh->list); - ipoib_neigh_free(n->dev, neigh); + neigh = *to_ipoib_neigh(n); + if (neigh) { + if (neigh->ah) + ah = neigh->ah; + list_del(&neigh->list); + ipoib_neigh_free(n->dev, neigh); + } spin_unlock_irqrestore(&priv->lock, flags); @@ -843,8 +838,7 @@ static void ipoib_neigh_cleanup(struct neighbour *n) ipoib_put_ah(ah); } -struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour, - struct net_device *dev) +struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) { struct ipoib_neigh *neigh; @@ -853,7 +847,6 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour, return NULL; neigh->neighbour = neighbour; - neigh->dev = dev; *to_ipoib_neigh(neighbour) = neigh; skb_queue_head_init(&neigh->queue); ipoib_cm_set(neigh, NULL); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 9bcfc7ad6aa6..827820ec66d1 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -705,8 +705,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) if (skb->dst && skb->dst->neighbour && !*to_ipoib_neigh(skb->dst->neighbour)) { - struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour, - skb->dev); + struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour); if (neigh) { kref_get(&mcast->ah->ref); diff --git a/trunk/drivers/input/Kconfig b/trunk/drivers/input/Kconfig index 63512d906f02..2d87357e2b2b 100644 --- a/trunk/drivers/input/Kconfig +++ b/trunk/drivers/input/Kconfig @@ -114,6 +114,28 @@ config INPUT_JOYDEV To compile this driver as a module, choose M here: the module will be called joydev. +config INPUT_TSDEV + tristate "Touchscreen interface" + ---help--- + Say Y here if you have an application that only can understand the + Compaq touchscreen protocol for absolute pointer data. This is + useful namely for embedded configurations. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called tsdev. + +config INPUT_TSDEV_SCREEN_X + int "Horizontal screen resolution" + depends on INPUT_TSDEV + default "240" + +config INPUT_TSDEV_SCREEN_Y + int "Vertical screen resolution" + depends on INPUT_TSDEV + default "320" + config INPUT_EVDEV tristate "Event interface" help diff --git a/trunk/drivers/input/Makefile b/trunk/drivers/input/Makefile index 99af903bd3ce..15eb752697b3 100644 --- a/trunk/drivers/input/Makefile +++ b/trunk/drivers/input/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o +obj-$(CONFIG_INPUT_TSDEV) += tsdev.o obj-$(CONFIG_INPUT_EVBUG) += evbug.o obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 1d62c8b88e12..f1c3d6cebd58 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -30,8 +30,6 @@ struct evdev { wait_queue_head_t wait; struct evdev_client *grab; struct list_head client_list; - spinlock_t client_lock; /* protects client_list */ - struct mutex mutex; struct device dev; }; @@ -39,54 +37,39 @@ struct evdev_client { struct input_event buffer[EVDEV_BUFFER_SIZE]; int head; int tail; - spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; }; static struct evdev *evdev_table[EVDEV_MINORS]; -static DEFINE_MUTEX(evdev_table_mutex); -static void evdev_pass_event(struct evdev_client *client, - struct input_event *event) -{ - /* - * Interrupts are disabled, just acquire the lock - */ - spin_lock(&client->buffer_lock); - client->buffer[client->head++] = *event; - client->head &= EVDEV_BUFFER_SIZE - 1; - spin_unlock(&client->buffer_lock); - - kill_fasync(&client->fasync, SIGIO, POLL_IN); -} - -/* - * Pass incoming event to all connected clients. - */ -static void evdev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct evdev *evdev = handle->private; struct evdev_client *client; - struct input_event event; - do_gettimeofday(&event.time); - event.type = type; - event.code = code; - event.value = value; + if (evdev->grab) { + client = evdev->grab; - rcu_read_lock(); + do_gettimeofday(&client->buffer[client->head].time); + client->buffer[client->head].type = type; + client->buffer[client->head].code = code; + client->buffer[client->head].value = value; + client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); - client = rcu_dereference(evdev->grab); - if (client) - evdev_pass_event(client, &event); - else - list_for_each_entry_rcu(client, &evdev->client_list, node) - evdev_pass_event(client, &event); + kill_fasync(&client->fasync, SIGIO, POLL_IN); + } else + list_for_each_entry(client, &evdev->client_list, node) { - rcu_read_unlock(); + do_gettimeofday(&client->buffer[client->head].time); + client->buffer[client->head].type = type; + client->buffer[client->head].code = code; + client->buffer[client->head].value = value; + client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); + + kill_fasync(&client->fasync, SIGIO, POLL_IN); + } wake_up_interruptible(&evdev->wait); } @@ -105,140 +88,38 @@ static int evdev_flush(struct file *file, fl_owner_t id) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - int retval; - - retval = mutex_lock_interruptible(&evdev->mutex); - if (retval) - return retval; if (!evdev->exist) - retval = -ENODEV; - else - retval = input_flush_device(&evdev->handle, file); + return -ENODEV; - mutex_unlock(&evdev->mutex); - return retval; + return input_flush_device(&evdev->handle, file); } static void evdev_free(struct device *dev) { struct evdev *evdev = container_of(dev, struct evdev, dev); + evdev_table[evdev->minor] = NULL; kfree(evdev); } -/* - * Grabs an event device (along with underlying input device). - * This function is called with evdev->mutex taken. - */ -static int evdev_grab(struct evdev *evdev, struct evdev_client *client) -{ - int error; - - if (evdev->grab) - return -EBUSY; - - error = input_grab_device(&evdev->handle); - if (error) - return error; - - rcu_assign_pointer(evdev->grab, client); - synchronize_rcu(); - - return 0; -} - -static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) -{ - if (evdev->grab != client) - return -EINVAL; - - rcu_assign_pointer(evdev->grab, NULL); - synchronize_rcu(); - input_release_device(&evdev->handle); - - return 0; -} - -static void evdev_attach_client(struct evdev *evdev, - struct evdev_client *client) -{ - spin_lock(&evdev->client_lock); - list_add_tail_rcu(&client->node, &evdev->client_list); - spin_unlock(&evdev->client_lock); - synchronize_rcu(); -} - -static void evdev_detach_client(struct evdev *evdev, - struct evdev_client *client) -{ - spin_lock(&evdev->client_lock); - list_del_rcu(&client->node); - spin_unlock(&evdev->client_lock); - synchronize_rcu(); -} - -static int evdev_open_device(struct evdev *evdev) -{ - int retval; - - retval = mutex_lock_interruptible(&evdev->mutex); - if (retval) - return retval; - - if (!evdev->exist) - retval = -ENODEV; - else if (!evdev->open++) { - retval = input_open_device(&evdev->handle); - if (retval) - evdev->open--; - } - - mutex_unlock(&evdev->mutex); - return retval; -} - -static void evdev_close_device(struct evdev *evdev) -{ - mutex_lock(&evdev->mutex); - - if (evdev->exist && !--evdev->open) - input_close_device(&evdev->handle); - - mutex_unlock(&evdev->mutex); -} - -/* - * Wake up users waiting for IO so they can disconnect from - * dead device. - */ -static void evdev_hangup(struct evdev *evdev) -{ - struct evdev_client *client; - - spin_lock(&evdev->client_lock); - list_for_each_entry(client, &evdev->client_list, node) - kill_fasync(&client->fasync, SIGIO, POLL_HUP); - spin_unlock(&evdev->client_lock); - - wake_up_interruptible(&evdev->wait); -} - static int evdev_release(struct inode *inode, struct file *file) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - mutex_lock(&evdev->mutex); - if (evdev->grab == client) - evdev_ungrab(evdev, client); - mutex_unlock(&evdev->mutex); + if (evdev->grab == client) { + input_release_device(&evdev->handle); + evdev->grab = NULL; + } evdev_fasync(-1, file, 0); - evdev_detach_client(evdev, client); + list_del(&client->node); kfree(client); - evdev_close_device(evdev); + if (!--evdev->open && evdev->exist) + input_close_device(&evdev->handle); + put_device(&evdev->dev); return 0; @@ -246,44 +127,41 @@ static int evdev_release(struct inode *inode, struct file *file) static int evdev_open(struct inode *inode, struct file *file) { - struct evdev *evdev; struct evdev_client *client; + struct evdev *evdev; int i = iminor(inode) - EVDEV_MINOR_BASE; int error; if (i >= EVDEV_MINORS) return -ENODEV; - error = mutex_lock_interruptible(&evdev_table_mutex); - if (error) - return error; evdev = evdev_table[i]; - if (evdev) - get_device(&evdev->dev); - mutex_unlock(&evdev_table_mutex); - if (!evdev) + if (!evdev || !evdev->exist) return -ENODEV; + get_device(&evdev->dev); + client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); if (!client) { error = -ENOMEM; goto err_put_evdev; } - spin_lock_init(&client->buffer_lock); client->evdev = evdev; - evdev_attach_client(evdev, client); + list_add_tail(&client->node, &evdev->client_list); - error = evdev_open_device(evdev); - if (error) - goto err_free_client; + if (!evdev->open++ && evdev->exist) { + error = input_open_device(&evdev->handle); + if (error) + goto err_free_client; + } file->private_data = client; return 0; err_free_client: - evdev_detach_client(evdev, client); + list_del(&client->node); kfree(client); err_put_evdev: put_device(&evdev->dev); @@ -319,14 +197,12 @@ static inline size_t evdev_event_size(void) sizeof(struct input_event_compat) : sizeof(struct input_event); } -static int evdev_event_from_user(const char __user *buffer, - struct input_event *event) +static int evdev_event_from_user(const char __user *buffer, struct input_event *event) { if (COMPAT_TEST) { struct input_event_compat compat_event; - if (copy_from_user(&compat_event, buffer, - sizeof(struct input_event_compat))) + if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat))) return -EFAULT; event->time.tv_sec = compat_event.time.tv_sec; @@ -343,8 +219,7 @@ static int evdev_event_from_user(const char __user *buffer, return 0; } -static int evdev_event_to_user(char __user *buffer, - const struct input_event *event) +static int evdev_event_to_user(char __user *buffer, const struct input_event *event) { if (COMPAT_TEST) { struct input_event_compat compat_event; @@ -355,8 +230,7 @@ static int evdev_event_to_user(char __user *buffer, compat_event.code = event->code; compat_event.value = event->value; - if (copy_to_user(buffer, &compat_event, - sizeof(struct input_event_compat))) + if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) return -EFAULT; } else { @@ -374,8 +248,7 @@ static inline size_t evdev_event_size(void) return sizeof(struct input_event); } -static int evdev_event_from_user(const char __user *buffer, - struct input_event *event) +static int evdev_event_from_user(const char __user *buffer, struct input_event *event) { if (copy_from_user(event, buffer, sizeof(struct input_event))) return -EFAULT; @@ -383,8 +256,7 @@ static int evdev_event_from_user(const char __user *buffer, return 0; } -static int evdev_event_to_user(char __user *buffer, - const struct input_event *event) +static int evdev_event_to_user(char __user *buffer, const struct input_event *event) { if (copy_to_user(buffer, event, sizeof(struct input_event))) return -EFAULT; @@ -394,71 +266,37 @@ static int evdev_event_to_user(char __user *buffer, #endif /* CONFIG_COMPAT */ -static ssize_t evdev_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; struct input_event event; - int retval; + int retval = 0; - retval = mutex_lock_interruptible(&evdev->mutex); - if (retval) - return retval; - - if (!evdev->exist) { - retval = -ENODEV; - goto out; - } + if (!evdev->exist) + return -ENODEV; while (retval < count) { - if (evdev_event_from_user(buffer + retval, &event)) { - retval = -EFAULT; - goto out; - } - - input_inject_event(&evdev->handle, - event.type, event.code, event.value); + if (evdev_event_from_user(buffer + retval, &event)) + return -EFAULT; + input_inject_event(&evdev->handle, event.type, event.code, event.value); retval += evdev_event_size(); } - out: - mutex_unlock(&evdev->mutex); return retval; } -static int evdev_fetch_next_event(struct evdev_client *client, - struct input_event *event) -{ - int have_event; - - spin_lock_irq(&client->buffer_lock); - - have_event = client->head != client->tail; - if (have_event) { - *event = client->buffer[client->tail++]; - client->tail &= EVDEV_BUFFER_SIZE - 1; - } - - spin_unlock_irq(&client->buffer_lock); - - return have_event; -} - -static ssize_t evdev_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - struct input_event event; int retval; if (count < evdev_event_size()) return -EINVAL; - if (client->head == client->tail && evdev->exist && - (file->f_flags & O_NONBLOCK)) + if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; retval = wait_event_interruptible(evdev->wait, @@ -469,12 +307,14 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, if (!evdev->exist) return -ENODEV; - while (retval + evdev_event_size() <= count && - evdev_fetch_next_event(client, &event)) { + while (client->head != client->tail && retval + evdev_event_size() <= count) { + + struct input_event *event = (struct input_event *) client->buffer + client->tail; - if (evdev_event_to_user(buffer + retval, &event)) + if (evdev_event_to_user(buffer + retval, event)) return -EFAULT; + client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += evdev_event_size(); } @@ -569,8 +409,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) return copy_to_user(p, str, len) ? -EFAULT : len; } -static long evdev_do_ioctl(struct file *file, unsigned int cmd, - void __user *p, int compat_mode) +static long evdev_ioctl_handler(struct file *file, unsigned int cmd, + void __user *p, int compat_mode) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; @@ -581,289 +421,215 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, int i, t, u, v; int error; - switch (cmd) { + if (!evdev->exist) + return -ENODEV; - case EVIOCGVERSION: - return put_user(EV_VERSION, ip); + switch (cmd) { - case EVIOCGID: - if (copy_to_user(p, &dev->id, sizeof(struct input_id))) - return -EFAULT; - return 0; + case EVIOCGVERSION: + return put_user(EV_VERSION, ip); - case EVIOCGREP: - if (!test_bit(EV_REP, dev->evbit)) - return -ENOSYS; - if (put_user(dev->rep[REP_DELAY], ip)) - return -EFAULT; - if (put_user(dev->rep[REP_PERIOD], ip + 1)) - return -EFAULT; - return 0; + case EVIOCGID: + if (copy_to_user(p, &dev->id, sizeof(struct input_id))) + return -EFAULT; + return 0; - case EVIOCSREP: - if (!test_bit(EV_REP, dev->evbit)) - return -ENOSYS; - if (get_user(u, ip)) - return -EFAULT; - if (get_user(v, ip + 1)) - return -EFAULT; + case EVIOCGREP: + if (!test_bit(EV_REP, dev->evbit)) + return -ENOSYS; + if (put_user(dev->rep[REP_DELAY], ip)) + return -EFAULT; + if (put_user(dev->rep[REP_PERIOD], ip + 1)) + return -EFAULT; + return 0; - input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); - input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); + case EVIOCSREP: + if (!test_bit(EV_REP, dev->evbit)) + return -ENOSYS; + if (get_user(u, ip)) + return -EFAULT; + if (get_user(v, ip + 1)) + return -EFAULT; - return 0; + input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); + input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); - case EVIOCGKEYCODE: - if (get_user(t, ip)) - return -EFAULT; + return 0; - error = dev->getkeycode(dev, t, &v); - if (error) - return error; + case EVIOCGKEYCODE: + if (get_user(t, ip)) + return -EFAULT; - if (put_user(v, ip + 1)) - return -EFAULT; + error = dev->getkeycode(dev, t, &v); + if (error) + return error; - return 0; + if (put_user(v, ip + 1)) + return -EFAULT; - case EVIOCSKEYCODE: - if (get_user(t, ip) || get_user(v, ip + 1)) - return -EFAULT; + return 0; - return dev->setkeycode(dev, t, v); + case EVIOCSKEYCODE: + if (get_user(t, ip) || get_user(v, ip + 1)) + return -EFAULT; - case EVIOCSFF: - if (copy_from_user(&effect, p, sizeof(effect))) - return -EFAULT; + return dev->setkeycode(dev, t, v); - error = input_ff_upload(dev, &effect, file); + case EVIOCSFF: + if (copy_from_user(&effect, p, sizeof(effect))) + return -EFAULT; - if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) - return -EFAULT; + error = input_ff_upload(dev, &effect, file); - return error; + if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) + return -EFAULT; - case EVIOCRMFF: - return input_ff_erase(dev, (int)(unsigned long) p, file); + return error; - case EVIOCGEFFECTS: - i = test_bit(EV_FF, dev->evbit) ? - dev->ff->max_effects : 0; - if (put_user(i, ip)) - return -EFAULT; - return 0; + case EVIOCRMFF: + return input_ff_erase(dev, (int)(unsigned long) p, file); - case EVIOCGRAB: - if (p) - return evdev_grab(evdev, client); - else - return evdev_ungrab(evdev, client); + case EVIOCGEFFECTS: + i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; + if (put_user(i, ip)) + return -EFAULT; + return 0; + + case EVIOCGRAB: + if (p) { + if (evdev->grab) + return -EBUSY; + if (input_grab_device(&evdev->handle)) + return -EBUSY; + evdev->grab = client; + return 0; + } else { + if (evdev->grab != client) + return -EINVAL; + input_release_device(&evdev->handle); + evdev->grab = NULL; + return 0; + } - default: + default: - if (_IOC_TYPE(cmd) != 'E') - return -EINVAL; + if (_IOC_TYPE(cmd) != 'E') + return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { + if (_IOC_DIR(cmd) == _IOC_READ) { - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { - unsigned long *bits; - int len; + unsigned long *bits; + int len; - switch (_IOC_NR(cmd) & EV_MAX) { + switch (_IOC_NR(cmd) & EV_MAX) { + case 0: bits = dev->evbit; len = EV_MAX; break; + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; + case EV_REL: bits = dev->relbit; len = REL_MAX; break; + case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; + case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; + case EV_LED: bits = dev->ledbit; len = LED_MAX; break; + case EV_SND: bits = dev->sndbit; len = SND_MAX; break; + case EV_FF: bits = dev->ffbit; len = FF_MAX; break; + case EV_SW: bits = dev->swbit; len = SW_MAX; break; + default: return -EINVAL; + } + return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); + } - case 0: bits = dev->evbit; len = EV_MAX; break; - case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; - case EV_REL: bits = dev->relbit; len = REL_MAX; break; - case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; - case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; - case EV_LED: bits = dev->ledbit; len = LED_MAX; break; - case EV_SND: bits = dev->sndbit; len = SND_MAX; break; - case EV_FF: bits = dev->ffbit; len = FF_MAX; break; - case EV_SW: bits = dev->swbit; len = SW_MAX; break; - default: return -EINVAL; - } - return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) + return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) - return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), - p, compat_mode); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) + return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) - return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), - p, compat_mode); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) + return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) - return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), - p, compat_mode); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) + return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) - return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), - p, compat_mode); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) + return str_to_user(dev->name, _IOC_SIZE(cmd), p); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) - return str_to_user(dev->name, _IOC_SIZE(cmd), p); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) + return str_to_user(dev->phys, _IOC_SIZE(cmd), p); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) - return str_to_user(dev->phys, _IOC_SIZE(cmd), p); + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) + return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) - return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { + t = _IOC_NR(cmd) & ABS_MAX; - t = _IOC_NR(cmd) & ABS_MAX; + abs.value = dev->abs[t]; + abs.minimum = dev->absmin[t]; + abs.maximum = dev->absmax[t]; + abs.fuzz = dev->absfuzz[t]; + abs.flat = dev->absflat[t]; - abs.value = dev->abs[t]; - abs.minimum = dev->absmin[t]; - abs.maximum = dev->absmax[t]; - abs.fuzz = dev->absfuzz[t]; - abs.flat = dev->absflat[t]; + if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) + return -EFAULT; - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) - return -EFAULT; + return 0; + } - return 0; } - } - - if (_IOC_DIR(cmd) == _IOC_WRITE) { + if (_IOC_DIR(cmd) == _IOC_WRITE) { - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { - t = _IOC_NR(cmd) & ABS_MAX; + t = _IOC_NR(cmd) & ABS_MAX; - if (copy_from_user(&abs, p, - sizeof(struct input_absinfo))) - return -EFAULT; + if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) + return -EFAULT; - /* - * Take event lock to ensure that we are not - * changing device parameters in the middle - * of event. - */ - spin_lock_irq(&dev->event_lock); + dev->abs[t] = abs.value; + dev->absmin[t] = abs.minimum; + dev->absmax[t] = abs.maximum; + dev->absfuzz[t] = abs.fuzz; + dev->absflat[t] = abs.flat; - dev->abs[t] = abs.value; - dev->absmin[t] = abs.minimum; - dev->absmax[t] = abs.maximum; - dev->absfuzz[t] = abs.fuzz; - dev->absflat[t] = abs.flat; - - spin_unlock_irq(&dev->event_lock); - - return 0; + return 0; + } } - } } return -EINVAL; } -static long evdev_ioctl_handler(struct file *file, unsigned int cmd, - void __user *p, int compat_mode) -{ - struct evdev_client *client = file->private_data; - struct evdev *evdev = client->evdev; - int retval; - - retval = mutex_lock_interruptible(&evdev->mutex); - if (retval) - return retval; - - if (!evdev->exist) { - retval = -ENODEV; - goto out; - } - - retval = evdev_do_ioctl(file, cmd, p, compat_mode); - - out: - mutex_unlock(&evdev->mutex); - return retval; -} - static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); } #ifdef CONFIG_COMPAT -static long evdev_ioctl_compat(struct file *file, - unsigned int cmd, unsigned long arg) +static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); } #endif static const struct file_operations evdev_fops = { - .owner = THIS_MODULE, - .read = evdev_read, - .write = evdev_write, - .poll = evdev_poll, - .open = evdev_open, - .release = evdev_release, - .unlocked_ioctl = evdev_ioctl, + .owner = THIS_MODULE, + .read = evdev_read, + .write = evdev_write, + .poll = evdev_poll, + .open = evdev_open, + .release = evdev_release, + .unlocked_ioctl = evdev_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = evdev_ioctl_compat, + .compat_ioctl = evdev_ioctl_compat, #endif - .fasync = evdev_fasync, - .flush = evdev_flush + .fasync = evdev_fasync, + .flush = evdev_flush }; -static int evdev_install_chrdev(struct evdev *evdev) -{ - /* - * No need to do any locking here as calls to connect and - * disconnect are serialized by the input core - */ - evdev_table[evdev->minor] = evdev; - return 0; -} - -static void evdev_remove_chrdev(struct evdev *evdev) -{ - /* - * Lock evdev table to prevent race with evdev_open() - */ - mutex_lock(&evdev_table_mutex); - evdev_table[evdev->minor] = NULL; - mutex_unlock(&evdev_table_mutex); -} - -/* - * Mark device non-existent. This disables writes, ioctls and - * prevents new users from opening the device. Already posted - * blocking reads will stay, however new ones will fail. - */ -static void evdev_mark_dead(struct evdev *evdev) -{ - mutex_lock(&evdev->mutex); - evdev->exist = 0; - mutex_unlock(&evdev->mutex); -} - -static void evdev_cleanup(struct evdev *evdev) -{ - struct input_handle *handle = &evdev->handle; - - evdev_mark_dead(evdev); - evdev_hangup(evdev); - evdev_remove_chrdev(evdev); - - /* evdev is marked dead so no one else accesses evdev->open */ - if (evdev->open) { - input_flush_device(handle, NULL); - input_close_device(handle); - } -} - -/* - * Create new evdev device. Note that input core serializes calls - * to connect and disconnect so we don't need to lock evdev_table here. - */ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { @@ -871,10 +637,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, int minor; int error; - for (minor = 0; minor < EVDEV_MINORS; minor++) - if (!evdev_table[minor]) - break; - + for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); if (minor == EVDEV_MINORS) { printk(KERN_ERR "evdev: no more free evdev devices\n"); return -ENFILE; @@ -885,44 +648,38 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, return -ENOMEM; INIT_LIST_HEAD(&evdev->client_list); - spin_lock_init(&evdev->client_lock); - mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); - snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); evdev->exist = 1; evdev->minor = minor; - evdev->handle.dev = dev; evdev->handle.name = evdev->name; evdev->handle.handler = handler; evdev->handle.private = evdev; + snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); - strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); + snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id), + "event%d", minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; + evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); evdev->dev.release = evdev_free; device_initialize(&evdev->dev); - error = input_register_handle(&evdev->handle); - if (error) - goto err_free_evdev; + evdev_table[minor] = evdev; - error = evdev_install_chrdev(evdev); + error = device_add(&evdev->dev); if (error) - goto err_unregister_handle; + goto err_free_evdev; - error = device_add(&evdev->dev); + error = input_register_handle(&evdev->handle); if (error) - goto err_cleanup_evdev; + goto err_delete_evdev; return 0; - err_cleanup_evdev: - evdev_cleanup(evdev); - err_unregister_handle: - input_unregister_handle(&evdev->handle); + err_delete_evdev: + device_del(&evdev->dev); err_free_evdev: put_device(&evdev->dev); return error; @@ -931,10 +688,21 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, static void evdev_disconnect(struct input_handle *handle) { struct evdev *evdev = handle->private; + struct evdev_client *client; - device_del(&evdev->dev); - evdev_cleanup(evdev); input_unregister_handle(handle); + device_del(&evdev->dev); + + evdev->exist = 0; + + if (evdev->open) { + input_flush_device(handle, NULL); + input_close_device(handle); + list_for_each_entry(client, &evdev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + wake_up_interruptible(&evdev->wait); + } + put_device(&evdev->dev); } @@ -946,13 +714,13 @@ static const struct input_device_id evdev_ids[] = { MODULE_DEVICE_TABLE(input, evdev_ids); static struct input_handler evdev_handler = { - .event = evdev_event, - .connect = evdev_connect, - .disconnect = evdev_disconnect, - .fops = &evdev_fops, - .minor = EVDEV_MINOR_BASE, - .name = "evdev", - .id_table = evdev_ids, + .event = evdev_event, + .connect = evdev_connect, + .disconnect = evdev_disconnect, + .fops = &evdev_fops, + .minor = EVDEV_MINOR_BASE, + .name = "evdev", + .id_table = evdev_ids, }; static int __init evdev_init(void) diff --git a/trunk/drivers/input/input-polldev.c b/trunk/drivers/input/input-polldev.c index 92b359894e81..b773d4c756a6 100644 --- a/trunk/drivers/input/input-polldev.c +++ b/trunk/drivers/input/input-polldev.c @@ -70,7 +70,6 @@ static int input_open_polled_device(struct input_dev *input) { struct input_polled_dev *dev = input->private; int error; - unsigned long ticks; error = input_polldev_start_workqueue(); if (error) @@ -79,10 +78,8 @@ static int input_open_polled_device(struct input_dev *input) if (dev->flush) dev->flush(dev); - ticks = msecs_to_jiffies(dev->poll_interval); - if (ticks >= HZ) - ticks = round_jiffies(ticks); - queue_delayed_work(polldev_wq, &dev->work, ticks); + queue_delayed_work(polldev_wq, &dev->work, + msecs_to_jiffies(dev->poll_interval)); return 0; } diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 2f2b020cd629..5dc361c954e2 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -17,10 +17,10 @@ #include #include #include +#include #include #include #include -#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -31,245 +31,167 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); -/* - * input_mutex protects access to both input_dev_list and input_handler_list. - * This also causes input_[un]register_device and input_[un]register_handler - * be mutually exclusive which simplifies locking in drivers implementing - * input handlers. - */ -static DEFINE_MUTEX(input_mutex); - static struct input_handler *input_table[8]; -static inline int is_event_supported(unsigned int code, - unsigned long *bm, unsigned int max) +/** + * input_event() - report new input event + * @dev: device that generated the event + * @type: type of the event + * @code: event code + * @value: value of the event + * + * This function should be used by drivers implementing various input devices + * See also input_inject_event() + */ +void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - return code <= max && test_bit(code, bm); -} + struct input_handle *handle; -static int input_defuzz_abs_event(int value, int old_val, int fuzz) -{ - if (fuzz) { - if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2) - return old_val; + if (type > EV_MAX || !test_bit(type, dev->evbit)) + return; - if (value > old_val - fuzz && value < old_val + fuzz) - return (old_val * 3 + value) / 4; + add_input_randomness(type, code, value); - if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2) - return (old_val + value) / 2; - } + switch (type) { - return value; -} + case EV_SYN: + switch (code) { + case SYN_CONFIG: + if (dev->event) + dev->event(dev, type, code, value); + break; + + case SYN_REPORT: + if (dev->sync) + return; + dev->sync = 1; + break; + } + break; -/* - * Pass event through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. - */ -static void input_pass_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - struct input_handle *handle; + case EV_KEY: - rcu_read_lock(); + if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) + return; - handle = rcu_dereference(dev->grab); - if (handle) - handle->handler->event(handle, type, code, value); - else - list_for_each_entry_rcu(handle, &dev->h_list, d_node) - if (handle->open) - handle->handler->event(handle, - type, code, value); - rcu_read_unlock(); -} + if (value == 2) + break; -/* - * Generate software autorepeat event. Note that we take - * dev->event_lock here to avoid racing with input_event - * which may cause keys get "stuck". - */ -static void input_repeat_key(unsigned long data) -{ - struct input_dev *dev = (void *) data; - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); + change_bit(code, dev->key); - if (test_bit(dev->repeat_key, dev->key) && - is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { + if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) { + dev->repeat_key = code; + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); + } - input_pass_event(dev, EV_KEY, dev->repeat_key, 2); + break; - if (dev->sync) { - /* - * Only send SYN_REPORT if we are not in a middle - * of driver parsing a new hardware packet. - * Otherwise assume that the driver will send - * SYN_REPORT once it's done. - */ - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } + case EV_SW: - if (dev->rep[REP_PERIOD]) - mod_timer(&dev->timer, jiffies + - msecs_to_jiffies(dev->rep[REP_PERIOD])); - } + if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value) + return; - spin_unlock_irqrestore(&dev->event_lock, flags); -} + change_bit(code, dev->sw); -static void input_start_autorepeat(struct input_dev *dev, int code) -{ - if (test_bit(EV_REP, dev->evbit) && - dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && - dev->timer.data) { - dev->repeat_key = code; - mod_timer(&dev->timer, - jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); - } -} + break; -#define INPUT_IGNORE_EVENT 0 -#define INPUT_PASS_TO_HANDLERS 1 -#define INPUT_PASS_TO_DEVICE 2 -#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) + case EV_ABS: -static void input_handle_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - int disposition = INPUT_IGNORE_EVENT; + if (code > ABS_MAX || !test_bit(code, dev->absbit)) + return; - switch (type) { + if (dev->absfuzz[code]) { + if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) && + (value < dev->abs[code] + (dev->absfuzz[code] >> 1))) + return; - case EV_SYN: - switch (code) { - case SYN_CONFIG: - disposition = INPUT_PASS_TO_ALL; - break; + if ((value > dev->abs[code] - dev->absfuzz[code]) && + (value < dev->abs[code] + dev->absfuzz[code])) + value = (dev->abs[code] * 3 + value) >> 2; - case SYN_REPORT: - if (!dev->sync) { - dev->sync = 1; - disposition = INPUT_PASS_TO_HANDLERS; + if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) && + (value < dev->abs[code] + (dev->absfuzz[code] << 1))) + value = (dev->abs[code] + value) >> 1; } - break; - } - break; - case EV_KEY: - if (is_event_supported(code, dev->keybit, KEY_MAX) && - !!test_bit(code, dev->key) != value) { + if (dev->abs[code] == value) + return; - if (value != 2) { - __change_bit(code, dev->key); - if (value) - input_start_autorepeat(dev, code); - } + dev->abs[code] = value; + break; - disposition = INPUT_PASS_TO_HANDLERS; - } - break; + case EV_REL: - case EV_SW: - if (is_event_supported(code, dev->swbit, SW_MAX) && - !!test_bit(code, dev->sw) != value) { + if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0)) + return; - __change_bit(code, dev->sw); - disposition = INPUT_PASS_TO_HANDLERS; - } - break; + break; - case EV_ABS: - if (is_event_supported(code, dev->absbit, ABS_MAX)) { + case EV_MSC: - value = input_defuzz_abs_event(value, - dev->abs[code], dev->absfuzz[code]); + if (code > MSC_MAX || !test_bit(code, dev->mscbit)) + return; - if (dev->abs[code] != value) { - dev->abs[code] = value; - disposition = INPUT_PASS_TO_HANDLERS; - } - } - break; + if (dev->event) + dev->event(dev, type, code, value); - case EV_REL: - if (is_event_supported(code, dev->relbit, REL_MAX) && value) - disposition = INPUT_PASS_TO_HANDLERS; + break; - break; + case EV_LED: - case EV_MSC: - if (is_event_supported(code, dev->mscbit, MSC_MAX)) - disposition = INPUT_PASS_TO_ALL; + if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) + return; - break; + change_bit(code, dev->led); - case EV_LED: - if (is_event_supported(code, dev->ledbit, LED_MAX) && - !!test_bit(code, dev->led) != value) { + if (dev->event) + dev->event(dev, type, code, value); - __change_bit(code, dev->led); - disposition = INPUT_PASS_TO_ALL; - } - break; + break; - case EV_SND: - if (is_event_supported(code, dev->sndbit, SND_MAX)) { + case EV_SND: + + if (code > SND_MAX || !test_bit(code, dev->sndbit)) + return; if (!!test_bit(code, dev->snd) != !!value) - __change_bit(code, dev->snd); - disposition = INPUT_PASS_TO_ALL; - } - break; + change_bit(code, dev->snd); - case EV_REP: - if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) { - dev->rep[code] = value; - disposition = INPUT_PASS_TO_ALL; - } - break; + if (dev->event) + dev->event(dev, type, code, value); - case EV_FF: - if (value >= 0) - disposition = INPUT_PASS_TO_ALL; - break; - } + break; - if (type != EV_SYN) - dev->sync = 0; + case EV_REP: - if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) - dev->event(dev, type, code, value); + if (code > REP_MAX || value < 0 || dev->rep[code] == value) + return; - if (disposition & INPUT_PASS_TO_HANDLERS) - input_pass_event(dev, type, code, value); -} + dev->rep[code] = value; + if (dev->event) + dev->event(dev, type, code, value); -/** - * input_event() - report new input event - * @dev: device that generated the event - * @type: type of the event - * @code: event code - * @value: value of the event - * - * This function should be used by drivers implementing various input - * devices. See also input_inject_event(). - */ + break; -void input_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - unsigned long flags; + case EV_FF: - if (is_event_supported(type, dev->evbit, EV_MAX)) { + if (value < 0) + return; - spin_lock_irqsave(&dev->event_lock, flags); - add_input_randomness(type, code, value); - input_handle_event(dev, type, code, value); - spin_unlock_irqrestore(&dev->event_lock, flags); + if (dev->event) + dev->event(dev, type, code, value); + break; } + + if (type != EV_SYN) + dev->sync = 0; + + if (dev->grab) + dev->grab->handler->event(dev->grab, type, code, value); + else + list_for_each_entry(handle, &dev->h_list, d_node) + if (handle->open) + handle->handler->event(handle, type, code, value); } EXPORT_SYMBOL(input_event); @@ -280,228 +202,102 @@ EXPORT_SYMBOL(input_event); * @code: event code * @value: value of the event * - * Similar to input_event() but will ignore event if device is - * "grabbed" and handle injecting event is not the one that owns - * the device. + * Similar to input_event() but will ignore event if device is "grabbed" and handle + * injecting event is not the one that owns the device. */ -void input_inject_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { - struct input_dev *dev = handle->dev; - struct input_handle *grab; - unsigned long flags; - - if (is_event_supported(type, dev->evbit, EV_MAX)) { - spin_lock_irqsave(&dev->event_lock, flags); - - rcu_read_lock(); - grab = rcu_dereference(dev->grab); - if (!grab || grab == handle) - input_handle_event(dev, type, code, value); - rcu_read_unlock(); - - spin_unlock_irqrestore(&dev->event_lock, flags); - } + if (!handle->dev->grab || handle->dev->grab == handle) + input_event(handle->dev, type, code, value); } EXPORT_SYMBOL(input_inject_event); -/** - * input_grab_device - grabs device for exclusive use - * @handle: input handle that wants to own the device - * - * When a device is grabbed by an input handle all events generated by - * the device are delivered only to this handle. Also events injected - * by other input handles are ignored while device is grabbed. - */ -int input_grab_device(struct input_handle *handle) +static void input_repeat_key(unsigned long data) { - struct input_dev *dev = handle->dev; - int retval; + struct input_dev *dev = (void *) data; - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + if (!test_bit(dev->repeat_key, dev->key)) + return; - if (dev->grab) { - retval = -EBUSY; - goto out; - } + input_event(dev, EV_KEY, dev->repeat_key, 2); + input_sync(dev); - rcu_assign_pointer(dev->grab, handle); - synchronize_rcu(); + if (dev->rep[REP_PERIOD]) + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); +} - out: - mutex_unlock(&dev->mutex); - return retval; +int input_grab_device(struct input_handle *handle) +{ + if (handle->dev->grab) + return -EBUSY; + + handle->dev->grab = handle; + return 0; } EXPORT_SYMBOL(input_grab_device); -static void __input_release_device(struct input_handle *handle) +void input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; if (dev->grab == handle) { - rcu_assign_pointer(dev->grab, NULL); - /* Make sure input_pass_event() notices that grab is gone */ - synchronize_rcu(); + dev->grab = NULL; list_for_each_entry(handle, &dev->h_list, d_node) - if (handle->open && handle->handler->start) + if (handle->handler->start) handle->handler->start(handle); } } - -/** - * input_release_device - release previously grabbed device - * @handle: input handle that owns the device - * - * Releases previously grabbed device so that other input handles can - * start receiving input events. Upon release all handlers attached - * to the device have their start() method called so they have a change - * to synchronize device state with the rest of the system. - */ -void input_release_device(struct input_handle *handle) -{ - struct input_dev *dev = handle->dev; - - mutex_lock(&dev->mutex); - __input_release_device(handle); - mutex_unlock(&dev->mutex); -} EXPORT_SYMBOL(input_release_device); -/** - * input_open_device - open input device - * @handle: handle through which device is being accessed - * - * This function should be called by input handlers when they - * want to start receive events from given input device. - */ int input_open_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - int retval; - - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + int err; - if (dev->going_away) { - retval = -ENODEV; - goto out; - } + err = mutex_lock_interruptible(&dev->mutex); + if (err) + return err; handle->open++; if (!dev->users++ && dev->open) - retval = dev->open(dev); - - if (retval) { - dev->users--; - if (!--handle->open) { - /* - * Make sure we are not delivering any more events - * through this handle - */ - synchronize_rcu(); - } - } + err = dev->open(dev); + + if (err) + handle->open--; - out: mutex_unlock(&dev->mutex); - return retval; + + return err; } EXPORT_SYMBOL(input_open_device); -int input_flush_device(struct input_handle *handle, struct file *file) +int input_flush_device(struct input_handle* handle, struct file* file) { - struct input_dev *dev = handle->dev; - int retval; + if (handle->dev->flush) + return handle->dev->flush(handle->dev, file); - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; - - if (dev->flush) - retval = dev->flush(dev, file); - - mutex_unlock(&dev->mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_flush_device); -/** - * input_close_device - close input device - * @handle: handle through which device is being accessed - * - * This function should be called by input handlers when they - * want to stop receive events from given input device. - */ void input_close_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - mutex_lock(&dev->mutex); + input_release_device(handle); - __input_release_device(handle); + mutex_lock(&dev->mutex); if (!--dev->users && dev->close) dev->close(dev); - - if (!--handle->open) { - /* - * synchronize_rcu() makes sure that input_pass_event() - * completed and that no more input events are delivered - * through this handle - */ - synchronize_rcu(); - } + handle->open--; mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_close_device); -/* - * Prepare device for unregistering - */ -static void input_disconnect_device(struct input_dev *dev) -{ - struct input_handle *handle; - int code; - - /* - * Mark device as going away. Note that we take dev->mutex here - * not to protect access to dev->going_away but rather to ensure - * that there are no threads in the middle of input_open_device() - */ - mutex_lock(&dev->mutex); - dev->going_away = 1; - mutex_unlock(&dev->mutex); - - spin_lock_irq(&dev->event_lock); - - /* - * Simulate keyup events for all pressed keys so that handlers - * are not left with "stuck" keys. The driver may continue - * generate events even after we done here but they will not - * reach any handlers. - */ - if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { - for (code = 0; code <= KEY_MAX; code++) { - if (is_event_supported(code, dev->keybit, KEY_MAX) && - test_bit(code, dev->key)) { - input_pass_event(dev, EV_KEY, code, 0); - } - } - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } - - list_for_each_entry(handle, &dev->h_list, d_node) - handle->open = 0; - - spin_unlock_irq(&dev->event_lock); -} - static int input_fetch_keycode(struct input_dev *dev, int scancode) { switch (dev->keycodesize) { @@ -677,8 +473,7 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) { - if (mutex_lock_interruptible(&input_mutex)) - return NULL; + /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ return seq_list_start(&input_dev_list, *pos); } @@ -690,7 +485,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void input_devices_seq_stop(struct seq_file *seq, void *v) { - mutex_unlock(&input_mutex); + /* release lock here */ } static void input_seq_print_bitmap(struct seq_file *seq, const char *name, @@ -774,9 +569,7 @@ static const struct file_operations input_devices_fileops = { static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) { - if (mutex_lock_interruptible(&input_mutex)) - return NULL; - + /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ seq->private = (void *)(unsigned long)*pos; return seq_list_start(&input_handler_list, *pos); } @@ -789,7 +582,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void input_handlers_seq_stop(struct seq_file *seq, void *v) { - mutex_unlock(&input_mutex); + /* release lock here */ } static int input_handlers_seq_show(struct seq_file *seq, void *v) @@ -1190,7 +983,6 @@ struct input_dev *input_allocate_device(void) dev->dev.class = &input_class; device_initialize(&dev->dev); mutex_init(&dev->mutex); - spin_lock_init(&dev->event_lock); INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->node); @@ -1208,7 +1000,7 @@ EXPORT_SYMBOL(input_allocate_device); * This function should only be used if input_register_device() * was not called yet or if it failed. Once device was registered * use input_unregister_device() and memory will be freed once last - * reference to the device is dropped. + * refrence to the device is dropped. * * Device should be allocated by input_allocate_device(). * @@ -1278,18 +1070,6 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int } EXPORT_SYMBOL(input_set_capability); -/** - * input_register_device - register device with input core - * @dev: device to be registered - * - * This function registers device with input core. The device must be - * allocated with input_allocate_device() and all it's capabilities - * set up before registering. - * If function fails the device must be freed with input_free_device(). - * Once device has been successfully registered it can be unregistered - * with input_unregister_device(); input_free_device() should not be - * called in this case. - */ int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); @@ -1297,7 +1077,7 @@ int input_register_device(struct input_dev *dev) const char *path; int error; - __set_bit(EV_SYN, dev->evbit); + set_bit(EV_SYN, dev->evbit); /* * If delay and period are pre-set by the driver, then autorepeating @@ -1318,6 +1098,8 @@ int input_register_device(struct input_dev *dev) if (!dev->setkeycode) dev->setkeycode = input_default_setkeycode; + list_add_tail(&dev->node, &input_dev_list); + snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); @@ -1333,79 +1115,49 @@ int input_register_device(struct input_dev *dev) dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); - error = mutex_lock_interruptible(&input_mutex); - if (error) { - device_del(&dev->dev); - return error; - } - - list_add_tail(&dev->node, &input_dev_list); - list_for_each_entry(handler, &input_handler_list, node) input_attach_handler(dev, handler); input_wakeup_procfs_readers(); - mutex_unlock(&input_mutex); - return 0; } EXPORT_SYMBOL(input_register_device); -/** - * input_unregister_device - unregister previously registered device - * @dev: device to be unregistered - * - * This function unregisters an input device. Once device is unregistered - * the caller should not try to access it as it may get freed at any moment. - */ void input_unregister_device(struct input_dev *dev) { struct input_handle *handle, *next; + int code; - input_disconnect_device(dev); + for (code = 0; code <= KEY_MAX; code++) + if (test_bit(code, dev->key)) + input_report_key(dev, code, 0); + input_sync(dev); - mutex_lock(&input_mutex); + del_timer_sync(&dev->timer); list_for_each_entry_safe(handle, next, &dev->h_list, d_node) handle->handler->disconnect(handle); WARN_ON(!list_empty(&dev->h_list)); - del_timer_sync(&dev->timer); list_del_init(&dev->node); - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); - device_unregister(&dev->dev); + + input_wakeup_procfs_readers(); } EXPORT_SYMBOL(input_unregister_device); -/** - * input_register_handler - register a new input handler - * @handler: handler to be registered - * - * This function registers a new input handler (interface) for input - * devices in the system and attaches it to all input devices that - * are compatible with the handler. - */ int input_register_handler(struct input_handler *handler) { struct input_dev *dev; - int retval; - - retval = mutex_lock_interruptible(&input_mutex); - if (retval) - return retval; INIT_LIST_HEAD(&handler->h_list); if (handler->fops != NULL) { - if (input_table[handler->minor >> 5]) { - retval = -EBUSY; - goto out; - } + if (input_table[handler->minor >> 5]) + return -EBUSY; + input_table[handler->minor >> 5] = handler; } @@ -1415,26 +1167,14 @@ int input_register_handler(struct input_handler *handler) input_attach_handler(dev, handler); input_wakeup_procfs_readers(); - - out: - mutex_unlock(&input_mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_register_handler); -/** - * input_unregister_handler - unregisters an input handler - * @handler: handler to be unregistered - * - * This function disconnects a handler from its input devices and - * removes it from lists of known handlers. - */ void input_unregister_handler(struct input_handler *handler) { struct input_handle *handle, *next; - mutex_lock(&input_mutex); - list_for_each_entry_safe(handle, next, &handler->h_list, h_node) handler->disconnect(handle); WARN_ON(!list_empty(&handler->h_list)); @@ -1445,45 +1185,14 @@ void input_unregister_handler(struct input_handler *handler) input_table[handler->minor >> 5] = NULL; input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); } EXPORT_SYMBOL(input_unregister_handler); -/** - * input_register_handle - register a new input handle - * @handle: handle to register - * - * This function puts a new input handle onto device's - * and handler's lists so that events can flow through - * it once it is opened using input_open_device(). - * - * This function is supposed to be called from handler's - * connect() method. - */ int input_register_handle(struct input_handle *handle) { struct input_handler *handler = handle->handler; - struct input_dev *dev = handle->dev; - int error; - - /* - * We take dev->mutex here to prevent race with - * input_release_device(). - */ - error = mutex_lock_interruptible(&dev->mutex); - if (error) - return error; - list_add_tail_rcu(&handle->d_node, &dev->h_list); - mutex_unlock(&dev->mutex); - synchronize_rcu(); - /* - * Since we are supposed to be called from ->connect() - * which is mutually exclusive with ->disconnect() - * we can't be racing with input_unregister_handle() - * and so separate lock is not needed here. - */ + list_add_tail(&handle->d_node, &handle->dev->h_list); list_add_tail(&handle->h_node, &handler->h_list); if (handler->start) @@ -1493,29 +1202,10 @@ int input_register_handle(struct input_handle *handle) } EXPORT_SYMBOL(input_register_handle); -/** - * input_unregister_handle - unregister an input handle - * @handle: handle to unregister - * - * This function removes input handle from device's - * and handler's lists. - * - * This function is supposed to be called from handler's - * disconnect() method. - */ void input_unregister_handle(struct input_handle *handle) { - struct input_dev *dev = handle->dev; - list_del_init(&handle->h_node); - - /* - * Take dev->mutex to prevent race with input_release_device(). - */ - mutex_lock(&dev->mutex); - list_del_rcu(&handle->d_node); - mutex_unlock(&dev->mutex); - synchronize_rcu(); + list_del_init(&handle->d_node); } EXPORT_SYMBOL(input_unregister_handle); diff --git a/trunk/drivers/input/joydev.c b/trunk/drivers/input/joydev.c index 2b201f9aa024..a9a0180bfd46 100644 --- a/trunk/drivers/input/joydev.c +++ b/trunk/drivers/input/joydev.c @@ -43,8 +43,6 @@ struct joydev { struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; - spinlock_t client_lock; /* protects client_list */ - struct mutex mutex; struct device dev; struct js_corr corr[ABS_MAX + 1]; @@ -63,61 +61,31 @@ struct joydev_client { int head; int tail; int startup; - spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct fasync_struct *fasync; struct joydev *joydev; struct list_head node; }; static struct joydev *joydev_table[JOYDEV_MINORS]; -static DEFINE_MUTEX(joydev_table_mutex); static int joydev_correct(int value, struct js_corr *corr) { switch (corr->type) { - - case JS_CORR_NONE: - break; - - case JS_CORR_BROKEN: - value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : - ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : - ((corr->coef[2] * (value - corr->coef[0])) >> 14); - break; - - default: - return 0; + case JS_CORR_NONE: + break; + case JS_CORR_BROKEN: + value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : + ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : + ((corr->coef[2] * (value - corr->coef[0])) >> 14); + break; + default: + return 0; } return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); } -static void joydev_pass_event(struct joydev_client *client, - struct js_event *event) -{ - struct joydev *joydev = client->joydev; - - /* - * IRQs already disabled, just acquire the lock - */ - spin_lock(&client->buffer_lock); - - client->buffer[client->head] = *event; - - if (client->startup == joydev->nabs + joydev->nkey) { - client->head++; - client->head &= JOYDEV_BUFFER_SIZE - 1; - if (client->tail == client->head) - client->startup = 0; - } - - spin_unlock(&client->buffer_lock); - - kill_fasync(&client->fasync, SIGIO, POLL_IN); -} - -static void joydev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct joydev *joydev = handle->private; struct joydev_client *client; @@ -125,34 +93,39 @@ static void joydev_event(struct input_handle *handle, switch (type) { - case EV_KEY: - if (code < BTN_MISC || value == 2) - return; - event.type = JS_EVENT_BUTTON; - event.number = joydev->keymap[code - BTN_MISC]; - event.value = value; - break; + case EV_KEY: + if (code < BTN_MISC || value == 2) + return; + event.type = JS_EVENT_BUTTON; + event.number = joydev->keymap[code - BTN_MISC]; + event.value = value; + break; - case EV_ABS: - event.type = JS_EVENT_AXIS; - event.number = joydev->absmap[code]; - event.value = joydev_correct(value, - &joydev->corr[event.number]); - if (event.value == joydev->abs[event.number]) - return; - joydev->abs[event.number] = event.value; - break; + case EV_ABS: + event.type = JS_EVENT_AXIS; + event.number = joydev->absmap[code]; + event.value = joydev_correct(value, joydev->corr + event.number); + if (event.value == joydev->abs[event.number]) + return; + joydev->abs[event.number] = event.value; + break; - default: - return; + default: + return; } event.time = jiffies_to_msecs(jiffies); - rcu_read_lock(); - list_for_each_entry_rcu(client, &joydev->client_list, node) - joydev_pass_event(client, &event); - rcu_read_unlock(); + list_for_each_entry(client, &joydev->client_list, node) { + + memcpy(client->buffer + client->head, &event, sizeof(struct js_event)); + + if (client->startup == joydev->nabs + joydev->nkey) + if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) + client->startup = 0; + + kill_fasync(&client->fasync, SIGIO, POLL_IN); + } wake_up_interruptible(&joydev->wait); } @@ -171,83 +144,23 @@ static void joydev_free(struct device *dev) { struct joydev *joydev = container_of(dev, struct joydev, dev); + joydev_table[joydev->minor] = NULL; kfree(joydev); } -static void joydev_attach_client(struct joydev *joydev, - struct joydev_client *client) -{ - spin_lock(&joydev->client_lock); - list_add_tail_rcu(&client->node, &joydev->client_list); - spin_unlock(&joydev->client_lock); - synchronize_rcu(); -} - -static void joydev_detach_client(struct joydev *joydev, - struct joydev_client *client) -{ - spin_lock(&joydev->client_lock); - list_del_rcu(&client->node); - spin_unlock(&joydev->client_lock); - synchronize_rcu(); -} - -static int joydev_open_device(struct joydev *joydev) -{ - int retval; - - retval = mutex_lock_interruptible(&joydev->mutex); - if (retval) - return retval; - - if (!joydev->exist) - retval = -ENODEV; - else if (!joydev->open++) { - retval = input_open_device(&joydev->handle); - if (retval) - joydev->open--; - } - - mutex_unlock(&joydev->mutex); - return retval; -} - -static void joydev_close_device(struct joydev *joydev) -{ - mutex_lock(&joydev->mutex); - - if (joydev->exist && !--joydev->open) - input_close_device(&joydev->handle); - - mutex_unlock(&joydev->mutex); -} - -/* - * Wake up users waiting for IO so they can disconnect from - * dead device. - */ -static void joydev_hangup(struct joydev *joydev) -{ - struct joydev_client *client; - - spin_lock(&joydev->client_lock); - list_for_each_entry(client, &joydev->client_list, node) - kill_fasync(&client->fasync, SIGIO, POLL_HUP); - spin_unlock(&joydev->client_lock); - - wake_up_interruptible(&joydev->wait); -} - static int joydev_release(struct inode *inode, struct file *file) { struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; joydev_fasync(-1, file, 0); - joydev_detach_client(joydev, client); + + list_del(&client->node); kfree(client); - joydev_close_device(joydev); + if (!--joydev->open && joydev->exist) + input_close_device(&joydev->handle); + put_device(&joydev->dev); return 0; @@ -263,146 +176,49 @@ static int joydev_open(struct inode *inode, struct file *file) if (i >= JOYDEV_MINORS) return -ENODEV; - error = mutex_lock_interruptible(&joydev_table_mutex); - if (error) - return error; joydev = joydev_table[i]; - if (joydev) - get_device(&joydev->dev); - mutex_unlock(&joydev_table_mutex); - - if (!joydev) + if (!joydev || !joydev->exist) return -ENODEV; + get_device(&joydev->dev); + client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); if (!client) { error = -ENOMEM; goto err_put_joydev; } - spin_lock_init(&client->buffer_lock); client->joydev = joydev; - joydev_attach_client(joydev, client); + list_add_tail(&client->node, &joydev->client_list); - error = joydev_open_device(joydev); - if (error) - goto err_free_client; + if (!joydev->open++ && joydev->exist) { + error = input_open_device(&joydev->handle); + if (error) + goto err_free_client; + } file->private_data = client; return 0; err_free_client: - joydev_detach_client(joydev, client); + list_del(&client->node); kfree(client); err_put_joydev: put_device(&joydev->dev); return error; } -static int joydev_generate_startup_event(struct joydev_client *client, - struct input_dev *input, - struct js_event *event) -{ - struct joydev *joydev = client->joydev; - int have_event; - - spin_lock_irq(&client->buffer_lock); - - have_event = client->startup < joydev->nabs + joydev->nkey; - - if (have_event) { - - event->time = jiffies_to_msecs(jiffies); - if (client->startup < joydev->nkey) { - event->type = JS_EVENT_BUTTON | JS_EVENT_INIT; - event->number = client->startup; - event->value = !!test_bit(joydev->keypam[event->number], - input->key); - } else { - event->type = JS_EVENT_AXIS | JS_EVENT_INIT; - event->number = client->startup - joydev->nkey; - event->value = joydev->abs[event->number]; - } - client->startup++; - } - - spin_unlock_irq(&client->buffer_lock); - - return have_event; -} - -static int joydev_fetch_next_event(struct joydev_client *client, - struct js_event *event) -{ - int have_event; - - spin_lock_irq(&client->buffer_lock); - - have_event = client->head != client->tail; - if (have_event) { - *event = client->buffer[client->tail++]; - client->tail &= JOYDEV_BUFFER_SIZE - 1; - } - - spin_unlock_irq(&client->buffer_lock); - - return have_event; -} - -/* - * Old joystick interface - */ -static ssize_t joydev_0x_read(struct joydev_client *client, - struct input_dev *input, - char __user *buf) -{ - struct joydev *joydev = client->joydev; - struct JS_DATA_TYPE data; - int i; - - spin_lock_irq(&input->event_lock); - - /* - * Get device state - */ - for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) - data.buttons |= - test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; - data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; - data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; - - /* - * Reset reader's event queue - */ - spin_lock(&client->buffer_lock); - client->startup = 0; - client->tail = client->head; - spin_unlock(&client->buffer_lock); - - spin_unlock_irq(&input->event_lock); - - if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) - return -EFAULT; - - return sizeof(struct JS_DATA_TYPE); -} - -static inline int joydev_data_pending(struct joydev_client *client) +static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct joydev *joydev = client->joydev; - - return client->startup < joydev->nabs + joydev->nkey || - client->head != client->tail; + return -EINVAL; } -static ssize_t joydev_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; struct input_dev *input = joydev->handle.dev; - struct js_event event; - int retval; + int retval = 0; if (!joydev->exist) return -ENODEV; @@ -410,35 +226,68 @@ static ssize_t joydev_read(struct file *file, char __user *buf, if (count < sizeof(struct js_event)) return -EINVAL; - if (count == sizeof(struct JS_DATA_TYPE)) - return joydev_0x_read(client, input, buf); + if (count == sizeof(struct JS_DATA_TYPE)) { + + struct JS_DATA_TYPE data; + int i; + + for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) + data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; + data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; + data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; + + if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) + return -EFAULT; + + client->startup = 0; + client->tail = client->head; - if (!joydev_data_pending(client) && (file->f_flags & O_NONBLOCK)) + return sizeof(struct JS_DATA_TYPE); + } + + if (client->startup == joydev->nabs + joydev->nkey && + client->head == client->tail && (file->f_flags & O_NONBLOCK)) return -EAGAIN; retval = wait_event_interruptible(joydev->wait, - !joydev->exist || joydev_data_pending(client)); + !joydev->exist || + client->startup < joydev->nabs + joydev->nkey || + client->head != client->tail); if (retval) return retval; if (!joydev->exist) return -ENODEV; - while (retval + sizeof(struct js_event) <= count && - joydev_generate_startup_event(client, input, &event)) { + while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) { + + struct js_event event; + + event.time = jiffies_to_msecs(jiffies); + + if (client->startup < joydev->nkey) { + event.type = JS_EVENT_BUTTON | JS_EVENT_INIT; + event.number = client->startup; + event.value = !!test_bit(joydev->keypam[event.number], input->key); + } else { + event.type = JS_EVENT_AXIS | JS_EVENT_INIT; + event.number = client->startup - joydev->nkey; + event.value = joydev->abs[event.number]; + } if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) return -EFAULT; + client->startup++; retval += sizeof(struct js_event); } - while (retval + sizeof(struct js_event) <= count && - joydev_fetch_next_event(client, &event)) { + while (client->head != client->tail && retval + sizeof(struct js_event) <= count) { - if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) + if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event))) return -EFAULT; + client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1); retval += sizeof(struct js_event); } @@ -452,144 +301,126 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) struct joydev *joydev = client->joydev; poll_wait(file, &joydev->wait, wait); - return (joydev_data_pending(client) ? (POLLIN | POLLRDNORM) : 0) | - (joydev->exist ? 0 : (POLLHUP | POLLERR)); + return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ? + (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR)); } -static int joydev_ioctl_common(struct joydev *joydev, - unsigned int cmd, void __user *argp) +static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) { struct input_dev *dev = joydev->handle.dev; int i, j; switch (cmd) { - case JS_SET_CAL: - return copy_from_user(&joydev->glue.JS_CORR, argp, + case JS_SET_CAL: + return copy_from_user(&joydev->glue.JS_CORR, argp, sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; - case JS_GET_CAL: - return copy_to_user(argp, &joydev->glue.JS_CORR, + case JS_GET_CAL: + return copy_to_user(argp, &joydev->glue.JS_CORR, sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; - case JS_SET_TIMEOUT: - return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); - - case JS_GET_TIMEOUT: - return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); - - case JSIOCGVERSION: - return put_user(JS_VERSION, (__u32 __user *) argp); - - case JSIOCGAXES: - return put_user(joydev->nabs, (__u8 __user *) argp); - - case JSIOCGBUTTONS: - return put_user(joydev->nkey, (__u8 __user *) argp); + case JS_SET_TIMEOUT: + return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); - case JSIOCSCORR: - if (copy_from_user(joydev->corr, argp, - sizeof(joydev->corr[0]) * joydev->nabs)) - return -EFAULT; + case JS_GET_TIMEOUT: + return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); - for (i = 0; i < joydev->nabs; i++) { - j = joydev->abspam[i]; - joydev->abs[i] = joydev_correct(dev->abs[j], - &joydev->corr[i]); - } - return 0; - - case JSIOCGCORR: - return copy_to_user(argp, joydev->corr, - sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; - - case JSIOCSAXMAP: - if (copy_from_user(joydev->abspam, argp, - sizeof(__u8) * (ABS_MAX + 1))) - return -EFAULT; - - for (i = 0; i < joydev->nabs; i++) { - if (joydev->abspam[i] > ABS_MAX) - return -EINVAL; - joydev->absmap[joydev->abspam[i]] = i; - } - return 0; - - case JSIOCGAXMAP: - return copy_to_user(argp, joydev->abspam, - sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; + case JSIOCGVERSION: + return put_user(JS_VERSION, (__u32 __user *) argp); - case JSIOCSBTNMAP: - if (copy_from_user(joydev->keypam, argp, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) - return -EFAULT; + case JSIOCGAXES: + return put_user(joydev->nabs, (__u8 __user *) argp); - for (i = 0; i < joydev->nkey; i++) { - if (joydev->keypam[i] > KEY_MAX || - joydev->keypam[i] < BTN_MISC) - return -EINVAL; - joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; - } + case JSIOCGBUTTONS: + return put_user(joydev->nkey, (__u8 __user *) argp); - return 0; + case JSIOCSCORR: + if (copy_from_user(joydev->corr, argp, + sizeof(joydev->corr[0]) * joydev->nabs)) + return -EFAULT; + for (i = 0; i < joydev->nabs; i++) { + j = joydev->abspam[i]; + joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); + } + return 0; - case JSIOCGBTNMAP: - return copy_to_user(argp, joydev->keypam, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; + case JSIOCGCORR: + return copy_to_user(argp, joydev->corr, + sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; - default: - if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { - int len; - if (!dev->name) - return 0; - len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - if (copy_to_user(argp, dev->name, len)) + case JSIOCSAXMAP: + if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) return -EFAULT; - return len; - } + for (i = 0; i < joydev->nabs; i++) { + if (joydev->abspam[i] > ABS_MAX) + return -EINVAL; + joydev->absmap[joydev->abspam[i]] = i; + } + return 0; + + case JSIOCGAXMAP: + return copy_to_user(argp, joydev->abspam, + sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; + + case JSIOCSBTNMAP: + if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) + return -EFAULT; + for (i = 0; i < joydev->nkey; i++) { + if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) + return -EINVAL; + joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; + } + return 0; + + case JSIOCGBTNMAP: + return copy_to_user(argp, joydev->keypam, + sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; + + default: + if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { + int len; + if (!dev->name) + return 0; + len = strlen(dev->name) + 1; + if (len > _IOC_SIZE(cmd)) + len = _IOC_SIZE(cmd); + if (copy_to_user(argp, dev->name, len)) + return -EFAULT; + return len; + } } return -EINVAL; } #ifdef CONFIG_COMPAT -static long joydev_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; void __user *argp = (void __user *)arg; s32 tmp32; struct JS_DATA_SAVE_TYPE_32 ds32; - int retval; - - retval = mutex_lock_interruptible(&joydev->mutex); - if (retval) - return retval; - - if (!joydev->exist) { - retval = -ENODEV; - goto out; - } + int err; - switch (cmd) { + if (!joydev->exist) + return -ENODEV; + switch(cmd) { case JS_SET_TIMELIMIT: - retval = get_user(tmp32, (s32 __user *) arg); - if (retval == 0) + err = get_user(tmp32, (s32 __user *) arg); + if (err == 0) joydev->glue.JS_TIMELIMIT = tmp32; break; - case JS_GET_TIMELIMIT: tmp32 = joydev->glue.JS_TIMELIMIT; - retval = put_user(tmp32, (s32 __user *) arg); + err = put_user(tmp32, (s32 __user *) arg); break; case JS_SET_ALL: - retval = copy_from_user(&ds32, argp, - sizeof(ds32)) ? -EFAULT : 0; - if (retval == 0) { + err = copy_from_user(&ds32, argp, + sizeof(ds32)) ? -EFAULT : 0; + if (err == 0) { joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; joydev->glue.BUSY = ds32.BUSY; joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; @@ -607,119 +438,55 @@ static long joydev_compat_ioctl(struct file *file, ds32.JS_SAVE = joydev->glue.JS_SAVE; ds32.JS_CORR = joydev->glue.JS_CORR; - retval = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; + err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; break; default: - retval = joydev_ioctl_common(joydev, cmd, argp); - break; + err = joydev_ioctl_common(joydev, cmd, argp); } - - out: - mutex_unlock(&joydev->mutex); - return retval; + return err; } #endif /* CONFIG_COMPAT */ -static long joydev_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; void __user *argp = (void __user *)arg; - int retval; - - retval = mutex_lock_interruptible(&joydev->mutex); - if (retval) - return retval; - - if (!joydev->exist) { - retval = -ENODEV; - goto out; - } - - switch (cmd) { - - case JS_SET_TIMELIMIT: - retval = get_user(joydev->glue.JS_TIMELIMIT, - (long __user *) arg); - break; - - case JS_GET_TIMELIMIT: - retval = put_user(joydev->glue.JS_TIMELIMIT, - (long __user *) arg); - break; - - case JS_SET_ALL: - retval = copy_from_user(&joydev->glue, argp, - sizeof(joydev->glue)) ? -EFAULT: 0; - break; - case JS_GET_ALL: - retval = copy_to_user(argp, &joydev->glue, - sizeof(joydev->glue)) ? -EFAULT : 0; - break; + if (!joydev->exist) + return -ENODEV; - default: - retval = joydev_ioctl_common(joydev, cmd, argp); - break; + switch(cmd) { + case JS_SET_TIMELIMIT: + return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); + case JS_GET_TIMELIMIT: + return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); + case JS_SET_ALL: + return copy_from_user(&joydev->glue, argp, + sizeof(joydev->glue)) ? -EFAULT : 0; + case JS_GET_ALL: + return copy_to_user(argp, &joydev->glue, + sizeof(joydev->glue)) ? -EFAULT : 0; + default: + return joydev_ioctl_common(joydev, cmd, argp); } - out: - mutex_unlock(&joydev->mutex); - return retval; } static const struct file_operations joydev_fops = { - .owner = THIS_MODULE, - .read = joydev_read, - .poll = joydev_poll, - .open = joydev_open, - .release = joydev_release, - .unlocked_ioctl = joydev_ioctl, + .owner = THIS_MODULE, + .read = joydev_read, + .write = joydev_write, + .poll = joydev_poll, + .open = joydev_open, + .release = joydev_release, + .ioctl = joydev_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = joydev_compat_ioctl, + .compat_ioctl = joydev_compat_ioctl, #endif - .fasync = joydev_fasync, + .fasync = joydev_fasync, }; -static int joydev_install_chrdev(struct joydev *joydev) -{ - joydev_table[joydev->minor] = joydev; - return 0; -} - -static void joydev_remove_chrdev(struct joydev *joydev) -{ - mutex_lock(&joydev_table_mutex); - joydev_table[joydev->minor] = NULL; - mutex_unlock(&joydev_table_mutex); -} - -/* - * Mark device non-existant. This disables writes, ioctls and - * prevents new users from opening the device. Already posted - * blocking reads will stay, however new ones will fail. - */ -static void joydev_mark_dead(struct joydev *joydev) -{ - mutex_lock(&joydev->mutex); - joydev->exist = 0; - mutex_unlock(&joydev->mutex); -} - -static void joydev_cleanup(struct joydev *joydev) -{ - struct input_handle *handle = &joydev->handle; - - joydev_mark_dead(joydev); - joydev_hangup(joydev); - joydev_remove_chrdev(joydev); - - /* joydev is marked dead so noone else accesses joydev->open */ - if (joydev->open) - input_close_device(handle); -} - static int joydev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { @@ -727,10 +494,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, int i, j, t, minor; int error; - for (minor = 0; minor < JOYDEV_MINORS; minor++) - if (!joydev_table[minor]) - break; - + for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); if (minor == JOYDEV_MINORS) { printk(KERN_ERR "joydev: no more free joydev devices\n"); return -ENFILE; @@ -741,19 +505,15 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, return -ENOMEM; INIT_LIST_HEAD(&joydev->client_list); - spin_lock_init(&joydev->client_lock); - mutex_init(&joydev->mutex); init_waitqueue_head(&joydev->wait); - snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); - joydev->exist = 1; joydev->minor = minor; - joydev->exist = 1; joydev->handle.dev = dev; joydev->handle.name = joydev->name; joydev->handle.handler = handler; joydev->handle.private = joydev; + snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); for (i = 0; i < ABS_MAX + 1; i++) if (test_bit(i, dev->absbit)) { @@ -785,65 +545,67 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, } joydev->corr[i].type = JS_CORR_BROKEN; joydev->corr[i].prec = dev->absfuzz[j]; - joydev->corr[i].coef[0] = - (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; - joydev->corr[i].coef[1] = - (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; - - t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; - if (t) { - joydev->corr[i].coef[2] = (1 << 29) / t; - joydev->corr[i].coef[3] = (1 << 29) / t; - - joydev->abs[i] = joydev_correct(dev->abs[j], - joydev->corr + i); - } + joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; + joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; + if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]))) + continue; + joydev->corr[i].coef[2] = (1 << 29) / t; + joydev->corr[i].coef[3] = (1 << 29) / t; + + joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); } - strlcpy(joydev->dev.bus_id, joydev->name, sizeof(joydev->dev.bus_id)); - joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); + snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id), + "js%d", minor); joydev->dev.class = &input_class; joydev->dev.parent = &dev->dev; + joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); joydev->dev.release = joydev_free; device_initialize(&joydev->dev); - error = input_register_handle(&joydev->handle); - if (error) - goto err_free_joydev; + joydev_table[minor] = joydev; - error = joydev_install_chrdev(joydev); + error = device_add(&joydev->dev); if (error) - goto err_unregister_handle; + goto err_free_joydev; - error = device_add(&joydev->dev); + error = input_register_handle(&joydev->handle); if (error) - goto err_cleanup_joydev; + goto err_delete_joydev; return 0; - err_cleanup_joydev: - joydev_cleanup(joydev); - err_unregister_handle: - input_unregister_handle(&joydev->handle); + err_delete_joydev: + device_del(&joydev->dev); err_free_joydev: put_device(&joydev->dev); return error; } + static void joydev_disconnect(struct input_handle *handle) { struct joydev *joydev = handle->private; + struct joydev_client *client; - device_del(&joydev->dev); - joydev_cleanup(joydev); input_unregister_handle(handle); + device_del(&joydev->dev); + + joydev->exist = 0; + + if (joydev->open) { + input_close_device(handle); + list_for_each_entry(client, &joydev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + wake_up_interruptible(&joydev->wait); + } + put_device(&joydev->dev); } static const struct input_device_id joydev_blacklist[] = { { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, .evbit = { BIT(EV_KEY) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, }, /* Avoid itouchpads, touchscreens and tablets */ @@ -852,20 +614,17 @@ static const struct input_device_id joydev_blacklist[] = { static const struct input_device_id joydev_ids[] = { { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_X) }, }, { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_WHEEL) }, }, { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_THROTTLE) }, }, @@ -875,14 +634,14 @@ static const struct input_device_id joydev_ids[] = { MODULE_DEVICE_TABLE(input, joydev_ids); static struct input_handler joydev_handler = { - .event = joydev_event, - .connect = joydev_connect, - .disconnect = joydev_disconnect, - .fops = &joydev_fops, - .minor = JOYDEV_MINOR_BASE, - .name = "joydev", - .id_table = joydev_ids, - .blacklist = joydev_blacklist, + .event = joydev_event, + .connect = joydev_connect, + .disconnect = joydev_disconnect, + .fops = &joydev_fops, + .minor = JOYDEV_MINOR_BASE, + .name = "joydev", + .id_table = joydev_ids, + .blacklist = joydev_blacklist, }; static int __init joydev_init(void) diff --git a/trunk/drivers/input/joystick/xpad.c b/trunk/drivers/input/joystick/xpad.c index 623629a69b03..28080395899c 100644 --- a/trunk/drivers/input/joystick/xpad.c +++ b/trunk/drivers/input/joystick/xpad.c @@ -223,16 +223,12 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d struct input_dev *dev = xpad->dev; /* left stick */ - input_report_abs(dev, ABS_X, - (__s16) le16_to_cpup((__le16 *)(data + 12))); - input_report_abs(dev, ABS_Y, - (__s16) le16_to_cpup((__le16 *)(data + 14))); + input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); + input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); /* right stick */ - input_report_abs(dev, ABS_RX, - (__s16) le16_to_cpup((__le16 *)(data + 16))); - input_report_abs(dev, ABS_RY, - (__s16) le16_to_cpup((__le16 *)(data + 18))); + input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); + input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); /* triggers left/right */ input_report_abs(dev, ABS_Z, data[10]); @@ -240,10 +236,8 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d /* digital pad */ if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { - input_report_abs(dev, ABS_HAT0X, - !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, - !!(data[2] & 0x02) - !!(data[2] & 0x01)); + input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { input_report_key(dev, BTN_LEFT, data[2] & 0x04); input_report_key(dev, BTN_RIGHT, data[2] & 0x08); @@ -280,17 +274,14 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d * http://www.free60.org/wiki/Gamepad */ -static void xpad360_process_packet(struct usb_xpad *xpad, - u16 cmd, unsigned char *data) +static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { struct input_dev *dev = xpad->dev; /* digital pad */ if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { - input_report_abs(dev, ABS_HAT0X, - !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, - !!(data[2] & 0x02) - !!(data[2] & 0x01)); + input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { /* dpad as buttons (right, left, down, up) */ input_report_key(dev, BTN_LEFT, data[2] & 0x04); @@ -317,16 +308,12 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_report_key(dev, BTN_MODE, data[3] & 0x04); /* left stick */ - input_report_abs(dev, ABS_X, - (__s16) le16_to_cpup((__le16 *)(data + 6))); - input_report_abs(dev, ABS_Y, - (__s16) le16_to_cpup((__le16 *)(data + 8))); + input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6])); + input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8])); /* right stick */ - input_report_abs(dev, ABS_RX, - (__s16) le16_to_cpup((__le16 *)(data + 10))); - input_report_abs(dev, ABS_RY, - (__s16) le16_to_cpup((__le16 *)(data + 12))); + input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10])); + input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12])); /* triggers left/right */ input_report_abs(dev, ABS_Z, data[4]); @@ -348,12 +335,10 @@ static void xpad_irq_in(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } @@ -382,12 +367,10 @@ static void xpad_irq_out(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } @@ -395,7 +378,7 @@ static void xpad_irq_out(struct urb *urb) retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); + __FUNCTION__, retval); } static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) @@ -612,7 +595,7 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = interface_to_usbdev (intf); struct usb_xpad *xpad; struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; diff --git a/trunk/drivers/input/keyboard/Kconfig b/trunk/drivers/input/keyboard/Kconfig index 2316a018fae6..c97d5eb0075d 100644 --- a/trunk/drivers/input/keyboard/Kconfig +++ b/trunk/drivers/input/keyboard/Kconfig @@ -208,27 +208,6 @@ config KEYBOARD_HIL This driver implements support for HIL-keyboards attached to your machine, so normally you should say Y here. -config KEYBOARD_HP6XX - tristate "HP Jornada 6XX Keyboard support" - depends on SH_HP6XX - select INPUT_POLLDEV - help - This adds support for the onboard keyboard found on - HP Jornada 620/660/680/690. - - To compile this driver as a module, choose M here: the - module will be called jornada680_kbd. - -config KEYBOARD_HP7XX - tristate "HP Jornada 7XX Keyboard Driver" - depends on SA1100_JORNADA720_SSP && SA1100_SSP - help - Say Y here to add support for the HP Jornada 7xx (710/720/728) - onboard keyboard. - - To compile this driver as a module, choose M here: the - module will be called jornada720_kbd. - config KEYBOARD_OMAP tristate "TI OMAP keypad support" depends on (ARCH_OMAP1 || ARCH_OMAP2) @@ -274,23 +253,4 @@ config KEYBOARD_GPIO To compile this driver as a module, choose M here: the module will be called gpio-keys. -config KEYBOARD_MAPLE - tristate "Maple bus keyboard" - depends on SH_DREAMCAST && MAPLE - help - Say Y here if you have a Dreamcast console running Linux and have - a keyboard attached to its Maple bus. - - To compile this driver as a module, choose M here: the - module will be called maple_keyb. - -config KEYBOARD_BFIN - tristate "Blackfin BF54x keypad support" - depends on BF54x - help - Say Y here if you want to use the BF54x keypad. - - To compile this driver as a module, choose M here: the - module will be called bf54x-keys. - endif diff --git a/trunk/drivers/input/keyboard/Makefile b/trunk/drivers/input/keyboard/Makefile index e97455fdcc83..28d211b87b14 100644 --- a/trunk/drivers/input/keyboard/Makefile +++ b/trunk/drivers/input/keyboard/Makefile @@ -21,7 +21,4 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o -obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o -obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o -obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o + diff --git a/trunk/drivers/input/keyboard/atakbd.c b/trunk/drivers/input/keyboard/atakbd.c index a1800151b6ce..f948d3a14a93 100644 --- a/trunk/drivers/input/keyboard/atakbd.c +++ b/trunk/drivers/input/keyboard/atakbd.c @@ -217,7 +217,7 @@ static void atakbd_interrupt(unsigned char scancode, char down) static int __init atakbd_init(void) { - int i, error; + int i; if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) return -EIO; @@ -247,10 +247,9 @@ static int __init atakbd_init(void) } /* error check */ - error = input_register_device(atakbd_dev); - if (error) { + if (input_register_device(atakbd_dev)) { input_free_device(atakbd_dev); - return error; + return -ENOMEM; } atari_input_keyboard_interrupt_hook = atakbd_interrupt; diff --git a/trunk/drivers/input/keyboard/bf54x-keys.c b/trunk/drivers/input/keyboard/bf54x-keys.c deleted file mode 100644 index a67b29b089ef..000000000000 --- a/trunk/drivers/input/keyboard/bf54x-keys.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * File: drivers/input/keyboard/bf54x-keys.c - * Based on: - * Author: Michael Hennerich - * - * Created: - * Description: keypad driver for Analog Devices Blackfin BF54x Processors - * - * - * Modified: - * Copyright 2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "bf54x-keys" -#define TIME_SCALE 100 /* 100 ns */ -#define MAX_MULT (0xFF * TIME_SCALE) -#define MAX_RC 8 /* Max Row/Col */ - -static const u16 per_rows[] = { - P_KEY_ROW7, - P_KEY_ROW6, - P_KEY_ROW5, - P_KEY_ROW4, - P_KEY_ROW3, - P_KEY_ROW2, - P_KEY_ROW1, - P_KEY_ROW0, - 0 -}; - -static const u16 per_cols[] = { - P_KEY_COL7, - P_KEY_COL6, - P_KEY_COL5, - P_KEY_COL4, - P_KEY_COL3, - P_KEY_COL2, - P_KEY_COL1, - P_KEY_COL0, - 0 -}; - -struct bf54x_kpad { - struct input_dev *input; - int irq; - unsigned short lastkey; - unsigned short *keycode; - struct timer_list timer; - unsigned int keyup_test_jiffies; -}; - -static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, - struct input_dev *input, u16 keyident) -{ - u16 i; - - for (i = 0; i < input->keycodemax; i++) - if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) - return bf54x_kpad->keycode[i]; - return -1; -} - -static inline void bfin_keycodecpy(unsigned short *keycode, - const unsigned int *pdata_kc, - unsigned short keymapsize) -{ - unsigned int i; - - for (i = 0; i < keymapsize; i++) { - keycode[i] = pdata_kc[i] & 0xffff; - keycode[i + keymapsize] = pdata_kc[i] >> 16; - } -} - -static inline u16 bfin_kpad_get_prescale(u32 timescale) -{ - u32 sclk = get_sclk(); - - return ((((sclk / 1000) * timescale) / 1024) - 1); -} - -static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) -{ - return (bfin_read_KPAD_STAT() & KPAD_PRESSED); -} - -static inline void bfin_kpad_clear_irq(void) -{ - bfin_write_KPAD_STAT(0xFFFF); - bfin_write_KPAD_ROWCOL(0xFFFF); -} - -static void bfin_kpad_timer(unsigned long data) -{ - struct platform_device *pdev = (struct platform_device *) data; - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - - if (bfin_kpad_get_keypressed(bf54x_kpad)) { - /* Try again later */ - mod_timer(&bf54x_kpad->timer, - jiffies + bf54x_kpad->keyup_test_jiffies); - return; - } - - input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); - input_sync(bf54x_kpad->input); - - /* Clear IRQ Status */ - - bfin_kpad_clear_irq(); - enable_irq(bf54x_kpad->irq); -} - -static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) -{ - struct platform_device *pdev = dev_id; - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - struct input_dev *input = bf54x_kpad->input; - int key; - u16 rowcol = bfin_read_KPAD_ROWCOL(); - - key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); - - input_report_key(input, key, 1); - input_sync(input); - - if (bfin_kpad_get_keypressed(bf54x_kpad)) { - disable_irq(bf54x_kpad->irq); - bf54x_kpad->lastkey = key; - mod_timer(&bf54x_kpad->timer, - jiffies + bf54x_kpad->keyup_test_jiffies); - } else { - input_report_key(input, key, 0); - input_sync(input); - - bfin_kpad_clear_irq(); - } - - return IRQ_HANDLED; -} - -static int __devinit bfin_kpad_probe(struct platform_device *pdev) -{ - struct bf54x_kpad *bf54x_kpad; - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; - struct input_dev *input; - int i, error; - - if (!pdata->rows || !pdata->cols || !pdata->keymap) { - printk(KERN_ERR DRV_NAME - ": No rows, cols or keymap from pdata\n"); - return -EINVAL; - } - - if (!pdata->keymapsize || - pdata->keymapsize > (pdata->rows * pdata->cols)) { - printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); - return -EINVAL; - } - - bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); - if (!bf54x_kpad) - return -ENOMEM; - - platform_set_drvdata(pdev, bf54x_kpad); - - /* Allocate memory for keymap followed by private LUT */ - bf54x_kpad->keycode = kmalloc(pdata->keymapsize * - sizeof(unsigned short) * 2, GFP_KERNEL); - if (!bf54x_kpad->keycode) { - error = -ENOMEM; - goto out; - } - - if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || - !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { - printk(KERN_ERR DRV_NAME - ": Invalid Debounce/Columdrive Time from pdata\n"); - bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ - } else { - bfin_write_KPAD_MSEL( - ((pdata->debounce_time / TIME_SCALE) - & DBON_SCALE) | - (((pdata->coldrive_time / TIME_SCALE) << 8) - & COLDRV_SCALE)); - - } - - if (!pdata->keyup_test_interval) - bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); - else - bf54x_kpad->keyup_test_jiffies = - msecs_to_jiffies(pdata->keyup_test_interval); - - if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], - DRV_NAME)) { - printk(KERN_ERR DRV_NAME - ": Requesting Peripherals failed\n"); - error = -EFAULT; - goto out0; - } - - if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], - DRV_NAME)) { - printk(KERN_ERR DRV_NAME - ": Requesting Peripherals failed\n"); - error = -EFAULT; - goto out1; - } - - bf54x_kpad->irq = platform_get_irq(pdev, 0); - if (bf54x_kpad->irq < 0) { - error = -ENODEV; - goto out2; - } - - error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, - IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); - if (error) { - printk(KERN_ERR DRV_NAME - ": unable to claim irq %d; error %d\n", - bf54x_kpad->irq, error); - error = -EBUSY; - goto out2; - } - - input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto out3; - } - - bf54x_kpad->input = input; - - input->name = pdev->name; - input->phys = "bf54x-keys/input0"; - input->dev.parent = &pdev->dev; - - input_set_drvdata(input, bf54x_kpad); - - input->id.bustype = BUS_HOST; - input->id.vendor = 0x0001; - input->id.product = 0x0001; - input->id.version = 0x0100; - - input->keycodesize = sizeof(unsigned short); - input->keycodemax = pdata->keymapsize; - input->keycode = bf54x_kpad->keycode; - - bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); - - /* setup input device */ - __set_bit(EV_KEY, input->evbit); - - if (pdata->repeat) - __set_bit(EV_REP, input->evbit); - - for (i = 0; i < input->keycodemax; i++) - __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit); - __clear_bit(KEY_RESERVED, input->keybit); - - error = input_register_device(input); - if (error) { - printk(KERN_ERR DRV_NAME - ": Unable to register input device (%d)\n", error); - goto out4; - } - - /* Init Keypad Key Up/Release test timer */ - - setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); - - bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); - - bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | - (((pdata->rows - 1) << 10) & KPAD_ROWEN) | - (2 & KPAD_IRQMODE)); - - bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); - - printk(KERN_ERR DRV_NAME - ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); - - return 0; - -out4: - input_free_device(input); -out3: - free_irq(bf54x_kpad->irq, pdev); -out2: - peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); -out1: - peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); -out0: - kfree(bf54x_kpad->keycode); -out: - kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); - - return error; -} - -static int __devexit bfin_kpad_remove(struct platform_device *pdev) -{ - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - - del_timer_sync(&bf54x_kpad->timer); - free_irq(bf54x_kpad->irq, pdev); - - input_unregister_device(bf54x_kpad->input); - - peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); - peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); - - kfree(bf54x_kpad->keycode); - kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -struct platform_driver bfin_kpad_device_driver = { - .probe = bfin_kpad_probe, - .remove = __devexit_p(bfin_kpad_remove), - .driver = { - .name = DRV_NAME, - } -}; - -static int __init bfin_kpad_init(void) -{ - return platform_driver_register(&bfin_kpad_device_driver); -} - -static void __exit bfin_kpad_exit(void) -{ - platform_driver_unregister(&bfin_kpad_device_driver); -} - -module_init(bfin_kpad_init); -module_exit(bfin_kpad_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); diff --git a/trunk/drivers/input/keyboard/gpio_keys.c b/trunk/drivers/input/keyboard/gpio_keys.c index e2a3293bc67e..f0b22b8b2769 100644 --- a/trunk/drivers/input/keyboard/gpio_keys.c +++ b/trunk/drivers/input/keyboard/gpio_keys.c @@ -54,7 +54,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input; int i, error; - int wakeup = 0; input = input_allocate_device(); if (!input) @@ -78,51 +77,31 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) int irq = gpio_to_irq(button->gpio); unsigned int type = button->type ?: EV_KEY; - if (irq < 0) { - error = irq; - printk(KERN_ERR - "gpio-keys: " - "Unable to get irq number for GPIO %d," - "error %d\n", - button->gpio, error); - goto fail; - } - - error = request_irq(irq, gpio_keys_isr, - IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, - button->desc ? button->desc : "gpio_keys", - pdev); + set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); + error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM, + button->desc ? button->desc : "gpio_keys", + pdev); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to claim irq %d; error %d\n", + printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, error); goto fail; } - if (button->wakeup) - wakeup = 1; - input_set_capability(input, type, button->code); } error = input_register_device(input); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to register input device, " - "error: %d\n", error); + printk(KERN_ERR "Unable to register gpio-keys input device\n"); goto fail; } - device_init_wakeup(&pdev->dev, wakeup); - return 0; fail: - while (--i >= 0) + for (i = i - 1; i >= 0; i--) free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); - platform_set_drvdata(pdev, NULL); input_free_device(input); return error; @@ -134,8 +113,6 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) struct input_dev *input = platform_get_drvdata(pdev); int i; - device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); free_irq(irq, pdev); @@ -146,53 +123,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) return 0; } - -#ifdef CONFIG_PM -static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; - int i; - - if (device_may_wakeup(&pdev->dev)) { - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup) { - int irq = gpio_to_irq(button->gpio); - enable_irq_wake(irq); - } - } - } - - return 0; -} - -static int gpio_keys_resume(struct platform_device *pdev) -{ - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; - int i; - - if (device_may_wakeup(&pdev->dev)) { - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup) { - int irq = gpio_to_irq(button->gpio); - disable_irq_wake(irq); - } - } - } - - return 0; -} -#else -#define gpio_keys_suspend NULL -#define gpio_keys_resume NULL -#endif - struct platform_driver gpio_keys_device_driver = { .probe = gpio_keys_probe, .remove = __devexit_p(gpio_keys_remove), - .suspend = gpio_keys_suspend, - .resume = gpio_keys_resume, .driver = { .name = "gpio-keys", } diff --git a/trunk/drivers/input/keyboard/jornada680_kbd.c b/trunk/drivers/input/keyboard/jornada680_kbd.c deleted file mode 100644 index bec1cf483723..000000000000 --- a/trunk/drivers/input/keyboard/jornada680_kbd.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * drivers/input/keyboard/jornada680_kbd.c - * - * HP Jornada 620/660/680/690 scan keyboard platform driver - * Copyright (C) 2007 Kristoffer Ericson - * - * Based on hp680_keyb.c - * Copyright (C) 2006 Paul Mundt - * Copyright (C) 2005 Andriy Skulysh - * Split from drivers/input/keyboard/hp600_keyb.c - * Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table) - * Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PCCR 0xa4000104 -#define PDCR 0xa4000106 -#define PECR 0xa4000108 -#define PFCR 0xa400010a -#define PCDR 0xa4000124 -#define PDDR 0xa4000126 -#define PEDR 0xa4000128 -#define PFDR 0xa400012a -#define PGDR 0xa400012c -#define PHDR 0xa400012e -#define PJDR 0xa4000130 -#define PKDR 0xa4000132 -#define PLDR 0xa4000134 - -static const unsigned short jornada_scancodes[] = { -/* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */ - KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */ -/* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */ - KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */ -/* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */ - 0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */ -/* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */ - KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */ -/* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */ - KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */ -/* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */ - 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */ -/* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */ - KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */ -/* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */ - KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */ -/* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - -#define JORNADA_SCAN_SIZE 18 - -struct jornadakbd { - struct input_polled_dev *poll_dev; - unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; - unsigned char length; - unsigned char old_scan[JORNADA_SCAN_SIZE]; - unsigned char new_scan[JORNADA_SCAN_SIZE]; -}; - -static void jornada_parse_kbd(struct jornadakbd *jornadakbd) -{ - struct input_dev *input_dev = jornadakbd->poll_dev->input; - unsigned short *keymap = jornadakbd->keymap; - unsigned int sync_me = 0; - unsigned int i, j; - - for (i = 0; i < JORNADA_SCAN_SIZE; i++) { - unsigned char new = jornadakbd->new_scan[i]; - unsigned char old = jornadakbd->old_scan[i]; - unsigned int xor = new ^ old; - - if (xor == 0) - continue; - - for (j = 0; j < 8; j++) { - unsigned int bit = 1 << j; - if (xor & bit) { - unsigned int scancode = (i << 3) + j; - input_event(input_dev, - EV_MSC, MSC_SCAN, scancode); - input_report_key(input_dev, - keymap[scancode], - !(new & bit)); - sync_me = 1; - } - } - } - - if (sync_me) - input_sync(input_dev); -} - -static void jornada_scan_keyb(unsigned char *s) -{ - int i; - unsigned short ec_static, dc_static; /* = UINT16_t */ - unsigned char matrix_switch[] = { - 0xfd, 0xff, /* PTD1 PD(1) */ - 0xdf, 0xff, /* PTD5 PD(5) */ - 0x7f, 0xff, /* PTD7 PD(7) */ - 0xff, 0xfe, /* PTE0 PE(0) */ - 0xff, 0xfd, /* PTE1 PE(1) */ - 0xff, 0xf7, /* PTE3 PE(3) */ - 0xff, 0xbf, /* PTE6 PE(6) */ - 0xff, 0x7f, /* PTE7 PE(7) */ - }, *t = matrix_switch; - /* PD(x) : - 1. 0xcc0c & (1~(1 << (2*(x)+1))))) - 2. (0xf0cf & 0xfffff) */ - /* PE(x) : - 1. 0xcc0c & 0xffff - 2. 0xf0cf & (1~(1 << (2*(x)+1))))) */ - unsigned short matrix_PDE[] = { - 0xcc04, 0xf0cf, /* PD(1) */ - 0xc40c, 0xf0cf, /* PD(5) */ - 0x4c0c, 0xf0cf, /* PD(7) */ - 0xcc0c, 0xf0cd, /* PE(0) */ - 0xcc0c, 0xf0c7, /* PE(1) */ - 0xcc0c, 0xf04f, /* PE(3) */ - 0xcc0c, 0xd0cf, /* PE(6) */ - 0xcc0c, 0x70cf, /* PE(7) */ - }, *y = matrix_PDE; - - /* Save these control reg bits */ - dc_static = (ctrl_inw(PDCR) & (~0xcc0c)); - ec_static = (ctrl_inw(PECR) & (~0xf0cf)); - - for (i = 0; i < 8; i++) { - /* disable output for all but the one we want to scan */ - ctrl_outw((dc_static | *y++), PDCR); - ctrl_outw((ec_static | *y++), PECR); - udelay(5); - - /* Get scanline row */ - ctrl_outb(*t++, PDDR); - ctrl_outb(*t++, PEDR); - udelay(50); - - /* Read data */ - *s++ = ctrl_inb(PCDR); - *s++ = ctrl_inb(PFDR); - } - /* Scan no lines */ - ctrl_outb(0xff, PDDR); - ctrl_outb(0xff, PEDR); - - /* Enable all scanlines */ - ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR); - ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR); - - /* Ignore extra keys and events */ - *s++ = ctrl_inb(PGDR); - *s++ = ctrl_inb(PHDR); -} - -static void jornadakbd680_poll(struct input_polled_dev *dev) -{ - struct jornadakbd *jornadakbd = dev->private; - - jornada_scan_keyb(jornadakbd->new_scan); - jornada_parse_kbd(jornadakbd); - memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE); -} - -static int __devinit jornada680kbd_probe(struct platform_device *pdev) -{ - struct jornadakbd *jornadakbd; - struct input_polled_dev *poll_dev; - struct input_dev *input_dev; - int i, error; - - jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); - if (!jornadakbd) - return -ENOMEM; - - poll_dev = input_allocate_polled_device(); - if (!poll_dev) { - error = -ENOMEM; - goto failed; - } - - platform_set_drvdata(pdev, jornadakbd); - - jornadakbd->poll_dev = poll_dev; - - memcpy(jornadakbd->keymap, jornada_scancodes, - sizeof(jornadakbd->keymap)); - - poll_dev->private = jornadakbd; - poll_dev->poll = jornadakbd680_poll; - poll_dev->poll_interval = 50; /* msec */ - - input_dev = poll_dev->input; - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - input_dev->name = "HP Jornada 680 keyboard"; - input_dev->phys = "jornadakbd/input0"; - input_dev->keycode = jornadakbd->keymap; - input_dev->keycodesize = sizeof(unsigned short); - input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); - input_dev->dev.parent = &pdev->dev; - input_dev->id.bustype = BUS_HOST; - - for (i = 0; i < 128; i++) - if (jornadakbd->keymap[i]) - __set_bit(jornadakbd->keymap[i], input_dev->keybit); - __clear_bit(KEY_RESERVED, input_dev->keybit); - - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - - error = input_register_polled_device(jornadakbd->poll_dev); - if (error) - goto failed; - - return 0; - - failed: - printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", - error); - platform_set_drvdata(pdev, NULL); - input_free_polled_device(poll_dev); - kfree(jornadakbd); - return error; - -} - -static int __devexit jornada680kbd_remove(struct platform_device *pdev) -{ - struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - input_unregister_polled_device(jornadakbd->poll_dev); - input_free_polled_device(jornadakbd->poll_dev); - kfree(jornadakbd); - - return 0; -} - -static struct platform_driver jornada680kbd_driver = { - .driver = { - .name = "jornada680_kbd", - }, - .probe = jornada680kbd_probe, - .remove = __devexit_p(jornada680kbd_remove), -}; - -static int __init jornada680kbd_init(void) -{ - return platform_driver_register(&jornada680kbd_driver); -} - -static void __exit jornada680kbd_exit(void) -{ - platform_driver_unregister(&jornada680kbd_driver); -} - -module_init(jornada680kbd_init); -module_exit(jornada680kbd_exit); - -MODULE_AUTHOR("Kristoffer Ericson "); -MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver"); -MODULE_LICENSE("GPLv2"); diff --git a/trunk/drivers/input/keyboard/jornada720_kbd.c b/trunk/drivers/input/keyboard/jornada720_kbd.c deleted file mode 100644 index e6696b3c9416..000000000000 --- a/trunk/drivers/input/keyboard/jornada720_kbd.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * drivers/input/keyboard/jornada720_kbd.c - * - * HP Jornada 720 keyboard platform driver - * - * Copyright (C) 2006/2007 Kristoffer Ericson - * - * Copyright (C) 2006 jornada 720 kbd driver by - Filip Zyzniewsk - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Kristoffer Ericson "); -MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); -MODULE_LICENSE("GPLv2"); - -static unsigned short jornada_std_keymap[128] = { /* ROW */ - 0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */ - KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */ - 0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */ - KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */ - 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */ - KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */ - 0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */ - KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */ - 0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */ - KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */ - 0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */ - KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */ - 0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */ - KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */ - 0, 0, 0, KEY_POWER, /* -> */ -}; - -struct jornadakbd { - unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)]; - struct input_dev *input; -}; - -static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) -{ - struct platform_device *pdev = dev_id; - struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); - struct input_dev *input = jornadakbd->input; - u8 count, kbd_data, scan_code; - - /* startup ssp with spinlock */ - jornada_ssp_start(); - - if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { - printk(KERN_DEBUG - "jornada720_kbd: " - "GetKeycode command failed with ETIMEDOUT, " - "flushed bus\n"); - } else { - /* How many keycodes are waiting for us? */ - count = jornada_ssp_byte(TXDUMMY); - - /* Lets drag them out one at a time */ - while (count--) { - /* Exchange TxDummy for location (keymap[kbddata]) */ - kbd_data = jornada_ssp_byte(TXDUMMY); - scan_code = kbd_data & 0x7f; - - input_event(input, EV_MSC, MSC_SCAN, scan_code); - input_report_key(input, jornadakbd->keymap[scan_code], - !(kbd_data & 0x80)); - input_sync(input); - } - } - - /* release spinlock and turn off ssp */ - jornada_ssp_end(); - - return IRQ_HANDLED; -}; - -static int __devinit jornada720_kbd_probe(struct platform_device *pdev) -{ - struct jornadakbd *jornadakbd; - struct input_dev *input_dev; - int i, err; - - jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!jornadakbd || !input_dev) { - err = -ENOMEM; - goto fail1; - } - - platform_set_drvdata(pdev, jornadakbd); - - memcpy(jornadakbd->keymap, jornada_std_keymap, - sizeof(jornada_std_keymap)); - jornadakbd->input = input_dev; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - input_dev->name = "HP Jornada 720 keyboard"; - input_dev->phys = "jornadakbd/input0"; - input_dev->keycode = jornadakbd->keymap; - input_dev->keycodesize = sizeof(unsigned short); - input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap); - input_dev->id.bustype = BUS_HOST; - input_dev->dev.parent = &pdev->dev; - - for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++) - __set_bit(jornadakbd->keymap[i], input_dev->keybit); - __clear_bit(KEY_RESERVED, input_dev->keybit); - - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - - err = request_irq(IRQ_GPIO0, - jornada720_kbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_FALLING, - "jornadakbd", pdev); - if (err) { - printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); - goto fail1; - } - - err = input_register_device(jornadakbd->input); - if (err) - goto fail2; - - return 0; - - fail2: /* IRQ, DEVICE, MEMORY */ - free_irq(IRQ_GPIO0, pdev); - fail1: /* DEVICE, MEMORY */ - platform_set_drvdata(pdev, NULL); - input_free_device(input_dev); - kfree(jornadakbd); - return err; -}; - -static int __devexit jornada720_kbd_remove(struct platform_device *pdev) -{ - struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); - - free_irq(IRQ_GPIO0, pdev); - platform_set_drvdata(pdev, NULL); - input_unregister_device(jornadakbd->input); - kfree(jornadakbd); - - return 0; -} - -static struct platform_driver jornada720_kbd_driver = { - .driver = { - .name = "jornada720_kbd", - }, - .probe = jornada720_kbd_probe, - .remove = __devexit_p(jornada720_kbd_remove), -}; - -static int __init jornada720_kbd_init(void) -{ - return platform_driver_register(&jornada720_kbd_driver); -} - -static void __exit jornada720_kbd_exit(void) -{ - platform_driver_unregister(&jornada720_kbd_driver); -} - -module_init(jornada720_kbd_init); -module_exit(jornada720_kbd_exit); diff --git a/trunk/drivers/input/keyboard/maple_keyb.c b/trunk/drivers/input/keyboard/maple_keyb.c deleted file mode 100644 index 2b404284c28a..000000000000 --- a/trunk/drivers/input/keyboard/maple_keyb.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * SEGA Dreamcast keyboard driver - * Based on drivers/usb/usbkbd.c - * Copyright YAEGASHI Takeshi, 2001 - * Porting to 2.6 Copyright Adrian McMenamin, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Very simple mutex to ensure proper cleanup */ -static DEFINE_MUTEX(maple_keyb_mutex); - -#define NR_SCANCODES 256 - -MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); -MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); -MODULE_LICENSE("GPL"); - -struct dc_kbd { - struct input_dev *dev; - unsigned short keycode[NR_SCANCODES]; - unsigned char new[8]; - unsigned char old[8]; -}; - -static const unsigned short dc_kbd_keycode[NR_SCANCODES] = { - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D, - KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, - KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, - KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, - KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, - KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, - KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, - KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, - KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, - KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, - KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, - KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, - KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, - KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, - KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, - KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, - KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, - KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN, - KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, - KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA, - KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, - KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, - KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED -}; - -static void dc_scan_kbd(struct dc_kbd *kbd) -{ - struct input_dev *dev = kbd->dev; - void *ptr; - int code, keycode; - int i; - - for (i = 0; i < 8; i++) { - code = i + 224; - keycode = kbd->keycode[code]; - input_event(dev, EV_MSC, MSC_SCAN, code); - input_report_key(dev, keycode, (kbd->new[0] >> i) & 1); - } - - for (i = 2; i < 8; i++) { - ptr = memchr(kbd->new + 2, kbd->old[i], 6); - code = kbd->old[i]; - if (code > 3 && ptr == NULL) { - keycode = kbd->keycode[code]; - if (keycode) { - input_event(dev, EV_MSC, MSC_SCAN, code); - input_report_key(dev, keycode, 0); - } else - printk(KERN_DEBUG "maple_keyb: " - "Unknown key (scancode %#x) released.", - code); - } - ptr = memchr(kbd->old + 2, kbd->new[i], 6); - code = kbd->new[i]; - if (code > 3 && ptr) { - keycode = kbd->keycode[code]; - if (keycode) { - input_event(dev, EV_MSC, MSC_SCAN, code); - input_report_key(dev, keycode, 1); - } else - printk(KERN_DEBUG "maple_keyb: " - "Unknown key (scancode %#x) pressed.", - code); - } - } - input_sync(dev); - memcpy(kbd->old, kbd->new, 8); -} - -static void dc_kbd_callback(struct mapleq *mq) -{ - struct maple_device *mapledev = mq->dev; - struct dc_kbd *kbd = mapledev->private_data; - unsigned long *buf = mq->recvbuf; - - /* - * We should always be getting the lock because the only - * time it may be locked if driver is in cleanup phase. - */ - if (likely(mutex_trylock(&maple_keyb_mutex))) { - - if (buf[1] == mapledev->function) { - memcpy(kbd->new, buf + 2, 8); - dc_scan_kbd(kbd); - } - - mutex_unlock(&maple_keyb_mutex); - } -} - -static int dc_kbd_connect(struct maple_device *mdev) -{ - int i, error; - struct dc_kbd *kbd; - struct input_dev *dev; - - if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) - return -EINVAL; - - kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); - dev = input_allocate_device(); - if (!kbd || !dev) { - error = -ENOMEM; - goto fail; - } - - mdev->private_data = kbd; - - kbd->dev = dev; - memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); - - dev->name = mdev->product_name; - dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - dev->keycode = kbd->keycode; - dev->keycodesize = sizeof (unsigned short); - dev->keycodemax = ARRAY_SIZE(kbd->keycode); - dev->id.bustype = BUS_HOST; - dev->dev.parent = &mdev->dev; - - for (i = 0; i < NR_SCANCODES; i++) - __set_bit(dc_kbd_keycode[i], dev->keybit); - __clear_bit(KEY_RESERVED, dev->keybit); - - input_set_capability(dev, EV_MSC, MSC_SCAN); - input_set_drvdata(dev, kbd); - - error = input_register_device(dev); - if (error) - goto fail; - - /* Maple polling is locked to VBLANK - which may be just 50/s */ - maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD); - return 0; - - fail: - input_free_device(dev); - kfree(kbd); - mdev->private_data = NULL; - return error; -} - -static void dc_kbd_disconnect(struct maple_device *mdev) -{ - struct dc_kbd *kbd; - - mutex_lock(&maple_keyb_mutex); - - kbd = mdev->private_data; - mdev->private_data = NULL; - input_unregister_device(kbd->dev); - kfree(kbd); - - mutex_unlock(&maple_keyb_mutex); -} - -/* allow the keyboard to be used */ -static int probe_maple_kbd(struct device *dev) -{ - struct maple_device *mdev = to_maple_dev(dev); - struct maple_driver *mdrv = to_maple_driver(dev->driver); - int error; - - error = dc_kbd_connect(mdev); - if (error) - return error; - - mdev->driver = mdrv; - mdev->registered = 1; - - return 0; -} - -static struct maple_driver dc_kbd_driver = { - .function = MAPLE_FUNC_KEYBOARD, - .connect = dc_kbd_connect, - .disconnect = dc_kbd_disconnect, - .drv = { - .name = "Dreamcast_keyboard", - .probe = probe_maple_kbd, - }, -}; - -static int __init dc_kbd_init(void) -{ - return maple_driver_register(&dc_kbd_driver.drv); -} - -static void __exit dc_kbd_exit(void) -{ - driver_unregister(&dc_kbd_driver.drv); -} - -module_init(dc_kbd_init); -module_exit(dc_kbd_exit); diff --git a/trunk/drivers/input/keyboard/omap-keypad.c b/trunk/drivers/input/keyboard/omap-keypad.c index 76f1969552c5..3a228634f101 100644 --- a/trunk/drivers/input/keyboard/omap-keypad.c +++ b/trunk/drivers/input/keyboard/omap-keypad.c @@ -233,7 +233,7 @@ static void omap_kp_tasklet(unsigned long data) omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); kp_cur_group = -1; } - } + } } static ssize_t omap_kp_enable_show(struct device *dev, @@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) keymap = pdata->keymap; if (pdata->rep) - __set_bit(EV_REP, input_dev->evbit); + set_bit(EV_REP, input_dev->evbit); if (pdata->delay) omap_kp->delay = pdata->delay; @@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev) goto err2; /* setup input device */ - __set_bit(EV_KEY, input_dev->evbit); + set_bit(EV_KEY, input_dev->evbit); for (i = 0; keymap[i] != 0; i++) - __set_bit(keymap[i] & KEY_MAX, input_dev->keybit); + set_bit(keymap[i] & KEY_MAX, input_dev->keybit); input_dev->name = "omap-keypad"; input_dev->phys = "omap-keypad/input0"; input_dev->dev.parent = &pdev->dev; @@ -377,6 +377,10 @@ static int __init omap_kp_probe(struct platform_device *pdev) input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; + input_dev->keycode = keymap; + input_dev->keycodesize = sizeof(unsigned int); + input_dev->keycodemax = pdata->keymapsize; + ret = input_register_device(omap_kp->input); if (ret < 0) { printk(KERN_ERR "Unable to register omap-keypad input device\n"); @@ -399,15 +403,15 @@ static int __init omap_kp_probe(struct platform_device *pdev) } else { for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), - omap_kp_interrupt, + omap_kp_interrupt, IRQF_TRIGGER_FALLING, - "omap-keypad", omap_kp) < 0) + "omap-keypad", omap_kp) < 0) goto err5; } } return 0; err5: - for (i = irq_idx - 1; i >=0; i--) + for (i = irq_idx-1; i >=0; i--) free_irq(row_gpios[i], 0); err4: input_unregister_device(omap_kp->input); @@ -436,9 +440,9 @@ static int omap_kp_remove(struct platform_device *pdev) if (cpu_is_omap24xx()) { int i; for (i = 0; i < omap_kp->cols; i++) - omap_free_gpio(col_gpios[i]); + omap_free_gpio(col_gpios[i]); for (i = 0; i < omap_kp->rows; i++) { - omap_free_gpio(row_gpios[i]); + omap_free_gpio(row_gpios[i]); free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); } } else { diff --git a/trunk/drivers/input/mouse/alps.c b/trunk/drivers/input/mouse/alps.c index 64d70a9b714c..2c5f11a4f6b4 100644 --- a/trunk/drivers/input/mouse/alps.c +++ b/trunk/drivers/input/mouse/alps.c @@ -48,13 +48,11 @@ static const struct alps_model_info alps_model_data[] = { { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ - { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - { { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ }; /* diff --git a/trunk/drivers/input/mouse/appletouch.c b/trunk/drivers/input/mouse/appletouch.c index 0117817bf538..a1804bfdbb8c 100644 --- a/trunk/drivers/input/mouse/appletouch.c +++ b/trunk/drivers/input/mouse/appletouch.c @@ -502,23 +502,18 @@ static void atp_complete(struct urb* urb) /* reset the accumulator on release */ memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); - } - - /* Geyser 3 will continue to send packets continually after - the first touch unless reinitialised. Do so if it's been - idle for a while in order to avoid waking the kernel up - several hundred times a second */ - if (atp_is_geyser_3(dev)) { - if (!x && !y && !key) { + /* Geyser 3 will continue to send packets continually after + the first touch unless reinitialised. Do so if it's been + idle for a while in order to avoid waking the kernel up + several hundred times a second */ + if (!key && atp_is_geyser_3(dev)) { dev->idlecount++; if (dev->idlecount == 10) { dev->valid = 0; schedule_work(&dev->work); } } - else - dev->idlecount = 0; } input_report_key(dev->input, BTN_LEFT, key); diff --git a/trunk/drivers/input/mouse/lifebook.c b/trunk/drivers/input/mouse/lifebook.c index d7de4c53b3d8..608674d0be8b 100644 --- a/trunk/drivers/input/mouse/lifebook.c +++ b/trunk/drivers/input/mouse/lifebook.c @@ -96,14 +96,6 @@ static const struct dmi_system_id lifebook_dmi_table[] = { }, .callback = lifebook_set_6byte_proto, }, - { - .ident = "CF-72", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), - }, - .callback = lifebook_set_serio_phys, - .driver_data = "isa0060/serio3", - }, { .ident = "Lifebook B142", .matches = { @@ -290,7 +282,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) int lifebook_init(struct psmouse *psmouse) { struct input_dev *dev1 = psmouse->dev; - int max_coord = lifebook_use_6byte_proto ? 4096 : 1024; + int max_coord = lifebook_use_6byte_proto ? 1024 : 4096; if (lifebook_absolute_mode(psmouse)) return -1; diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c index 073525756532..b9f0fb2530e2 100644 --- a/trunk/drivers/input/mouse/psmouse-base.c +++ b/trunk/drivers/input/mouse/psmouse-base.c @@ -648,10 +648,9 @@ static int psmouse_extensions(struct psmouse *psmouse, /* * Reset to defaults in case the device got confused by extended - * protocol probes. Note that we follow up with full reset because - * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. + * protocol probes. Note that we do full reset becuase some mice + * put themselves to sleep when see PSMOUSE_RESET_DIS. */ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); psmouse_reset(psmouse); if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c index 79146d6ed2ab..9173916b8be5 100644 --- a/trunk/drivers/input/mousedev.c +++ b/trunk/drivers/input/mousedev.c @@ -61,11 +61,9 @@ struct mousedev { int open; int minor; char name[16]; - struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; - spinlock_t client_lock; /* protects client_list */ - struct mutex mutex; + struct input_handle handle; struct device dev; struct list_head mixdev_node; @@ -115,137 +113,108 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; static struct input_handler mousedev_handler; static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; -static DEFINE_MUTEX(mousedev_table_mutex); static struct mousedev *mousedev_mix; static LIST_HEAD(mousedev_mix_list); -static void mixdev_open_devices(void); -static void mixdev_close_devices(void); - #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) -static void mousedev_touchpad_event(struct input_dev *dev, - struct mousedev *mousedev, - unsigned int code, int value) +static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) { int size, tmp; enum { FRACTION_DENOM = 128 }; switch (code) { + case ABS_X: + fx(0) = value; + if (mousedev->touch && mousedev->pkt_count >= 2) { + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) + size = 256 * 2; + tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; + tmp += mousedev->frac_dx; + mousedev->packet.dx = tmp / FRACTION_DENOM; + mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; + } + break; - case ABS_X: - fx(0) = value; - if (mousedev->touch && mousedev->pkt_count >= 2) { - size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) - size = 256 * 2; - tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size; - tmp += mousedev->frac_dx; - mousedev->packet.dx = tmp / FRACTION_DENOM; - mousedev->frac_dx = - tmp - mousedev->packet.dx * FRACTION_DENOM; - } - break; - - case ABS_Y: - fy(0) = value; - if (mousedev->touch && mousedev->pkt_count >= 2) { - /* use X size to keep the same scale */ - size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) - size = 256 * 2; - tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size; - tmp += mousedev->frac_dy; - mousedev->packet.dy = tmp / FRACTION_DENOM; - mousedev->frac_dy = tmp - - mousedev->packet.dy * FRACTION_DENOM; - } - break; + case ABS_Y: + fy(0) = value; + if (mousedev->touch && mousedev->pkt_count >= 2) { + /* use X size to keep the same scale */ + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) + size = 256 * 2; + tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; + tmp += mousedev->frac_dy; + mousedev->packet.dy = tmp / FRACTION_DENOM; + mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; + } + break; } } -static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, - unsigned int code, int value) +static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) { int size; switch (code) { + case ABS_X: + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) + size = xres ? : 1; + if (value > dev->absmax[ABS_X]) + value = dev->absmax[ABS_X]; + if (value < dev->absmin[ABS_X]) + value = dev->absmin[ABS_X]; + mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; + mousedev->packet.abs_event = 1; + break; - case ABS_X: - size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) - size = xres ? : 1; - if (value > dev->absmax[ABS_X]) - value = dev->absmax[ABS_X]; - if (value < dev->absmin[ABS_X]) - value = dev->absmin[ABS_X]; - mousedev->packet.x = - ((value - dev->absmin[ABS_X]) * xres) / size; - mousedev->packet.abs_event = 1; - break; - - case ABS_Y: - size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; - if (size == 0) - size = yres ? : 1; - if (value > dev->absmax[ABS_Y]) - value = dev->absmax[ABS_Y]; - if (value < dev->absmin[ABS_Y]) - value = dev->absmin[ABS_Y]; - mousedev->packet.y = yres - - ((value - dev->absmin[ABS_Y]) * yres) / size; - mousedev->packet.abs_event = 1; - break; + case ABS_Y: + size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; + if (size == 0) + size = yres ? : 1; + if (value > dev->absmax[ABS_Y]) + value = dev->absmax[ABS_Y]; + if (value < dev->absmin[ABS_Y]) + value = dev->absmin[ABS_Y]; + mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; + mousedev->packet.abs_event = 1; + break; } } -static void mousedev_rel_event(struct mousedev *mousedev, - unsigned int code, int value) +static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value) { switch (code) { - case REL_X: - mousedev->packet.dx += value; - break; - - case REL_Y: - mousedev->packet.dy -= value; - break; - - case REL_WHEEL: - mousedev->packet.dz -= value; - break; + case REL_X: mousedev->packet.dx += value; break; + case REL_Y: mousedev->packet.dy -= value; break; + case REL_WHEEL: mousedev->packet.dz -= value; break; } } -static void mousedev_key_event(struct mousedev *mousedev, - unsigned int code, int value) +static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value) { int index; switch (code) { - - case BTN_TOUCH: - case BTN_0: - case BTN_LEFT: index = 0; break; - - case BTN_STYLUS: - case BTN_1: - case BTN_RIGHT: index = 1; break; - - case BTN_2: - case BTN_FORWARD: - case BTN_STYLUS2: - case BTN_MIDDLE: index = 2; break; - - case BTN_3: - case BTN_BACK: - case BTN_SIDE: index = 3; break; - - case BTN_4: - case BTN_EXTRA: index = 4; break; - - default: return; + case BTN_TOUCH: + case BTN_0: + case BTN_LEFT: index = 0; break; + case BTN_STYLUS: + case BTN_1: + case BTN_RIGHT: index = 1; break; + case BTN_2: + case BTN_FORWARD: + case BTN_STYLUS2: + case BTN_MIDDLE: index = 2; break; + case BTN_3: + case BTN_BACK: + case BTN_SIDE: index = 3; break; + case BTN_4: + case BTN_EXTRA: index = 4; break; + default: return; } if (value) { @@ -257,23 +226,19 @@ static void mousedev_key_event(struct mousedev *mousedev, } } -static void mousedev_notify_readers(struct mousedev *mousedev, - struct mousedev_hw_data *packet) +static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) { struct mousedev_client *client; struct mousedev_motion *p; - unsigned int new_head; + unsigned long flags; int wake_readers = 0; - rcu_read_lock(); - list_for_each_entry_rcu(client, &mousedev->client_list, node) { - - /* Just acquire the lock, interrupts already disabled */ - spin_lock(&client->packet_lock); + list_for_each_entry(client, &mousedev->client_list, node) { + spin_lock_irqsave(&client->packet_lock, flags); p = &client->packets[client->head]; if (client->ready && p->buttons != mousedev->packet.buttons) { - new_head = (client->head + 1) % PACKET_QUEUE_LEN; + unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN; if (new_head != client->tail) { p = &client->packets[client->head = new_head]; memset(p, 0, sizeof(struct mousedev_motion)); @@ -288,29 +253,25 @@ static void mousedev_notify_readers(struct mousedev *mousedev, } client->pos_x += packet->dx; - client->pos_x = client->pos_x < 0 ? - 0 : (client->pos_x >= xres ? xres : client->pos_x); + client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x); client->pos_y += packet->dy; - client->pos_y = client->pos_y < 0 ? - 0 : (client->pos_y >= yres ? yres : client->pos_y); + client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y); p->dx += packet->dx; p->dy += packet->dy; p->dz += packet->dz; p->buttons = mousedev->packet.buttons; - if (p->dx || p->dy || p->dz || - p->buttons != client->last_buttons) + if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons) client->ready = 1; - spin_unlock(&client->packet_lock); + spin_unlock_irqrestore(&client->packet_lock, flags); if (client->ready) { kill_fasync(&client->fasync, SIGIO, POLL_IN); wake_readers = 1; } } - rcu_read_unlock(); if (wake_readers) wake_up_interruptible(&mousedev->wait); @@ -320,8 +281,7 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) { if (!value) { if (mousedev->touch && - time_before(jiffies, - mousedev->touch + msecs_to_jiffies(tap_time))) { + time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) { /* * Toggle left button to emulate tap. * We rely on the fact that mousedev_mix always has 0 @@ -330,8 +290,7 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) set_bit(0, &mousedev->packet.buttons); set_bit(0, &mousedev_mix->packet.buttons); mousedev_notify_readers(mousedev, &mousedev_mix->packet); - mousedev_notify_readers(mousedev_mix, - &mousedev_mix->packet); + mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet); clear_bit(0, &mousedev->packet.buttons); clear_bit(0, &mousedev_mix->packet.buttons); } @@ -343,61 +302,54 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) mousedev->touch = jiffies; } -static void mousedev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct mousedev *mousedev = handle->private; switch (type) { + case EV_ABS: + /* Ignore joysticks */ + if (test_bit(BTN_TRIGGER, handle->dev->keybit)) + return; - case EV_ABS: - /* Ignore joysticks */ - if (test_bit(BTN_TRIGGER, handle->dev->keybit)) - return; - - if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) - mousedev_touchpad_event(handle->dev, - mousedev, code, value); - else - mousedev_abs_event(handle->dev, mousedev, code, value); + if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) + mousedev_touchpad_event(handle->dev, mousedev, code, value); + else + mousedev_abs_event(handle->dev, mousedev, code, value); - break; + break; - case EV_REL: - mousedev_rel_event(mousedev, code, value); - break; + case EV_REL: + mousedev_rel_event(mousedev, code, value); + break; - case EV_KEY: - if (value != 2) { - if (code == BTN_TOUCH && - test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) - mousedev_touchpad_touch(mousedev, value); - else - mousedev_key_event(mousedev, code, value); - } - break; - - case EV_SYN: - if (code == SYN_REPORT) { - if (mousedev->touch) { - mousedev->pkt_count++; - /* - * Input system eats duplicate events, - * but we need all of them to do correct - * averaging so apply present one forward - */ - fx(0) = fx(1); - fy(0) = fy(1); + case EV_KEY: + if (value != 2) { + if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) + mousedev_touchpad_touch(mousedev, value); + else + mousedev_key_event(mousedev, code, value); } + break; - mousedev_notify_readers(mousedev, &mousedev->packet); - mousedev_notify_readers(mousedev_mix, &mousedev->packet); - - mousedev->packet.dx = mousedev->packet.dy = - mousedev->packet.dz = 0; - mousedev->packet.abs_event = 0; - } - break; + case EV_SYN: + if (code == SYN_REPORT) { + if (mousedev->touch) { + mousedev->pkt_count++; + /* Input system eats duplicate events, but we need all of them + * to do correct averaging so apply present one forward + */ + fx(0) = fx(1); + fy(0) = fy(1); + } + + mousedev_notify_readers(mousedev, &mousedev->packet); + mousedev_notify_readers(mousedev_mix, &mousedev->packet); + + mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; + mousedev->packet.abs_event = 0; + } + break; } } @@ -415,48 +367,41 @@ static void mousedev_free(struct device *dev) { struct mousedev *mousedev = container_of(dev, struct mousedev, dev); + mousedev_table[mousedev->minor] = NULL; kfree(mousedev); } -static int mousedev_open_device(struct mousedev *mousedev) +static int mixdev_add_device(struct mousedev *mousedev) { - int retval; + int error; - retval = mutex_lock_interruptible(&mousedev->mutex); - if (retval) - return retval; + if (mousedev_mix->open) { + error = input_open_device(&mousedev->handle); + if (error) + return error; - if (mousedev->minor == MOUSEDEV_MIX) - mixdev_open_devices(); - else if (!mousedev->exist) - retval = -ENODEV; - else if (!mousedev->open++) { - retval = input_open_device(&mousedev->handle); - if (retval) - mousedev->open--; + mousedev->open++; + mousedev->mixdev_open = 1; } - mutex_unlock(&mousedev->mutex); - return retval; + get_device(&mousedev->dev); + list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); + + return 0; } -static void mousedev_close_device(struct mousedev *mousedev) +static void mixdev_remove_device(struct mousedev *mousedev) { - mutex_lock(&mousedev->mutex); - - if (mousedev->minor == MOUSEDEV_MIX) - mixdev_close_devices(); - else if (mousedev->exist && !--mousedev->open) - input_close_device(&mousedev->handle); + if (mousedev->mixdev_open) { + mousedev->mixdev_open = 0; + if (!--mousedev->open && mousedev->exist) + input_close_device(&mousedev->handle); + } - mutex_unlock(&mousedev->mutex); + list_del_init(&mousedev->mixdev_node); + put_device(&mousedev->dev); } -/* - * Open all available devices so they can all be multiplexed in one. - * stream. Note that this function is called with mousedev_mix->mutex - * held. - */ static void mixdev_open_devices(void) { struct mousedev *mousedev; @@ -466,19 +411,16 @@ static void mixdev_open_devices(void) list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { if (!mousedev->mixdev_open) { - if (mousedev_open_device(mousedev)) - continue; + if (!mousedev->open && mousedev->exist) + if (input_open_device(&mousedev->handle)) + continue; + mousedev->open++; mousedev->mixdev_open = 1; } } } -/* - * Close all devices that were opened as part of multiplexed - * device. Note that this function is called with mousedev_mix->mutex - * held. - */ static void mixdev_close_devices(void) { struct mousedev *mousedev; @@ -489,45 +431,33 @@ static void mixdev_close_devices(void) list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { if (mousedev->mixdev_open) { mousedev->mixdev_open = 0; - mousedev_close_device(mousedev); + if (!--mousedev->open && mousedev->exist) + input_close_device(&mousedev->handle); } } } - -static void mousedev_attach_client(struct mousedev *mousedev, - struct mousedev_client *client) -{ - spin_lock(&mousedev->client_lock); - list_add_tail_rcu(&client->node, &mousedev->client_list); - spin_unlock(&mousedev->client_lock); - synchronize_rcu(); -} - -static void mousedev_detach_client(struct mousedev *mousedev, - struct mousedev_client *client) -{ - spin_lock(&mousedev->client_lock); - list_del_rcu(&client->node); - spin_unlock(&mousedev->client_lock); - synchronize_rcu(); -} - static int mousedev_release(struct inode *inode, struct file *file) { struct mousedev_client *client = file->private_data; struct mousedev *mousedev = client->mousedev; mousedev_fasync(-1, file, 0); - mousedev_detach_client(mousedev, client); + + list_del(&client->node); kfree(client); - mousedev_close_device(mousedev); + if (mousedev->minor == MOUSEDEV_MIX) + mixdev_close_devices(); + else if (!--mousedev->open && mousedev->exist) + input_close_device(&mousedev->handle); + put_device(&mousedev->dev); return 0; } + static int mousedev_open(struct inode *inode, struct file *file) { struct mousedev_client *client; @@ -545,17 +475,12 @@ static int mousedev_open(struct inode *inode, struct file *file) if (i >= MOUSEDEV_MINORS) return -ENODEV; - error = mutex_lock_interruptible(&mousedev_table_mutex); - if (error) - return error; mousedev = mousedev_table[i]; - if (mousedev) - get_device(&mousedev->dev); - mutex_unlock(&mousedev_table_mutex); - if (!mousedev) return -ENODEV; + get_device(&mousedev->dev); + client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); if (!client) { error = -ENOMEM; @@ -566,17 +491,21 @@ static int mousedev_open(struct inode *inode, struct file *file) client->pos_x = xres / 2; client->pos_y = yres / 2; client->mousedev = mousedev; - mousedev_attach_client(mousedev, client); + list_add_tail(&client->node, &mousedev->client_list); - error = mousedev_open_device(mousedev); - if (error) - goto err_free_client; + if (mousedev->minor == MOUSEDEV_MIX) + mixdev_open_devices(); + else if (!mousedev->open++ && mousedev->exist) { + error = input_open_device(&mousedev->handle); + if (error) + goto err_free_client; + } file->private_data = client; return 0; err_free_client: - mousedev_detach_client(mousedev, client); + list_del(&client->node); kfree(client); err_put_mousedev: put_device(&mousedev->dev); @@ -588,41 +517,41 @@ static inline int mousedev_limit_delta(int delta, int limit) return delta > limit ? limit : (delta < -limit ? -limit : delta); } -static void mousedev_packet(struct mousedev_client *client, - signed char *ps2_data) +static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data) { - struct mousedev_motion *p = &client->packets[client->tail]; + struct mousedev_motion *p; + unsigned long flags; + + spin_lock_irqsave(&client->packet_lock, flags); + p = &client->packets[client->tail]; - ps2_data[0] = 0x08 | - ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); + ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); ps2_data[1] = mousedev_limit_delta(p->dx, 127); ps2_data[2] = mousedev_limit_delta(p->dy, 127); p->dx -= ps2_data[1]; p->dy -= ps2_data[2]; switch (client->mode) { - case MOUSEDEV_EMUL_EXPS: - ps2_data[3] = mousedev_limit_delta(p->dz, 7); - p->dz -= ps2_data[3]; - ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); - client->bufsiz = 4; - break; - - case MOUSEDEV_EMUL_IMPS: - ps2_data[0] |= - ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); - ps2_data[3] = mousedev_limit_delta(p->dz, 127); - p->dz -= ps2_data[3]; - client->bufsiz = 4; - break; - - case MOUSEDEV_EMUL_PS2: - default: - ps2_data[0] |= - ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); - p->dz = 0; - client->bufsiz = 3; - break; + case MOUSEDEV_EMUL_EXPS: + ps2_data[3] = mousedev_limit_delta(p->dz, 7); + p->dz -= ps2_data[3]; + ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); + client->bufsiz = 4; + break; + + case MOUSEDEV_EMUL_IMPS: + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); + ps2_data[3] = mousedev_limit_delta(p->dz, 127); + p->dz -= ps2_data[3]; + client->bufsiz = 4; + break; + + case MOUSEDEV_EMUL_PS2: + default: + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); + p->dz = 0; + client->bufsiz = 3; + break; } if (!p->dx && !p->dy && !p->dz) { @@ -632,56 +561,12 @@ static void mousedev_packet(struct mousedev_client *client, } else client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; } -} - -static void mousedev_generate_response(struct mousedev_client *client, - int command) -{ - client->ps2[0] = 0xfa; /* ACK */ - switch (command) { - - case 0xeb: /* Poll */ - mousedev_packet(client, &client->ps2[1]); - client->bufsiz++; /* account for leading ACK */ - break; - - case 0xf2: /* Get ID */ - switch (client->mode) { - case MOUSEDEV_EMUL_PS2: - client->ps2[1] = 0; - break; - case MOUSEDEV_EMUL_IMPS: - client->ps2[1] = 3; - break; - case MOUSEDEV_EMUL_EXPS: - client->ps2[1] = 4; - break; - } - client->bufsiz = 2; - break; - - case 0xe9: /* Get info */ - client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; - client->bufsiz = 4; - break; - - case 0xff: /* Reset */ - client->impsseq = client->imexseq = 0; - client->mode = MOUSEDEV_EMUL_PS2; - client->ps2[1] = 0xaa; client->ps2[2] = 0x00; - client->bufsiz = 3; - break; - - default: - client->bufsiz = 1; - break; - } - client->buffer = client->bufsiz; + spin_unlock_irqrestore(&client->packet_lock, flags); } -static ssize_t mousedev_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) + +static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct mousedev_client *client = file->private_data; unsigned char c; @@ -692,8 +577,6 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, if (get_user(c, buffer + i)) return -EFAULT; - spin_lock_irq(&client->packet_lock); - if (c == mousedev_imex_seq[client->imexseq]) { if (++client->imexseq == MOUSEDEV_SEQ_LEN) { client->imexseq = 0; @@ -710,39 +593,68 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, } else client->impsseq = 0; - mousedev_generate_response(client, c); + client->ps2[0] = 0xfa; + + switch (c) { + + case 0xeb: /* Poll */ + mousedev_packet(client, &client->ps2[1]); + client->bufsiz++; /* account for leading ACK */ + break; + + case 0xf2: /* Get ID */ + switch (client->mode) { + case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break; + case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break; + case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break; + } + client->bufsiz = 2; + break; + + case 0xe9: /* Get info */ + client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; + client->bufsiz = 4; + break; + + case 0xff: /* Reset */ + client->impsseq = client->imexseq = 0; + client->mode = MOUSEDEV_EMUL_PS2; + client->ps2[1] = 0xaa; client->ps2[2] = 0x00; + client->bufsiz = 3; + break; + + default: + client->bufsiz = 1; + break; + } - spin_unlock_irq(&client->packet_lock); + client->buffer = client->bufsiz; } kill_fasync(&client->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&client->mousedev->wait); return count; } -static ssize_t mousedev_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct mousedev_client *client = file->private_data; - struct mousedev *mousedev = client->mousedev; - signed char data[sizeof(client->ps2)]; int retval = 0; - if (!client->ready && !client->buffer && mousedev->exist && - (file->f_flags & O_NONBLOCK)) + if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(mousedev->wait, - !mousedev->exist || client->ready || client->buffer); + retval = wait_event_interruptible(client->mousedev->wait, + !client->mousedev->exist || client->ready || client->buffer); + if (retval) return retval; - if (!mousedev->exist) + if (!client->mousedev->exist) return -ENODEV; - spin_lock_irq(&client->packet_lock); - if (!client->buffer && client->ready) { mousedev_packet(client, client->ps2); client->buffer = client->bufsiz; @@ -751,12 +663,9 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, if (count > client->buffer) count = client->buffer; - memcpy(data, client->ps2 + client->bufsiz - client->buffer, count); client->buffer -= count; - spin_unlock_irq(&client->packet_lock); - - if (copy_to_user(buffer, data, count)) + if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count)) return -EFAULT; return count; @@ -783,60 +692,6 @@ static const struct file_operations mousedev_fops = { .fasync = mousedev_fasync, }; -static int mousedev_install_chrdev(struct mousedev *mousedev) -{ - mousedev_table[mousedev->minor] = mousedev; - return 0; -} - -static void mousedev_remove_chrdev(struct mousedev *mousedev) -{ - mutex_lock(&mousedev_table_mutex); - mousedev_table[mousedev->minor] = NULL; - mutex_unlock(&mousedev_table_mutex); -} - -/* - * Mark device non-existent. This disables writes, ioctls and - * prevents new users from opening the device. Already posted - * blocking reads will stay, however new ones will fail. - */ -static void mousedev_mark_dead(struct mousedev *mousedev) -{ - mutex_lock(&mousedev->mutex); - mousedev->exist = 0; - mutex_unlock(&mousedev->mutex); -} - -/* - * Wake up users waiting for IO so they can disconnect from - * dead device. - */ -static void mousedev_hangup(struct mousedev *mousedev) -{ - struct mousedev_client *client; - - spin_lock(&mousedev->client_lock); - list_for_each_entry(client, &mousedev->client_list, node) - kill_fasync(&client->fasync, SIGIO, POLL_HUP); - spin_unlock(&mousedev->client_lock); - - wake_up_interruptible(&mousedev->wait); -} - -static void mousedev_cleanup(struct mousedev *mousedev) -{ - struct input_handle *handle = &mousedev->handle; - - mousedev_mark_dead(mousedev); - mousedev_hangup(mousedev); - mousedev_remove_chrdev(mousedev); - - /* mousedev is marked dead so no one else accesses mousedev->open */ - if (mousedev->open) - input_close_device(handle); -} - static struct mousedev *mousedev_create(struct input_dev *dev, struct input_handler *handler, int minor) @@ -852,10 +707,6 @@ static struct mousedev *mousedev_create(struct input_dev *dev, INIT_LIST_HEAD(&mousedev->client_list); INIT_LIST_HEAD(&mousedev->mixdev_node); - spin_lock_init(&mousedev->client_lock); - mutex_init(&mousedev->mutex); - lockdep_set_subclass(&mousedev->mutex, - minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0); init_waitqueue_head(&mousedev->wait); if (minor == MOUSEDEV_MIX) @@ -880,27 +731,14 @@ static struct mousedev *mousedev_create(struct input_dev *dev, mousedev->dev.release = mousedev_free; device_initialize(&mousedev->dev); - if (minor != MOUSEDEV_MIX) { - error = input_register_handle(&mousedev->handle); - if (error) - goto err_free_mousedev; - } - - error = mousedev_install_chrdev(mousedev); - if (error) - goto err_unregister_handle; + mousedev_table[minor] = mousedev; error = device_add(&mousedev->dev); if (error) - goto err_cleanup_mousedev; + goto err_free_mousedev; return mousedev; - err_cleanup_mousedev: - mousedev_cleanup(mousedev); - err_unregister_handle: - if (minor != MOUSEDEV_MIX) - input_unregister_handle(&mousedev->handle); err_free_mousedev: put_device(&mousedev->dev); err_out: @@ -909,64 +747,29 @@ static struct mousedev *mousedev_create(struct input_dev *dev, static void mousedev_destroy(struct mousedev *mousedev) { - device_del(&mousedev->dev); - mousedev_cleanup(mousedev); - if (mousedev->minor != MOUSEDEV_MIX) - input_unregister_handle(&mousedev->handle); - put_device(&mousedev->dev); -} - -static int mixdev_add_device(struct mousedev *mousedev) -{ - int retval; - - retval = mutex_lock_interruptible(&mousedev_mix->mutex); - if (retval) - return retval; - - if (mousedev_mix->open) { - retval = mousedev_open_device(mousedev); - if (retval) - goto out; - - mousedev->mixdev_open = 1; - } - - get_device(&mousedev->dev); - list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); - - out: - mutex_unlock(&mousedev_mix->mutex); - return retval; -} + struct mousedev_client *client; -static void mixdev_remove_device(struct mousedev *mousedev) -{ - mutex_lock(&mousedev_mix->mutex); + device_del(&mousedev->dev); + mousedev->exist = 0; - if (mousedev->mixdev_open) { - mousedev->mixdev_open = 0; - mousedev_close_device(mousedev); + if (mousedev->open) { + input_close_device(&mousedev->handle); + list_for_each_entry(client, &mousedev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + wake_up_interruptible(&mousedev->wait); } - list_del_init(&mousedev->mixdev_node); - mutex_unlock(&mousedev_mix->mutex); - put_device(&mousedev->dev); } -static int mousedev_connect(struct input_handler *handler, - struct input_dev *dev, +static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct mousedev *mousedev; int minor; int error; - for (minor = 0; minor < MOUSEDEV_MINORS; minor++) - if (!mousedev_table[minor]) - break; - + for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); if (minor == MOUSEDEV_MINORS) { printk(KERN_ERR "mousedev: no more free mousedev devices\n"); return -ENFILE; @@ -976,13 +779,21 @@ static int mousedev_connect(struct input_handler *handler, if (IS_ERR(mousedev)) return PTR_ERR(mousedev); + error = input_register_handle(&mousedev->handle); + if (error) + goto err_delete_mousedev; + error = mixdev_add_device(mousedev); - if (error) { - mousedev_destroy(mousedev); - return error; - } + if (error) + goto err_unregister_handle; return 0; + + err_unregister_handle: + input_unregister_handle(&mousedev->handle); + err_delete_mousedev: + device_unregister(&mousedev->dev); + return error; } static void mousedev_disconnect(struct input_handle *handle) @@ -990,42 +801,33 @@ static void mousedev_disconnect(struct input_handle *handle) struct mousedev *mousedev = handle->private; mixdev_remove_device(mousedev); + input_unregister_handle(handle); mousedev_destroy(mousedev); } static const struct input_device_id mousedev_ids[] = { { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT | - INPUT_DEVICE_ID_MATCH_RELBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, .relbit = { BIT(REL_X) | BIT(REL_Y) }, - }, /* A mouse like device, at least one button, - two relative axes */ + }, /* A mouse like device, at least one button, two relative axes */ { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_RELBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT, .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, .relbit = { BIT(REL_WHEEL) }, }, /* A separate scrollwheel */ { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, - }, /* A tablet like device, at least touch detection, - two absolute axes */ + }, /* A tablet like device, at least touch detection, two absolute axes */ { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT | - INPUT_DEVICE_ID_MATCH_ABSBIT, + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, - .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | - BIT(ABS_TOOL_WIDTH) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) }, }, /* A touchpad */ { }, /* Terminating entry */ diff --git a/trunk/drivers/input/serio/i8042.c b/trunk/drivers/input/serio/i8042.c index 11dafc0ee994..c2eea2767e10 100644 --- a/trunk/drivers/input/serio/i8042.c +++ b/trunk/drivers/input/serio/i8042.c @@ -385,8 +385,6 @@ static int i8042_enable_kbd_port(void) i8042_ctr |= I8042_CTR_KBDINT; if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { - i8042_ctr &= ~I8042_CTR_KBDINT; - i8042_ctr |= I8042_CTR_KBDDIS; printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); return -EIO; } @@ -404,8 +402,6 @@ static int i8042_enable_aux_port(void) i8042_ctr |= I8042_CTR_AUXINT; if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { - i8042_ctr &= ~I8042_CTR_AUXINT; - i8042_ctr |= I8042_CTR_AUXDIS; printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); return -EIO; } diff --git a/trunk/drivers/input/touchscreen/Kconfig b/trunk/drivers/input/touchscreen/Kconfig index e3e0baa1a158..f929fcdbae2e 100644 --- a/trunk/drivers/input/touchscreen/Kconfig +++ b/trunk/drivers/input/touchscreen/Kconfig @@ -126,16 +126,6 @@ config TOUCHSCREEN_HP600 To compile this driver as a module, choose M here: the module will be called hp680_ts_input. -config TOUCHSCREEN_HP7XX - tristate "HP Jornada 710/720/728 touchscreen" - depends on SA1100_JORNADA720_SSP - help - Say Y here if you have a HP Jornada 710/720/728 and want - to support the built-in touchscreen. - - To compile this driver as a module, choose M here: the - module will be called jornada720_ts. - config TOUCHSCREEN_PENMOUNT tristate "Penmount serial touchscreen" select SERIO @@ -201,7 +191,6 @@ config TOUCHSCREEN_USB_COMPOSITE - Gunze AHL61 - DMC TSC-10/25 - IRTOUCHSYSTEMS/UNITOP - - IdealTEK URTC1000 Have a look at for a usage description and the required user-space stuff. @@ -249,14 +238,4 @@ config TOUCHSCREEN_USB_IRTOUCH bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED depends on TOUCHSCREEN_USB_COMPOSITE -config TOUCHSCREEN_USB_IDEALTEK - default y - bool "IdealTEK URTC1000 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_GENERAL_TOUCH - default y - bool "GeneralTouch Touchscreen device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - endif diff --git a/trunk/drivers/input/touchscreen/Makefile b/trunk/drivers/input/touchscreen/Makefile index 35d4097df35a..5de8933c4993 100644 --- a/trunk/drivers/input/touchscreen/Makefile +++ b/trunk/drivers/input/touchscreen/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o diff --git a/trunk/drivers/input/touchscreen/jornada720_ts.c b/trunk/drivers/input/touchscreen/jornada720_ts.c deleted file mode 100644 index 42a1c9a1940e..000000000000 --- a/trunk/drivers/input/touchscreen/jornada720_ts.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * drivers/input/touchscreen/jornada720_ts.c - * - * Copyright (C) 2007 Kristoffer Ericson - * - * Copyright (C) 2006 Filip Zyzniewski - * based on HP Jornada 56x touchscreen driver by Alex Lange - * - * 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. - * - * HP Jornada 710/720/729 Touchscreen Driver - */ - -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Kristoffer Ericson "); -MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); -MODULE_LICENSE("GPLv2"); - -struct jornada_ts { - struct input_dev *dev; - int x_data[4]; /* X sample values */ - int y_data[4]; /* Y sample values */ -}; - -static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts) -{ - - /* 3 low word X samples */ - jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY); - jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY); - jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY); - - /* 3 low word Y samples */ - jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY); - jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY); - jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY); - - /* combined x samples bits */ - jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY); - - /* combined y samples bits */ - jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY); -} - -static int jornada720_ts_average(int coords[4]) -{ - int coord, high_bits = coords[3]; - - coord = coords[0] | ((high_bits & 0x03) << 8); - coord += coords[1] | ((high_bits & 0x0c) << 6); - coord += coords[2] | ((high_bits & 0x30) << 4); - - return coord / 3; -} - -static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) -{ - struct platform_device *pdev = dev_id; - struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); - struct input_dev *input = jornada_ts->dev; - int x, y; - - /* If GPIO_GPIO9 is set to high then report pen up */ - if (GPLR & GPIO_GPIO(9)) { - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - } else { - jornada_ssp_start(); - - /* proper reply to request is always TXDUMMY */ - if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) { - jornada720_ts_collect_data(jornada_ts); - - x = jornada720_ts_average(jornada_ts->x_data); - y = jornada720_ts_average(jornada_ts->y_data); - - input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - input_sync(input); - } - - jornada_ssp_end(); - } - - return IRQ_HANDLED; -} - -static int __devinit jornada720_ts_probe(struct platform_device *pdev) -{ - struct jornada_ts *jornada_ts; - struct input_dev *input_dev; - int error; - - jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - - if (!jornada_ts || !input_dev) { - error = -ENOMEM; - goto fail1; - } - - platform_set_drvdata(pdev, jornada_ts); - - jornada_ts->dev = input_dev; - - input_dev->name = "HP Jornada 7xx Touchscreen"; - input_dev->phys = "jornadats/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); - - error = request_irq(IRQ_GPIO9, - jornada720_ts_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "HP7XX Touchscreen driver", pdev); - if (error) { - printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); - goto fail1; - } - - error = input_register_device(jornada_ts->dev); - if (error) - goto fail2; - - return 0; - - fail2: - free_irq(IRQ_GPIO9, pdev); - fail1: - platform_set_drvdata(pdev, NULL); - input_free_device(input_dev); - kfree(jornada_ts); - return error; -} - -static int __devexit jornada720_ts_remove(struct platform_device *pdev) -{ - struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); - - free_irq(IRQ_GPIO9, pdev); - platform_set_drvdata(pdev, NULL); - input_unregister_device(jornada_ts->dev); - kfree(jornada_ts); - - return 0; -} - -static struct platform_driver jornada720_ts_driver = { - .probe = jornada720_ts_probe, - .remove = __devexit_p(jornada720_ts_remove), - .driver = { - .name = "jornada_ts", - }, -}; - -static int __init jornada720_ts_init(void) -{ - return platform_driver_register(&jornada720_ts_driver); -} - -static void __exit jornada720_ts_exit(void) -{ - platform_driver_unregister(&jornada720_ts_driver); -} - -module_init(jornada720_ts_init); -module_exit(jornada720_ts_exit); diff --git a/trunk/drivers/input/touchscreen/ucb1400_ts.c b/trunk/drivers/input/touchscreen/ucb1400_ts.c index 86aed64ec0fb..36f944019158 100644 --- a/trunk/drivers/input/touchscreen/ucb1400_ts.c +++ b/trunk/drivers/input/touchscreen/ucb1400_ts.c @@ -130,7 +130,8 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel) if (val & UCB_ADC_DAT_VALID) break; /* yield to other processes */ - schedule_timeout_uninterruptible(1); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); } return UCB_ADC_DAT_VALUE(val); diff --git a/trunk/drivers/input/touchscreen/usbtouchscreen.c b/trunk/drivers/input/touchscreen/usbtouchscreen.c index 9fb3d5c30999..741f6c6f1e50 100644 --- a/trunk/drivers/input/touchscreen/usbtouchscreen.c +++ b/trunk/drivers/input/touchscreen/usbtouchscreen.c @@ -10,7 +10,6 @@ * - Gunze AHL61 * - DMC TSC-10/25 * - IRTOUCHSYSTEMS/UNITOP - * - IdealTEK URTC1000 * * Copyright (C) 2004-2006 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) @@ -93,7 +92,7 @@ struct usbtouch_usb { }; -#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK) +#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) #define MULTI_PACKET #endif @@ -113,8 +112,6 @@ enum { DEVTYPE_GUNZE, DEVTYPE_DMC_TSC10, DEVTYPE_IRTOUCH, - DEVTYPE_IDEALTEK, - DEVTYPE_GENERAL_TOUCH, }; static struct usb_device_id usbtouch_devices[] = { @@ -160,14 +157,6 @@ static struct usb_device_id usbtouch_devices[] = { {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, #endif -#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK - {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH - {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, -#endif - {} }; @@ -407,8 +396,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); if (ret < 0) return ret; - if ((buf[0] != 0x06 || buf[1] != 0x00) && - (buf[0] != 0x15 || buf[1] != 0x01)) + if (buf[0] != 0x06 || buf[1] != 0x00) return -ENODEV; /* start sending data */ @@ -449,57 +437,6 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) #endif -/***************************************************************************** - * IdealTEK URTC1000 Part - */ -#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK -static int idealtek_get_pkt_len(unsigned char *buf, int len) -{ - if (buf[0] & 0x80) - return 5; - if (buf[0] == 0x01) - return len; - return 0; -} - -static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - switch (pkt[0] & 0x98) { - case 0x88: - /* touch data in IdealTEK mode */ - dev->x = (pkt[1] << 5) | (pkt[2] >> 2); - dev->y = (pkt[3] << 5) | (pkt[4] >> 2); - dev->touch = (pkt[0] & 0x40) ? 1 : 0; - return 1; - - case 0x98: - /* touch data in MT emulation mode */ - dev->x = (pkt[2] << 5) | (pkt[1] >> 2); - dev->y = (pkt[4] << 5) | (pkt[3] >> 2); - dev->touch = (pkt[0] & 0x40) ? 1 : 0; - return 1; - - default: - return 0; - } -} -#endif - -/***************************************************************************** - * General Touch Part - */ -#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH -static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; - dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; - dev->press = pkt[5] & 0xff; - dev->touch = pkt[0] & 0x01; - - return 1; -} -#endif - /***************************************************************************** * the different device descriptors */ @@ -600,32 +537,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .read_data = irtouch_read_data, }, #endif - -#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK - [DEVTYPE_IDEALTEK] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 8, - .flags = USBTOUCH_FLG_BUFFER, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = idealtek_get_pkt_len, - .read_data = idealtek_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH - [DEVTYPE_GENERAL_TOUCH] = { - .min_xc = 0x0, - .max_xc = 0x0500, - .min_yc = 0x0, - .max_yc = 0x0500, - .rept_size = 7, - .read_data = general_touch_read_data, - } -#endif - }; diff --git a/trunk/drivers/input/tsdev.c b/trunk/drivers/input/tsdev.c new file mode 100644 index 000000000000..d2f882e98e5e --- /dev/null +++ b/trunk/drivers/input/tsdev.c @@ -0,0 +1,533 @@ +/* + * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $ + * + * Copyright (c) 2001 "Crazy" james Simmons + * + * Compaq touchscreen protocol driver. The protocol emulated by this driver + * is obsolete; for new programs use the tslib library which can read directly + * from evdev and perform dejittering, variance filtering and calibration - + * all in user space, not at kernel level. The meaning of this driver is + * to allow usage of newer input drivers with old applications that use the + * old /dev/h3600_ts and /dev/h3600_tsraw devices. + * + * 09-Apr-2004: Andrew Zabolotny + * Fixed to actually work, not just output random numbers. + * Added support for both h3600_ts and h3600_tsraw protocol + * emulation. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to . + */ + +#define TSDEV_MINOR_BASE 128 +#define TSDEV_MINORS 32 +/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ +#define TSDEV_MINOR_MASK 15 +#define TSDEV_BUFFER_SIZE 64 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_INPUT_TSDEV_SCREEN_X +#define CONFIG_INPUT_TSDEV_SCREEN_X 240 +#endif +#ifndef CONFIG_INPUT_TSDEV_SCREEN_Y +#define CONFIG_INPUT_TSDEV_SCREEN_Y 320 +#endif + +/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw + * devices. The first one must output X/Y data in 'cooked' format, e.g. + * filtered, dejittered and calibrated. Second device just outputs raw + * data received from the hardware. + * + * This driver doesn't support filtering and dejittering; it supports only + * calibration. Filtering and dejittering must be done in the low-level + * driver, if needed, because it may gain additional benefits from knowing + * the low-level details, the nature of noise and so on. + * + * The driver precomputes a calibration matrix given the initial xres and + * yres values (quite innacurate for most touchscreens) that will result + * in a more or less expected range of output values. The driver supports + * the TS_SET_CAL ioctl, which will replace the calibration matrix with a + * new one, supposedly generated from the values taken from the raw device. + */ + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Input driver to touchscreen converter"); +MODULE_LICENSE("GPL"); + +static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; +module_param(xres, uint, 0); +MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); + +static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; +module_param(yres, uint, 0); +MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); + +/* From Compaq's Touch Screen Specification version 0.2 (draft) */ +struct ts_event { + short pressure; + short x; + short y; + short millisecs; +}; + +struct ts_calibration { + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; + +struct tsdev { + int exist; + int open; + int minor; + char name[8]; + struct input_handle handle; + wait_queue_head_t wait; + struct list_head client_list; + struct device dev; + + int x, y, pressure; + struct ts_calibration cal; +}; + +struct tsdev_client { + struct fasync_struct *fasync; + struct list_head node; + struct tsdev *tsdev; + int head, tail; + struct ts_event event[TSDEV_BUFFER_SIZE]; + int raw; +}; + +/* The following ioctl codes are defined ONLY for backward compatibility. + * Don't use tsdev for new developement; use the tslib library instead. + * Touchscreen calibration is a fully userspace task. + */ +/* Use 'f' as magic number */ +#define IOC_H3600_TS_MAGIC 'f' +#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) +#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) + +static struct tsdev *tsdev_table[TSDEV_MINORS/2]; + +static int tsdev_fasync(int fd, struct file *file, int on) +{ + struct tsdev_client *client = file->private_data; + int retval; + + retval = fasync_helper(fd, file, on, &client->fasync); + return retval < 0 ? retval : 0; +} + +static int tsdev_open(struct inode *inode, struct file *file) +{ + int i = iminor(inode) - TSDEV_MINOR_BASE; + struct tsdev_client *client; + struct tsdev *tsdev; + int error; + + printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " + "for removal.\nSee Documentation/feature-removal-schedule.txt " + "for details.\n"); + + if (i >= TSDEV_MINORS) + return -ENODEV; + + tsdev = tsdev_table[i & TSDEV_MINOR_MASK]; + if (!tsdev || !tsdev->exist) + return -ENODEV; + + get_device(&tsdev->dev); + + client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); + if (!client) { + error = -ENOMEM; + goto err_put_tsdev; + } + + client->tsdev = tsdev; + client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; + list_add_tail(&client->node, &tsdev->client_list); + + if (!tsdev->open++ && tsdev->exist) { + error = input_open_device(&tsdev->handle); + if (error) + goto err_free_client; + } + + file->private_data = client; + return 0; + + err_free_client: + list_del(&client->node); + kfree(client); + err_put_tsdev: + put_device(&tsdev->dev); + return error; +} + +static void tsdev_free(struct device *dev) +{ + struct tsdev *tsdev = container_of(dev, struct tsdev, dev); + + tsdev_table[tsdev->minor] = NULL; + kfree(tsdev); +} + +static int tsdev_release(struct inode *inode, struct file *file) +{ + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; + + tsdev_fasync(-1, file, 0); + + list_del(&client->node); + kfree(client); + + if (!--tsdev->open && tsdev->exist) + input_close_device(&tsdev->handle); + + put_device(&tsdev->dev); + + return 0; +} + +static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, + loff_t *ppos) +{ + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; + int retval = 0; + + if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK)) + return -EAGAIN; + + retval = wait_event_interruptible(tsdev->wait, + client->head != client->tail || !tsdev->exist); + if (retval) + return retval; + + if (!tsdev->exist) + return -ENODEV; + + while (client->head != client->tail && + retval + sizeof (struct ts_event) <= count) { + if (copy_to_user (buffer + retval, client->event + client->tail, + sizeof (struct ts_event))) + return -EFAULT; + client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1); + retval += sizeof (struct ts_event); + } + + return retval; +} + +/* No kernel lock - fine */ +static unsigned int tsdev_poll(struct file *file, poll_table *wait) +{ + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; + + poll_wait(file, &tsdev->wait, wait); + return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | + (tsdev->exist ? 0 : (POLLHUP | POLLERR)); +} + +static int tsdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct tsdev_client *client = file->private_data; + struct tsdev *tsdev = client->tsdev; + int retval = 0; + + switch (cmd) { + case TS_GET_CAL: + if (copy_to_user((void __user *)arg, &tsdev->cal, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + + case TS_SET_CAL: + if (copy_from_user(&tsdev->cal, (void __user *)arg, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + + default: + retval = -EINVAL; + break; + } + + return retval; +} + +static const struct file_operations tsdev_fops = { + .owner = THIS_MODULE, + .open = tsdev_open, + .release = tsdev_release, + .read = tsdev_read, + .poll = tsdev_poll, + .fasync = tsdev_fasync, + .ioctl = tsdev_ioctl, +}; + +static void tsdev_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + struct tsdev *tsdev = handle->private; + struct tsdev_client *client; + struct timeval time; + + switch (type) { + case EV_ABS: + switch (code) { + case ABS_X: + tsdev->x = value; + break; + + case ABS_Y: + tsdev->y = value; + break; + + case ABS_PRESSURE: + if (value > handle->dev->absmax[ABS_PRESSURE]) + value = handle->dev->absmax[ABS_PRESSURE]; + value -= handle->dev->absmin[ABS_PRESSURE]; + if (value < 0) + value = 0; + tsdev->pressure = value; + break; + } + break; + + case EV_REL: + switch (code) { + case REL_X: + tsdev->x += value; + if (tsdev->x < 0) + tsdev->x = 0; + else if (tsdev->x > xres) + tsdev->x = xres; + break; + + case REL_Y: + tsdev->y += value; + if (tsdev->y < 0) + tsdev->y = 0; + else if (tsdev->y > yres) + tsdev->y = yres; + break; + } + break; + + case EV_KEY: + if (code == BTN_TOUCH || code == BTN_MOUSE) { + switch (value) { + case 0: + tsdev->pressure = 0; + break; + + case 1: + if (!tsdev->pressure) + tsdev->pressure = 1; + break; + } + } + break; + } + + if (type != EV_SYN || code != SYN_REPORT) + return; + + list_for_each_entry(client, &tsdev->client_list, node) { + int x, y, tmp; + + do_gettimeofday(&time); + client->event[client->head].millisecs = time.tv_usec / 1000; + client->event[client->head].pressure = tsdev->pressure; + + x = tsdev->x; + y = tsdev->y; + + /* Calibration */ + if (!client->raw) { + x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; + y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; + if (tsdev->cal.xyswap) { + tmp = x; x = y; y = tmp; + } + } + + client->event[client->head].x = x; + client->event[client->head].y = y; + client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1); + kill_fasync(&client->fasync, SIGIO, POLL_IN); + } + wake_up_interruptible(&tsdev->wait); +} + +static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) +{ + struct tsdev *tsdev; + int minor, delta; + int error; + + for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); + if (minor >= TSDEV_MINORS / 2) { + printk(KERN_ERR + "tsdev: You have way too many touchscreens\n"); + return -ENFILE; + } + + tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL); + if (!tsdev) + return -ENOMEM; + + INIT_LIST_HEAD(&tsdev->client_list); + init_waitqueue_head(&tsdev->wait); + + tsdev->exist = 1; + tsdev->minor = minor; + tsdev->handle.dev = dev; + tsdev->handle.name = tsdev->name; + tsdev->handle.handler = handler; + tsdev->handle.private = tsdev; + snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor); + + /* Precompute the rough calibration matrix */ + delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.xscale = (xres << 8) / delta; + tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); + + delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.yscale = (yres << 8) / delta; + tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); + + snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id), + "ts%d", minor); + tsdev->dev.class = &input_class; + tsdev->dev.parent = &dev->dev; + tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor); + tsdev->dev.release = tsdev_free; + device_initialize(&tsdev->dev); + + tsdev_table[minor] = tsdev; + + error = device_add(&tsdev->dev); + if (error) + goto err_free_tsdev; + + error = input_register_handle(&tsdev->handle); + if (error) + goto err_delete_tsdev; + + return 0; + + err_delete_tsdev: + device_del(&tsdev->dev); + err_free_tsdev: + put_device(&tsdev->dev); + return error; +} + +static void tsdev_disconnect(struct input_handle *handle) +{ + struct tsdev *tsdev = handle->private; + struct tsdev_client *client; + + input_unregister_handle(handle); + device_del(&tsdev->dev); + + tsdev->exist = 0; + + if (tsdev->open) { + input_close_device(handle); + list_for_each_entry(client, &tsdev->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + wake_up_interruptible(&tsdev->wait); + } + + put_device(&tsdev->dev); +} + +static const struct input_device_id tsdev_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, + .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, + .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, + .relbit = { BIT(REL_X) | BIT(REL_Y) }, + }, /* A mouse like device, at least one button, two relative axes */ + + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, + .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, + }, /* A tablet like device, at least touch detection, two absolute axes */ + + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, + }, /* A tablet like device with several gradations of pressure */ + + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(input, tsdev_ids); + +static struct input_handler tsdev_handler = { + .event = tsdev_event, + .connect = tsdev_connect, + .disconnect = tsdev_disconnect, + .fops = &tsdev_fops, + .minor = TSDEV_MINOR_BASE, + .name = "tsdev", + .id_table = tsdev_ids, +}; + +static int __init tsdev_init(void) +{ + return input_register_handler(&tsdev_handler); +} + +static void __exit tsdev_exit(void) +{ + input_unregister_handler(&tsdev_handler); +} + +module_init(tsdev_init); +module_exit(tsdev_exit); diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig index 77f50b63a970..56cd8998fe4b 100644 --- a/trunk/drivers/macintosh/Kconfig +++ b/trunk/drivers/macintosh/Kconfig @@ -172,7 +172,6 @@ config INPUT_ADBHID config MAC_EMUMOUSEBTN bool "Support for mouse button 2+3 emulation" - select INPUT help This provides generic support for emulating the 2nd and 3rd mouse button with keypresses. If you say Y here, the emulation is still diff --git a/trunk/drivers/macintosh/adbhid.c b/trunk/drivers/macintosh/adbhid.c index 8cce016b3d09..48d17bf6c927 100644 --- a/trunk/drivers/macintosh/adbhid.c +++ b/trunk/drivers/macintosh/adbhid.c @@ -52,11 +52,6 @@ MODULE_AUTHOR("Franz Sirl "); -static int restore_capslock_events; -module_param(restore_capslock_events, int, 0644); -MODULE_PARM_DESC(restore_capslock_events, - "Produce keypress events for capslock on both keyup and keydown."); - #define KEYB_KEYREG 0 /* register # for key up/down data */ #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ @@ -222,8 +217,6 @@ struct adbhid { #define FLAG_FN_KEY_PRESSED 0x00000001 #define FLAG_POWER_FROM_FN 0x00000002 #define FLAG_EMU_FWDEL_DOWN 0x00000004 -#define FLAG_CAPSLOCK_TRANSLATE 0x00000008 -#define FLAG_CAPSLOCK_DOWN 0x00000010 static struct adbhid *adbhid[16]; @@ -279,50 +272,19 @@ adbhid_keyboard_input(unsigned char *data, int nb, int apoll) } static void -adbhid_input_keycode(int id, int scancode, int repeat) +adbhid_input_keycode(int id, int keycode, int repeat) { struct adbhid *ahid = adbhid[id]; - int keycode, up_flag; - - keycode = scancode & 0x7f; - up_flag = scancode & 0x80; - - if (restore_capslock_events) { - if (keycode == ADB_KEY_CAPSLOCK && !up_flag) { - /* Key pressed, turning on the CapsLock LED. - * The next 0xff will be interpreted as a release. */ - ahid->flags |= FLAG_CAPSLOCK_TRANSLATE - | FLAG_CAPSLOCK_DOWN; - } else if (scancode == 0xff) { - /* Scancode 0xff usually signifies that the capslock - * key was either pressed or released. */ - if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) { - keycode = ADB_KEY_CAPSLOCK; - if (ahid->flags & FLAG_CAPSLOCK_DOWN) { - /* Key released */ - up_flag = 1; - ahid->flags &= ~FLAG_CAPSLOCK_DOWN; - } else { - /* Key pressed */ - up_flag = 0; - ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE; - } - } else { - printk(KERN_INFO "Spurious caps lock event " - "(scancode 0xff)."); - } - } - } + int up_flag, key; + + up_flag = (keycode & 0x80); + keycode &= 0x7f; switch (keycode) { - case ADB_KEY_CAPSLOCK: - if (!restore_capslock_events) { - /* Generate down/up events for CapsLock everytime. */ - input_report_key(ahid->input, KEY_CAPSLOCK, 1); - input_sync(ahid->input); - input_report_key(ahid->input, KEY_CAPSLOCK, 0); - input_sync(ahid->input); - } + case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */ + input_report_key(ahid->input, KEY_CAPSLOCK, 1); + input_report_key(ahid->input, KEY_CAPSLOCK, 0); + input_sync(ahid->input); return; #ifdef CONFIG_PPC_PMAC case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ @@ -334,7 +296,7 @@ adbhid_input_keycode(int id, int scancode, int repeat) keycode = ADB_KEY_POWER; } break; - case ADB_KEY_POWER: + case ADB_KEY_POWER: /* Fn + Command will produce a bogus "power" keycode */ if (ahid->flags & FLAG_FN_KEY_PRESSED) { keycode = ADB_KEY_CMD; diff --git a/trunk/drivers/misc/thinkpad_acpi.c b/trunk/drivers/misc/thinkpad_acpi.c index 81e068fa7ac5..216948dd71a5 100644 --- a/trunk/drivers/misc/thinkpad_acpi.c +++ b/trunk/drivers/misc/thinkpad_acpi.c @@ -945,15 +945,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ - KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -974,9 +974,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, diff --git a/trunk/drivers/mtd/maps/pxa2xx-flash.c b/trunk/drivers/mtd/maps/pxa2xx-flash.c index 82113295c266..cb933ac475d5 100644 --- a/trunk/drivers/mtd/maps/pxa2xx-flash.c +++ b/trunk/drivers/mtd/maps/pxa2xx-flash.c @@ -14,20 +14,20 @@ #include #include #include +#include #include #include #include #include #include -#include #include static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len) { - flush_ioremap_region(map->phys, map->cached, from, len); + consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); } struct pxa2xx_flash_info { diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 8f99a0626616..9c635a237a9d 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1780,15 +1780,6 @@ config SC92031 To compile this driver as a module, choose M here: the module will be called sc92031. This is recommended. -config CPMAC - tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" - depends on NET_ETHERNET && EXPERIMENTAL && AR7 - select PHYLIB - select FIXED_PHY - select FIXED_MII_100_FDX - help - TI AR7 CPMAC Ethernet support - config NET_POCKET bool "Pocket and portable adapters" depends on PARPORT diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index 22f78cbd126b..d2e0f35da42e 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -159,7 +159,6 @@ obj-$(CONFIG_8139CP) += 8139cp.o obj-$(CONFIG_8139TOO) += 8139too.o obj-$(CONFIG_ZNET) += znet.o obj-$(CONFIG_LAN_SAA9730) += saa9730.o -obj-$(CONFIG_CPMAC) += cpmac.o obj-$(CONFIG_DEPCA) += depca.o obj-$(CONFIG_EWRK3) += ewrk3.o obj-$(CONFIG_ATP) += atp.o diff --git a/trunk/drivers/net/au1000_eth.c b/trunk/drivers/net/au1000_eth.c index 185f98e3964c..b46c5d8a77bd 100644 --- a/trunk/drivers/net/au1000_eth.c +++ b/trunk/drivers/net/au1000_eth.c @@ -54,16 +54,13 @@ #include #include #include - -#include #include #include #include #include -#include -#include - +#include +#include #include "au1000_eth.h" #ifdef AU1000_ETH_DEBUG @@ -99,6 +96,11 @@ static void mdio_write(struct net_device *, int, int, u16); static void au1000_adjust_link(struct net_device *); static void enable_mac(struct net_device *, int); +// externs +extern int get_ethernet_addr(char *ethernet_addr); +extern void str2eaddr(unsigned char *ea, unsigned char *str); +extern char * prom_getcmdline(void); + /* * Theory of operation * @@ -617,6 +619,7 @@ static struct net_device * au1000_probe(int port_num) struct au1000_private *aup = NULL; struct net_device *dev = NULL; db_dest_t *pDB, *pDBfree; + char *pmac, *argptr; char ethaddr[6]; int irq, i, err; u32 base, macen; @@ -674,12 +677,21 @@ static struct net_device * au1000_probe(int port_num) au_macs[port_num] = aup; if (port_num == 0) { - if (prom_get_ethernet_addr(ethaddr) == 0) + /* Check the environment variables first */ + if (get_ethernet_addr(ethaddr) == 0) memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); else { - printk(KERN_INFO "%s: No MAC address found\n", - dev->name); + /* Check command line */ + argptr = prom_getcmdline(); + if ((pmac = strstr(argptr, "ethaddr=")) == NULL) + printk(KERN_INFO "%s: No MAC address found\n", + dev->name); /* Use the hard coded MAC addresses */ + else { + str2eaddr(ethaddr, pmac + strlen("ethaddr=")); + memcpy(au1000_mac_addr, ethaddr, + sizeof(au1000_mac_addr)); + } } setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index db80f243dd37..64bfec32e2a6 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -98,7 +98,6 @@ static char *xmit_hash_policy = NULL; static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; static char *arp_validate = NULL; -static int fail_over_mac = 0; struct bond_params bonding_defaults; module_param(max_bonds, int, 0); @@ -132,8 +131,6 @@ module_param_array(arp_ip_target, charp, NULL, 0); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); module_param(arp_validate, charp, 0); MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); -module_param(fail_over_mac, int, 0); -MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. 0 of off (default), 1 for on."); /*----------------------------- Global variables ----------------------------*/ @@ -1099,21 +1096,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if (new_active) { bond_set_slave_active_flags(new_active); } - - /* when bonding does not set the slave MAC address, the bond MAC - * address is the one of the active slave. - */ - if (new_active && bond->params.fail_over_mac) - memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, - new_active->dev->addr_len); - if (bond->curr_active_slave && - test_bit(__LINK_STATE_LINKWATCH_PENDING, - &bond->curr_active_slave->dev->state)) { - dprintk("delaying gratuitous arp on %s\n", - bond->curr_active_slave->dev->name); - bond->send_grat_arp = 1; - } else - bond_send_gratuitous_arp(bond); + bond_send_gratuitous_arp(bond); } } @@ -1234,8 +1217,7 @@ static int bond_compute_features(struct bonding *bond) struct slave *slave; struct net_device *bond_dev = bond->dev; unsigned long features = bond_dev->features; - unsigned short max_hard_header_len = max((u16)ETH_HLEN, - bond_dev->hard_header_len); + unsigned short max_hard_header_len = ETH_HLEN; int i; features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); @@ -1256,23 +1238,6 @@ static int bond_compute_features(struct bonding *bond) return 0; } - -static void bond_setup_by_slave(struct net_device *bond_dev, - struct net_device *slave_dev) -{ - struct bonding *bond = bond_dev->priv; - - bond_dev->neigh_setup = slave_dev->neigh_setup; - - bond_dev->type = slave_dev->type; - bond_dev->hard_header_len = slave_dev->hard_header_len; - bond_dev->addr_len = slave_dev->addr_len; - - memcpy(bond_dev->broadcast, slave_dev->broadcast, - slave_dev->addr_len); - bond->setup_by_slave = 1; -} - /* enslave device to bond device */ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) { @@ -1293,9 +1258,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* bond must be initialized by bond_open() before enslaving */ if (!(bond_dev->flags & IFF_UP)) { - printk(KERN_WARNING DRV_NAME - " %s: master_dev is not up in bond_enslave\n", - bond_dev->name); + dprintk("Error, master_dev is not up\n"); + return -EPERM; } /* already enslaved */ @@ -1348,42 +1312,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } - /* set bonding device ether type by slave - bonding netdevices are - * created with ether_setup, so when the slave type is not ARPHRD_ETHER - * there is a need to override some of the type dependent attribs/funcs. - * - * bond ether type mutual exclusion - don't allow slaves of dissimilar - * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond - */ - if (bond->slave_cnt == 0) { - if (slave_dev->type != ARPHRD_ETHER) - bond_setup_by_slave(bond_dev, slave_dev); - } else if (bond_dev->type != slave_dev->type) { - printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different " - "from other slaves (%d), can not enslave it.\n", - slave_dev->name, - slave_dev->type, bond_dev->type); - res = -EINVAL; - goto err_undo_flags; - } - if (slave_dev->set_mac_address == NULL) { - if (bond->slave_cnt == 0) { - printk(KERN_WARNING DRV_NAME - ": %s: Warning: The first slave device " - "specified does not support setting the MAC " - "address. Enabling the fail_over_mac option.", - bond_dev->name); - bond->params.fail_over_mac = 1; - } else if (!bond->params.fail_over_mac) { - printk(KERN_ERR DRV_NAME - ": %s: Error: The slave device specified " - "does not support setting the MAC address, " - "but fail_over_mac is not enabled.\n" - , bond_dev->name); - res = -EOPNOTSUPP; - goto err_undo_flags; - } + printk(KERN_ERR DRV_NAME + ": %s: Error: The slave device you specified does " + "not support setting the MAC address. " + "Your kernel likely does not support slave " + "devices.\n", bond_dev->name); + res = -EOPNOTSUPP; + goto err_undo_flags; } new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); @@ -1404,18 +1340,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) */ memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); - if (!bond->params.fail_over_mac) { - /* - * Set slave to master's mac address. The application already - * set the master's mac address to that of the first slave - */ - memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); - addr.sa_family = slave_dev->type; - res = dev_set_mac_address(slave_dev, &addr); - if (res) { - dprintk("Error %d calling set_mac_address\n", res); - goto err_free; - } + /* + * Set slave to master's mac address. The application already + * set the master's mac address to that of the first slave + */ + memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); + addr.sa_family = slave_dev->type; + res = dev_set_mac_address(slave_dev, &addr); + if (res) { + dprintk("Error %d calling set_mac_address\n", res); + goto err_free; } res = netdev_set_master(slave_dev, bond_dev); @@ -1640,11 +1574,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) dev_close(slave_dev); err_restore_mac: - if (!bond->params.fail_over_mac) { - memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); - addr.sa_family = slave_dev->type; - dev_set_mac_address(slave_dev, &addr); - } + memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); + addr.sa_family = slave_dev->type; + dev_set_mac_address(slave_dev, &addr); err_free: kfree(new_slave); @@ -1817,12 +1749,10 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) /* close slave before restoring its mac address */ dev_close(slave_dev); - if (!bond->params.fail_over_mac) { - /* restore original ("permanent") mac address */ - memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); - addr.sa_family = slave_dev->type; - dev_set_mac_address(slave_dev, &addr); - } + /* restore original ("permanent") mac address */ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); + addr.sa_family = slave_dev->type; + dev_set_mac_address(slave_dev, &addr); slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | IFF_SLAVE_INACTIVE | IFF_BONDING | @@ -1833,35 +1763,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) return 0; /* deletion OK */ } -/* -* Destroy a bonding device. -* Must be under rtnl_lock when this function is called. -*/ -void bond_destroy(struct bonding *bond) -{ - bond_deinit(bond->dev); - bond_destroy_sysfs_entry(bond); - unregister_netdevice(bond->dev); -} - -/* -* First release a slave and than destroy the bond if no more slaves iare left. -* Must be under rtnl_lock when this function is called. -*/ -int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev) -{ - struct bonding *bond = bond_dev->priv; - int ret; - - ret = bond_release(bond_dev, slave_dev); - if ((ret == 0) && (bond->slave_cnt == 0)) { - printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n", - bond_dev->name, bond_dev->name); - bond_destroy(bond); - } - return ret; -} - /* * This function releases all slaves. */ @@ -1938,12 +1839,10 @@ static int bond_release_all(struct net_device *bond_dev) /* close slave before restoring its mac address */ dev_close(slave_dev); - if (!bond->params.fail_over_mac) { - /* restore original ("permanent") mac address*/ - memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); - addr.sa_family = slave_dev->type; - dev_set_mac_address(slave_dev, &addr); - } + /* restore original ("permanent") mac address*/ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); + addr.sa_family = slave_dev->type; + dev_set_mac_address(slave_dev, &addr); slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | IFF_SLAVE_INACTIVE); @@ -2114,17 +2013,6 @@ void bond_mii_monitor(struct net_device *bond_dev) * program could monitor the link itself if needed. */ - if (bond->send_grat_arp) { - if (bond->curr_active_slave && test_bit(__LINK_STATE_LINKWATCH_PENDING, - &bond->curr_active_slave->dev->state)) - dprintk("Needs to send gratuitous arp but not yet\n"); - else { - dprintk("sending delayed gratuitous arp on on %s\n", - bond->curr_active_slave->dev->name); - bond_send_gratuitous_arp(bond); - bond->send_grat_arp = 0; - } - } read_lock(&bond->curr_slave_lock); oldcurrent = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); @@ -2526,7 +2414,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond) if (bond->master_ip) { bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, - bond->master_ip, 0); + bond->master_ip, 0); } list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { @@ -3063,15 +2951,9 @@ static void bond_info_show_master(struct seq_file *seq) curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); - seq_printf(seq, "Bonding Mode: %s", + seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name(bond->params.mode)); - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP && - bond->params.fail_over_mac) - seq_printf(seq, " (fail_over_mac)"); - - seq_printf(seq, "\n"); - if (bond->params.mode == BOND_MODE_XOR || bond->params.mode == BOND_MODE_8023AD) { seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", @@ -3366,11 +3248,6 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave * ... Or is it this? */ break; - case NETDEV_GOING_DOWN: - dprintk("slave %s is going down\n", slave_dev->name); - if (bond->setup_by_slave) - bond_release_and_destroy(bond_dev, slave_dev); - break; case NETDEV_CHANGEMTU: /* * TODO: Should slaves be allowed to @@ -4003,13 +3880,6 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); - /* - * If fail_over_mac is enabled, do nothing and return success. - * Returning an error causes ifenslave to fail. - */ - if (bond->params.fail_over_mac) - return 0; - if (!is_valid_ether_addr(sa->sa_data)) { return -EADDRNOTAVAIL; } @@ -4347,8 +4217,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond->current_arp_slave = NULL; bond->primary_slave = NULL; bond->dev = bond_dev; - bond->send_grat_arp = 0; - bond->setup_by_slave = 0; INIT_LIST_HEAD(&bond->vlan_list); /* Initialize the device entry points */ @@ -4397,6 +4265,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) #ifdef CONFIG_PROC_FS bond_create_proc_entry(bond); #endif + list_add_tail(&bond->bond_list, &bond_dev_list); return 0; @@ -4730,11 +4599,6 @@ static int bond_check_params(struct bond_params *params) primary = NULL; } - if (fail_over_mac && (bond_mode != BOND_MODE_ACTIVEBACKUP)) - printk(KERN_WARNING DRV_NAME - ": Warning: fail_over_mac only affects " - "active-backup mode.\n"); - /* fill params struct with the proper values */ params->mode = bond_mode; params->xmit_policy = xmit_hashtype; @@ -4746,7 +4610,6 @@ static int bond_check_params(struct bond_params *params) params->use_carrier = use_carrier; params->lacp_fast = lacp_fast; params->primary[0] = 0; - params->fail_over_mac = fail_over_mac; if (primary) { strncpy(params->primary, primary, IFNAMSIZ); diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 80c0c8c415ed..6f49ca7e9b66 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -164,7 +164,9 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t printk(KERN_INFO DRV_NAME ": %s is being deleted...\n", bond->dev->name); - bond_destroy(bond); + bond_deinit(bond->dev); + bond_destroy_sysfs_entry(bond); + unregister_netdevice(bond->dev); rtnl_unlock(); goto out; } @@ -258,16 +260,17 @@ static ssize_t bonding_store_slaves(struct device *d, char command[IFNAMSIZ + 1] = { 0, }; char *ifname; int i, res, found, ret = count; - u32 original_mtu; struct slave *slave; struct net_device *dev = NULL; struct bonding *bond = to_bond(d); /* Quick sanity check -- is the bond interface up? */ if (!(bond->dev->flags & IFF_UP)) { - printk(KERN_WARNING DRV_NAME - ": %s: doing slave updates when interface is down.\n", + printk(KERN_ERR DRV_NAME + ": %s: Unable to update slaves because interface is down.\n", bond->dev->name); + ret = -EPERM; + goto out; } /* Note: We can't hold bond->lock here, as bond_create grabs it. */ @@ -324,7 +327,6 @@ static ssize_t bonding_store_slaves(struct device *d, } /* Set the slave's MTU to match the bond */ - original_mtu = dev->mtu; if (dev->mtu != bond->dev->mtu) { if (dev->change_mtu) { res = dev->change_mtu(dev, @@ -339,9 +341,6 @@ static ssize_t bonding_store_slaves(struct device *d, } rtnl_lock(); res = bond_enslave(bond->dev, dev); - bond_for_each_slave(bond, slave, i) - if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) - slave->original_mtu = original_mtu; rtnl_unlock(); if (res) { ret = res; @@ -354,17 +353,13 @@ static ssize_t bonding_store_slaves(struct device *d, bond_for_each_slave(bond, slave, i) if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { dev = slave->dev; - original_mtu = slave->original_mtu; break; } if (dev) { printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", bond->dev->name, dev->name); rtnl_lock(); - if (bond->setup_by_slave) - res = bond_release_and_destroy(bond->dev, dev); - else - res = bond_release(bond->dev, dev); + res = bond_release(bond->dev, dev); rtnl_unlock(); if (res) { ret = res; @@ -372,9 +367,9 @@ static ssize_t bonding_store_slaves(struct device *d, } /* set the slave MTU to the default */ if (dev->change_mtu) { - dev->change_mtu(dev, original_mtu); + dev->change_mtu(dev, 1500); } else { - dev->mtu = original_mtu; + dev->mtu = 1500; } } else { @@ -567,54 +562,6 @@ static ssize_t bonding_store_arp_validate(struct device *d, static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); -/* - * Show and store fail_over_mac. User only allowed to change the - * value when there are no slaves. - */ -static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf) -{ - struct bonding *bond = to_bond(d); - - return sprintf(buf, "%d\n", bond->params.fail_over_mac) + 1; -} - -static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count) -{ - int new_value; - int ret = count; - struct bonding *bond = to_bond(d); - - if (bond->slave_cnt != 0) { - printk(KERN_ERR DRV_NAME - ": %s: Can't alter fail_over_mac with slaves in bond.\n", - bond->dev->name); - ret = -EPERM; - goto out; - } - - if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME - ": %s: no fail_over_mac value specified.\n", - bond->dev->name); - ret = -EINVAL; - goto out; - } - - if ((new_value == 0) || (new_value == 1)) { - bond->params.fail_over_mac = new_value; - printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %d.\n", - bond->dev->name, new_value); - } else { - printk(KERN_INFO DRV_NAME - ": %s: Ignoring invalid fail_over_mac value %d.\n", - bond->dev->name, new_value); - } -out: - return ret; -} - -static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac); - /* * Show and set the arp timer interval. There are two tricky bits * here. First, if ARP monitoring is activated, then we must disable @@ -1436,7 +1383,6 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); static struct attribute *per_bond_attrs[] = { &dev_attr_slaves.attr, &dev_attr_mode.attr, - &dev_attr_fail_over_mac.attr, &dev_attr_arp_validate.attr, &dev_attr_arp_interval.attr, &dev_attr_arp_ip_target.attr, diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index a8bbd563265c..2a6af7d23728 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.0" -#define DRV_RELDATE "September 13, 2007" +#define DRV_VERSION "3.1.3" +#define DRV_RELDATE "June 13, 2007" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -128,7 +128,6 @@ struct bond_params { int arp_interval; int arp_validate; int use_carrier; - int fail_over_mac; int updelay; int downdelay; int lacp_fast; @@ -157,7 +156,6 @@ struct slave { s8 link; /* one of BOND_LINK_XXXX */ s8 state; /* one of BOND_STATE_XXXX */ u32 original_flags; - u32 original_mtu; u32 link_failure_count; u16 speed; u8 duplex; @@ -187,8 +185,6 @@ struct bonding { struct timer_list mii_timer; struct timer_list arp_timer; s8 kill_timers; - s8 send_grat_arp; - s8 setup_by_slave; struct net_device_stats stats; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry; @@ -296,8 +292,6 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond) struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); int bond_create(char *name, struct bond_params *params, struct bonding **newbond); -void bond_destroy(struct bonding *bond); -int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev); void bond_deinit(struct net_device *bond_dev); int bond_create_sysfs(void); void bond_destroy_sysfs(void); diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c index 7df31b5561cc..563bf5f6fa2a 100644 --- a/trunk/drivers/net/cassini.c +++ b/trunk/drivers/net/cassini.c @@ -4443,7 +4443,7 @@ static struct { {REG_MAC_COLL_EXCESS}, {REG_MAC_COLL_LATE} }; -#define CAS_REG_LEN ARRAY_SIZE(ethtool_register_table) +#define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int)) #define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) static void cas_read_regs(struct cas *cp, u8 *ptr, int len) diff --git a/trunk/drivers/net/cpmac.c b/trunk/drivers/net/cpmac.c deleted file mode 100644 index ed53aaab4c02..000000000000 --- a/trunk/drivers/net/cpmac.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Eugene Konev - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Eugene Konev "); -MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); -MODULE_LICENSE("GPL"); - -static int debug_level = 8; -static int dumb_switch; - -/* Next 2 are only used in cpmac_probe, so it's pointless to change them */ -module_param(debug_level, int, 0444); -module_param(dumb_switch, int, 0444); - -MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); -MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); - -#define CPMAC_VERSION "0.5.0" -/* stolen from net/ieee80211.h */ -#ifndef MAC_FMT -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \ - ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5] -#endif -/* frame size + 802.1q tag */ -#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) -#define CPMAC_QUEUES 8 - -/* Ethernet registers */ -#define CPMAC_TX_CONTROL 0x0004 -#define CPMAC_TX_TEARDOWN 0x0008 -#define CPMAC_RX_CONTROL 0x0014 -#define CPMAC_RX_TEARDOWN 0x0018 -#define CPMAC_MBP 0x0100 -# define MBP_RXPASSCRC 0x40000000 -# define MBP_RXQOS 0x20000000 -# define MBP_RXNOCHAIN 0x10000000 -# define MBP_RXCMF 0x01000000 -# define MBP_RXSHORT 0x00800000 -# define MBP_RXCEF 0x00400000 -# define MBP_RXPROMISC 0x00200000 -# define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16) -# define MBP_RXBCAST 0x00002000 -# define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8) -# define MBP_RXMCAST 0x00000020 -# define MBP_MCASTCHAN(channel) ((channel) & 0x7) -#define CPMAC_UNICAST_ENABLE 0x0104 -#define CPMAC_UNICAST_CLEAR 0x0108 -#define CPMAC_MAX_LENGTH 0x010c -#define CPMAC_BUFFER_OFFSET 0x0110 -#define CPMAC_MAC_CONTROL 0x0160 -# define MAC_TXPTYPE 0x00000200 -# define MAC_TXPACE 0x00000040 -# define MAC_MII 0x00000020 -# define MAC_TXFLOW 0x00000010 -# define MAC_RXFLOW 0x00000008 -# define MAC_MTEST 0x00000004 -# define MAC_LOOPBACK 0x00000002 -# define MAC_FDX 0x00000001 -#define CPMAC_MAC_STATUS 0x0164 -# define MAC_STATUS_QOS 0x00000004 -# define MAC_STATUS_RXFLOW 0x00000002 -# define MAC_STATUS_TXFLOW 0x00000001 -#define CPMAC_TX_INT_ENABLE 0x0178 -#define CPMAC_TX_INT_CLEAR 0x017c -#define CPMAC_MAC_INT_VECTOR 0x0180 -# define MAC_INT_STATUS 0x00080000 -# define MAC_INT_HOST 0x00040000 -# define MAC_INT_RX 0x00020000 -# define MAC_INT_TX 0x00010000 -#define CPMAC_MAC_EOI_VECTOR 0x0184 -#define CPMAC_RX_INT_ENABLE 0x0198 -#define CPMAC_RX_INT_CLEAR 0x019c -#define CPMAC_MAC_INT_ENABLE 0x01a8 -#define CPMAC_MAC_INT_CLEAR 0x01ac -#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4) -#define CPMAC_MAC_ADDR_MID 0x01d0 -#define CPMAC_MAC_ADDR_HI 0x01d4 -#define CPMAC_MAC_HASH_LO 0x01d8 -#define CPMAC_MAC_HASH_HI 0x01dc -#define CPMAC_TX_PTR(channel) (0x0600 + (channel) * 4) -#define CPMAC_RX_PTR(channel) (0x0620 + (channel) * 4) -#define CPMAC_TX_ACK(channel) (0x0640 + (channel) * 4) -#define CPMAC_RX_ACK(channel) (0x0660 + (channel) * 4) -#define CPMAC_REG_END 0x0680 -/* - * Rx/Tx statistics - * TODO: use some of them to fill stats in cpmac_stats() - */ -#define CPMAC_STATS_RX_GOOD 0x0200 -#define CPMAC_STATS_RX_BCAST 0x0204 -#define CPMAC_STATS_RX_MCAST 0x0208 -#define CPMAC_STATS_RX_PAUSE 0x020c -#define CPMAC_STATS_RX_CRC 0x0210 -#define CPMAC_STATS_RX_ALIGN 0x0214 -#define CPMAC_STATS_RX_OVER 0x0218 -#define CPMAC_STATS_RX_JABBER 0x021c -#define CPMAC_STATS_RX_UNDER 0x0220 -#define CPMAC_STATS_RX_FRAG 0x0224 -#define CPMAC_STATS_RX_FILTER 0x0228 -#define CPMAC_STATS_RX_QOSFILTER 0x022c -#define CPMAC_STATS_RX_OCTETS 0x0230 - -#define CPMAC_STATS_TX_GOOD 0x0234 -#define CPMAC_STATS_TX_BCAST 0x0238 -#define CPMAC_STATS_TX_MCAST 0x023c -#define CPMAC_STATS_TX_PAUSE 0x0240 -#define CPMAC_STATS_TX_DEFER 0x0244 -#define CPMAC_STATS_TX_COLLISION 0x0248 -#define CPMAC_STATS_TX_SINGLECOLL 0x024c -#define CPMAC_STATS_TX_MULTICOLL 0x0250 -#define CPMAC_STATS_TX_EXCESSCOLL 0x0254 -#define CPMAC_STATS_TX_LATECOLL 0x0258 -#define CPMAC_STATS_TX_UNDERRUN 0x025c -#define CPMAC_STATS_TX_CARRIERSENSE 0x0260 -#define CPMAC_STATS_TX_OCTETS 0x0264 - -#define cpmac_read(base, reg) (readl((void __iomem *)(base) + (reg))) -#define cpmac_write(base, reg, val) (writel(val, (void __iomem *)(base) + \ - (reg))) - -/* MDIO bus */ -#define CPMAC_MDIO_VERSION 0x0000 -#define CPMAC_MDIO_CONTROL 0x0004 -# define MDIOC_IDLE 0x80000000 -# define MDIOC_ENABLE 0x40000000 -# define MDIOC_PREAMBLE 0x00100000 -# define MDIOC_FAULT 0x00080000 -# define MDIOC_FAULTDETECT 0x00040000 -# define MDIOC_INTTEST 0x00020000 -# define MDIOC_CLKDIV(div) ((div) & 0xff) -#define CPMAC_MDIO_ALIVE 0x0008 -#define CPMAC_MDIO_LINK 0x000c -#define CPMAC_MDIO_ACCESS(channel) (0x0080 + (channel) * 8) -# define MDIO_BUSY 0x80000000 -# define MDIO_WRITE 0x40000000 -# define MDIO_REG(reg) (((reg) & 0x1f) << 21) -# define MDIO_PHY(phy) (((phy) & 0x1f) << 16) -# define MDIO_DATA(data) ((data) & 0xffff) -#define CPMAC_MDIO_PHYSEL(channel) (0x0084 + (channel) * 8) -# define PHYSEL_LINKSEL 0x00000040 -# define PHYSEL_LINKINT 0x00000020 - -struct cpmac_desc { - u32 hw_next; - u32 hw_data; - u16 buflen; - u16 bufflags; - u16 datalen; - u16 dataflags; -#define CPMAC_SOP 0x8000 -#define CPMAC_EOP 0x4000 -#define CPMAC_OWN 0x2000 -#define CPMAC_EOQ 0x1000 - struct sk_buff *skb; - struct cpmac_desc *next; - dma_addr_t mapping; - dma_addr_t data_mapping; -}; - -struct cpmac_priv { - spinlock_t lock; - spinlock_t rx_lock; - struct cpmac_desc *rx_head; - int ring_size; - struct cpmac_desc *desc_ring; - dma_addr_t dma_ring; - void __iomem *regs; - struct mii_bus *mii_bus; - struct phy_device *phy; - char phy_name[BUS_ID_SIZE]; - int oldlink, oldspeed, oldduplex; - u32 msg_enable; - struct net_device *dev; - struct work_struct reset_work; - struct platform_device *pdev; -}; - -static irqreturn_t cpmac_irq(int, void *); -static void cpmac_hw_start(struct net_device *dev); -static void cpmac_hw_stop(struct net_device *dev); -static int cpmac_stop(struct net_device *dev); -static int cpmac_open(struct net_device *dev); - -static void cpmac_dump_regs(struct net_device *dev) -{ - int i; - struct cpmac_priv *priv = netdev_priv(dev); - for (i = 0; i < CPMAC_REG_END; i += 4) { - if (i % 16 == 0) { - if (i) - printk("\n"); - printk(KERN_DEBUG "%s: reg[%p]:", dev->name, - priv->regs + i); - } - printk(" %08x", cpmac_read(priv->regs, i)); - } - printk("\n"); -} - -static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc) -{ - int i; - printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc); - for (i = 0; i < sizeof(*desc) / 4; i++) - printk(" %08x", ((u32 *)desc)[i]); - printk("\n"); -} - -static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) -{ - int i; - printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len); - for (i = 0; i < skb->len; i++) { - if (i % 16 == 0) { - if (i) - printk("\n"); - printk(KERN_DEBUG "%s: data[%p]:", dev->name, - skb->data + i); - } - printk(" %02x", ((u8 *)skb->data)[i]); - } - printk("\n"); -} - -static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg) -{ - u32 val; - - while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) - cpu_relax(); - cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_REG(reg) | - MDIO_PHY(phy_id)); - while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY) - cpu_relax(); - return MDIO_DATA(val); -} - -static int cpmac_mdio_write(struct mii_bus *bus, int phy_id, - int reg, u16 val) -{ - while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) - cpu_relax(); - cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE | - MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val)); - return 0; -} - -static int cpmac_mdio_reset(struct mii_bus *bus) -{ - ar7_device_reset(AR7_RESET_BIT_MDIO); - cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE | - MDIOC_CLKDIV(ar7_cpmac_freq() / 2200000 - 1)); - return 0; -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, }; - -static struct mii_bus cpmac_mii = { - .name = "cpmac-mii", - .read = cpmac_mdio_read, - .write = cpmac_mdio_write, - .reset = cpmac_mdio_reset, - .irq = mii_irqs, -}; - -static int cpmac_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) - return -EBUSY; - - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) - return -EOPNOTSUPP; - - /* ignore other fields */ - return 0; -} - -static void cpmac_set_multicast_list(struct net_device *dev) -{ - struct dev_mc_list *iter; - int i; - u8 tmp; - u32 mbp, bit, hash[2] = { 0, }; - struct cpmac_priv *priv = netdev_priv(dev); - - mbp = cpmac_read(priv->regs, CPMAC_MBP); - if (dev->flags & IFF_PROMISC) { - cpmac_write(priv->regs, CPMAC_MBP, (mbp & ~MBP_PROMISCCHAN(0)) | - MBP_RXPROMISC); - } else { - cpmac_write(priv->regs, CPMAC_MBP, mbp & ~MBP_RXPROMISC); - if (dev->flags & IFF_ALLMULTI) { - /* enable all multicast mode */ - cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff); - cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff); - } else { - /* - * cpmac uses some strange mac address hashing - * (not crc32) - */ - for (i = 0, iter = dev->mc_list; i < dev->mc_count; - i++, iter = iter->next) { - bit = 0; - tmp = iter->dmi_addr[0]; - bit ^= (tmp >> 2) ^ (tmp << 4); - tmp = iter->dmi_addr[1]; - bit ^= (tmp >> 4) ^ (tmp << 2); - tmp = iter->dmi_addr[2]; - bit ^= (tmp >> 6) ^ tmp; - tmp = iter->dmi_addr[3]; - bit ^= (tmp >> 2) ^ (tmp << 4); - tmp = iter->dmi_addr[4]; - bit ^= (tmp >> 4) ^ (tmp << 2); - tmp = iter->dmi_addr[5]; - bit ^= (tmp >> 6) ^ tmp; - bit &= 0x3f; - hash[bit / 32] |= 1 << (bit % 32); - } - - cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, hash[0]); - cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, hash[1]); - } - } -} - -static struct sk_buff *cpmac_rx_one(struct net_device *dev, - struct cpmac_priv *priv, - struct cpmac_desc *desc) -{ - struct sk_buff *skb, *result = NULL; - - if (unlikely(netif_msg_hw(priv))) - cpmac_dump_desc(dev, desc); - cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping); - if (unlikely(!desc->datalen)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: rx: spurious interrupt\n", - dev->name); - return NULL; - } - - skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); - if (likely(skb)) { - skb_reserve(skb, 2); - skb_put(desc->skb, desc->datalen); - desc->skb->protocol = eth_type_trans(desc->skb, dev); - desc->skb->ip_summed = CHECKSUM_NONE; - dev->stats.rx_packets++; - dev->stats.rx_bytes += desc->datalen; - result = desc->skb; - dma_unmap_single(&dev->dev, desc->data_mapping, CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); - desc->skb = skb; - desc->data_mapping = dma_map_single(&dev->dev, skb->data, - CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); - desc->hw_data = (u32)desc->data_mapping; - if (unlikely(netif_msg_pktdata(priv))) { - printk(KERN_DEBUG "%s: received packet:\n", dev->name); - cpmac_dump_skb(dev, result); - } - } else { - if (netif_msg_rx_err(priv) && net_ratelimit()) - printk(KERN_WARNING - "%s: low on skbs, dropping packet\n", dev->name); - dev->stats.rx_dropped++; - } - - desc->buflen = CPMAC_SKB_SIZE; - desc->dataflags = CPMAC_OWN; - - return result; -} - -static int cpmac_poll(struct net_device *dev, int *budget) -{ - struct sk_buff *skb; - struct cpmac_desc *desc; - int received = 0, quota = min(dev->quota, *budget); - struct cpmac_priv *priv = netdev_priv(dev); - - spin_lock(&priv->rx_lock); - if (unlikely(!priv->rx_head)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: rx: polling, but no queue\n", - dev->name); - netif_rx_complete(dev); - return 0; - } - - desc = priv->rx_head; - while ((received < quota) && ((desc->dataflags & CPMAC_OWN) == 0)) { - skb = cpmac_rx_one(dev, priv, desc); - if (likely(skb)) { - netif_receive_skb(skb); - received++; - } - desc = desc->next; - } - - priv->rx_head = desc; - spin_unlock(&priv->rx_lock); - *budget -= received; - dev->quota -= received; - if (unlikely(netif_msg_rx_status(priv))) - printk(KERN_DEBUG "%s: poll processed %d packets\n", dev->name, - received); - if (desc->dataflags & CPMAC_OWN) { - netif_rx_complete(dev); - cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); - cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); - return 0; - } - - return 1; -} - -static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - int queue, len; - struct cpmac_desc *desc; - struct cpmac_priv *priv = netdev_priv(dev); - - if (unlikely(skb_padto(skb, ETH_ZLEN))) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING - "%s: tx: padding failed, dropping\n", dev->name); - spin_lock(&priv->lock); - dev->stats.tx_dropped++; - spin_unlock(&priv->lock); - return -ENOMEM; - } - - len = max(skb->len, ETH_ZLEN); - queue = skb->queue_mapping; -#ifdef CONFIG_NETDEVICES_MULTIQUEUE - netif_stop_subqueue(dev, queue); -#else - netif_stop_queue(dev); -#endif - - desc = &priv->desc_ring[queue]; - if (unlikely(desc->dataflags & CPMAC_OWN)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: tx dma ring full, dropping\n", - dev->name); - spin_lock(&priv->lock); - dev->stats.tx_dropped++; - spin_unlock(&priv->lock); - dev_kfree_skb_any(skb); - return -ENOMEM; - } - - spin_lock(&priv->lock); - dev->trans_start = jiffies; - spin_unlock(&priv->lock); - desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN; - desc->skb = skb; - desc->data_mapping = dma_map_single(&dev->dev, skb->data, len, - DMA_TO_DEVICE); - desc->hw_data = (u32)desc->data_mapping; - desc->datalen = len; - desc->buflen = len; - if (unlikely(netif_msg_tx_queued(priv))) - printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb, - skb->len); - if (unlikely(netif_msg_hw(priv))) - cpmac_dump_desc(dev, desc); - if (unlikely(netif_msg_pktdata(priv))) - cpmac_dump_skb(dev, skb); - cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping); - - return 0; -} - -static void cpmac_end_xmit(struct net_device *dev, int queue) -{ - struct cpmac_desc *desc; - struct cpmac_priv *priv = netdev_priv(dev); - - desc = &priv->desc_ring[queue]; - cpmac_write(priv->regs, CPMAC_TX_ACK(queue), (u32)desc->mapping); - if (likely(desc->skb)) { - spin_lock(&priv->lock); - dev->stats.tx_packets++; - dev->stats.tx_bytes += desc->skb->len; - spin_unlock(&priv->lock); - dma_unmap_single(&dev->dev, desc->data_mapping, desc->skb->len, - DMA_TO_DEVICE); - - if (unlikely(netif_msg_tx_done(priv))) - printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name, - desc->skb, desc->skb->len); - - dev_kfree_skb_irq(desc->skb); - desc->skb = NULL; -#ifdef CONFIG_NETDEVICES_MULTIQUEUE - if (netif_subqueue_stopped(dev, queue)) - netif_wake_subqueue(dev, queue); -#else - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); -#endif - } else { - if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING - "%s: end_xmit: spurious interrupt\n", dev->name); -#ifdef CONFIG_NETDEVICES_MULTIQUEUE - if (netif_subqueue_stopped(dev, queue)) - netif_wake_subqueue(dev, queue); -#else - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); -#endif - } -} - -static void cpmac_hw_stop(struct net_device *dev) -{ - int i; - struct cpmac_priv *priv = netdev_priv(dev); - struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; - - ar7_device_reset(pdata->reset_bit); - cpmac_write(priv->regs, CPMAC_RX_CONTROL, - cpmac_read(priv->regs, CPMAC_RX_CONTROL) & ~1); - cpmac_write(priv->regs, CPMAC_TX_CONTROL, - cpmac_read(priv->regs, CPMAC_TX_CONTROL) & ~1); - for (i = 0; i < 8; i++) { - cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); - cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); - } - cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_MAC_CONTROL, - cpmac_read(priv->regs, CPMAC_MAC_CONTROL) & ~MAC_MII); -} - -static void cpmac_hw_start(struct net_device *dev) -{ - int i; - struct cpmac_priv *priv = netdev_priv(dev); - struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; - - ar7_device_reset(pdata->reset_bit); - for (i = 0; i < 8; i++) { - cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); - cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); - } - cpmac_write(priv->regs, CPMAC_RX_PTR(0), priv->rx_head->mapping); - - cpmac_write(priv->regs, CPMAC_MBP, MBP_RXSHORT | MBP_RXBCAST | - MBP_RXMCAST); - cpmac_write(priv->regs, CPMAC_BUFFER_OFFSET, 0); - for (i = 0; i < 8; i++) - cpmac_write(priv->regs, CPMAC_MAC_ADDR_LO(i), dev->dev_addr[5]); - cpmac_write(priv->regs, CPMAC_MAC_ADDR_MID, dev->dev_addr[4]); - cpmac_write(priv->regs, CPMAC_MAC_ADDR_HI, dev->dev_addr[0] | - (dev->dev_addr[1] << 8) | (dev->dev_addr[2] << 16) | - (dev->dev_addr[3] << 24)); - cpmac_write(priv->regs, CPMAC_MAX_LENGTH, CPMAC_SKB_SIZE); - cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); - cpmac_write(priv->regs, CPMAC_UNICAST_ENABLE, 1); - cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); - cpmac_write(priv->regs, CPMAC_TX_INT_ENABLE, 0xff); - cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); - - cpmac_write(priv->regs, CPMAC_RX_CONTROL, - cpmac_read(priv->regs, CPMAC_RX_CONTROL) | 1); - cpmac_write(priv->regs, CPMAC_TX_CONTROL, - cpmac_read(priv->regs, CPMAC_TX_CONTROL) | 1); - cpmac_write(priv->regs, CPMAC_MAC_CONTROL, - cpmac_read(priv->regs, CPMAC_MAC_CONTROL) | MAC_MII | - MAC_FDX); -} - -static void cpmac_clear_rx(struct net_device *dev) -{ - struct cpmac_priv *priv = netdev_priv(dev); - struct cpmac_desc *desc; - int i; - if (unlikely(!priv->rx_head)) - return; - desc = priv->rx_head; - for (i = 0; i < priv->ring_size; i++) { - if ((desc->dataflags & CPMAC_OWN) == 0) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: packet dropped\n", - dev->name); - if (unlikely(netif_msg_hw(priv))) - cpmac_dump_desc(dev, desc); - desc->dataflags = CPMAC_OWN; - dev->stats.rx_dropped++; - } - desc = desc->next; - } -} - -static void cpmac_clear_tx(struct net_device *dev) -{ - struct cpmac_priv *priv = netdev_priv(dev); - int i; - if (unlikely(!priv->desc_ring)) - return; - for (i = 0; i < CPMAC_QUEUES; i++) - if (priv->desc_ring[i].skb) { - dev_kfree_skb_any(priv->desc_ring[i].skb); - if (netif_subqueue_stopped(dev, i)) - netif_wake_subqueue(dev, i); - } -} - -static void cpmac_hw_error(struct work_struct *work) -{ - struct cpmac_priv *priv = - container_of(work, struct cpmac_priv, reset_work); - - spin_lock(&priv->rx_lock); - cpmac_clear_rx(priv->dev); - spin_unlock(&priv->rx_lock); - cpmac_clear_tx(priv->dev); - cpmac_hw_start(priv->dev); - netif_start_queue(priv->dev); -} - -static irqreturn_t cpmac_irq(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct cpmac_priv *priv; - int queue; - u32 status; - - if (!dev) - return IRQ_NONE; - - priv = netdev_priv(dev); - - status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR); - - if (unlikely(netif_msg_intr(priv))) - printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name, - status); - - if (status & MAC_INT_TX) - cpmac_end_xmit(dev, (status & 7)); - - if (status & MAC_INT_RX) { - queue = (status >> 8) & 7; - netif_rx_schedule(dev); - cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); - } - - cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); - - if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) { - if (netif_msg_drv(priv) && net_ratelimit()) - printk(KERN_ERR "%s: hw error, resetting...\n", - dev->name); - netif_stop_queue(dev); - cpmac_hw_stop(dev); - schedule_work(&priv->reset_work); - if (unlikely(netif_msg_hw(priv))) - cpmac_dump_regs(dev); - } - - return IRQ_HANDLED; -} - -static void cpmac_tx_timeout(struct net_device *dev) -{ - struct cpmac_priv *priv = netdev_priv(dev); - int i; - - spin_lock(&priv->lock); - dev->stats.tx_errors++; - spin_unlock(&priv->lock); - if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: transmit timeout\n", dev->name); - /* - * FIXME: waking up random queue is not the best thing to - * do... on the other hand why we got here at all? - */ -#ifdef CONFIG_NETDEVICES_MULTIQUEUE - for (i = 0; i < CPMAC_QUEUES; i++) - if (priv->desc_ring[i].skb) { - dev_kfree_skb_any(priv->desc_ring[i].skb); - netif_wake_subqueue(dev, i); - break; - } -#else - if (priv->desc_ring[0].skb) - dev_kfree_skb_any(priv->desc_ring[0].skb); - netif_wake_queue(dev); -#endif -} - -static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct cpmac_priv *priv = netdev_priv(dev); - if (!(netif_running(dev))) - return -EINVAL; - if (!priv->phy) - return -EINVAL; - if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || - (cmd == SIOCSMIIREG)) - return phy_mii_ioctl(priv->phy, if_mii(ifr), cmd); - - return -EOPNOTSUPP; -} - -static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct cpmac_priv *priv = netdev_priv(dev); - - if (priv->phy) - return phy_ethtool_gset(priv->phy, cmd); - - return -EINVAL; -} - -static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct cpmac_priv *priv = netdev_priv(dev); - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (priv->phy) - return phy_ethtool_sset(priv->phy, cmd); - - return -EINVAL; -} - -static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) -{ - struct cpmac_priv *priv = netdev_priv(dev); - - ring->rx_max_pending = 1024; - ring->rx_mini_max_pending = 1; - ring->rx_jumbo_max_pending = 1; - ring->tx_max_pending = 1; - - ring->rx_pending = priv->ring_size; - ring->rx_mini_pending = 1; - ring->rx_jumbo_pending = 1; - ring->tx_pending = 1; -} - -static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) -{ - struct cpmac_priv *priv = netdev_priv(dev); - - if (dev->flags && IFF_UP) - return -EBUSY; - priv->ring_size = ring->rx_pending; - return 0; -} - -static void cpmac_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "cpmac"); - strcpy(info->version, CPMAC_VERSION); - info->fw_version[0] = '\0'; - sprintf(info->bus_info, "%s", "cpmac"); - info->regdump_len = 0; -} - -static const struct ethtool_ops cpmac_ethtool_ops = { - .get_settings = cpmac_get_settings, - .set_settings = cpmac_set_settings, - .get_drvinfo = cpmac_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_ringparam = cpmac_get_ringparam, - .set_ringparam = cpmac_set_ringparam, -}; - -static void cpmac_adjust_link(struct net_device *dev) -{ - struct cpmac_priv *priv = netdev_priv(dev); - int new_state = 0; - - spin_lock(&priv->lock); - if (priv->phy->link) { - netif_start_queue(dev); - if (priv->phy->duplex != priv->oldduplex) { - new_state = 1; - priv->oldduplex = priv->phy->duplex; - } - - if (priv->phy->speed != priv->oldspeed) { - new_state = 1; - priv->oldspeed = priv->phy->speed; - } - - if (!priv->oldlink) { - new_state = 1; - priv->oldlink = 1; - netif_schedule(dev); - } - } else if (priv->oldlink) { - netif_stop_queue(dev); - new_state = 1; - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - } - - if (new_state && netif_msg_link(priv) && net_ratelimit()) - phy_print_status(priv->phy); - - spin_unlock(&priv->lock); -} - -static int cpmac_open(struct net_device *dev) -{ - int i, size, res; - struct cpmac_priv *priv = netdev_priv(dev); - struct resource *mem; - struct cpmac_desc *desc; - struct sk_buff *skb; - - priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, - 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(priv->phy)) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: Could not attach to PHY\n", - dev->name); - return PTR_ERR(priv->phy); - } - - mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); - if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: failed to request registers\n", - dev->name); - res = -ENXIO; - goto fail_reserve; - } - - priv->regs = ioremap(mem->start, mem->end - mem->start); - if (!priv->regs) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: failed to remap registers\n", - dev->name); - res = -ENXIO; - goto fail_remap; - } - - size = priv->ring_size + CPMAC_QUEUES; - priv->desc_ring = dma_alloc_coherent(&dev->dev, - sizeof(struct cpmac_desc) * size, - &priv->dma_ring, - GFP_KERNEL); - if (!priv->desc_ring) { - res = -ENOMEM; - goto fail_alloc; - } - - for (i = 0; i < size; i++) - priv->desc_ring[i].mapping = priv->dma_ring + sizeof(*desc) * i; - - priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; - for (i = 0, desc = priv->rx_head; i < priv->ring_size; i++, desc++) { - skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); - if (unlikely(!skb)) { - res = -ENOMEM; - goto fail_desc; - } - skb_reserve(skb, 2); - desc->skb = skb; - desc->data_mapping = dma_map_single(&dev->dev, skb->data, - CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); - desc->hw_data = (u32)desc->data_mapping; - desc->buflen = CPMAC_SKB_SIZE; - desc->dataflags = CPMAC_OWN; - desc->next = &priv->rx_head[(i + 1) % priv->ring_size]; - desc->hw_next = (u32)desc->next->mapping; - } - - if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, - dev->name, dev))) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: failed to obtain irq\n", - dev->name); - goto fail_irq; - } - - INIT_WORK(&priv->reset_work, cpmac_hw_error); - cpmac_hw_start(dev); - - priv->phy->state = PHY_CHANGELINK; - phy_start(priv->phy); - - return 0; - -fail_irq: -fail_desc: - for (i = 0; i < priv->ring_size; i++) { - if (priv->rx_head[i].skb) { - dma_unmap_single(&dev->dev, - priv->rx_head[i].data_mapping, - CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); - kfree_skb(priv->rx_head[i].skb); - } - } -fail_alloc: - kfree(priv->desc_ring); - iounmap(priv->regs); - -fail_remap: - release_mem_region(mem->start, mem->end - mem->start); - -fail_reserve: - phy_disconnect(priv->phy); - - return res; -} - -static int cpmac_stop(struct net_device *dev) -{ - int i; - struct cpmac_priv *priv = netdev_priv(dev); - struct resource *mem; - - netif_stop_queue(dev); - - cancel_work_sync(&priv->reset_work); - phy_stop(priv->phy); - phy_disconnect(priv->phy); - priv->phy = NULL; - - cpmac_hw_stop(dev); - - for (i = 0; i < 8; i++) - cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); - cpmac_write(priv->regs, CPMAC_RX_PTR(0), 0); - cpmac_write(priv->regs, CPMAC_MBP, 0); - - free_irq(dev->irq, dev); - iounmap(priv->regs); - mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); - release_mem_region(mem->start, mem->end - mem->start); - priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; - for (i = 0; i < priv->ring_size; i++) { - if (priv->rx_head[i].skb) { - dma_unmap_single(&dev->dev, - priv->rx_head[i].data_mapping, - CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); - kfree_skb(priv->rx_head[i].skb); - } - } - - dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) * - (CPMAC_QUEUES + priv->ring_size), - priv->desc_ring, priv->dma_ring); - return 0; -} - -static int external_switch; - -static int __devinit cpmac_probe(struct platform_device *pdev) -{ - int rc, phy_id; - struct resource *mem; - struct cpmac_priv *priv; - struct net_device *dev; - struct plat_cpmac_data *pdata; - - pdata = pdev->dev.platform_data; - - for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { - if (!(pdata->phy_mask & (1 << phy_id))) - continue; - if (!cpmac_mii.phy_map[phy_id]) - continue; - break; - } - - if (phy_id == PHY_MAX_ADDR) { - if (external_switch || dumb_switch) - phy_id = 0; - else { - printk(KERN_ERR "cpmac: no PHY present\n"); - return -ENODEV; - } - } - - dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); - - if (!dev) { - printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); - return -ENOMEM; - } - - platform_set_drvdata(pdev, dev); - priv = netdev_priv(dev); - - priv->pdev = pdev; - mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); - if (!mem) { - rc = -ENODEV; - goto fail; - } - - dev->irq = platform_get_irq_byname(pdev, "irq"); - - dev->open = cpmac_open; - dev->stop = cpmac_stop; - dev->set_config = cpmac_config; - dev->hard_start_xmit = cpmac_start_xmit; - dev->do_ioctl = cpmac_ioctl; - dev->set_multicast_list = cpmac_set_multicast_list; - dev->tx_timeout = cpmac_tx_timeout; - dev->ethtool_ops = &cpmac_ethtool_ops; - dev->poll = cpmac_poll; - dev->weight = 64; - dev->features |= NETIF_F_MULTI_QUEUE; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->rx_lock); - priv->dev = dev; - priv->ring_size = 64; - priv->msg_enable = netif_msg_init(debug_level, 0xff); - memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - if (phy_id == 31) { - snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, - cpmac_mii.id, phy_id); - } else - snprintf(priv->phy_name, BUS_ID_SIZE, "fixed@%d:%d", 100, 1); - - if ((rc = register_netdev(dev))) { - printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, - dev->name); - goto fail; - } - - if (netif_msg_probe(priv)) { - printk(KERN_INFO - "cpmac: device %s (regs: %p, irq: %d, phy: %s, mac: " - MAC_FMT ")\n", dev->name, (void *)mem->start, dev->irq, - priv->phy_name, MAC_ARG(dev->dev_addr)); - } - return 0; - -fail: - free_netdev(dev); - return rc; -} - -static int __devexit cpmac_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(dev); - free_netdev(dev); - return 0; -} - -static struct platform_driver cpmac_driver = { - .driver.name = "cpmac", - .probe = cpmac_probe, - .remove = __devexit_p(cpmac_remove), -}; - -int __devinit cpmac_init(void) -{ - u32 mask; - int i, res; - - cpmac_mii.priv = ioremap(AR7_REGS_MDIO, 256); - - if (!cpmac_mii.priv) { - printk(KERN_ERR "Can't ioremap mdio registers\n"); - return -ENXIO; - } - -#warning FIXME: unhardcode gpio&reset bits - ar7_gpio_disable(26); - ar7_gpio_disable(27); - ar7_device_reset(AR7_RESET_BIT_CPMAC_LO); - ar7_device_reset(AR7_RESET_BIT_CPMAC_HI); - ar7_device_reset(AR7_RESET_BIT_EPHY); - - cpmac_mii.reset(&cpmac_mii); - - for (i = 0; i < 300000; i++) - if ((mask = cpmac_read(cpmac_mii.priv, CPMAC_MDIO_ALIVE))) - break; - else - cpu_relax(); - - mask &= 0x7fffffff; - if (mask & (mask - 1)) { - external_switch = 1; - mask = 0; - } - - cpmac_mii.phy_mask = ~(mask | 0x80000000); - - res = mdiobus_register(&cpmac_mii); - if (res) - goto fail_mii; - - res = platform_driver_register(&cpmac_driver); - if (res) - goto fail_cpmac; - - return 0; - -fail_cpmac: - mdiobus_unregister(&cpmac_mii); - -fail_mii: - iounmap(cpmac_mii.priv); - - return res; -} - -void __devexit cpmac_exit(void) -{ - platform_driver_unregister(&cpmac_driver); - mdiobus_unregister(&cpmac_mii); - iounmap(cpmac_mii.priv); -} - -module_init(cpmac_init); -module_exit(cpmac_exit); diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index 558440c15b6c..0db5e6fabe73 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -168,6 +168,7 @@ static int gfar_probe(struct platform_device *pdev) struct gfar_private *priv = NULL; struct gianfar_platform_data *einfo; struct resource *r; + int idx; int err = 0; DECLARE_MAC_BUF(mac); @@ -260,9 +261,7 @@ static int gfar_probe(struct platform_device *pdev) dev->hard_start_xmit = gfar_start_xmit; dev->tx_timeout = gfar_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_GFAR_NAPI netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT); -#endif #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = gfar_netpoll; #endif @@ -932,14 +931,9 @@ int startup_gfar(struct net_device *dev) /* Returns 0 for success. */ static int gfar_enet_open(struct net_device *dev) { -#ifdef CONFIG_GFAR_NAPI - struct gfar_private *priv = netdev_priv(dev); -#endif int err; -#ifdef CONFIG_GFAR_NAPI napi_enable(&priv->napi); -#endif /* Initialize a bunch of registers */ init_registers(dev); @@ -949,17 +943,13 @@ static int gfar_enet_open(struct net_device *dev) err = init_phy(dev); if(err) { -#ifdef CONFIG_GFAR_NAPI napi_disable(&priv->napi); -#endif return err; } err = startup_gfar(dev); if (err) -#ifdef CONFIG_GFAR_NAPI napi_disable(&priv->napi); -#endif netif_start_queue(dev); @@ -1113,9 +1103,7 @@ static int gfar_close(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); -#ifdef CONFIG_GFAR_NAPI napi_disable(&priv->napi); -#endif stop_gfar(dev); diff --git a/trunk/drivers/net/ibm_emac/ibm_emac_mal.c b/trunk/drivers/net/ibm_emac/ibm_emac_mal.c index dcd8826fc749..4e49e8c4f871 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac_mal.c +++ b/trunk/drivers/net/ibm_emac/ibm_emac_mal.c @@ -413,10 +413,7 @@ static int __init mal_probe(struct ocp_device *ocpdev) ocpdev->def->index); return -ENOMEM; } - - /* XXX This only works for native dcr for now */ - mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0); - + mal->dcrbase = maldata->dcr_base; mal->def = ocpdev->def; INIT_LIST_HEAD(&mal->poll_list); diff --git a/trunk/drivers/net/ibm_emac/ibm_emac_mal.h b/trunk/drivers/net/ibm_emac/ibm_emac_mal.h index b8adbe6d4b01..8f54d621994d 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac_mal.h +++ b/trunk/drivers/net/ibm_emac/ibm_emac_mal.h @@ -191,6 +191,7 @@ struct mal_commac { }; struct ibm_ocp_mal { + int dcrbase; dcr_host_t dcrhost; struct list_head poll_list; @@ -208,12 +209,12 @@ struct ibm_ocp_mal { static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) { - return dcr_read(mal->dcrhost, reg); + return dcr_read(mal->dcrhost, mal->dcrbase + reg); } static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) { - dcr_write(mal->dcrhost, reg, val); + dcr_write(mal->dcrhost, mal->dcrbase + reg, val); } /* Register MAL devices */ diff --git a/trunk/drivers/net/ibm_newemac/mal.c b/trunk/drivers/net/ibm_newemac/mal.c index 39f4cb6b0cf3..58854117b1a9 100644 --- a/trunk/drivers/net/ibm_newemac/mal.c +++ b/trunk/drivers/net/ibm_newemac/mal.c @@ -461,7 +461,6 @@ static int __devinit mal_probe(struct of_device *ofdev, struct mal_instance *mal; int err = 0, i, bd_size; int index = mal_count++; - unsigned int dcr_base; const u32 *prop; u32 cfg; @@ -498,14 +497,14 @@ static int __devinit mal_probe(struct of_device *ofdev, } mal->num_rx_chans = prop[0]; - dcr_base = dcr_resource_start(ofdev->node, 0); - if (dcr_base == 0) { + mal->dcr_base = dcr_resource_start(ofdev->node, 0); + if (mal->dcr_base == 0) { printk(KERN_ERR "mal%d: can't find DCR resource!\n", index); err = -ENODEV; goto fail; } - mal->dcr_host = dcr_map(ofdev->node, dcr_base, 0x100); + mal->dcr_host = dcr_map(ofdev->node, mal->dcr_base, 0x100); if (!DCR_MAP_OK(mal->dcr_host)) { printk(KERN_ERR "mal%d: failed to map DCRs !\n", index); @@ -627,7 +626,7 @@ static int __devinit mal_probe(struct of_device *ofdev, fail2: dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma); fail_unmap: - dcr_unmap(mal->dcr_host, 0x100); + dcr_unmap(mal->dcr_host, mal->dcr_base, 0x100); fail: kfree(mal); diff --git a/trunk/drivers/net/ibm_newemac/mal.h b/trunk/drivers/net/ibm_newemac/mal.h index 784edb8ea822..cb1a16d589fe 100644 --- a/trunk/drivers/net/ibm_newemac/mal.h +++ b/trunk/drivers/net/ibm_newemac/mal.h @@ -185,6 +185,7 @@ struct mal_commac { struct mal_instance { int version; + int dcr_base; dcr_host_t dcr_host; int num_tx_chans; /* Number of TX channels */ @@ -212,12 +213,12 @@ struct mal_instance { static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg) { - return dcr_read(mal->dcr_host, reg); + return dcr_read(mal->dcr_host, mal->dcr_base + reg); } static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val) { - dcr_write(mal->dcr_host, reg, val); + dcr_write(mal->dcr_host, mal->dcr_base + reg, val); } /* Register MAL devices */ diff --git a/trunk/drivers/net/irda/donauboe.c b/trunk/drivers/net/irda/donauboe.c index a82d8f98383d..3e5eca1aa987 100644 --- a/trunk/drivers/net/irda/donauboe.c +++ b/trunk/drivers/net/irda/donauboe.c @@ -840,7 +840,7 @@ toshoboe_probe (struct toshoboe_cb *self) /* test 1: SIR filter and back to back */ - for (j = 0; j < ARRAY_SIZE(bauds); ++j) + for (j = 0; j < (sizeof (bauds) / sizeof (int)); ++j) { int fir = (j > 1); toshoboe_stopchip (self); diff --git a/trunk/drivers/net/jazzsonic.c b/trunk/drivers/net/jazzsonic.c index 5c154fe13859..d3825c8ee994 100644 --- a/trunk/drivers/net/jazzsonic.c +++ b/trunk/drivers/net/jazzsonic.c @@ -208,6 +208,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev) struct sonic_local *lp; struct resource *res; int err = 0; + int i; DECLARE_MAC_BUF(mac); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/trunk/drivers/net/mipsnet.c b/trunk/drivers/net/mipsnet.c index 37707a0c0498..d593175ab6f0 100644 --- a/trunk/drivers/net/mipsnet.c +++ b/trunk/drivers/net/mipsnet.c @@ -7,12 +7,12 @@ #define DEBUG #include -#include #include #include #include #include #include +#include #include #include "mipsnet.h" /* actual device IO mapping */ @@ -33,8 +33,9 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, if (available_len < len) return -EFAULT; - for (; len > 0; len--, kdata++) + for (; len > 0; len--, kdata++) { *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); + } return inl(mipsnet_reg_address(dev, rxDataCount)); } @@ -46,15 +47,16 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, char *buf_ptr = skb->data; pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n", - dev->name, __FUNCTION__, skb->len); + dev->name, __FUNCTION__, skb->len); outl(skb->len, mipsnet_reg_address(dev, txDataCount)); pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", - dev->name, __FUNCTION__, skb->len); + dev->name, __FUNCTION__, skb->len); - for (; count_to_go; buf_ptr++, count_to_go--) + for (; count_to_go; buf_ptr++, count_to_go--) { outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); + } dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -65,7 +67,7 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) { pr_debug("%s:%s(): transmitting %d bytes\n", - dev->name, __FUNCTION__, skb->len); + dev->name, __FUNCTION__, skb->len); /* Only one packet at a time. Once TXDONE interrupt is serviced, the * queue will be restarted. @@ -81,8 +83,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) struct sk_buff *skb; size_t len = count; - skb = alloc_skb(len + 2, GFP_KERNEL); - if (!skb) { + if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { dev->stats.rx_dropped++; return -ENOMEM; } @@ -95,7 +96,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) skb->ip_summed = CHECKSUM_UNNECESSARY; pr_debug("%s:%s(): pushing RXed data to kernel\n", - dev->name, __FUNCTION__); + dev->name, __FUNCTION__); netif_rx(skb); dev->stats.rx_packets++; @@ -113,44 +114,42 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) if (irq == dev->irq) { pr_debug("%s:%s(): irq %d for device\n", - dev->name, __FUNCTION__, irq); + dev->name, __FUNCTION__, irq); retval = IRQ_HANDLED; interruptFlags = inl(mipsnet_reg_address(dev, interruptControl)); pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name, - __FUNCTION__, interruptFlags); + __FUNCTION__, interruptFlags); if (interruptFlags & MIPSNET_INTCTL_TXDONE) { pr_debug("%s:%s(): got TXDone\n", - dev->name, __FUNCTION__); + dev->name, __FUNCTION__); outl(MIPSNET_INTCTL_TXDONE, mipsnet_reg_address(dev, interruptControl)); - /* only one packet at a time, we are done. */ + // only one packet at a time, we are done. netif_wake_queue(dev); } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { pr_debug("%s:%s(): got RX data\n", - dev->name, __FUNCTION__); + dev->name, __FUNCTION__); mipsnet_get_fromdev(dev, - inl(mipsnet_reg_address(dev, rxDataCount))); + inl(mipsnet_reg_address(dev, rxDataCount))); pr_debug("%s:%s(): clearing RX int\n", - dev->name, __FUNCTION__); + dev->name, __FUNCTION__); outl(MIPSNET_INTCTL_RXDONE, mipsnet_reg_address(dev, interruptControl)); } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { pr_debug("%s:%s(): got test interrupt\n", - dev->name, __FUNCTION__); - /* - * TESTBIT is cleared on read. - * And takes effect after a write with 0 - */ + dev->name, __FUNCTION__); + // TESTBIT is cleared on read. + // And takes effect after a write with 0 outl(0, mipsnet_reg_address(dev, interruptControl)); } else { pr_debug("%s:%s(): no valid fags 0x%016llx\n", - dev->name, __FUNCTION__, interruptFlags); - /* Maybe shared IRQ, just ignore, no clearing. */ + dev->name, __FUNCTION__, interruptFlags); + // Maybe shared IRQ, just ignore, no clearing. retval = IRQ_NONE; } @@ -160,7 +159,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) retval = IRQ_NONE; } return retval; -} +} //mipsnet_interrupt() static int mipsnet_open(struct net_device *dev) { @@ -172,18 +171,18 @@ static int mipsnet_open(struct net_device *dev) if (err) { pr_debug("%s: %s(): can't get irq %d\n", - dev->name, __FUNCTION__, dev->irq); + dev->name, __FUNCTION__, dev->irq); release_region(dev->base_addr, MIPSNET_IO_EXTENT); return err; } pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n", - dev->name, __FUNCTION__, dev->base_addr, dev->irq); + dev->name, __FUNCTION__, dev->base_addr, dev->irq); netif_start_queue(dev); - /* test interrupt handler */ + // test interrupt handler outl(MIPSNET_INTCTL_TESTBIT, mipsnet_reg_address(dev, interruptControl)); @@ -200,6 +199,8 @@ static int mipsnet_close(struct net_device *dev) static void mipsnet_set_mclist(struct net_device *dev) { + // we don't do anything + return; } static int __init mipsnet_probe(struct device *dev) @@ -225,13 +226,13 @@ static int __init mipsnet_probe(struct device *dev) */ netdev->base_addr = 0x4200; netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + - inl(mipsnet_reg_address(netdev, interruptInfo)); + inl(mipsnet_reg_address(netdev, interruptInfo)); - /* Get the io region now, get irq on open() */ + // Get the io region now, get irq on open() if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " - "for dev is not availble.\n", netdev->name, - __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); + "for dev is not availble.\n", netdev->name, + __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); err = -EBUSY; goto out_free_netdev; } diff --git a/trunk/drivers/net/mipsnet.h b/trunk/drivers/net/mipsnet.h index 0132c6714a40..026c732024c9 100644 --- a/trunk/drivers/net/mipsnet.h +++ b/trunk/drivers/net/mipsnet.h @@ -9,34 +9,32 @@ /* * Id of this Net device, as seen by the core. */ -#define MIPS_NET_DEV_ID ((uint64_t) \ - ((uint64_t) 'M' << 0)| \ - ((uint64_t) 'I' << 8)| \ - ((uint64_t) 'P' << 16)| \ - ((uint64_t) 'S' << 24)| \ - ((uint64_t) 'N' << 32)| \ - ((uint64_t) 'E' << 40)| \ - ((uint64_t) 'T' << 48)| \ - ((uint64_t) '0' << 56)) +#define MIPS_NET_DEV_ID ((uint64_t) \ + ((uint64_t)'M'<< 0)| \ + ((uint64_t)'I'<< 8)| \ + ((uint64_t)'P'<<16)| \ + ((uint64_t)'S'<<24)| \ + ((uint64_t)'N'<<32)| \ + ((uint64_t)'E'<<40)| \ + ((uint64_t)'T'<<48)| \ + ((uint64_t)'0'<<56)) /* * Net status/control block as seen by sw in the core. * (Why not use bit fields? can't be bothered with cross-platform struct * packing.) */ -struct net_control_block { - /* - * dev info for probing - * reads as MIPSNET%d where %d is some form of version - */ - uint64_t devId; /* 0x00 */ +typedef struct _net_control_block { + /// dev info for probing + /// reads as MIPSNET%d where %d is some form of version + uint64_t devId; /*0x00 */ /* * read only busy flag. * Set and cleared by the Net Device to indicate that an rx or a tx * is in progress. */ - uint32_t busy; /* 0x08 */ + uint32_t busy; /*0x08 */ /* * Set by the Net Device. @@ -45,16 +43,16 @@ struct net_control_block { * rxDataBuffer. The value will decrease till 0 until all the data * from rxDataBuffer has been read. */ - uint32_t rxDataCount; /* 0x0c */ + uint32_t rxDataCount; /*0x0c */ #define MIPSNET_MAX_RXTX_DATACOUNT (1<<16) /* - * Settable from the MIPS core, cleared by the Net Device. The core - * should set the number of bytes it wants to send, then it should - * write those bytes of data to txDataBuffer. The device will clear - * txDataCount has been processed (not necessarily sent). + * Settable from the MIPS core, cleared by the Net Device. + * The core should set the number of bytes it wants to send, + * then it should write those bytes of data to txDataBuffer. + * The device will clear txDataCount has been processed (not necessarily sent). */ - uint32_t txDataCount; /* 0x10 */ + uint32_t txDataCount; /*0x10 */ /* * Interrupt control @@ -71,42 +69,39 @@ struct net_control_block { * To clear the test interrupt, write 0 to this register. */ uint32_t interruptControl; /*0x14 */ -#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0)) -#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1)) -#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31)) -#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \ - MIPSNET_INTCTL_RXDONE | \ - MIPSNET_INTCTL_TESTBIT) +#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0)) +#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1)) +#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31)) +#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT) /* - * Readonly core-specific interrupt info for the device to signal the - * core. The meaning of the contents of this field might change. - * - * TODO: the whole memIntf interrupt scheme is messy: the device should - * have no control what so ever of what VPE/register set is being - * used. The MemIntf should only expose interrupt lines, and - * something in the config should be responsible for the - * line<->core/vpe bindings. + * Readonly core-specific interrupt info for the device to signal the core. + * The meaning of the contents of this field might change. */ - uint32_t interruptInfo; /* 0x18 */ + /*###\todo: the whole memIntf interrupt scheme is messy: the device should have + * no control what so ever of what VPE/register set is being used. + * The MemIntf should only expose interrupt lines, and something in the + * config should be responsible for the line<->core/vpe bindings. + */ + uint32_t interruptInfo; /*0x18 */ /* * This is where the received data is read out. * There is more data to read until rxDataReady is 0. * Only 1 byte at this regs offset is used. */ - uint32_t rxDataBuffer; /* 0x1c */ + uint32_t rxDataBuffer; /*0x1c */ /* - * This is where the data to transmit is written. Data should be - * written for the amount specified in the txDataCount register. Only - * 1 byte at this regs offset is used. + * This is where the data to transmit is written. + * Data should be written for the amount specified in the txDataCount register. + * Only 1 byte at this regs offset is used. */ - uint32_t txDataBuffer; /* 0x20 */ -}; + uint32_t txDataBuffer; /*0x20 */ +} MIPS_T_NetControl; #define MIPSNET_IO_EXTENT 0x40 /* being generous */ -#define field_offset(field) (offsetof(struct net_control_block, field)) +#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field) #endif /* __MIPSNET_H */ diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 64c8151f2004..e8afa101433e 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.2-1.287" +#define MYRI10GE_VERSION_STR "1.3.2-1.269" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -214,8 +214,6 @@ struct myri10ge_priv { unsigned long serial_number; int vendor_specific_offset; int fw_multicast_support; - unsigned long features; - u32 max_tso6; u32 read_dma; u32 write_dma; u32 read_write_dma; @@ -313,7 +311,6 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) static void myri10ge_set_multicast_list(struct net_device *dev); -static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev); static inline void put_be32(__be32 val, __be32 __iomem * p) { @@ -615,7 +612,6 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) __be32 buf[16]; u32 dma_low, dma_high, size; int status, i; - struct myri10ge_cmd cmd; size = 0; status = myri10ge_load_hotplug_firmware(mgp, &size); @@ -692,14 +688,6 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) dev_info(&mgp->pdev->dev, "handoff confirmed\n"); myri10ge_dummy_rdma(mgp, 1); - /* probe for IPv6 TSO support */ - mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; - status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, - &cmd, 0); - if (status == 0) { - mgp->max_tso6 = cmd.data0; - mgp->features |= NETIF_F_TSO6; - } return 0; } @@ -1059,8 +1047,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; - /* allocate an skb to attach the page(s) to. This is done - * after trying LRO, so as to avoid skb allocation overheads */ + /* allocate an skb to attach the page(s) to. */ skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); if (unlikely(skb == NULL)) { @@ -1230,8 +1217,7 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) static int myri10ge_poll(struct napi_struct *napi, int budget) { - struct myri10ge_priv *mgp = - container_of(napi, struct myri10ge_priv, napi); + struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi); struct net_device *netdev = mgp->dev; struct myri10ge_rx_done *rx_done = &mgp->rx_done; int work_done; @@ -1396,18 +1382,6 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) return 0; } -static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) -{ - struct myri10ge_priv *mgp = netdev_priv(netdev); - unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO); - - if (tso_enabled) - netdev->features |= flags; - else - netdev->features &= ~flags; - return 0; -} - static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", @@ -1532,7 +1506,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .set_rx_csum = myri10ge_set_rx_csum, .set_tx_csum = ethtool_op_set_tx_hw_csum, .set_sg = ethtool_op_set_sg, - .set_tso = myri10ge_set_tso, + .set_tso = ethtool_op_set_tso, .get_link = ethtool_op_get_link, .get_strings = myri10ge_get_strings, .get_sset_count = myri10ge_get_sset_count, @@ -2190,8 +2164,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) pseudo_hdr_offset = cksum_offset + skb->csum_offset; /* If the headers are excessively large, then we must * fall back to a software checksum */ - if (unlikely(!mss && (cksum_offset > 255 || - pseudo_hdr_offset > 127))) { + if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { if (skb_checksum_help(skb)) goto drop; cksum_offset = 0; @@ -2211,18 +2184,9 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) /* negative cum_len signifies to the * send loop that we are still in the * header portion of the TSO packet. - * TSO header can be at most 1KB long */ + * TSO header must be at most 134 bytes long */ cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); - /* for IPv6 TSO, the checksum offset stores the - * TCP header length, to save the firmware from - * the need to parse the headers */ - if (skb_is_gso_v6(skb)) { - cksum_offset = tcp_hdrlen(skb); - /* Can only handle headers <= max_tso6 long */ - if (unlikely(-cum_len > mgp->max_tso6)) - return myri10ge_sw_tso(skb, dev); - } /* for TSO, pseudo_hdr_offset holds mss. * The firmware figures out where to put * the checksum by parsing the header. */ @@ -2337,12 +2301,10 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) req++; count++; rdma_count++; - if (cksum_offset != 0 && !(mss && skb_is_gso_v6(skb))) { - if (unlikely(cksum_offset > seglen)) - cksum_offset -= seglen; - else - cksum_offset = 0; - } + if (unlikely(cksum_offset > seglen)) + cksum_offset -= seglen; + else + cksum_offset = 0; } if (frag_idx == frag_cnt) break; @@ -2425,41 +2387,6 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) } -static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev) -{ - struct sk_buff *segs, *curr; - struct myri10ge_priv *mgp = dev->priv; - int status; - - segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6); - if (unlikely(IS_ERR(segs))) - goto drop; - - while (segs) { - curr = segs; - segs = segs->next; - curr->next = NULL; - status = myri10ge_xmit(curr, dev); - if (status != 0) { - dev_kfree_skb_any(curr); - if (segs != NULL) { - curr = segs; - segs = segs->next; - curr->next = NULL; - dev_kfree_skb_any(segs); - } - goto drop; - } - } - dev_kfree_skb_any(skb); - return 0; - -drop: - dev_kfree_skb_any(skb); - mgp->stats.tx_dropped += 1; - return 0; -} - static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) { struct myri10ge_priv *mgp = netdev_priv(dev); @@ -2779,6 +2706,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) } #ifdef CONFIG_PM + static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) { struct myri10ge_priv *mgp; @@ -2859,6 +2787,7 @@ static int myri10ge_resume(struct pci_dev *pdev) return -EIO; } + #endif /* CONFIG_PM */ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) @@ -3025,7 +2954,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp = netdev_priv(netdev); mgp->dev = netdev; - netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight); + netif_napi_add(netdev, &mgp->napi, + myri10ge_poll, myri10ge_napi_weight); mgp->pdev = pdev; mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->pause = myri10ge_flow_control; @@ -3147,7 +3077,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->change_mtu = myri10ge_change_mtu; netdev->set_multicast_list = myri10ge_set_multicast_list; netdev->set_mac_address = myri10ge_set_mac_address; - netdev->features = mgp->features; + netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; if (dac_enabled) netdev->features |= NETIF_F_HIGHDMA; diff --git a/trunk/drivers/net/myri10ge/myri10ge_mcp.h b/trunk/drivers/net/myri10ge/myri10ge_mcp.h index 58e57178c563..a1d2a22296a9 100644 --- a/trunk/drivers/net/myri10ge/myri10ge_mcp.h +++ b/trunk/drivers/net/myri10ge/myri10ge_mcp.h @@ -10,7 +10,7 @@ struct mcp_dma_addr { __be32 low; }; -/* 4 Bytes. 8 Bytes for NDIS drivers. */ +/* 4 Bytes */ struct mcp_slot { __sum16 checksum; __be16 length; @@ -205,87 +205,8 @@ enum myri10ge_mcp_cmd_type { /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned * chipset */ - MXGEFW_CMD_UNALIGNED_STATUS, - /* return data = boolean, true if the chipset is known to be unaligned */ - - MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS, - /* data0 = number of big buffers to use. It must be 0 or a power of 2. - * 0 indicates that the NIC consumes as many buffers as they are required - * for packet. This is the default behavior. - * A power of 2 number indicates that the NIC always uses the specified - * number of buffers for each big receive packet. - * It is up to the driver to ensure that this value is big enough for - * the NIC to be able to receive maximum-sized packets. - */ - - MXGEFW_CMD_GET_MAX_RSS_QUEUES, - MXGEFW_CMD_ENABLE_RSS_QUEUES, - /* data0 = number of slices n (0, 1, ..., n-1) to enable - * data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue. - * If all queues share one interrupt, the driver must have set - * RSS_SHARED_INTERRUPT_DMA before enabling queues. - */ - MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET, - MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA, - /* data0, data1 = bus address lsw, msw */ - MXGEFW_CMD_GET_RSS_TABLE_OFFSET, - /* get the offset of the indirection table */ - MXGEFW_CMD_SET_RSS_TABLE_SIZE, - /* set the size of the indirection table */ - MXGEFW_CMD_GET_RSS_KEY_OFFSET, - /* get the offset of the secret key */ - MXGEFW_CMD_RSS_KEY_UPDATED, - /* tell nic that the secret key's been updated */ - MXGEFW_CMD_SET_RSS_ENABLE, - /* data0 = enable/disable rss - * 0: disable rss. nic does not distribute receive packets. - * 1: enable rss. nic distributes receive packets among queues. - * data1 = hash type - * 1: IPV4 - * 2: TCP_IPV4 - * 3: IPV4 | TCP_IPV4 - */ - - MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, - /* Return data = the max. size of the entire headers of a IPv6 TSO packet. - * If the header size of a IPv6 TSO packet is larger than the specified - * value, then the driver must not use TSO. - * This size restriction only applies to IPv6 TSO. - * For IPv4 TSO, the maximum size of the headers is fixed, and the NIC - * always has enough header buffer to store maximum-sized headers. - */ - - MXGEFW_CMD_SET_TSO_MODE, - /* data0 = TSO mode. - * 0: Linux/FreeBSD style (NIC default) - * 1: NDIS/NetBSD style - */ - - MXGEFW_CMD_MDIO_READ, - /* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */ - MXGEFW_CMD_MDIO_WRITE, - /* data0 = dev_addr, data1 = register/addr, data2 = value */ - - MXGEFW_CMD_XFP_I2C_READ, - /* Starts to get a fresh copy of one byte or of the whole xfp i2c table, the - * obtained data is cached inside the xaui-xfi chip : - * data0 : "all" flag : 0 => get one byte, 1=> get 256 bytes, - * data1 : if (data0 == 0): index of byte to refresh [ not used otherwise ] - * The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes - * During the i2c operation, MXGEFW_CMD_XFP_I2C_READ or MXGEFW_CMD_XFP_BYTE attempts - * will return MXGEFW_CMD_ERROR_BUSY - */ - MXGEFW_CMD_XFP_BYTE, - /* Return the last obtained copy of a given byte in the xfp i2c table - * (copy cached during the last relevant MXGEFW_CMD_XFP_I2C_READ) - * data0 : index of the desired table entry - * Return data = the byte stored at the requested index in the table - */ - - MXGEFW_CMD_GET_VPUMP_OFFSET, - /* Return data = NIC memory offset of mcp_vpump_public_global */ - MXGEFW_CMD_RESET_VPUMP, - /* Resets the VPUMP state */ + MXGEFW_CMD_UNALIGNED_STATUS + /* return data = boolean, true if the chipset is known to be unaligned */ }; enum myri10ge_mcp_cmd_status { @@ -299,10 +220,7 @@ enum myri10ge_mcp_cmd_status { MXGEFW_CMD_ERROR_BAD_PORT, MXGEFW_CMD_ERROR_RESOURCES, MXGEFW_CMD_ERROR_MULTICAST, - MXGEFW_CMD_ERROR_UNALIGNED, - MXGEFW_CMD_ERROR_NO_MDIO, - MXGEFW_CMD_ERROR_XFP_FAILURE, - MXGEFW_CMD_ERROR_XFP_ABSENT + MXGEFW_CMD_ERROR_UNALIGNED }; #define MXGEFW_OLD_IRQ_DATA_LEN 40 diff --git a/trunk/drivers/net/natsemi.c b/trunk/drivers/net/natsemi.c index 50e1ec67ef9c..527f9dcc7f69 100644 --- a/trunk/drivers/net/natsemi.c +++ b/trunk/drivers/net/natsemi.c @@ -1576,7 +1576,7 @@ static int netdev_open(struct net_device *dev) /* Set the timer to check for link beat. */ init_timer(&np->timer); - np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ); + np->timer.expires = jiffies + NATSEMI_TIMER_FREQ; np->timer.data = (unsigned long)dev; np->timer.function = &netdev_timer; /* timer handler */ add_timer(&np->timer); @@ -1856,11 +1856,7 @@ static void netdev_timer(unsigned long data) next_tick = 1; } } - - if (next_tick > 1) - mod_timer(&np->timer, round_jiffies(jiffies + next_tick)); - else - mod_timer(&np->timer, jiffies + next_tick); + mod_timer(&np->timer, jiffies + next_tick); } static void dump_ring(struct net_device *dev) @@ -3314,19 +3310,13 @@ static int natsemi_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); struct netdev_private *np = netdev_priv(dev); - int ret = 0; rtnl_lock(); if (netif_device_present(dev)) goto out; if (netif_running(dev)) { BUG_ON(!np->hands_off); - ret = pci_enable_device(pdev); - if (ret < 0) { - dev_err(&pdev->dev, - "pci_enable_device() failed: %d\n", ret); - goto out; - } + pci_enable_device(pdev); /* pci_power_on(pdev); */ napi_enable(&np->napi); @@ -3341,12 +3331,12 @@ static int natsemi_resume (struct pci_dev *pdev) spin_unlock_irq(&np->lock); enable_irq(dev->irq); - mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ)); + mod_timer(&np->timer, jiffies + 1*HZ); } netif_device_attach(dev); out: rtnl_unlock(); - return ret; + return 0; } #endif /* CONFIG_PM */ diff --git a/trunk/drivers/net/ne-h8300.c b/trunk/drivers/net/ne-h8300.c index fbc7531d3c7d..368f2560856d 100644 --- a/trunk/drivers/net/ne-h8300.c +++ b/trunk/drivers/net/ne-h8300.c @@ -93,7 +93,7 @@ static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr bus_width = *(volatile unsigned char *)ABWCR; bus_width &= 1 << ((base_addr >> 21) & 7); - for (i = 0; i < ARRAY_SIZE(reg_offset); i++) + for (i = 0; i < sizeof(reg_offset) / sizeof(u32); i++) if (bus_width == 0) reg_offset[i] = i * 2 + 1; else @@ -115,7 +115,7 @@ static int h8300_ne_irq[] = {EXT_IRQ5}; static inline int init_dev(struct net_device *dev) { - if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) { + if (h8300_ne_count < (sizeof(h8300_ne_base) / sizeof(unsigned long))) { dev->base_addr = h8300_ne_base[h8300_ne_count]; dev->irq = h8300_ne_irq[h8300_ne_count]; h8300_ne_count++; diff --git a/trunk/drivers/net/saa9730.c b/trunk/drivers/net/saa9730.c index c65199df8a7f..14361e885415 100644 --- a/trunk/drivers/net/saa9730.c +++ b/trunk/drivers/net/saa9730.c @@ -97,16 +97,13 @@ static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) &lp->evm_saa9730_regs->InterruptBlock1); } -static void __used show_saa9730_regs(struct net_device *dev) +static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) { - struct lan_saa9730_private *lp = netdev_priv(dev); int i, j; - printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]); printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]); printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]); printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]); - for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { printk("TxmBuffer[%d][%d] = %x\n", i, j, @@ -149,13 +146,11 @@ static void __used show_saa9730_regs(struct net_device *dev) readl(&lp->lan_saa9730_regs->RxCtl)); printk("lp->lan_saa9730_regs->RxStatus = %x\n", readl(&lp->lan_saa9730_regs->RxStatus)); - for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { writel(i, &lp->lan_saa9730_regs->CamAddress); printk("lp->lan_saa9730_regs->CamData = %x\n", readl(&lp->lan_saa9730_regs->CamData)); } - printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets); printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors); printk("dev->stats.tx_aborted_errors = %lx\n", @@ -860,7 +855,7 @@ static void lan_saa9730_tx_timeout(struct net_device *dev) /* Transmitter timeout, serious problems */ dev->stats.tx_errors++; printk("%s: transmit timed out, reset\n", dev->name); - /*show_saa9730_regs(dev); */ + /*show_saa9730_regs(lp); */ lan_saa9730_restart(lp); dev->trans_start = jiffies; diff --git a/trunk/drivers/net/tc35815.c b/trunk/drivers/net/tc35815.c index 8038f2882c9b..a679f4310ce1 100644 --- a/trunk/drivers/net/tc35815.c +++ b/trunk/drivers/net/tc35815.c @@ -1461,6 +1461,7 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id) } return IRQ_NONE; #else + struct tc35815_local *lp = dev->priv; int handled; u32 status; diff --git a/trunk/drivers/net/tehuti.c b/trunk/drivers/net/tehuti.c index 4e1b84e6d66a..8d04654f0c59 100644 --- a/trunk/drivers/net/tehuti.c +++ b/trunk/drivers/net/tehuti.c @@ -1906,7 +1906,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /************** pci *****************/ if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */ - goto err_pci; /* it's not a problem though */ + RET(err); /* it's not a problem though */ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { @@ -2076,7 +2076,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_release_regions(pdev); err_dma: pci_disable_device(pdev); -err_pci: vfree(nic); RET(err); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 76efb3feffbf..30b1cca8144c 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -9034,7 +9034,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) int i; u32 j; - for (i = 0; i < ARRAY_SIZE(test_pattern); i++) { + for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { for (j = 0; j < len; j += 4) { u32 val; diff --git a/trunk/drivers/net/tulip/de4x5.c b/trunk/drivers/net/tulip/de4x5.c index 41f34bb91cad..9b9cd83fb8b6 100644 --- a/trunk/drivers/net/tulip/de4x5.c +++ b/trunk/drivers/net/tulip/de4x5.c @@ -1041,7 +1041,7 @@ static struct InfoLeaf infoleaf_array[] = { {DC21142, dc21142_infoleaf}, {DC21143, dc21143_infoleaf} }; -#define INFOLEAF_SIZE ARRAY_SIZE(infoleaf_array) +#define INFOLEAF_SIZE (sizeof(infoleaf_array)/(sizeof(int)+sizeof(int *))) /* ** List the SROM info block functions @@ -1056,7 +1056,7 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = { compact_infoblock }; -#define COMPACT (ARRAY_SIZE(dc_infoblock) - 1) +#define COMPACT (sizeof(dc_infoblock)/sizeof(int *) - 1) /* ** Miscellaneous defines... diff --git a/trunk/drivers/net/ucc_geth.c b/trunk/drivers/net/ucc_geth.c index bec413ba9bca..d00e7d41f6a5 100644 --- a/trunk/drivers/net/ucc_geth.c +++ b/trunk/drivers/net/ucc_geth.c @@ -63,7 +63,7 @@ #define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 void uec_set_ethtool_ops(struct net_device *netdev); - + static DEFINE_SPINLOCK(ugeth_lock); static struct { @@ -3454,12 +3454,9 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit u16 length, howmany = 0; u32 bd_status; u8 *bdBuffer; - struct net_device * dev; ugeth_vdbg("%s: IN", __FUNCTION__); - dev = ugeth->dev; - /* collect received buffers */ bd = ugeth->rxBd[rxQ]; diff --git a/trunk/drivers/net/wan/sdla.c b/trunk/drivers/net/wan/sdla.c index 05df0a345b60..b39a541b2509 100644 --- a/trunk/drivers/net/wan/sdla.c +++ b/trunk/drivers/net/wan/sdla.c @@ -1342,11 +1342,11 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map) if (flp->initialized) return(-EINVAL); - for(i=0; i < ARRAY_SIZE(valid_port); i++) + for(i=0;i < sizeof(valid_port) / sizeof (int) ; i++) if (valid_port[i] == map->base_addr) break; - if (i == ARRAY_SIZE(valid_port)) + if (i == sizeof(valid_port) / sizeof(int)) return(-EINVAL); if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ @@ -1487,12 +1487,12 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map) } } - for(i=0; i < ARRAY_SIZE(valid_mem); i++) + for(i=0;i < sizeof(valid_mem) / sizeof (int) ; i++) if (valid_mem[i] == map->mem_start) break; err = -EINVAL; - if (i == ARRAY_SIZE(valid_mem)) + if (i == sizeof(valid_mem) / sizeof(int)) goto fail2; if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E) diff --git a/trunk/drivers/net/xen-netfront.c b/trunk/drivers/net/xen-netfront.c index 7fd505cc4f7a..f464b82c7d5f 100644 --- a/trunk/drivers/net/xen-netfront.c +++ b/trunk/drivers/net/xen-netfront.c @@ -74,12 +74,22 @@ struct netfront_info { struct napi_struct napi; - unsigned int evtchn; - struct xenbus_device *xbdev; + struct xen_netif_tx_front_ring tx; + struct xen_netif_rx_front_ring rx; spinlock_t tx_lock; - struct xen_netif_tx_front_ring tx; - int tx_ring_ref; + spinlock_t rx_lock; + + unsigned int evtchn; + + /* Receive-ring batched refills. */ +#define RX_MIN_TARGET 8 +#define RX_DFL_MIN_TARGET 64 +#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) + unsigned rx_min_target, rx_max_target, rx_target; + struct sk_buff_head rx_batch; + + struct timer_list rx_refill_timer; /* * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries @@ -98,23 +108,14 @@ struct netfront_info { grant_ref_t grant_tx_ref[NET_TX_RING_SIZE]; unsigned tx_skb_freelist; - spinlock_t rx_lock ____cacheline_aligned_in_smp; - struct xen_netif_rx_front_ring rx; - int rx_ring_ref; - - /* Receive-ring batched refills. */ -#define RX_MIN_TARGET 8 -#define RX_DFL_MIN_TARGET 64 -#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) - unsigned rx_min_target, rx_max_target, rx_target; - struct sk_buff_head rx_batch; - - struct timer_list rx_refill_timer; - struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; grant_ref_t gref_rx_head; grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; + struct xenbus_device *xbdev; + int tx_ring_ref; + int rx_ring_ref; + unsigned long rx_pfn_array[NET_RX_RING_SIZE]; struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; struct mmu_update rx_mmu[NET_RX_RING_SIZE]; diff --git a/trunk/drivers/scsi/gdth.c b/trunk/drivers/scsi/gdth.c index 3ac080ee6e2f..e8010a702e73 100644 --- a/trunk/drivers/scsi/gdth.c +++ b/trunk/drivers/scsi/gdth.c @@ -5213,10 +5213,6 @@ static int __init gdth_init(void) #endif /* CONFIG_PCI */ TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); - - if (list_empty(&gdth_instances)) - return -ENODEV; - #ifdef GDTH_STATISTICS TRACE2(("gdth_detect(): Initializing timer !\n")); init_timer(&gdth_timer); diff --git a/trunk/include/asm-blackfin/mach-bf548/bf54x_keys.h b/trunk/include/asm-blackfin/mach-bf548/bf54x_keys.h deleted file mode 100644 index 1fb4ec77cc25..000000000000 --- a/trunk/include/asm-blackfin/mach-bf548/bf54x_keys.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _BFIN_KPAD_H -#define _BFIN_KPAD_H - -struct bfin_kpad_platform_data { - int rows; - int cols; - const unsigned int *keymap; - unsigned short keymapsize; - unsigned short repeat; - u32 debounce_time; /* in ns */ - u32 coldrive_time; /* in ns */ - u32 keyup_test_interval; /* in ms */ -}; - -#define KEYVAL(col, row, val) (((1 << col) << 24) | ((1 << row) << 16) | (val)) - -#endif diff --git a/trunk/include/asm-mips/mach-au1x00/prom.h b/trunk/include/asm-mips/mach-au1x00/prom.h deleted file mode 100644 index e38715577c51..000000000000 --- a/trunk/include/asm-mips/mach-au1x00/prom.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __AU1X00_PROM_H -#define __AU1X00_PROM_H - -extern int prom_argc; -extern char **prom_argv; -extern char **prom_envp; - -extern void prom_init_cmdline(void); -extern char *prom_getcmdline(void); -extern char *prom_getenv(char *envname); -extern int prom_get_ethernet_addr(char *ethernet_addr); - -#endif diff --git a/trunk/include/asm-powerpc/dcr-mmio.h b/trunk/include/asm-powerpc/dcr-mmio.h index 08532ff1899c..6b82c3ba495a 100644 --- a/trunk/include/asm-powerpc/dcr-mmio.h +++ b/trunk/include/asm-powerpc/dcr-mmio.h @@ -33,16 +33,16 @@ typedef struct { extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, unsigned int dcr_c); -extern void dcr_unmap(dcr_host_t host, unsigned int dcr_c); +extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c); static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) { - return in_be32(host.token + ((host.base + dcr_n) * host.stride)); + return in_be32(host.token + dcr_n * host.stride); } static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) { - out_be32(host.token + ((host.base + dcr_n) * host.stride), value); + out_be32(host.token + dcr_n * host.stride, value); } extern u64 of_translate_dcr_address(struct device_node *dev, diff --git a/trunk/include/asm-powerpc/dcr-native.h b/trunk/include/asm-powerpc/dcr-native.h index 8dbb1ab0aa04..f41058c0f6cb 100644 --- a/trunk/include/asm-powerpc/dcr-native.h +++ b/trunk/include/asm-powerpc/dcr-native.h @@ -29,9 +29,9 @@ typedef struct { #define DCR_MAP_OK(host) (1) #define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) }) -#define dcr_unmap(host, dcr_c) do {} while (0) -#define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base) -#define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value) +#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0) +#define dcr_read(host, dcr_n) mfdcr(dcr_n) +#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) /* Device Control Registers */ void __mtdcr(int reg, unsigned int val); diff --git a/trunk/include/linux/gpio_keys.h b/trunk/include/linux/gpio_keys.h index c6d3a9de5634..265d17830a0f 100644 --- a/trunk/include/linux/gpio_keys.h +++ b/trunk/include/linux/gpio_keys.h @@ -8,7 +8,6 @@ struct gpio_keys_button { int active_low; char *desc; int type; /* input event type (EV_KEY, EV_SW) */ - int wakeup; /* configure the button as a wake-up source */ }; struct gpio_keys_platform_data { diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index f30da6fc08e3..52d1bd434a50 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -856,7 +856,7 @@ struct ff_rumble_effect { * defining effect parameters * * This structure is sent through ioctl from the application to the driver. - * To create a new effect application should set its @id to -1; the kernel + * To create a new effect aplication should set its @id to -1; the kernel * will return assigned @id which can later be used to update or delete * this effect. * @@ -936,82 +936,9 @@ struct ff_effect { #define BIT(x) (1UL<<((x)%BITS_PER_LONG)) #define LONG(x) ((x)/BITS_PER_LONG) -/** - * struct input_dev - represents an input device - * @name: name of the device - * @phys: physical path to the device in the system hierarchy - * @uniq: unique identification code for the device (if device has it) - * @id: id of the device (struct input_id) - * @evbit: bitmap of types of events supported by the device (EV_KEY, - * EV_REL, etc.) - * @keybit: bitmap of keys/buttons this device has - * @relbit: bitmap of relative axes for the device - * @absbit: bitmap of absolute axes for the device - * @mscbit: bitmap of miscellaneous events supported by the device - * @ledbit: bitmap of leds present on the device - * @sndbit: bitmap of sound effects supported by the device - * @ffbit: bitmap of force feedback effects supported by the device - * @swbit: bitmap of switches present on the device - * @keycodemax: size of keycode table - * @keycodesize: size of elements in keycode table - * @keycode: map of scancodes to keycodes for this device - * @setkeycode: optional method to alter current keymap, used to implement - * sparse keymaps. If not supplied default mechanism will be used - * @getkeycode: optional method to retrieve current keymap. If not supplied - * default mechanism will be used - * @ff: force feedback structure associated with the device if device - * supports force feedback effects - * @repeat_key: stores key code of the last key pressed; used to implement - * software autorepeat - * @timer: timer for software autorepeat - * @sync: set to 1 when there were no new events since last EV_SYNC - * @abs: current values for reports from absolute axes - * @rep: current values for autorepeat parameters (delay, rate) - * @key: reflects current state of device's keys/buttons - * @led: reflects current state of device's LEDs - * @snd: reflects current state of sound effects - * @sw: reflects current state of device's switches - * @absmax: maximum values for events coming from absolute axes - * @absmin: minimum values for events coming from absolute axes - * @absfuzz: describes noisiness for axes - * @absflat: size of the center flat position (used by joydev) - * @open: this method is called when the very first user calls - * input_open_device(). The driver must prepare the device - * to start generating events (start polling thread, - * request an IRQ, submit URB, etc.) - * @close: this method is called when the very last user calls - * input_close_device(). - * @flush: purges the device. Most commonly used to get rid of force - * feedback effects loaded into the device when disconnecting - * from it - * @event: event handler for events sent _to_ the device, like EV_LED - * or EV_SND. The device is expected to carry out the requested - * action (turn on a LED, play sound, etc.) The call is protected - * by @event_lock and must not sleep - * @grab: input handle that currently has the device grabbed (via - * EVIOCGRAB ioctl). When a handle grabs a device it becomes sole - * recipient for all input events coming from the device - * @event_lock: this spinlock is is taken when input core receives - * and processes a new event for the device (in input_event()). - * Code that accesses and/or modifies parameters of a device - * (such as keymap or absmin, absmax, absfuzz, etc.) after device - * has been registered with input core must take this lock. - * @mutex: serializes calls to open(), close() and flush() methods - * @users: stores number of users (input handlers) that opened this - * device. It is used by input_open_device() and input_close_device() - * to make sure that dev->open() is only called when the first - * user opens device and dev->close() is called when the very - * last user closes the device - * @going_away: marks devices that are in a middle of unregistering and - * causes input_open_device*() fail with -ENODEV. - * @dev: driver model's view of this device - * @h_list: list of input handles associated with the device. When - * accessing the list dev->mutex must be held - * @node: used to place the device onto input_dev_list - */ struct input_dev { - void *private; /* do not use */ + void *private; const char *name; const char *phys; @@ -1039,6 +966,8 @@ struct input_dev { unsigned int repeat_key; struct timer_list timer; + int state; + int sync; int abs[ABS_MAX + 1]; @@ -1061,11 +990,8 @@ struct input_dev { struct input_handle *grab; - spinlock_t event_lock; - struct mutex mutex; - + struct mutex mutex; /* serializes open and close operations */ unsigned int users; - int going_away; struct device dev; union { /* temporarily so while we switching to struct device */ @@ -1131,9 +1057,7 @@ struct input_handle; /** * struct input_handler - implements one of interfaces for input devices * @private: driver-specific data - * @event: event handler. This method is being called by input core with - * interrupts disabled and dev->event_lock spinlock held and so - * it may not sleep + * @event: event handler * @connect: called when attaching a handler to an input device * @disconnect: disconnects a handler from input device * @start: starts handler for given handle. This function is called by @@ -1145,18 +1069,10 @@ struct input_handle; * @name: name of the handler, to be shown in /proc/bus/input/handlers * @id_table: pointer to a table of input_device_ids this driver can * handle - * @blacklist: pointer to a table of input_device_ids this driver should + * @blacklist: prointer to a table of input_device_ids this driver should * ignore even if they match @id_table * @h_list: list of input handles associated with the handler * @node: for placing the driver onto input_handler_list - * - * Input handlers attach to input devices and create input handles. There - * are likely several handlers attached to any given input device at the - * same time. All of them will get their copy of input event generated by - * the device. - * - * Note that input core serializes calls to connect() and disconnect() - * methods. */ struct input_handler { @@ -1178,18 +1094,6 @@ struct input_handler { struct list_head node; }; -/** - * struct input_handle - links input device with an input handler - * @private: handler-specific data - * @open: counter showing whether the handle is 'open', i.e. should deliver - * events from its device - * @name: name given to the handle by handler that created it - * @dev: input device the handle is attached to - * @handler: handler that works with the device through this handle - * @d_node: used to put the handle on device's list of attached handles - * @h_node: used to put the handle on handler's list of handles from which - * it gets events - */ struct input_handle { void *private; @@ -1232,10 +1136,10 @@ static inline void input_set_drvdata(struct input_dev *dev, void *data) dev->private = data; } -int __must_check input_register_device(struct input_dev *); +int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); -int __must_check input_register_handler(struct input_handler *); +int input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); int input_register_handle(struct input_handle *); @@ -1312,7 +1216,7 @@ extern struct class input_class; * @max_effects: maximum number of effects supported by device * @effects: pointer to an array of effects currently loaded into device * @effect_owners: array of effect owners; when file handle owning - * an effect gets closed the effect is automatically erased + * an effect gets closed the effcet is automatically erased * * Every force-feedback device must implement upload() and playback() * methods; erase() is optional. set_gain() and set_autocenter() need diff --git a/trunk/include/linux/keyboard.h b/trunk/include/linux/keyboard.h index 33b5c2e325b9..7ddbc30aa8e7 100644 --- a/trunk/include/linux/keyboard.h +++ b/trunk/include/linux/keyboard.h @@ -416,7 +416,6 @@ extern unsigned short plain_map[NR_KEYS]; #define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) #define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) #define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) -#define K_CAPSSHIFTLOCK K(KT_LOCK,KG_CAPSSHIFT) #define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT) #define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL) @@ -426,9 +425,8 @@ extern unsigned short plain_map[NR_KEYS]; #define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR) #define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL) #define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) -#define K_CAPSSHIFT_SLOCK K(KT_SLOCK,KG_CAPSSHIFT) -#define NR_LOCK 9 +#define NR_LOCK 8 #define K_BRL_BLANK K(KT_BRL, 0) #define K_BRL_DOT1 K(KT_BRL, 1) diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 8101e8b0d7ba..a656cecd373c 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -1781,11 +1781,6 @@ static inline int skb_is_gso(const struct sk_buff *skb) return skb_shinfo(skb)->gso_size; } -static inline int skb_is_gso_v6(const struct sk_buff *skb) -{ - return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; -} - static inline void skb_forward_csum(struct sk_buff *skb) { /* Unfortunately we don't support this one. Any brave souls? */ diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 944189d96323..758bbef506d3 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -362,6 +362,44 @@ void kfree_skb(struct sk_buff *skb) __kfree_skb(skb); } +static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) +{ + new->tstamp = old->tstamp; + new->dev = old->dev; + new->transport_header = old->transport_header; + new->network_header = old->network_header; + new->mac_header = old->mac_header; + new->dst = dst_clone(old->dst); +#ifdef CONFIG_INET + new->sp = secpath_get(old->sp); +#endif + memcpy(new->cb, old->cb, sizeof(old->cb)); + new->csum_start = old->csum_start; + new->csum_offset = old->csum_offset; + new->local_df = old->local_df; + new->pkt_type = old->pkt_type; + new->ip_summed = old->ip_summed; + skb_copy_queue_mapping(new, old); + new->priority = old->priority; +#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) + new->ipvs_property = old->ipvs_property; +#endif + new->protocol = old->protocol; + new->mark = old->mark; + __nf_copy(new, old); +#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ + defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) + new->nf_trace = old->nf_trace; +#endif +#ifdef CONFIG_NET_SCHED + new->tc_index = old->tc_index; +#ifdef CONFIG_NET_CLS_ACT + new->tc_verd = old->tc_verd; +#endif +#endif + skb_copy_secmark(new, old); +} + /** * skb_clone - duplicate an sk_buff * @skb: buffer to clone @@ -397,51 +435,22 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) n->next = n->prev = NULL; n->sk = NULL; - C(tstamp); - C(dev); - C(transport_header); - C(network_header); - C(mac_header); - C(dst); - dst_clone(skb->dst); - C(sp); -#ifdef CONFIG_INET - secpath_get(skb->sp); -#endif - memcpy(n->cb, skb->cb, sizeof(skb->cb)); + __copy_skb_header(n, skb); + C(len); C(data_len); C(mac_len); - C(csum); - C(local_df); n->cloned = 1; n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; n->nohdr = 0; - C(pkt_type); - C(ip_summed); - skb_copy_queue_mapping(n, skb); - C(priority); -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) - C(ipvs_property); -#endif - C(protocol); n->destructor = NULL; - C(mark); - __nf_copy(n, skb); -#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ - defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) - C(nf_trace); -#endif -#ifdef CONFIG_NET_SCHED - C(tc_index); #ifdef CONFIG_NET_CLS_ACT - n->tc_verd = SET_TC_VERD(skb->tc_verd,0); + /* FIXME What is this and why don't we do it in copy_skb_header? */ + n->tc_verd = SET_TC_VERD(n->tc_verd,0); n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); n->tc_verd = CLR_TC_MUNGED(n->tc_verd); C(iif); #endif -#endif - skb_copy_secmark(n, skb); C(truesize); atomic_set(&n->users, 1); C(head); @@ -463,50 +472,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) */ unsigned long offset = new->data - old->data; #endif - new->sk = NULL; - new->dev = old->dev; - skb_copy_queue_mapping(new, old); - new->priority = old->priority; - new->protocol = old->protocol; - new->dst = dst_clone(old->dst); -#ifdef CONFIG_INET - new->sp = secpath_get(old->sp); -#endif - new->csum_start = old->csum_start; - new->csum_offset = old->csum_offset; - new->ip_summed = old->ip_summed; - new->transport_header = old->transport_header; - new->network_header = old->network_header; - new->mac_header = old->mac_header; + + __copy_skb_header(new, old); + #ifndef NET_SKBUFF_DATA_USES_OFFSET /* {transport,network,mac}_header are relative to skb->head */ new->transport_header += offset; new->network_header += offset; new->mac_header += offset; #endif - memcpy(new->cb, old->cb, sizeof(old->cb)); - new->local_df = old->local_df; - new->fclone = SKB_FCLONE_UNAVAILABLE; - new->pkt_type = old->pkt_type; - new->tstamp = old->tstamp; - new->destructor = NULL; - new->mark = old->mark; - __nf_copy(new, old); -#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ - defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) - new->nf_trace = old->nf_trace; -#endif -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) - new->ipvs_property = old->ipvs_property; -#endif -#ifdef CONFIG_NET_SCHED -#ifdef CONFIG_NET_CLS_ACT - new->tc_verd = old->tc_verd; -#endif - new->tc_index = old->tc_index; -#endif - skb_copy_secmark(new, old); - atomic_set(&new->users, 1); skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;