summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-09-25 02:17:47 -0700
committerPatrick Mochel <mochel@osdl.org>2003-09-25 02:17:47 -0700
commit9559f65da4677764ebcba5e37408698b3a413c09 (patch)
tree64510d518869a80ccb65f2c72778c84d526dc784
parent70b812cda02d7c74d3122666a44e103ec610793b (diff)
parent729fe396d4ccf2348bc3ff6c9eef9f8a6d7148cf (diff)
Merge bk://kernel.bkbits.net//home/mochel/linux-2.5-power
into osdl.org:/home/mochel/src/kernel/linux-2.5-power
-rw-r--r--Documentation/i2c/sysfs-interface5
-rw-r--r--drivers/block/ll_rw_blk.c9
-rw-r--r--drivers/i2c/Kconfig38
-rw-r--r--drivers/i2c/Makefile5
-rw-r--r--drivers/i2c/algos/Kconfig45
-rw-r--r--drivers/i2c/algos/Makefile7
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c (renamed from drivers/i2c/i2c-algo-bit.c)0
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c (renamed from drivers/i2c/i2c-algo-ite.c)2
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.h (renamed from drivers/i2c/i2c-ite.h)0
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c (renamed from drivers/i2c/i2c-algo-pcf.c)2
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.h (renamed from drivers/i2c/i2c-pcf8584.h)0
-rw-r--r--drivers/i2c/busses/i2c-elektor.c2
-rw-r--r--drivers/i2c/chips/Kconfig12
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/eeprom.c276
-rw-r--r--drivers/i2c/i2c-sensor.c5
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/Makefile.lib1
-rw-r--r--drivers/usb/class/usb-midi.c2
-rw-r--r--drivers/usb/core/config.c3
-rw-r--r--drivers/usb/core/driverfs.c26
-rw-r--r--drivers/usb/core/hcd-pci.c14
-rw-r--r--drivers/usb/core/message.c126
-rw-r--r--drivers/usb/core/usb.c85
-rw-r--r--drivers/usb/gadget/ether.c241
-rw-r--r--drivers/usb/gadget/inode.c34
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/image/scanner.c37
-rw-r--r--drivers/usb/image/scanner.h19
-rw-r--r--drivers/usb/input/Kconfig4
-rw-r--r--drivers/usb/net/Kconfig19
-rw-r--r--drivers/usb/net/Makefile1
-rw-r--r--drivers/usb/net/Makefile.mii1
-rw-r--r--drivers/usb/net/ax8817x.c1340
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c8
-rw-r--r--drivers/usb/serial/ftdi_sio.h7
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/storage/transport.c1
39 files changed, 772 insertions, 1615 deletions
diff --git a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
index a62f15ecaf3e..d601296ce5a9 100644
--- a/Documentation/i2c/sysfs-interface
+++ b/Documentation/i2c/sysfs-interface
@@ -77,7 +77,10 @@ curr_min[1-n] Current min or hysteresis value.
curr_input[1-n] Current input value
Fixed point XXXXX, divide by 1000 to get Amps.
Read only.
-
+
+eeprom Raw EEPROM data in binary form.
+ Read only.
+
fan_min[1-3] Fan minimum value
Integer value indicating RPM
Read/Write.
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 339d8c50e2c5..1284a252dace 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -376,6 +376,11 @@ void blk_queue_hardsect_size(request_queue_t *q, unsigned short size)
q->hardsect_size = size;
}
+/*
+ * Returns the minimum that is _not_ zero, unless both are zero.
+ */
+#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
+
/**
* blk_queue_stack_limits - inherit underlying queue limits for stacked drivers
* @t: the stacking driver (top)
@@ -383,7 +388,9 @@ void blk_queue_hardsect_size(request_queue_t *q, unsigned short size)
**/
void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
{
- t->max_sectors = min(t->max_sectors,b->max_sectors);
+ /* zero is "infinity" */
+ t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
+
t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
t->max_segment_size = min(t->max_segment_size,b->max_segment_size);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 939448e93662..da0727d9377f 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -37,43 +37,7 @@ config I2C_CHARDEV
This support is also available as a module. If so, the module
will be called i2c-dev.
-config I2C_ALGOBIT
- tristate "I2C bit-banging interfaces"
- depends on I2C
- help
- This allows you to use a range of I2C adapters called bit-banging
- adapters. Say Y if you own an I2C adapter belonging to this class
- and then say Y to the specific driver for you adapter below.
-
- This support is also available as a module. If so, the module
- will be called i2c-algo-bit.
-
-config I2C_ALGOPCF
- tristate "I2C PCF 8584 interfaces"
- depends on I2C
- help
- This allows you to use a range of I2C adapters called PCF adapters.
- Say Y if you own an I2C adapter belonging to this class and then say
- Y to the specific driver for you adapter below.
-
- This support is also available as a module. If so, the module
- will be called i2c-algo-pcf.
-
-config I2C_ALGOITE
- tristate "ITE I2C Algorithm"
- depends on MIPS_ITE8172 && I2C
- help
- This supports the use of the ITE8172 I2C interface found on some MIPS
- systems. Say Y if you have one of these. You should also say Y for
- the ITE I2C peripheral driver support below.
-
- This support is also available as a module. If so, the module
- will be called i2c-algo-ite.
-
-config I2C_ALGO8XX
- tristate "MPC8xx CPM I2C interface"
- depends on 8xx && I2C
-
+ source drivers/i2c/algos/Kconfig
source drivers/i2c/busses/Kconfig
source drivers/i2c/chips/Kconfig
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 1cec46521453..b2ded05c1e7f 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -5,7 +5,4 @@
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
-obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
-obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
-obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
-obj-y += busses/ chips/
+obj-y += busses/ chips/ algos/
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
new file mode 100644
index 000000000000..04d3e0b7c450
--- /dev/null
+++ b/drivers/i2c/algos/Kconfig
@@ -0,0 +1,45 @@
+#
+# Character device configuration
+#
+
+menu "I2C Algorithms"
+
+config I2C_ALGOBIT
+ tristate "I2C bit-banging interfaces"
+ depends on I2C
+ help
+ This allows you to use a range of I2C adapters called bit-banging
+ adapters. Say Y if you own an I2C adapter belonging to this class
+ and then say Y to the specific driver for you adapter below.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-algo-bit.
+
+config I2C_ALGOPCF
+ tristate "I2C PCF 8584 interfaces"
+ depends on I2C
+ help
+ This allows you to use a range of I2C adapters called PCF adapters.
+ Say Y if you own an I2C adapter belonging to this class and then say
+ Y to the specific driver for you adapter below.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-algo-pcf.
+
+config I2C_ALGOITE
+ tristate "ITE I2C Algorithm"
+ depends on MIPS_ITE8172 && I2C
+ help
+ This supports the use of the ITE8172 I2C interface found on some MIPS
+ systems. Say Y if you have one of these. You should also say Y for
+ the ITE I2C peripheral driver support below.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-algo-ite.
+
+config I2C_ALGO8XX
+ tristate "MPC8xx CPM I2C interface"
+ depends on 8xx && I2C
+
+endmenu
+
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
new file mode 100644
index 000000000000..fba9ef96d68c
--- /dev/null
+++ b/drivers/i2c/algos/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the i2c algorithms
+#
+
+obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
+obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
+obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
diff --git a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index f8330b3ef5d3..f8330b3ef5d3 100644
--- a/drivers/i2c/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
diff --git a/drivers/i2c/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index f53adcd25dd4..d8f601a31672 100644
--- a/drivers/i2c/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -46,7 +46,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-ite.h>
-#include "i2c-ite.h"
+#include "i2c-algo-ite.h"
#define PM_DSR IT8172_PCI_IO_BASE + IT_PM_DSR
#define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04
diff --git a/drivers/i2c/i2c-ite.h b/drivers/i2c/algos/i2c-algo-ite.h
index a8ca3c9b546a..a8ca3c9b546a 100644
--- a/drivers/i2c/i2c-ite.h
+++ b/drivers/i2c/algos/i2c-algo-ite.h
diff --git a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index f8af2ffc85ca..6ed11937c00e 100644
--- a/drivers/i2c/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -37,7 +37,7 @@
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-pcf.h>
-#include "i2c-pcf8584.h"
+#include "i2c-algo-pcf.h"
/* ----- global defines ----------------------------------------------- */
diff --git a/drivers/i2c/i2c-pcf8584.h b/drivers/i2c/algos/i2c-algo-pcf.h
index 4908ebae5526..4908ebae5526 100644
--- a/drivers/i2c/i2c-pcf8584.h
+++ b/drivers/i2c/algos/i2c-algo-pcf.h
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 98db1a13a0c2..2a8b03bd8bbd 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -41,7 +41,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include "../i2c-pcf8584.h"
+#include "../algos/i2c-algo-pcf.h"
#define DEFAULT_BASE 0x330
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 7c0db1408429..7e8db5a4bfb0 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -21,6 +21,18 @@ config SENSORS_ADM1021
This driver can also be built as a module. If so, the module
will be called adm1021.
+config SENSORS_EEPROM
+ tristate "EEPROM (DIMM) reader"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get read-only access to the EEPROM data
+ available on modern memory DIMMs, and which could theoretically
+ also be available on other devices.
+
+ This driver can also be built as a module. If so, the module
+ will be called eeprom.
+
config SENSORS_IT87
tristate "National Semiconductors IT87 and compatibles"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 7c244c8b5cd0..e4896edfae26 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
+obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_LM78) += lm78.o
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
new file mode 100644
index 000000000000..7e8940a3c7e2
--- /dev/null
+++ b/drivers/i2c/chips/eeprom.c
@@ -0,0 +1,276 @@
+/*
+ eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
+ Philip Edelbrock <phil@netroedge.com>
+ Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
+ Copyright (C) 2003 IBM Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* #define DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { 0x50, 0x57, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(eeprom);
+
+static int checksum = 0;
+MODULE_PARM(checksum, "i");
+MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
+
+
+/* EEPROM registers */
+#define EEPROM_REG_CHECKSUM 0x3f
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE 256
+
+/* possible types of eeprom devices */
+enum eeprom_nature {
+ UNKNOWN,
+ VAIO,
+};
+
+/* Each client has this additional data */
+struct eeprom_data {
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 data[EEPROM_SIZE]; /* Register values */
+};
+
+
+static int eeprom_attach_adapter(struct i2c_adapter *adapter);
+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
+static int eeprom_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver eeprom_driver = {
+ .owner = THIS_MODULE,
+ .name = "eeprom",
+ .id = I2C_DRIVERID_EEPROM,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = eeprom_attach_adapter,
+ .detach_client = eeprom_detach_client,
+};
+
+static int eeprom_id = 0;
+
+static void eeprom_update_client(struct i2c_client *client)
+{
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ int i, j;
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > 300 * HZ) |
+ (jiffies < data->last_updated) || !data->valid) {
+ dev_dbg(&client->dev, "Starting eeprom update\n");
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ for (i=0; i < EEPROM_SIZE; i += I2C_SMBUS_I2C_BLOCK_MAX)
+ if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_I2C_BLOCK_MAX)
+ goto exit;
+ } else {
+ if (i2c_smbus_write_byte(client, 0)) {
+ dev_dbg(&client->dev, "eeprom read start has failed!\n");
+ goto exit;
+ }
+ for (i = 0; i < EEPROM_SIZE; i++) {
+ j = i2c_smbus_read_byte(client);
+ if (j < 0)
+ goto exit;
+ data->data[i] = (u8) j;
+ }
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+exit:
+ up(&data->update_lock);
+}
+
+static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct eeprom_data *data = i2c_get_clientdata(client);
+
+ eeprom_update_client(client);
+
+ if (off > EEPROM_SIZE)
+ return 0;
+ if (off + count > EEPROM_SIZE)
+ count = EEPROM_SIZE - off;
+
+ memcpy(buf, &data->data[off], count);
+ return count;
+}
+
+static struct bin_attribute eeprom_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = eeprom_read,
+};
+
+static int eeprom_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, eeprom_detect);
+}
+
+/* This function is called by i2c_detect */
+int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int i, cs;
+ struct i2c_client *new_client;
+ struct eeprom_data *data;
+ enum eeprom_nature nature = UNKNOWN;
+ int err = 0;
+
+ /* Make sure we aren't probing the ISA bus!! This is just a safety check
+ at this moment; i2c_detect really won't call us. */
+#ifdef DEBUG
+ if (i2c_is_isa_adapter(adapter)) {
+ dev_dbg(&adapter->dev, " eeprom_detect called for an ISA bus adapter?!?\n");
+ return 0;
+ }
+#endif
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto exit;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access eeprom_{read,write}_value. */
+ if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+ sizeof(struct eeprom_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(new_client, 0x00, sizeof(struct i2c_client) +
+ sizeof(struct eeprom_data));
+
+ data = (struct eeprom_data *) (new_client + 1);
+ memset(data, 0xff, EEPROM_SIZE);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &eeprom_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. It is not there, unless you force
+ the checksum to work out. */
+ if (checksum) {
+ /* prevent 24RF08 corruption */
+ i2c_smbus_write_quick(new_client, 0);
+ cs = 0;
+ for (i = 0; i <= 0x3e; i++)
+ cs += i2c_smbus_read_byte_data(new_client, i);
+ cs &= 0xff;
+ if (i2c_smbus_read_byte_data (new_client, EEPROM_REG_CHECKSUM) != cs)
+ goto exit_kfree;
+ }
+
+ /* Detect the Vaio nature of EEPROMs.
+ We use the "PCG-" prefix as the signature. */
+ if (address == 0x57) {
+ if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P' &&
+ i2c_smbus_read_byte_data(new_client, 0x81) == 'C' &&
+ i2c_smbus_read_byte_data(new_client, 0x82) == 'G' &&
+ i2c_smbus_read_byte_data(new_client, 0x83) == '-')
+ nature = VAIO;
+ }
+
+ /* If this is a VIAO, then we only allow root to read from this file,
+ as BIOS passwords can be present here in plaintext */
+ switch (nature) {
+ case VAIO:
+ eeprom_attr.attr.mode = S_IRUSR;
+ break;
+ default:
+ eeprom_attr.attr.mode = S_IRUGO;
+ }
+
+ /* Fill in the remaining client fields */
+ strncpy(new_client->name, "eeprom", I2C_NAME_SIZE);
+ new_client->id = eeprom_id++;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_kfree;
+
+ /* create the sysfs eeprom file */
+ sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+
+ return 0;
+
+exit_kfree:
+ kfree(new_client);
+exit:
+ return err;
+}
+
+static int eeprom_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err) {
+ dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ kfree(client);
+
+ return 0;
+}
+
+static int __init eeprom_init(void)
+{
+ return i2c_add_driver(&eeprom_driver);
+}
+
+static void __exit eeprom_exit(void)
+{
+ i2c_del_driver(&eeprom_driver);
+}
+
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
+ "Philip Edelbrock <phil@netroedge.com> and "
+ "Greg Kroah-Hartman <greg@kroah.com>");
+MODULE_DESCRIPTION("I2C EEPROM driver");
+MODULE_LICENSE("GPL");
+
+module_init(eeprom_init);
+module_exit(eeprom_exit);
diff --git a/drivers/i2c/i2c-sensor.c b/drivers/i2c/i2c-sensor.c
index 37ef97d470f1..ccfb8baac06c 100644
--- a/drivers/i2c/i2c-sensor.c
+++ b/drivers/i2c/i2c-sensor.c
@@ -50,10 +50,7 @@ int i2c_detect(struct i2c_adapter *adapter,
return -1;
for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
- void *region_used = request_region(addr, 1, "foo");
- release_region(addr, 1);
- if ((is_isa && (region_used == NULL)) ||
- (!is_isa && i2c_check_addr(adapter, addr)))
+ if (!is_isa && i2c_check_addr(adapter, addr))
continue;
/* If it is in one of the force entries, we don't do any
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index c6446bd0d4e6..0531e2e7c519 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_USB_SE401) += media/
obj-$(CONFIG_USB_STV680) += media/
obj-$(CONFIG_USB_VICAM) += media/
-obj-$(CONFIG_USB_AX8817X) += net/
obj-$(CONFIG_USB_CATC) += net/
obj-$(CONFIG_USB_KAWETH) += net/
obj-$(CONFIG_USB_PEGASUS) += net/
diff --git a/drivers/usb/Makefile.lib b/drivers/usb/Makefile.lib
index 26e36d9c653d..78bfdd1ad89c 100644
--- a/drivers/usb/Makefile.lib
+++ b/drivers/usb/Makefile.lib
@@ -1,4 +1,3 @@
-obj-$(CONFIG_USB_AX8817X) += crc32.o
obj-$(CONFIG_USB_CATC) += crc32.o
obj-$(CONFIG_USB_SPEEDTOUCH) += crc32.o
obj-$(CONFIG_USB_USBNET) += crc32.o
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 8ffbd3cfa34a..e817e90c6948 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -1750,7 +1750,7 @@ static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s
return 0;
error_end:
- if ( mdevs != NULL && devices > 0 ) {
+ if ( mdevs != NULL ) {
for ( i=0 ; i<devices ; i++ ) {
if ( mdevs[i] != NULL ) {
unregister_sound_midi( mdevs[i]->dev_midi );
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 00a63ae9b7da..2332526cd803 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -237,9 +237,6 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer, int si
memset(interface, 0, sizeof(struct usb_interface));
interface->dev.release = usb_release_intf;
device_initialize(&interface->dev);
-
- /* put happens in usb_destroy_configuration */
- get_device(&interface->dev);
}
/* Go through the descriptors, checking their length and counting the
diff --git a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c
index 6e56fcb7cc7f..6a177d5932a4 100644
--- a/drivers/usb/core/driverfs.c
+++ b/drivers/usb/core/driverfs.c
@@ -23,22 +23,44 @@
#include "usb.h"
/* Active configuration fields */
-#define usb_actconfig_attr(field, format_string) \
+#define usb_actconfig_show(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf) \
{ \
struct usb_device *udev; \
\
udev = to_usb_device (dev); \
+ if (udev->actconfig) \
return sprintf (buf, format_string, udev->actconfig->desc.field); \
+ else return 0; \
} \
+
+#define usb_actconfig_attr(field, format_string) \
+usb_actconfig_show(field,format_string) \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_actconfig_attr (bNumInterfaces, "%2d\n")
-usb_actconfig_attr (bConfigurationValue, "%2d\n")
usb_actconfig_attr (bmAttributes, "%2x\n")
usb_actconfig_attr (bMaxPower, "%3dmA\n")
+/* configuration value is always present, and r/w */
+usb_actconfig_show(bConfigurationValue,"%u\n");
+
+static ssize_t
+set_bConfigurationValue (struct device *dev, const char *buf, size_t count)
+{
+ struct usb_device *udev = udev = to_usb_device (dev);
+ int config, value;
+
+ if (sscanf (buf, "%u", &config) != 1 || config > 255)
+ return -EINVAL;
+ value = usb_set_configuration (udev, config);
+ return (value < 0) ? value : count;
+}
+
+static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
+ show_bConfigurationValue, set_bConfigurationValue);
+
/* String fields */
static ssize_t show_product (struct device *dev, char *buf)
{
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index dc3a0734aa3b..6070530a09f4 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -273,17 +273,17 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
int retval = 0;
hcd = pci_get_drvdata(dev);
+ dev_dbg (hcd->controller, "suspend D%d --> D%d\n",
+ dev->current_state, state);
+
switch (hcd->state) {
case USB_STATE_HALT:
dev_dbg (hcd->controller, "halted; hcd not suspended\n");
break;
case USB_STATE_SUSPENDED:
- dev_dbg (hcd->controller, "suspend D%d --> D%d\n",
- dev->current_state, state);
+ dev_dbg (hcd->controller, "hcd already suspended\n");
break;
default:
- dev_dbg (hcd->controller, "suspend to state %d\n", state);
-
/* remote wakeup needs hub->suspend() cooperation */
// pci_enable_wake (dev, 3, 1);
@@ -292,6 +292,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
/* driver may want to disable DMA etc */
hcd->state = USB_STATE_QUIESCING;
retval = hcd->driver->suspend (hcd, state);
+ if (retval)
+ dev_dbg (hcd->controller, "suspend fail, retval %d\n",
+ retval);
}
pci_set_power_state (dev, state);
@@ -311,6 +314,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int retval;
hcd = pci_get_drvdata(dev);
+ dev_dbg (hcd->controller, "resume from state D%d\n",
+ dev->current_state);
+
if (hcd->state != USB_STATE_SUSPENDED) {
dev_dbg (hcd->controller, "can't resume, not suspended!\n");
return -EL3HLT;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 3990e5c6238c..374527d88b55 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -781,18 +781,40 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
* @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
*
* Disables all the device's endpoints, potentially including endpoint 0.
- * Deallocates hcd/hardware state for the endpoints ... and nukes all
- * pending urbs.
+ * Deallocates hcd/hardware state for the endpoints (nuking all or most
+ * pending urbs) and usbcore state for the interfaces, so that usbcore
+ * must usb_set_configuration() before any interfaces could be used.
*/
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
int i;
- dbg("nuking URBs for device %s", dev->dev.bus_id);
+ dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
+ skip_ep0 ? "non-ep0" : "all");
for (i = skip_ep0; i < 16; ++i) {
usb_disable_endpoint(dev, i);
usb_disable_endpoint(dev, i + USB_DIR_IN);
}
+ dev->toggle[0] = dev->toggle[1] = 0;
+ dev->halted[0] = dev->halted[1] = 0;
+
+ /* getting rid of interfaces will disconnect
+ * any drivers bound to them (a key side effect)
+ */
+ if (dev->actconfig) {
+ for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+ struct usb_interface *interface;
+
+ /* remove this interface */
+ interface = dev->actconfig->interface[i];
+ dev_dbg (&dev->dev, "unregistering interface %s\n",
+ interface->dev.bus_id);
+ device_del(&interface->dev);
+ }
+ dev->actconfig = 0;
+ if (dev->state == USB_STATE_CONFIGURED)
+ dev->state = USB_STATE_ADDRESS;
+ }
}
@@ -979,6 +1001,9 @@ int usb_reset_configuration(struct usb_device *dev)
int i, retval;
struct usb_host_config *config;
+ /* dev->serialize guards all config changes */
+ down(&dev->serialize);
+
for (i = 1; i < 16; ++i) {
usb_disable_endpoint(dev, i);
usb_disable_endpoint(dev, i + USB_DIR_IN);
@@ -989,8 +1014,10 @@ int usb_reset_configuration(struct usb_device *dev)
USB_REQ_SET_CONFIGURATION, 0,
config->desc.bConfigurationValue, 0,
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
- if (retval < 0)
- return retval;
+ if (retval < 0) {
+ dev->state = USB_STATE_ADDRESS;
+ goto done;
+ }
dev->toggle[0] = dev->toggle[1] = 0;
dev->halted[0] = dev->halted[1] = 0;
@@ -1002,7 +1029,9 @@ int usb_reset_configuration(struct usb_device *dev)
intf->act_altsetting = 0;
usb_enable_interface(dev, intf);
}
- return 0;
+done:
+ up(&dev->serialize);
+ return (retval < 0) ? retval : 0;
}
/**
@@ -1012,72 +1041,105 @@ int usb_reset_configuration(struct usb_device *dev)
* Context: !in_interrupt ()
*
* This is used to enable non-default device modes. Not all devices
- * support this kind of configurability. By default, configuration
- * zero is selected after enumeration; many devices only have a single
+ * use this kind of configurability; many devices only have one
* configuration.
*
- * USB devices may support one or more configurations, which affect
+ * USB device configurations may affect Linux interoperability,
* power consumption and the functionality available. For example,
* the default configuration is limited to using 100mA of bus power,
* so that when certain device functionality requires more power,
- * and the device is bus powered, that functionality will be in some
+ * and the device is bus powered, that functionality should be in some
* non-default device configuration. Other device modes may also be
* reflected as configuration options, such as whether two ISDN
- * channels are presented as independent 64Kb/s interfaces or as one
- * bonded 128Kb/s interface.
+ * channels are available independently; and choosing between open
+ * standard device protocols (like CDC) or proprietary ones.
*
* Note that USB has an additional level of device configurability,
* associated with interfaces. That configurability is accessed using
* usb_set_interface().
*
- * This call is synchronous, and may not be used in an interrupt context.
+ * This call is synchronous. The calling context must be able to sleep,
+ * and must not hold the driver model lock for USB; usb device driver
+ * probe() methods may not use this routine.
*
* Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
+ * underlying call that failed. On succesful completion, each interface
+ * in the original device configuration has been destroyed, and each one
+ * in the new configuration has been probed by all relevant usb device
+ * drivers currently known to the kernel.
*/
int usb_set_configuration(struct usb_device *dev, int configuration)
{
int i, ret;
struct usb_host_config *cp = NULL;
+ /* dev->serialize guards all config changes */
+ down(&dev->serialize);
+
for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
if (dev->config[i].desc.bConfigurationValue == configuration) {
cp = &dev->config[i];
break;
}
}
- if ((!cp && configuration != 0) || (cp && configuration == 0)) {
- warn("selecting invalid configuration %d", configuration);
- return -EINVAL;
+ if ((!cp && configuration != 0)) {
+ ret = -EINVAL;
+ goto out;
}
+ if (cp && configuration == 0)
+ dev_warn(&dev->dev, "config 0 descriptor??\n");
- /* if it's already configured, clear out old state first. */
+ /* if it's already configured, clear out old state first.
+ * getting rid of old interfaces means unbinding their drivers.
+ */
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device (dev, 1); // Skip ep0
- dev->toggle[0] = dev->toggle[1] = 0;
- dev->halted[0] = dev->halted[1] = 0;
- dev->state = USB_STATE_ADDRESS;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
- return ret;
- if (configuration)
- dev->state = USB_STATE_CONFIGURED;
- dev->actconfig = cp;
+ goto out;
- /* reset more hc/hcd interface/endpoint state */
- for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
- struct usb_interface *intf = cp->interface[i];
+ dev->actconfig = cp;
+ if (!configuration)
+ dev->state = USB_STATE_ADDRESS;
+ else {
+ dev->state = USB_STATE_CONFIGURED;
- intf->act_altsetting = 0;
- usb_enable_interface(dev, intf);
+ /* re-initialize hc/hcd/usbcore interface/endpoint state.
+ * this triggers binding of drivers to interfaces; and
+ * maybe probe() calls will choose different altsettings.
+ */
+ for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
+ struct usb_interface *intf = cp->interface[i];
+ struct usb_interface_descriptor *desc;
+
+ intf->act_altsetting = 0;
+ desc = &intf->altsetting [0].desc;
+ usb_enable_interface(dev, intf);
+
+ intf->dev.parent = &dev->dev;
+ intf->dev.driver = NULL;
+ intf->dev.bus = &usb_bus_type;
+ intf->dev.dma_mask = dev->dev.dma_mask;
+ sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
+ dev->bus->busnum, dev->devpath,
+ configuration,
+ desc->bInterfaceNumber);
+ dev_dbg (&dev->dev,
+ "registering %s (config #%d, interface %d)\n",
+ intf->dev.bus_id, configuration,
+ desc->bInterfaceNumber);
+ device_add (&intf->dev);
+ usb_create_driverfs_intf_files (intf);
+ }
}
- return 0;
+out:
+ up(&dev->serialize);
+ return ret;
}
-
/**
* usb_string - returns ISO 8859-1 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8717775dc0b1..5d2b6ebdf517 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -898,6 +898,7 @@ void usb_disconnect(struct usb_device **pdev)
* this device will fail.
*/
dev->state = USB_STATE_NOTATTACHED;
+ down(&dev->serialize);
dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum);
@@ -908,32 +909,19 @@ void usb_disconnect(struct usb_device **pdev)
usb_disconnect(child);
}
- /* deallocate hcd/hardware state ... and nuke all pending urbs */
+ /* deallocate hcd/hardware state ... nuking all pending urbs and
+ * cleaning up all state associated with the current configuration
+ */
usb_disable_device(dev, 0);
- /* disconnect() drivers from interfaces (a key side effect) */
- dev_dbg (&dev->dev, "unregistering interfaces\n");
- if (dev->actconfig) {
- for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *interface;
-
- /* remove this interface */
- interface = dev->actconfig->interface[i];
- device_unregister(&interface->dev);
- }
- }
-
dev_dbg (&dev->dev, "unregistering device\n");
/* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
usbfs_remove_device(dev);
}
+ up(&dev->serialize);
device_unregister(&dev->dev);
-
- /* Decrement the reference count, it'll auto free everything when */
- /* it hits 0 which could very well be now */
- usb_put_dev(dev);
}
/**
@@ -1017,7 +1005,6 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
dev->dev.driver = &usb_generic_driver;
dev->dev.bus = &usb_bus_type;
dev->dev.driver_data = &usb_generic_driver_data;
- usb_get_dev(dev);
if (dev->dev.bus_id[0] == 0)
sprintf (&dev->dev.bus_id[0], "%d-%s",
dev->bus->busnum, dev->devpath);
@@ -1090,27 +1077,12 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
err = usb_get_configuration(dev);
if (err < 0) {
- dev_err(&dev->dev, "unable to get device %d configuration (error=%d)\n",
- dev->devnum, err);
- goto fail;
- }
-
- /* choose and set the configuration here */
- if (dev->descriptor.bNumConfigurations != 1) {
- dev_info(&dev->dev,
- "configuration #%d chosen from %d choices\n",
- dev->config[0].desc.bConfigurationValue,
- dev->descriptor.bNumConfigurations);
- }
- err = usb_set_configuration(dev, dev->config[0].desc.bConfigurationValue);
- if (err) {
- dev_err(&dev->dev, "failed to set device %d default configuration (error=%d)\n",
- dev->devnum, err);
+ dev_err(&dev->dev, "can't read configurations, error %d\n",
+ err);
goto fail;
}
- /* USB device state == configured ... tell the world! */
-
+ /* Tell the world! */
dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
@@ -1123,30 +1095,32 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
#endif
- /* put into sysfs, with device and config specific files */
+ /* put device-specific files into sysfs */
err = device_add (&dev->dev);
- if (err)
+ if (err) {
+ dev_err(&dev->dev, "can't device_add, error %d\n", err);
goto fail;
+ }
usb_create_driverfs_dev_files (dev);
- /* Register all of the interfaces for this device with the driver core.
- * Remember, interfaces get bound to drivers, not devices. */
- for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *interface = dev->actconfig->interface[i];
- struct usb_interface_descriptor *desc;
-
- desc = &interface->altsetting [interface->act_altsetting].desc;
- interface->dev.parent = &dev->dev;
- interface->dev.driver = NULL;
- interface->dev.bus = &usb_bus_type;
- interface->dev.dma_mask = parent->dma_mask;
- sprintf (&interface->dev.bus_id[0], "%d-%s:%d",
- dev->bus->busnum, dev->devpath,
- desc->bInterfaceNumber);
- dev_dbg (&dev->dev, "%s - registering interface %s\n", __FUNCTION__, interface->dev.bus_id);
- device_add (&interface->dev);
- usb_create_driverfs_intf_files (interface);
+ /* choose and set the configuration. that registers the interfaces
+ * with the driver core, and lets usb device drivers bind to them.
+ */
+ if (dev->descriptor.bNumConfigurations != 1) {
+ dev_info(&dev->dev,
+ "configuration #%d chosen from %d choices\n",
+ dev->config[0].desc.bConfigurationValue,
+ dev->descriptor.bNumConfigurations);
}
+ err = usb_set_configuration(dev,
+ dev->config[0].desc.bConfigurationValue);
+ if (err) {
+ dev_err(&dev->dev, "can't set config #%d, error %d\n",
+ dev->config[0].desc.bConfigurationValue, err);
+ goto fail;
+ }
+
+ /* USB device state == configured ... usable */
/* add a /proc/bus/usb entry */
usbfs_add_device(dev);
@@ -1156,7 +1130,6 @@ fail:
dev->state = USB_STATE_DEFAULT;
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
- usb_put_dev(dev);
return err;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 9d0073171a8f..cdec8e8420f4 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -93,6 +93,7 @@ struct eth_dev {
struct usb_ep *in_ep, *out_ep, *status_ep;
const struct usb_endpoint_descriptor
*in, *out, *status;
+ struct list_head tx_reqs, rx_reqs;
struct net_device *net;
struct net_device_stats stats;
@@ -105,28 +106,6 @@ struct eth_dev {
/*-------------------------------------------------------------------------*/
-/* This driver keeps a variable number of requests queued, more at
- * high speeds. (Numbers are just educated guesses, untuned.)
- * Shrink the queue if memory is tight, or make it bigger to
- * handle bigger traffic bursts between IRQs.
- */
-
-static unsigned qmult = 4;
-
-#define HS_FACTOR 5
-
-#define qlen(gadget) \
- (qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1))
-
-/* defer IRQs on highspeed TX */
-#define TX_DELAY 8
-
-
-module_param (qmult, uint, S_IRUGO|S_IWUSR);
-
-
-/*-------------------------------------------------------------------------*/
-
/* Thanks to NetChip Technologies for donating this product ID.
*
* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
@@ -175,6 +154,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
*/
#ifdef CONFIG_USB_ETH_NET2280
#define CHIP "net2280"
+#define DEFAULT_QLEN 4 /* has dma chaining */
#define DRIVER_VERSION_NUM 0x0101
#define EP0_MAXPACKET 64
static const char EP_OUT_NAME [] = "ep-a";
@@ -220,7 +200,7 @@ static const char EP_IN_NAME [] = "ep1in-bulk";
/* supports remote wakeup, but this driver doesn't */
/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
+#define hw_optimize(g) do {} while (0)
#endif
/*
@@ -243,7 +223,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
/* doesn't support remote wakeup? */
/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
+#define hw_optimize(g) do {} while (0)
#endif
/*-------------------------------------------------------------------------*/
@@ -301,9 +281,32 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
/*-------------------------------------------------------------------------*/
+#ifndef DEFAULT_QLEN
+#define DEFAULT_QLEN 2 /* double buffering by default */
+#endif
+
+#ifdef HIGHSPEED
+
+static unsigned qmult = 5;
+module_param (qmult, uint, S_IRUGO|S_IWUSR);
+
+
+/* for dual-speed hardware, use deeper queues at highspeed */
+#define qlen(gadget) \
+ (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
+
+/* also defer IRQs on highspeed TX */
+#define TX_DELAY DEFAULT_QLEN
+
+#else /* !HIGHSPEED ... full speed: */
+#define qlen(gadget) DEFAULT_QLEN
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
#define xprintk(d,level,fmt,args...) \
- printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \
- ## args)
+ printk(level "%s: " fmt , (d)->net->name , ## args)
#ifdef DEBUG
#undef DEBUG
@@ -763,6 +766,7 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
/*-------------------------------------------------------------------------*/
static void eth_start (struct eth_dev *dev, int gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags);
static int
set_ether_config (struct eth_dev *dev, int gfp_flags)
@@ -852,11 +856,21 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
if (!result && (!dev->in_ep || !dev->out_ep))
result = -ENODEV;
+ if (result == 0)
+ result = alloc_requests (dev, qlen (gadget), gfp_flags);
+
#ifndef DEV_CONFIG_CDC
if (result == 0) {
netif_carrier_on (dev->net);
if (netif_running (dev->net))
eth_start (dev, GFP_ATOMIC);
+ } else {
+ (void) usb_ep_disable (dev->in_ep);
+ dev->in_ep = 0;
+ dev->in = 0;
+ (void) usb_ep_disable (dev->out_ep);
+ dev->out_ep = 0;
+ dev->out = 0;
}
#endif /* !CONFIG_CDC_ETHER */
@@ -869,6 +883,8 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
static void eth_reset_config (struct eth_dev *dev)
{
+ struct usb_request *req;
+
if (dev->config == 0)
return;
@@ -877,17 +893,30 @@ static void eth_reset_config (struct eth_dev *dev)
netif_stop_queue (dev->net);
netif_carrier_off (dev->net);
- /* just disable endpoints, forcing completion of pending i/o.
- * all our completion handlers free their requests in this case.
+ /* disable endpoints, forcing (synchronous) completion of
+ * pending i/o. then free the requests.
*/
if (dev->in_ep) {
usb_ep_disable (dev->in_ep);
+ while (likely (!list_empty (&dev->tx_reqs))) {
+ req = container_of (dev->tx_reqs.next,
+ struct usb_request, list);
+ list_del (&req->list);
+ usb_ep_free_request (dev->in_ep, req);
+ }
dev->in_ep = 0;
}
if (dev->out_ep) {
usb_ep_disable (dev->out_ep);
+ while (likely (!list_empty (&dev->rx_reqs))) {
+ req = container_of (dev->rx_reqs.next,
+ struct usb_request, list);
+ list_del (&req->list);
+ usb_ep_free_request (dev->out_ep, req);
+ }
dev->out_ep = 0;
}
+
#ifdef EP_STATUS_NUM
if (dev->status_ep) {
usb_ep_disable (dev->status_ep);
@@ -1345,7 +1374,8 @@ static int eth_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
static void defer_kevent (struct eth_dev *dev, int flag)
{
- set_bit (flag, &dev->todo);
+ if (test_and_set_bit (flag, &dev->todo))
+ return;
if (!schedule_work (&dev->work))
ERROR (dev, "kevent %d may have been dropped\n", flag);
else
@@ -1366,7 +1396,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
if ((skb = alloc_skb (size, gfp_flags)) == 0) {
DEBUG (dev, "no rx skb\n");
defer_kevent (dev, WORK_RX_MEMORY);
- usb_ep_free_request (dev->out_ep, req);
+ list_add (&req->list, &dev->rx_reqs);
return -ENOMEM;
}
@@ -1381,7 +1411,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
if (retval) {
DEBUG (dev, "rx submit --> %d\n", retval);
dev_kfree_skb_any (skb);
- usb_ep_free_request (dev->out_ep, req);
+ list_add (&req->list, &dev->rx_reqs);
}
return retval;
}
@@ -1421,6 +1451,14 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
case -ECONNRESET: // unlink
case -ESHUTDOWN: // disconnect etc
VDEBUG (dev, "rx shutdown, code %d\n", status);
+ goto quiesce;
+
+ /* for hardware automagic (such as pxa) */
+ case -ECONNABORTED: // endpoint reset
+ DEBUG (dev, "rx %s reset\n", ep->name);
+ defer_kevent (dev, WORK_RX_MEMORY);
+quiesce:
+ dev_kfree_skb_any (skb);
goto clean;
/* data overrun */
@@ -1438,28 +1476,96 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
dev_kfree_skb_any (skb);
if (!netif_running (dev->net)) {
clean:
- usb_ep_free_request (dev->out_ep, req);
+ list_add (&req->list, &dev->rx_reqs);
req = 0;
}
if (req)
rx_submit (dev, req, GFP_ATOMIC);
}
+static int prealloc (struct list_head *list, struct usb_ep *ep,
+ unsigned n, int gfp_flags)
+{
+ unsigned i;
+ struct usb_request *req;
+
+ if (!n)
+ return -ENOMEM;
+
+ /* queue/recycle up to N requests */
+ i = n;
+ list_for_each_entry (req, list, list) {
+ if (i-- == 0)
+ goto extra;
+ }
+ while (i--) {
+ req = usb_ep_alloc_request (ep, gfp_flags);
+ if (!req)
+ return list_empty (list) ? -ENOMEM : 0;
+ list_add (&req->list, list);
+ }
+ return 0;
+
+extra:
+ /* free extras */
+ for (;;) {
+ struct list_head *next;
+
+ next = req->list.next;
+ list_del (&req->list);
+ usb_ep_free_request (ep, req);
+
+ if (next == list)
+ break;
+
+ req = container_of (next, struct usb_request, list);
+ }
+ return 0;
+}
+
+static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags)
+{
+ int status;
+
+ status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
+ if (status < 0)
+ goto fail;
+ status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
+ if (status < 0)
+ goto fail;
+ return 0;
+fail:
+ DEBUG (dev, "can't alloc requests\n");
+ return status;
+}
+
+static void rx_fill (struct eth_dev *dev, int gfp_flags)
+{
+ struct usb_request *req;
+
+ clear_bit (WORK_RX_MEMORY, &dev->todo);
+
+ /* fill unused rxq slots with some skb */
+ while (!list_empty (&dev->rx_reqs)) {
+ req = container_of (dev->rx_reqs.next,
+ struct usb_request, list);
+ list_del_init (&req->list);
+ if (rx_submit (dev, req, gfp_flags) < 0) {
+ defer_kevent (dev, WORK_RX_MEMORY);
+ return;
+ }
+ }
+}
+
static void eth_work (void *_dev)
{
struct eth_dev *dev = _dev;
if (test_bit (WORK_RX_MEMORY, &dev->todo)) {
- struct usb_request *req = 0;
-
if (netif_running (dev->net))
- req = usb_ep_alloc_request (dev->in_ep, GFP_KERNEL);
+ rx_fill (dev, GFP_KERNEL);
else
clear_bit (WORK_RX_MEMORY, &dev->todo);
- if (req != 0) {
- clear_bit (WORK_RX_MEMORY, &dev->todo);
- rx_submit (dev, req, GFP_KERNEL);
- }
}
if (dev->todo)
@@ -1484,10 +1590,10 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
}
dev->stats.tx_packets++;
- usb_ep_free_request (ep, req);
+ list_add (&req->list, &dev->tx_reqs);
dev_kfree_skb_any (skb);
- atomic_inc (&dev->tx_qlen);
+ atomic_dec (&dev->tx_qlen);
if (netif_carrier_ok (dev->net))
netif_wake_queue (dev->net);
}
@@ -1499,10 +1605,10 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
int retval;
struct usb_request *req = 0;
- if (!(req = usb_ep_alloc_request (dev->in_ep, GFP_ATOMIC))) {
- DEBUG (dev, "no request\n");
- goto drop;
- }
+ req = container_of (dev->tx_reqs.next, struct usb_request, list);
+ list_del (&req->list);
+ if (list_empty (&dev->tx_reqs))
+ netif_stop_queue (net);
/* no buffer copies needed, unless the network stack did it
* or the hardware can't use skb buffers.
@@ -1537,42 +1643,28 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
break;
case 0:
net->trans_start = jiffies;
- if (atomic_dec_and_test (&dev->tx_qlen))
- netif_stop_queue (net);
+ atomic_inc (&dev->tx_qlen);
}
if (retval) {
- DEBUG (dev, "drop, code %d\n", retval);
-drop:
dev->stats.tx_dropped++;
dev_kfree_skb_any (skb);
- usb_ep_free_request (dev->in_ep, req);
+ if (list_empty (&dev->tx_reqs))
+ netif_start_queue (net);
+ list_add (&req->list, &dev->tx_reqs);
}
return 0;
}
static void eth_start (struct eth_dev *dev, int gfp_flags)
{
- struct usb_request *req;
- int retval = 0;
- unsigned i;
- int size = qlen (dev->gadget);
-
DEBUG (dev, "%s\n", __FUNCTION__);
/* fill the rx queue */
- for (i = 0; retval == 0 && i < size; i++) {
- req = usb_ep_alloc_request (dev->in_ep, gfp_flags);
- if (req)
- retval = rx_submit (dev, req, gfp_flags);
- else if (i > 0)
- defer_kevent (dev, WORK_RX_MEMORY);
- else
- retval = -ENOMEM;
- }
+ rx_fill (dev, gfp_flags);
/* and open the tx floodgates */
- atomic_set (&dev->tx_qlen, size);
+ atomic_set (&dev->tx_qlen, 0);
netif_wake_queue (dev->net);
}
@@ -1590,7 +1682,7 @@ static int eth_stop (struct net_device *net)
{
struct eth_dev *dev = (struct eth_dev *) net->priv;
- DEBUG (dev, "%s\n", __FUNCTION__);
+ VDEBUG (dev, "%s\n", __FUNCTION__);
netif_stop_queue (net);
DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -1604,6 +1696,7 @@ static int eth_stop (struct net_device *net)
usb_ep_disable (dev->out_ep);
if (netif_carrier_ok (dev->net)) {
DEBUG (dev, "host still using in/out endpoints\n");
+ // FIXME idiom may leave toggle wrong here
usb_ep_enable (dev->in_ep, dev->in);
usb_ep_enable (dev->out_ep, dev->out);
}
@@ -1662,6 +1755,8 @@ eth_bind (struct usb_gadget *gadget)
dev = net->priv;
spin_lock_init (&dev->lock);
INIT_WORK (&dev->work, eth_work, dev);
+ INIT_LIST_HEAD (&dev->tx_reqs);
+ INIT_LIST_HEAD (&dev->rx_reqs);
/* network device setup */
dev->net = net;
@@ -1714,10 +1809,6 @@ eth_bind (struct usb_gadget *gadget)
dev->gadget = gadget;
set_gadget_data (gadget, dev);
gadget->ep0->driver_data = dev;
- INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n", driver_desc);
-#ifdef DEV_CONFIG_CDC
- INFO (dev, "CDC host enet %s\n", ethaddr);
-#endif
/* two kinds of host-initiated state changes:
* - iff DATA transfer is active, carrier is "on"
@@ -1728,8 +1819,16 @@ eth_bind (struct usb_gadget *gadget)
// SET_NETDEV_DEV (dev->net, &gadget->dev);
status = register_netdev (dev->net);
- if (status == 0)
+ if (status == 0) {
+
+ INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n",
+ driver_desc);
+#ifdef DEV_CONFIG_CDC
+ INFO (dev, "CDC host enet %s\n", ethaddr);
+#endif
return status;
+ }
+ dev_dbg(&gadget->dev, "register_netdev failed, %d\n", status);
fail:
eth_unbind (gadget);
return status;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 64fef4a8580e..4f3574871c66 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -354,6 +354,7 @@ static ssize_t
ep_io (struct ep_data *epdata, void *buf, unsigned len)
{
DECLARE_COMPLETION (done);
+ int value;
spin_lock_irq (&epdata->dev->lock);
if (likely (epdata->ep != NULL)) {
@@ -363,14 +364,12 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
req->complete = epio_complete;
req->buf = buf;
req->length = len;
- epdata->status = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
+ value = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
} else
- epdata->status = -ENODEV;
+ value = -ENODEV;
spin_unlock_irq (&epdata->dev->lock);
- if (epdata->status == 0) {
- int value;
-
+ if (likely (value == 0)) {
value = wait_event_interruptible (done.wait, done.done);
if (value != 0) {
spin_lock_irq (&epdata->dev->lock);
@@ -378,17 +377,21 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
DBG (epdata->dev, "%s i/o interrupted\n",
epdata->name);
usb_ep_dequeue (epdata->ep, epdata->req);
+ spin_unlock_irq (&epdata->dev->lock);
+
wait_event (done.wait, done.done);
- if (epdata->status == 0)
- epdata->status = value;
+ if (epdata->status == -ECONNRESET)
+ epdata->status = -EINTR;
} else {
+ spin_unlock_irq (&epdata->dev->lock);
+
DBG (epdata->dev, "endpoint gone\n");
epdata->status = -ENODEV;
}
- spin_unlock_irq (&epdata->dev->lock);
}
+ return epdata->status;
}
- return epdata->status;
+ return value;
}
@@ -424,10 +427,12 @@ ep_read (struct file *fd, char *buf, size_t len, loff_t *ptr)
if (unlikely (!kbuf))
goto free1;
- VDEBUG (data->dev, "%s read %d OUT\n", data->name, len);
value = ep_io (data, kbuf, len);
+ VDEBUG (data->dev, "%s read %d OUT, status %d\n",
+ data->name, len, value);
if (value >= 0 && copy_to_user (buf, kbuf, value))
value = -EFAULT;
+
free1:
up (&data->lock);
kfree (kbuf);
@@ -470,8 +475,9 @@ ep_write (struct file *fd, const char *buf, size_t len, loff_t *ptr)
goto free1;
}
- VDEBUG (data->dev, "%s write %d IN\n", data->name, len);
value = ep_io (data, kbuf, len);
+ VDEBUG (data->dev, "%s write %d IN, status %d\n",
+ data->name, len, value);
free1:
up (&data->lock);
kfree (kbuf);
@@ -1200,9 +1206,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value >= 0)
value = min (ctrl->wLength, (u16) value);
break;
-
- default:
+ case USB_DT_STRING:
goto unrecognized;
+
+ default: // all others are errors
+ break;
}
break;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index b1cb550cbb47..6e6b4424e030 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -1965,13 +1965,11 @@ static void reset_hc(struct uhci_hcd *uhci)
outw(USBCMD_GRESET, io_addr + USBCMD);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((HZ*50+999) / 1000);
- set_current_state(TASK_RUNNING);
outw(0, io_addr + USBCMD);
/* Another 10ms delay */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((HZ*10+999) / 1000);
- set_current_state(TASK_RUNNING);
uhci->resume_detect = 0;
}
diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
index e9dcb02a846d..55d1aa68ed9b 100644
--- a/drivers/usb/image/scanner.c
+++ b/drivers/usb/image/scanner.c
@@ -1,7 +1,7 @@
/* -*- linux-c -*- */
/*
- * Driver for USB Scanners (linux-2.5)
+ * Driver for USB Scanners (linux-2.6)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 2002, 2003 Henning Meier-Geinitz
@@ -369,6 +369,18 @@
* - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys scanners.
* - Clean up irq urb when not enough memory is available.
*
+ * 0.4.15 2003-09-22
+ * - Use static declarations for usb_scanner_init/usb_scanner_exit
+ * (Daniele Bellucci).
+ * - Report back return codes of usb_register and usb_usbmit_urb instead of -1 or
+ * -ENONMEM (Daniele Bellucci).
+ * - Balancing usb_register_dev/usb_deregister_dev in probe_scanner when a fail
+ * condition occours (Daniele Bellucci).
+ * - Added vendor/product ids for Canon, HP, Microtek, Mustek, Siemens, UMAX, and
+ * Visioneer scanners.
+ * - Added test for USB_CLASS_CDC_DATA which is used by some fingerprint scanners.
+ *
+ *
* TODO
* - Performance
* - Select/poll methods
@@ -950,6 +962,7 @@ probe_scanner(struct usb_interface *intf,
if (interface[0].desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC &&
interface[0].desc.bInterfaceClass != USB_CLASS_PER_INTERFACE &&
+ interface[0].desc.bInterfaceClass != USB_CLASS_CDC_DATA &&
interface[0].desc.bInterfaceClass != SCN_CLASS_SCANJET) {
dbg("probe_scanner: This interface doesn't look like a scanner (class=0x%x).", interface[0].desc.bInterfaceClass);
return -ENODEV;
@@ -1043,6 +1056,7 @@ probe_scanner(struct usb_interface *intf,
scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL);
if (!scn->scn_irq) {
+ usb_deregister_dev(intf, &scanner_class);
kfree(scn);
up(&scn_mutex);
return -ENOMEM;
@@ -1061,11 +1075,13 @@ probe_scanner(struct usb_interface *intf,
// endpoint[(int)have_intr].bInterval);
250);
- if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) {
+ retval = usb_submit_urb(scn->scn_irq, GFP_KERNEL);
+ if (retval) {
err("probe_scanner(%d): Unable to allocate INT URB.", intf->minor);
+ usb_deregister_dev(intf, &scanner_class);
kfree(scn);
up(&scn_mutex);
- return -ENOMEM;
+ return retval;
}
}
@@ -1076,6 +1092,7 @@ probe_scanner(struct usb_interface *intf,
if (have_intr)
usb_unlink_urb(scn->scn_irq);
usb_free_urb(scn->scn_irq);
+ usb_deregister_dev(intf, &scanner_class);
kfree(scn);
up(&scn_mutex);
return -ENOMEM;
@@ -1087,6 +1104,7 @@ probe_scanner(struct usb_interface *intf,
if (have_intr)
usb_unlink_urb(scn->scn_irq);
usb_free_urb(scn->scn_irq);
+ usb_deregister_dev(intf, &scanner_class);
kfree(scn->obuf);
kfree(scn);
up(&scn_mutex);
@@ -1169,22 +1187,25 @@ usb_driver scanner_driver = {
.id_table = ids,
};
-void __exit
+static void __exit
usb_scanner_exit(void)
{
usb_deregister(&scanner_driver);
}
-int __init
+static int __init
usb_scanner_init (void)
{
- if (usb_register(&scanner_driver) < 0)
- return -1;
+ int retval;
+ retval = usb_register(&scanner_driver);
+ if (retval)
+ goto out;
info(DRIVER_VERSION ":" DRIVER_DESC);
if (vendor != -1 && product != -1)
info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product);
- return 0;
+ out:
+ return retval;
}
module_init(usb_scanner_init);
diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
index f5a4be152899..915a4f5e790b 100644
--- a/drivers/usb/image/scanner.h
+++ b/drivers/usb/image/scanner.h
@@ -1,5 +1,5 @@
/*
- * Driver for USB Scanners (linux-2.5)
+ * Driver for USB Scanners (linux-2.6)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Previously maintained by Brian Beattie
@@ -43,7 +43,7 @@
// #define DEBUG
-#define DRIVER_VERSION "0.4.14"
+#define DRIVER_VERSION "0.4.15"
#define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h>
@@ -122,7 +122,10 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */
{ USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */
{ USB_DEVICE(0x04a9, 0x220f) }, /* CanoScan 8000F */
+ { USB_DEVICE(0x04a9, 0x2210) }, /* CanoScan 9900F */
+ { USB_DEVICE(0x04a9, 0x2212) }, /* CanoScan 5000F */
{ USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */
+ { USB_DEVICE(0x04a9, 0x2215) }, /* CanoScan 3000 */
{ USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */
/* Colorado -- See Primax/Colorado below */
/* Compaq */
@@ -158,7 +161,9 @@ static struct usb_device_id scanner_device_ids [] = {
// { USB_DEVICE(0x03f0, 0x0701) }, /* ScanJet 5300C - NOT SUPPORTED - use hpusbscsi driver */
{ USB_DEVICE(0x03f0, 0x0705) }, /* ScanJet 4400C */
// { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
+ { USB_DEVICE(0x03f0, 0x0805) }, /* ScanJet 4470c */
{ USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */
+ { USB_DEVICE(0x03f0, 0x0a01) }, /* ScanJet 2400c */
{ USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */
{ USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */
{ USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */
@@ -177,9 +182,11 @@ static struct usb_device_id scanner_device_ids [] = {
/* Memorex */
{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek */
+ { USB_DEVICE(0x05da, 0x20a7) }, /* ScanMaker 5600 */
{ USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */
{ USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */
{ USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */
+ { USB_DEVICE(0x05da, 0x30d4) }, /* ScanMaker 3830 + 3840 */
{ USB_DEVICE(0x04a7, 0x0224) }, /* Scanport 3000 (actually Visioneer?)*/
/* The following SCSI-over-USB Microtek devices are supported by the
microtek driver: Enable SCSI and USB Microtek in kernel config */
@@ -214,6 +221,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x055f, 0x021e) }, /* BearPaw 1200 TA/CS */
{ USB_DEVICE(0x055f, 0x0400) }, /* BearPaw 2400 TA PRO */
{ USB_DEVICE(0x055f, 0x0401) }, /* P 3600 A3 Pro */
+ { USB_DEVICE(0x055f, 0x0409) }, /* BearPaw 2448TA Pro */
{ USB_DEVICE(0x055f, 0x0873) }, /* ScanExpress 600 USB */
{ USB_DEVICE(0x055f, 0x1000) }, /* BearPaw 4800 TA PRO */
// { USB_DEVICE(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */
@@ -279,6 +287,9 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
{ USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */
{ USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */
+ /* Siemens */
+ { USB_DEVICE(0x0681, 0x0005) }, /* ID Mouse Professional */
+ { USB_DEVICE(0x0681, 0x0010) }, /* Cherry FingerTIP ID Board - Sensor */
/* SYSCAN */
{ USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */
/* Trust */
@@ -289,6 +300,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */
{ USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */
{ USB_DEVICE(0x1606, 0x0060) }, /* Astra 3400U/3450U */
+ { USB_DEVICE(0x1606, 0x0070) }, /* Astra 4400 */
{ USB_DEVICE(0x1606, 0x0130) }, /* Astra 2100U */
{ USB_DEVICE(0x1606, 0x0160) }, /* Astra 5400U */
{ USB_DEVICE(0x1606, 0x0230) }, /* Astra 2200U */
@@ -296,7 +308,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04a7, 0x0211) }, /* OneTouch 7600 USB */
{ USB_DEVICE(0x04a7, 0x0221) }, /* OneTouch 5300 USB */
{ USB_DEVICE(0x04a7, 0x0224) }, /* OneTouch 4800 USB */
- { USB_DEVICE(0x04a7, 0x0226) }, /* OneTouch 5300 USB */
+ { USB_DEVICE(0x04a7, 0x0226) }, /* OneTouch 5800 USB */
+ { USB_DEVICE(0x04a7, 0x022c) }, /* OneTouch 9020 USB */
{ USB_DEVICE(0x04a7, 0x0231) }, /* 6100 USB */
{ USB_DEVICE(0x04a7, 0x0311) }, /* 6200 EPP/USB */
{ USB_DEVICE(0x04a7, 0x0321) }, /* OneTouch 8100 EPP/USB */
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index f469397c5780..0dfadc07c43a 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -112,8 +112,8 @@ config USB_MOUSE
depends on USB && INPUT
---help---
Say Y here only if you are absolutely sure that you don't want
- to use the generic HID driver for your USB keyboard and prefer
- to use the keyboard in its limited Boot Protocol mode instead.
+ to use the generic HID driver for your USB mouse and prefer
+ to use the mouse in its limited Boot Protocol mode instead.
This is almost certainly not what you want. This is mostly
useful for embedded applications or simple mice.
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index a1d356bbd0bd..16dcb976d38e 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -7,25 +7,6 @@ comment "USB Network adaptors"
comment "Networking support is needed for USB Networking device support"
depends on USB && !NET
-config USB_AX8817X_STANDALONE
- tristate "USB ASIX AX8817X Ethernet device support (EXPERIMENTAL)"
- depends on USB && NET && EXPERIMENTAL
- ---help---
- Say Y if you want to use one of the following 10/100Mps USB
- Ethernet devices based on the ASIX AX88172 chip. Supported
- devices are:
- ASIX AX88172
- D-Link DUB-E100
- Hawking UF200
- Netgear FA120
-
- This driver makes the adapter appear as a normal Ethernet interface,
- typically on eth0, if it is the only ethernet device, or perhaps on
- eth1, if you have a PCI or ISA ethernet card installed.
-
- To compile this driver as a module, choose M here: the
- module will be called ax8817x.
-
config USB_CATC
tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)"
depends on USB && NET && EXPERIMENTAL
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 3956f8655d7d..5eec1ed7e40a 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -2,7 +2,6 @@
# Makefile for USB Network drivers
#
-obj-$(CONFIG_USB_AX8817X_STANDALONE) += ax8817x.o
obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
diff --git a/drivers/usb/net/Makefile.mii b/drivers/usb/net/Makefile.mii
index 34c2f5585d10..20cf79adacc2 100644
--- a/drivers/usb/net/Makefile.mii
+++ b/drivers/usb/net/Makefile.mii
@@ -2,6 +2,5 @@
# Makefile for USB Network drivers which require generic MII code.
#
-obj-$(CONFIG_USB_AX8817X) += mii.o
obj-$(CONFIG_USB_PEGASUS) += mii.o
obj-$(CONFIG_USB_USBNET) += mii.o
diff --git a/drivers/usb/net/ax8817x.c b/drivers/usb/net/ax8817x.c
deleted file mode 100644
index e73ba35f691c..000000000000
--- a/drivers/usb/net/ax8817x.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/*
- * ASIX AX8817x USB 2.0 10/100/HomePNA Ethernet controller driver
- *
- * $Id: ax8817x.c,v 1.18 2003/07/24 11:08:17 dhollis Exp $
- *
- * Copyright (c) 2002-2003 TiVo Inc.
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * History
- *
- * 2003-07-24 - Dave Hollis <dhollis@davehollis.com> 2.0.2
- * * Minor fix that greatly increases rx performance
-
- * 2003-07-22 - Dave Hollis <dhollis@davehollis.com> 2.0.1
- * * Add Intellinet USB ids
- * * Fix mii/ethtool support - link check works!
- * * Add msglevel support
- * * Shamelessly 'borrowed' devdbg/err/info macros from usbnet
- * * Change strlcpy to strncpy
- * 2003-06-15 - Dave Hollis <dhollis@davehollis.com> 2.0.0
- * * Remove crc32 inline function, use core kernel instead
- * * Set sane defaults for rx_buffers
- * * Fix ethtool GETDRVINFO bits - use strlcpy and
- * usb_make_path
- *
- * 2003-06-05 - Dave Hollis <dhollis@davehollis.com> 0.10.0
- * * Port to 2.5 series kernels
- * * Remove #if 0 blocks that are confirmed
- * unnecessary
- * * Re-did tx routines based off pegasus driver.
- * This resolved hard crashes and greatly simplified
- * things.
- * * Redo mii/ethtool routines
- *
- * 2003-05-31 - Dave Hollis <dhollis@davehollis.com> 0.9.8
- * * Don't stop/start the queue in start_xmit
- * * Swallow URB status upon hard removal
- * * Cleanup remaining comments (kill // style)
- *
- * 2003-05-29 - Dave Hollis <dhollis@davehollis.com> 0.9.7
- * * Set module owner
- * * Follow-up on suggestions from David Brownell &
- * Oliver Neukum which should help with robustness
- * * Use ether_crc from stock kernel if available
- *
- * 2003-05-28 - Dave Hollis <dhollis@davehollis.com> 0.9.6
- * * Added basic ethtool & mii support
- *
- * 2003-05-28 - Dave Hollis <dhollis@davehollis.com> 0.9.5
- * * Workout devrequest change to usb_ctrlrequest structure
- * * Replace FILL_BULK_URB macros to non-deprecated
- * usb_fill_bulk_urb macros
- * * Replace printks with equivalent macros
- * * Use defines for module description, version, author to
- * simplify future changes
- *
- * Known Issues
- *
- * Todo
- * Fix receive performance on OHCI
-*/
-
-#include <linux/slab.h>
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-#include <asm/uaccess.h>
-
-/* Version Information */
-#define DRIVER_VERSION "v2.0.2"
-#define DRIVER_AUTHOR "TiVo, Inc."
-#define DRIVER_DESC "ASIX AX8817x USB Ethernet driver"
-#define DRIVER_NAME "ax8817x"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-
-#define AX_REQ_READ ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE )
-#define AX_REQ_WRITE ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE )
-
-#define AX_CMD_SET_SW_MII 0x06
-#define AX_CMD_READ_MII_REG 0x07
-#define AX_CMD_WRITE_MII_REG 0x08
-#define AX_CMD_SET_HW_MII 0x0a
-#define AX_CMD_WRITE_RX_CTL 0x10
-#define AX_CMD_WRITE_MULTI_FILTER 0x16
-#define AX_CMD_READ_NODE_ID 0x17
-#define AX_CMD_READ_PHY_ID 0x19
-#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
-#define AX_CMD_WRITE_GPIOS 0x1f
-
-#define AX_RX_MAX ETH_FRAME_LEN
-#define AX_TIMEOUT_CMD ( HZ / 10 )
-#define AX_TIMEOUT_TX ( HZ * 2 )
-#define AX_MCAST_FILTER_SIZE 8
-#define AX_MAX_MCAST 64
-
-#define AX_DRV_STATE_INITIALIZING 0x00
-#define AX_DRV_STATE_RUNNING 0x01
-#define AX_DRV_STATE_EXITING 0x02
-
-#define AX_PHY_STATE_INITIALIZING 0x00
-#define AX_PHY_STATE_NO_LINK 0x01
-#define AX_PHY_STATE_POLLING_1 0x02
-#define AX_PHY_STATE_POLLING_2 0x03
-#define AX_PHY_STATE_POLLING_3 0x04
-#define AX_PHY_STATE_POLLING_4 0x05
-#define AX_PHY_STATE_SETTING_MAC 0x06
-#define AX_PHY_STATE_LINK 0x07
-#define AX_PHY_STATE_ABORT_POLL 0x08
-#define AX_PHY_STATE_ABORTING 0x09
-
-#define AX_MAX_PHY_RETRY 50
-
-#define AX_RX_URBS_DEFAULT 2
-
-static int n_rx_urbs = AX_RX_URBS_DEFAULT;
-
-MODULE_PARM(n_rx_urbs, "i");
-MODULE_PARM_DESC(n_rx_urbs,
- "Number of rx buffers to queue at once (def 2)");
-
-struct ax8817x_info;
-struct ax_cmd_req;
-typedef int (*ax_cmd_callback_t) (struct ax8817x_info *,
- struct ax_cmd_req *);
-
-struct ax_cmd_req {
- struct list_head list;
- ax_cmd_callback_t cmd_callback;
- void *priv;
- int status;
- void *data;
- int data_size;
- int timeout;
- struct usb_ctrlrequest devreq;
-};
-
-struct ax8817x_info {
- struct usb_device *usb;
- struct net_device *net;
- struct net_device_stats stats;
- struct mii_if_info mii;
- struct urb **rx_urbs;
- struct urb *int_urb;
- struct urb *tx_urb;
- u8 *int_buf;
- struct urb *ctl_urb;
- struct list_head ctl_queue;
- spinlock_t ctl_lock;
- atomic_t rx_refill_cnt;
- struct ax_cmd_req phy_req;
- u8 phy_id;
- u8 phy_state;
- u8 drv_state;
- int msg_level;
-};
-
-
-const struct usb_device_id ax8817x_id_table[] = {
- /* Linksys USB200M */
- {USB_DEVICE(0x077b, 0x2226), driver_info:0x00130103},
- /* Hawking UF200, TRENDnet TU2-ET100 */
- {USB_DEVICE(0x07b8, 0x420a), driver_info:0x001f1d1f},
- /* NETGEAR FA120 */
- {USB_DEVICE(0x0846, 0x1040), driver_info:0x00130103},
- /* D-Link DUB-E100 */
- {USB_DEVICE(0x2001, 0x1a00), driver_info:0x009f9d9f},
- /* Intellinet USB Ethernet */
- {USB_DEVICE(0x0b95, 0x1720), driver_info:0x00130103},
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, ax8817x_id_table);
-
-/* The space before the ", ## arg" is deliberate: gcc-2.9x needs it */
-
-#ifdef DEBUG
-#define devdbg(ax_info, fmt, arg...) \
- printk(KERN_DEBUG "%s: " fmt "\n" , (ax_info)->net->name , ## arg)
-#else
-#define devdbg(ax_info, fmt, arg...) do {} while(0)
-#endif
-
-#define deverr(ax_info, fmt, arg...) \
- printk(KERN_ERR "%s: " fmt "\n", (ax_info)->net->name , ## arg)
-
-#define devinfo(ax_info, fmt, arg...) \
- do { if ((ax_info)->msg_level >= 1) \
- printk(KERN_INFO "%s: " fmt "\n", \
- (ax_info)->net->name , ## arg); \
- } while (0)
-
-static void ax_run_ctl_queue(struct ax8817x_info *, struct ax_cmd_req *,
- int);
-static void ax_rx_callback(struct urb *, struct pt_regs *);
-
-static void ax_ctl_callback(struct urb *urb, struct pt_regs *regs)
-{
- struct ax8817x_info *ax_info =
- (struct ax8817x_info *) urb->context;
-
- ax_run_ctl_queue(ax_info, NULL,
- urb->status ? urb->status : urb->actual_length);
-}
-
-/*
- * Queue a new ctl request, or dequeue the first in the list
-*/
-static void ax_run_ctl_queue(struct ax8817x_info *ax_info,
- struct ax_cmd_req *req, int status)
-{
- struct ax_cmd_req *next_req = NULL;
- struct ax_cmd_req *last_req = NULL;
- unsigned long flags;
-
- /* Need to lock around queue list manipulation */
- spin_lock_irqsave(&ax_info->ctl_lock, flags);
-
- if (req == NULL) {
- last_req =
- list_entry(ax_info->ctl_queue.next, struct ax_cmd_req,
- list);
- } else {
- if (list_empty(&ax_info->ctl_queue)) {
- next_req = req;
- }
-
- req->status = -EINPROGRESS;
- list_add_tail(&req->list, &ax_info->ctl_queue);
- }
-
- while (1) {
- if (last_req != NULL) {
- /* dequeue completed entry */
- list_del(&last_req->list);
-
- last_req->status = status;
- if (last_req->cmd_callback(ax_info, last_req)) {
- /* requeue if told to do so */
- last_req->status = -EINPROGRESS;
- list_add_tail(&last_req->list,
- &ax_info->ctl_queue);
- }
-
- if (list_empty(&ax_info->ctl_queue)) {
- next_req = NULL;
- } else {
- next_req =
- list_entry(ax_info->ctl_queue.next,
- struct ax_cmd_req, list);
- }
- }
-
- spin_unlock_irqrestore(&ax_info->ctl_lock, flags);
-
- if (next_req == NULL) {
- break;
- }
-
- /* XXX: do something with timeout */
- usb_fill_control_urb(ax_info->ctl_urb, ax_info->usb,
- next_req->devreq.
- bRequestType & USB_DIR_IN ?
- usb_rcvctrlpipe(ax_info->usb,
- 0) :
- usb_sndctrlpipe(ax_info->usb, 0),
- (void *) &next_req->devreq,
- next_req->data, next_req->data_size,
- ax_ctl_callback, ax_info);
-
- status = usb_submit_urb(ax_info->ctl_urb, GFP_ATOMIC);
- if (status >= 0) {
- break;
- }
-
- last_req = next_req;
-
- spin_lock_irqsave(&ax_info->ctl_lock, flags);
- }
-}
-
-static int ax_sync_cmd_callback(struct ax8817x_info *unused,
- struct ax_cmd_req *req)
-{
- wait_queue_head_t *wq = (wait_queue_head_t *) req->priv;
-
- wake_up(wq);
-
- return 0;
-}
-
-static int ax_async_cmd_callback(struct ax8817x_info *unused,
- struct ax_cmd_req *req)
-{
- if (req->status < 0) {
- err("%s: Async command %d failed: %d\n", __FUNCTION__,
- req->devreq.bRequest, req->status);
- }
-
- /* Nothing else to do here, just need to free the request (and its
- allocated data) */
- if (req->data != NULL) {
- kfree(req->data);
- }
- kfree(req);
-
- return 0;
-}
-
-/*
- * This is mostly the same as usb_control_msg(), except that it is able
- * to queue control messages
-*/
-static int ax_control_msg(struct ax8817x_info *ax_info, u8 requesttype,
- u8 request, u16 value, u16 index, void *data,
- u16 size, int timeout)
-{
- struct ax_cmd_req *req;
- DECLARE_WAIT_QUEUE_HEAD(wq);
- DECLARE_WAITQUEUE(wait, current);
- int ret;
-
- req = kmalloc(sizeof(struct ax_cmd_req), GFP_KERNEL);
- if (req == NULL) {
- return -ENOMEM;
- }
-
- req->devreq.bRequestType = requesttype;
- req->devreq.bRequest = request;
- req->devreq.wValue = cpu_to_le16(value);
- req->devreq.wIndex = cpu_to_le16(index);
- req->devreq.wLength = cpu_to_le16(size);
- req->data = data;
- req->data_size = size;
- req->timeout = timeout;
-
- req->priv = &wq;
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&wq, &wait);
-
- req->cmd_callback = ax_sync_cmd_callback;
-
- ax_run_ctl_queue(ax_info, req, 0);
- schedule();
-
- ret = req->status;
-
- kfree(req);
-
- return ret;
-}
-
-/*
- * Same, but can be used asynchronously, may fail, and returns no exit
- * status
-*/
-static void ax_control_msg_async(struct ax8817x_info *ax_info,
- u8 requesttype, u8 request, u16 value,
- u16 index, void *data, u16 size,
- int timeout)
-{
- struct ax_cmd_req *req;
-
- req = kmalloc(sizeof(struct ax_cmd_req), GFP_ATOMIC);
- if (req == NULL) {
- /* There's not much else we can do here... */
- err("%s: Failed alloc\n", __FUNCTION__);
- return;
- }
-
- req->devreq.bRequestType = requesttype;
- req->devreq.bRequest = request;
- req->devreq.wValue = cpu_to_le16(value);
- req->devreq.wIndex = cpu_to_le16(index);
- req->devreq.wLength = cpu_to_le16(size);
- req->data = data;
- req->data_size = size;
- req->timeout = timeout;
-
- req->cmd_callback = ax_async_cmd_callback;
-
- ax_run_ctl_queue(ax_info, req, 0);
-}
-
-static inline int ax_read_cmd(struct ax8817x_info *ax_info, u8 cmd,
- u16 value, u16 index, u16 size, void *data)
-{
- return ax_control_msg(ax_info, AX_REQ_READ, cmd, value, index,
- data, size, AX_TIMEOUT_CMD);
-}
-
-static inline int ax_write_cmd(struct ax8817x_info *ax_info, u8 cmd,
- u16 value, u16 index, u16 size, void *data)
-{
- return ax_control_msg(ax_info, AX_REQ_WRITE, cmd, value, index,
- data, size, AX_TIMEOUT_CMD);
-}
-
-static inline void ax_write_cmd_async(struct ax8817x_info *ax_info, u8 cmd,
- u16 value, u16 index, u16 size,
- void *data)
-{
- ax_control_msg_async(ax_info, AX_REQ_WRITE, cmd, value, index,
- data, size, AX_TIMEOUT_CMD);
-}
-
-static int ax_refill_rx_urb(struct ax8817x_info *ax_info, struct urb *urb)
-{
- struct sk_buff *skb;
- int ret;
-
- skb = dev_alloc_skb(AX_RX_MAX + 2);
- if (skb != NULL) {
- skb_reserve(skb, 2); /* for IP header alignment */
- skb->dev = ax_info->net;
-
- usb_fill_bulk_urb(urb, ax_info->usb,
- usb_rcvbulkpipe(ax_info->usb, 3),
- skb->data, AX_RX_MAX, ax_rx_callback,
- skb);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- err("Failed submit rx URB (%d)\n", ret);
- dev_kfree_skb_irq(skb);
- urb->context = NULL;
- } else {
- ret = 0;
- }
- } else {
- /* this just means we're low on memory at the moment. Try to
- handle it gracefully. */
- urb->context = NULL;
- ret = 1;
- }
-
- return ret;
-}
-
-static int ax_phy_cmd_callback(struct ax8817x_info *ax_info,
- struct ax_cmd_req *req)
-{
- int full_duplex;
- int flow_control;
- u16 mii_data_le;
-
- if (req->status < 0) {
- err("%s: Failed at state %d: %d\n", __FUNCTION__,
- ax_info->phy_state, req->status);
- /* Not sure what else we can do, so just bail */
- ax_info->phy_state = AX_PHY_STATE_ABORTING;
- }
-
- switch (ax_info->phy_state) {
- /* Now that we're in software MII mode, read the BMSR */
- case AX_PHY_STATE_POLLING_1:
- ax_info->phy_state = AX_PHY_STATE_POLLING_2;
- req->devreq.bRequestType = AX_REQ_READ;
- req->devreq.bRequest = AX_CMD_READ_MII_REG;
- req->devreq.wValue = cpu_to_le16(ax_info->phy_id);
- req->devreq.wIndex = cpu_to_le16(MII_BMSR);
- req->devreq.wLength = cpu_to_le16(2);
- req->data_size = 2;
- req->priv = 0; /* This is the retry count */
- return 1;
-
- /* Done reading BMSR */
- case AX_PHY_STATE_POLLING_2:
- mii_data_le = *(u16 *) req->data;
- if ((mii_data_le &
- cpu_to_le16(BMSR_LSTATUS | BMSR_ANEGCAPABLE))
- == cpu_to_le16(BMSR_LSTATUS | BMSR_ANEGCAPABLE)) {
- if (mii_data_le & cpu_to_le16(BMSR_ANEGCOMPLETE)) {
- /* Autonegotiation done, go on to read LPA */
- ax_info->phy_state =
- AX_PHY_STATE_POLLING_3;
- req->devreq.wIndex = cpu_to_le16(MII_LPA);
- return 1;
- } else if ((long) req->priv++ < AX_MAX_PHY_RETRY) {
- /* Reread BMSR if it's still autonegotiating. This is
- probably unnecessary logic, I've never seen it take
- more than 1 try... */
- return 1;
- }
- /* else fall through to abort */
- }
- /* XXX: should probably handle auto-neg failure better,
- by reverting to manual setting of something safe. (?) */
-
- ax_info->phy_state = AX_PHY_STATE_ABORT_POLL;
- /* and then fall through to set hw MII */
-
- /* Got what we needed from PHY, set back to hardware MII mode
- (Do same for abort in mid-poll) */
- case AX_PHY_STATE_POLLING_3:
- case AX_PHY_STATE_ABORT_POLL:
- ax_info->phy_state += 1;
- req->devreq.bRequestType = AX_REQ_WRITE;
- req->devreq.bRequest = AX_CMD_SET_HW_MII;
- req->devreq.wValue = cpu_to_le16(0);
- req->devreq.wIndex = cpu_to_le16(0);
- req->devreq.wLength = cpu_to_le16(0);
- req->data_size = 0;
- return 1;
-
- /* The end result, set the right duplex and flow control mode in the
- MAC (based on the PHY's LPA reg, which should still be in the data
- buffer) */
- case AX_PHY_STATE_POLLING_4:
- mii_data_le = *(u16 *) req->data;
- ax_info->phy_state = AX_PHY_STATE_SETTING_MAC;
- req->devreq.bRequest = AX_CMD_WRITE_MEDIUM_MODE;
- full_duplex = mii_data_le & cpu_to_le16(LPA_DUPLEX);
- flow_control = full_duplex &&
- (mii_data_le & cpu_to_le16(0x0400));
- req->devreq.wValue = cpu_to_le16(0x04) |
- (full_duplex ? cpu_to_le16(0x02) : 0) |
- (flow_control ? cpu_to_le16(0x10) : 0);
- info("%s: Link established, %s duplex, flow control %sabled\n", ax_info->net->name, full_duplex ? "full" : "half", flow_control ? "en" : "dis");
- return 1;
-
- /* All done */
- case AX_PHY_STATE_SETTING_MAC:
- ax_info->phy_state = AX_PHY_STATE_LINK;
- netif_carrier_on(ax_info->net);
- return 0;
-
- default:
- err("%s: Unknown state %d\n", __FUNCTION__,
- ax_info->phy_state);
- /* fall through */
- case AX_PHY_STATE_ABORTING:
- ax_info->phy_state = AX_PHY_STATE_NO_LINK;
- return 0;
- }
-}
-
-static void ax_int_callback(struct urb *urb, struct pt_regs *regs)
-{
- struct ax8817x_info *ax_info =
- (struct ax8817x_info *) urb->context;
- u8 phy_link;
-
- if (ax_info->drv_state == AX_DRV_STATE_EXITING ||
- urb->actual_length < 3) {
- return;
- }
-
- /* Ignore the first PHY link report, it will sometimes be reported as
- link active, even though we just told the PHY to reset. If it
- really has link, we'll pick it up next int callback.
- */
- if (ax_info->phy_state == AX_PHY_STATE_INITIALIZING) {
- netif_carrier_off(ax_info->net);
- ax_info->phy_state = AX_PHY_STATE_NO_LINK;
- return;
- }
-
- /* Assume we're only interested in the primary PHY for now. */
- phy_link = ax_info->int_buf[2] & 1;
-
- if (phy_link ==
- (ax_info->phy_state == AX_PHY_STATE_NO_LINK) ? 0 : 1) {
- /* Common case, no change */
- return;
- }
-
- if (phy_link == 0) {
- netif_carrier_off(ax_info->net);
- /* Abort an in-progress poll of the PHY if necessary */
- switch (ax_info->phy_state) {
- case AX_PHY_STATE_POLLING_1:
- case AX_PHY_STATE_POLLING_2:
- case AX_PHY_STATE_POLLING_3:
- ax_info->phy_state = AX_PHY_STATE_ABORT_POLL;
- break;
-
- case AX_PHY_STATE_POLLING_4:
- case AX_PHY_STATE_SETTING_MAC:
- ax_info->phy_state = AX_PHY_STATE_ABORTING;
- break;
-
- case AX_PHY_STATE_LINK:
- ax_info->phy_state = AX_PHY_STATE_NO_LINK;
- break;
-
- default:
- /* If we're already aborting, continue aborting */
- break;
- }
- } else {
- /* Note that we only fall into this case if previous phy_state was
- AX_PHY_STATE_NO_LINK. When the link is reported active while
- we're still polling, or when we're aborting, the logic above
- will just return, and we'll check again next int callback. */
-
- ax_info->phy_state = AX_PHY_STATE_POLLING_1;
- ax_info->phy_req.devreq.bRequestType = AX_REQ_WRITE;
- ax_info->phy_req.devreq.bRequest = AX_CMD_SET_SW_MII;
- ax_info->phy_req.devreq.wValue = cpu_to_le16(0);
- ax_info->phy_req.devreq.wIndex = cpu_to_le16(0);
- ax_info->phy_req.devreq.wLength = cpu_to_le16(0);
- ax_info->phy_req.data_size = 0;
- ax_info->phy_req.timeout = AX_TIMEOUT_CMD;
- ax_info->phy_req.cmd_callback = ax_phy_cmd_callback;
-
- ax_run_ctl_queue(ax_info, &ax_info->phy_req, 0);
- }
-}
-
-static void ax_rx_callback(struct urb *urb, struct pt_regs *regs)
-{
- struct sk_buff *skb = (struct sk_buff *) urb->context;
- struct net_device *net = skb->dev;
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
- int ret, len, refill;
-
- switch (urb->status) {
- case 0:
- break;
-
- default:
- err("%s: URB status %d\n", __FUNCTION__, urb->status);
- /* It's not clear that we can do much in this case, the rx pipe
- doesn't ever seem to stall, so if we got -ETIMEDOUT, that
- usually means the device was unplugged, and we just haven't
- noticed yet.
- Just fall through and free skb without resubmitting urb. */
- case -ENOENT: /* */
- case -ECONNRESET: /* Async unlink */
- case -ESHUTDOWN: /* Hardware gone */
- case -EILSEQ: /* Get this when you yank it out on UHCI */
- case -ETIMEDOUT: /* OHCI */
- case -EPROTO: /* EHCI */
- case -EPIPE:
- dev_kfree_skb_any(skb);
- urb->context = NULL;
- return;
- }
-
- if (ax_info->drv_state == AX_DRV_STATE_INITIALIZING) {
- /* Not really expecting this to ever happen, since we haven't yet
- enabled receive in the rx_ctl register, but ya never know... */
- goto refill_same;
- } else if (ax_info->drv_state == AX_DRV_STATE_EXITING) {
- dev_kfree_skb_any(skb);
- urb->context = NULL;
- return;
- }
-
- len = urb->actual_length;
- if (len == 0) {
- /* this shouldn't happen... */
- goto refill_same;
- }
-
- refill = ax_refill_rx_urb(ax_info, urb);
-
- if (refill == 0
- || atomic_read(&ax_info->rx_refill_cnt) < n_rx_urbs) {
- /* Send the receive buffer up the network stack */
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, net);
- net->last_rx = jiffies;
- ax_info->stats.rx_packets++;
- ax_info->stats.rx_bytes += len;
-
- netif_rx(skb);
-
- if (refill == 0) {
- int i;
-
- /* This is the common case. This URB got refilled OK, and
- no other URBs need to be refilled. */
- if (atomic_read(&ax_info->rx_refill_cnt) == 0) {
- return;
- }
-
- for (i = 0; i < n_rx_urbs; i++) {
- struct urb *urb = ax_info->rx_urbs[i];
-
- if (urb->context == NULL) {
- if (ax_refill_rx_urb(ax_info, urb)
- == 0) {
- atomic_dec(&ax_info->
- rx_refill_cnt);
- } else {
- break;
- }
- }
- }
- } else {
- /* remember to refill this one later */
- atomic_inc(&ax_info->rx_refill_cnt);
- }
-
- return;
- } else {
- ax_info->stats.rx_dropped++;
- if (refill < 0) {
- /* the error code was already printk'ed in ax_refill_rx_urb()
- so just note the consequences here: */
- warn("Halting rx due to error\n");
- return;
- }
-
- /* fall through to resubmit this URB with the existing skb
- will try to reallocate skb's on next rx callback */
- }
-
-refill_same:
- usb_fill_bulk_urb(urb, ax_info->usb,
- usb_rcvbulkpipe(ax_info->usb, 3), skb->data,
- AX_RX_MAX, ax_rx_callback, skb);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- err("Failed submit rx URB (%d)\n", ret);
- }
-}
-
-static int ax8817x_open(struct net_device *net)
-{
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
- u8 buf[4];
- int i, ret;
-
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf);
- if (ret < 0) {
- return ret;
- }
-
- ret = 0;
-
- ax_info->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (ax_info->tx_urb == NULL) {
- err("Error allocating tx_urb!");
- ret = -ENOMEM;
- }
-
- atomic_set(&ax_info->rx_refill_cnt, 0);
-
- for (i = 0; i < n_rx_urbs && ret == 0; i++) {
- struct urb *urb = ax_info->rx_urbs[i];
-
- if (urb == NULL) {
- urb = ax_info->rx_urbs[i] =
- usb_alloc_urb(0, GFP_KERNEL);
- if (urb == NULL) {
- ret = -ENOMEM;
- break;
- }
- if (n_rx_urbs > 1) {
- urb->transfer_flags |= URB_ZERO_PACKET;
- }
- }
- ret = ax_refill_rx_urb(ax_info, urb);
- if (ret == 1) {
- atomic_inc(&ax_info->rx_refill_cnt);
- ret = 0;
- }
- }
-
- /* XXX: should handle the case where we couldn't allocate any skb's
- better. They get allocated with GFP_ATOMIC, so they may all fail... */
- if (ret == 0 && atomic_read(&ax_info->rx_refill_cnt) < n_rx_urbs) {
- netif_start_queue(net);
- } else {
- /* Error: clean up anything we allocated and bail. */
- usb_free_urb(ax_info->tx_urb);
-
- for (i = 0; i < n_rx_urbs; i++) {
- struct urb *urb = ax_info->rx_urbs[i];
-
- if (urb != NULL) {
- /* skb gets freed in the URB callback */
- usb_unlink_urb(urb);
- usb_free_urb(urb);
- }
- }
-
- err("%s: Failed start rx queue (%d)\n", __FUNCTION__, ret);
- }
- return ret;
-}
-
-static int ax8817x_stop(struct net_device *net)
-{
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
- u8 buf[4];
- int i, ret;
-
- netif_stop_queue(net);
-
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf);
- if (ret < 0 && ax_info->drv_state != AX_DRV_STATE_EXITING) {
- err("%s: Failed cmd (%d)\n", __FUNCTION__, ret);
- }
- if (ax_info->tx_urb != NULL) {
- usb_unlink_urb(ax_info->tx_urb);
- usb_free_urb(ax_info->tx_urb);
- ax_info->tx_urb = NULL;
- }
-
- for (i = 0; i < n_rx_urbs; i++) {
- struct urb *urb = ax_info->rx_urbs[i];
- if (urb != NULL) {
- /* skb gets freed in the URB callback */
- usb_unlink_urb(urb);
- usb_free_urb(urb);
- ax_info->rx_urbs[i] = NULL;
- }
- }
-
- return 0;
-}
-
-static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
-{
- struct ax8817x_info *ax_info = urb->context;
-
- if (!ax_info || (ax_info->drv_state == AX_DRV_STATE_EXITING))
- return;
-
- if (!netif_device_present(ax_info->net))
- return;
-
- if (urb->status)
- info("%s: TX status %d", ax_info->net->name, urb->status);
-
- ax_info->net->trans_start = jiffies;
- netif_wake_queue(ax_info->net);
-}
-
-static int ax8817x_start_xmit(struct sk_buff *skb, struct net_device *net)
-{
- struct ax8817x_info *ax_info = net->priv;
- int res;
-
- netif_stop_queue(net);
-
- ax_info->tx_urb->transfer_flags |= URB_ZERO_PACKET;
- usb_fill_bulk_urb(ax_info->tx_urb, ax_info->usb,
- usb_sndbulkpipe(ax_info->usb, 2),
- skb->data, skb->len, write_bulk_callback,
- ax_info);
- if ((res = usb_submit_urb(ax_info->tx_urb, GFP_ATOMIC))) {
- warn("Failed tx_urb %d", res);
- ax_info->stats.tx_errors++;
- netif_start_queue(net);
- } else {
- ax_info->stats.tx_packets++;
- ax_info->stats.tx_bytes += skb->len;
- net->trans_start = jiffies;
- }
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-static void ax8817x_tx_timeout(struct net_device *net)
-{
- struct ax8817x_info *ax_info = net->priv;
-
- if (!ax_info)
- return;
-
- warn("%s: Tx timed out.", net->name);
- ax_info->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
- usb_unlink_urb(ax_info->tx_urb);
- ax_info->stats.tx_errors++;
-}
-
-static struct net_device_stats *ax8817x_stats(struct net_device *net)
-{
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
-
- return &ax_info->stats;
-}
-
-static void ax8817x_set_multicast(struct net_device *net)
-{
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
- u8 rx_ctl = 0x8c;
-
- if (net->flags & IFF_PROMISC) {
- rx_ctl |= 0x01;
- } else if (net->flags & IFF_ALLMULTI
- || net->mc_count > AX_MAX_MCAST) {
- rx_ctl |= 0x02;
- } else if (net->mc_count == 0) {
- /* just broadcast and directed */
- } else {
- struct dev_mc_list *mc_list = net->mc_list;
- u8 *multi_filter;
- u32 crc_bits;
- int i;
-
- multi_filter = kmalloc(AX_MCAST_FILTER_SIZE, GFP_ATOMIC);
- if (multi_filter == NULL) {
- /* Oops, couldn't allocate a DMA buffer for setting the multicast
- filter. Try all multi mode, although the ax_write_cmd_async
- will almost certainly fail, too... (but it will printk). */
- rx_ctl |= 0x02;
- } else {
- memset(multi_filter, 0, AX_MCAST_FILTER_SIZE);
-
- /* Build the multicast hash filter. */
- for (i = 0; i < net->mc_count; i++) {
- crc_bits =
- ether_crc(ETH_ALEN,
- mc_list->dmi_addr) >> 26;
- multi_filter[crc_bits >> 3] |=
- 1 << (crc_bits & 7);
- mc_list = mc_list->next;
- }
-
- ax_write_cmd_async(ax_info,
- AX_CMD_WRITE_MULTI_FILTER, 0, 0,
- AX_MCAST_FILTER_SIZE, multi_filter);
-
- rx_ctl |= 0x10;
- }
- }
-
- ax_write_cmd_async(ax_info, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0,
- NULL);
-}
-
-static int read_mii_word(struct ax8817x_info *ax_info, __u8 phy, __u8 indx,
- __u16 * regd)
-{
- int ret;
- u8 buf[4];
-
- devdbg(ax_info,"read_mii_word: phy=%02x, indx=%02x, regd=%04x", phy, indx, *regd);
-
- ax_write_cmd(ax_info, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
-
- ret = ax_read_cmd(ax_info, AX_CMD_READ_MII_REG, ax_info->phy_id, (__u16)indx, 2, regd);
- devdbg(ax_info,"read_mii_word: AX_CMD_READ_MII_REG ret=%02x, regd=%04x", ret, *regd);
-
- ax_write_cmd(ax_info, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
-
- return ret;
-}
-
-static int write_mii_word(struct ax8817x_info *ax_info, __u8 phy,
- __u8 indx, __u16 regd)
-{
- deverr(ax_info, "write_mii_word - not implemented!");
- return 0;
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int loc)
-{
- struct ax8817x_info *ax_info = dev->priv;
- int res;
-
- devdbg(ax_info, "mdio_read: phy_id=%02x, loc=%02x", phy_id, loc);
-
- read_mii_word(ax_info, phy_id, loc, (u16 *) & res);
- return res & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int loc,
- int val)
-{
- struct ax8817x_info *ax_info = dev->priv;
-
- devdbg(ax_info, "mdio_write: phy_id=%02x, loc=%02x", phy_id, loc);
- write_mii_word(ax_info, phy_id, loc, val);
-}
-
-static int ax8817x_ethtool_ioctl(struct net_device *net, void __user *uaddr)
-{
- struct ax8817x_info *ax_info;
- int cmd;
-
- ax_info = net->priv;
- if (get_user(cmd, (int *) uaddr))
- return -EFAULT;
-
- switch (cmd) {
- case ETHTOOL_GDRVINFO:{
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-
- strncpy(info.driver, DRIVER_NAME,
- sizeof(info.driver) - 1);
- strncpy(info.version, DRIVER_VERSION,
- sizeof(info.version) - 1);
- usb_make_path(ax_info->usb, info.bus_info,sizeof info.bus_info);
- if (copy_to_user(uaddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- case ETHTOOL_GSET:{
- struct ethtool_cmd ecmd;
-
- mii_ethtool_gset(&ax_info->mii, &ecmd);
- if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
- }
- case ETHTOOL_SSET:{
- int r;
- struct ethtool_cmd ecmd;
-
- if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
- return -EFAULT;
- r = mii_ethtool_sset(&ax_info->mii, &ecmd);
- return r;
- }
- case ETHTOOL_NWAY_RST:{
- return mii_nway_restart(&ax_info->mii);
- }
- case ETHTOOL_GLINK:{
- struct ethtool_value edata = { ETHTOOL_GLINK };
-
- edata.data = mii_link_ok(&ax_info->mii);
- if (copy_to_user(uaddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- case ETHTOOL_GMSGLVL:{
- struct ethtool_value edata = { ETHTOOL_GMSGLVL };
- edata.data = ax_info->msg_level;
- if (copy_to_user(uaddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- case ETHTOOL_SMSGLVL:{
- struct ethtool_value edata;
-
- if (copy_from_user(&edata, uaddr, sizeof(edata)))
- return -EFAULT;
- ax_info->msg_level = edata.data;
- return 0;
- }
- }
- return -EOPNOTSUPP;
-}
-
-static int ax8817x_ioctl(struct net_device *net, struct ifreq *ifr,
- int cmd)
-{
- struct ax8817x_info *ax_info;
-
- ax_info = net->priv;
-
- if (cmd == SIOCETHTOOL)
- return ax8817x_ethtool_ioctl(net, (void __user *) ifr->ifr_data);
-
- return generic_mii_ioctl(&ax_info->mii, (struct mii_ioctl_data *) &ifr->ifr_data, cmd, NULL);
-}
-
-static int ax8817x_net_init(struct net_device *net)
-{
- struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv;
- u8 buf[6];
- u16 *buf16 = (u16 *) buf;
- int ret;
-
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf);
- if (ret < 0) {
- return ret;
- }
-
- memset(buf, 0, 6);
-
- /* Get the MAC address */
- ret = ax_read_cmd(ax_info, AX_CMD_READ_NODE_ID, 0, 0, 6, buf);
- if (ret < 0) {
- return ret;
- }
-
- memcpy(net->dev_addr, buf, 6);
-
- /* Get the PHY id */
- ret = ax_read_cmd(ax_info, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
- if (ret < 0) {
- return ret;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- return -EIO;
- }
-
- /* Reset the PHY, and drop it into auto-negotiation mode */
- ax_info->phy_id = buf[1];
- ax_info->phy_state = AX_PHY_STATE_INITIALIZING;
-
- ret = ax_write_cmd(ax_info, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- if (ret < 0) {
- return ret;
- }
-
- *buf16 = cpu_to_le16(BMCR_RESET);
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG,
- ax_info->phy_id, MII_BMCR, 2, buf16);
- if (ret < 0) {
- return ret;
- }
-
- /* Advertise that we can do full-duplex pause */
- *buf16 = cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400);
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG,
- ax_info->phy_id, MII_ADVERTISE, 2, buf16);
- if (ret < 0) {
- return ret;
- }
-
- *buf16 = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG,
- ax_info->phy_id, MII_BMCR, 2, buf16);
- if (ret < 0) {
- return ret;
- }
-
- ret = ax_write_cmd(ax_info, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
- if (ret < 0) {
- return ret;
- }
-
- net->open = ax8817x_open;
- net->stop = ax8817x_stop;
- net->hard_start_xmit = ax8817x_start_xmit;
- net->tx_timeout = ax8817x_tx_timeout;
- net->watchdog_timeo = AX_TIMEOUT_TX;
- net->get_stats = ax8817x_stats;
- net->do_ioctl = ax8817x_ioctl;
- net->set_multicast_list = ax8817x_set_multicast;
-
- return 0;
-}
-
-static int ax8817x_bind(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *usb = interface_to_usbdev(intf);
- struct ax8817x_info *ax_info;
- struct net_device *net;
- int i, ret;
- unsigned long gpio_bits = id->driver_info;
- u8 buf[2];
-
- /* Allocate the URB lists along with the device info struct */
- ax_info = kmalloc(sizeof(struct ax8817x_info) +
- n_rx_urbs * sizeof(struct urb *), GFP_KERNEL);
- if (ax_info == NULL) {
- err("%s: Failed ax alloc\n", __FUNCTION__);
- goto exit_err;
- }
-
- memset(ax_info, 0, sizeof(struct ax8817x_info) +
- n_rx_urbs * sizeof(struct urb *));
-
- ax_info->drv_state = AX_DRV_STATE_INITIALIZING;
- ax_info->rx_urbs = (struct urb **) (ax_info + 1);
- ax_info->usb = usb;
-
- /* Set up the control URB queue */
-
- INIT_LIST_HEAD(&ax_info->ctl_queue);
- spin_lock_init(&ax_info->ctl_lock);
- ax_info->ctl_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (ax_info->ctl_urb == NULL) {
- goto exit_err_free_ax;
- }
-
- /* Toggle the GPIOs in a manufacturer/model specific way */
-
- for (i = 2; i >= 0; i--) {
- ret = ax_write_cmd(ax_info, AX_CMD_WRITE_GPIOS,
- (gpio_bits >> (i * 8)) & 0xff, 0, 0,
- buf);
- if (ret < 0) {
- goto exit_err_free_ax;
- }
- wait_ms(5);
- }
-
- /* Set up the net device */
-
- net = alloc_etherdev(0);
- if (net == NULL) {
- err("%s: Failed net alloc\n", __FUNCTION__);
- goto exit_err_free_ax;
- }
-
- ax_info->net = net;
-
- SET_MODULE_OWNER(net);
- net->init = ax8817x_net_init;
- net->priv = ax_info;
-
- SET_NETDEV_DEV(net, &intf->dev);
- ret = register_netdev(net);
- if (ret < 0) {
- err("%s: Failed net init (%d)\n", __FUNCTION__, ret);
- goto exit_err_free_net;
- }
-
- /* Setup mii structure */
- ax_info->mii.dev = net;
- ax_info->mii.mdio_read = mdio_read;
- ax_info->mii.mdio_write = mdio_write;
- ax_info->mii.phy_id = ax_info->phy_id;
- ax_info->mii.phy_id_mask = 0x3f;
- ax_info->mii.reg_num_mask = 0x1f;
-
- /* Set up the interrupt URB, and start PHY state monitoring */
-
- ax_info->int_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (ax_info->int_urb == NULL) {
- goto exit_err_unregister_net;
- }
- ax_info->int_buf = kmalloc(8, GFP_KERNEL);
- if (ax_info->int_buf == NULL) {
- goto exit_err_free_int_urb;
- }
- ax_info->phy_req.data = kmalloc(2, GFP_KERNEL);
- if (ax_info->phy_req.data == NULL) {
- goto exit_err_free_int_buf;
- }
-
- usb_fill_int_urb(ax_info->int_urb, usb, usb_rcvintpipe(usb, 1),
- ax_info->int_buf, 8, ax_int_callback, ax_info,
- usb->speed == USB_SPEED_HIGH? 8: 100);
-
- ret = usb_submit_urb(ax_info->int_urb, GFP_ATOMIC);
- if (ret < 0) {
- err("%s: Failed int URB submit (%d)\n", __FUNCTION__, ret);
- goto exit_err_free_phy_buf;
- }
-
- ax_info->drv_state = AX_DRV_STATE_RUNNING;
- usb_set_intfdata(intf, ax_info);
-
- return 0;
-
- exit_err_free_phy_buf:
- kfree(ax_info->phy_req.data);
-
- exit_err_free_int_buf:
- kfree(ax_info->int_buf);
-
- exit_err_free_int_urb:
- usb_free_urb(ax_info->int_urb);
-
- exit_err_unregister_net:
- ax_info->drv_state = AX_DRV_STATE_EXITING;
- unregister_netdev(net);
-
- exit_err_free_net:
- kfree(net);
-
- exit_err_free_ax:
- if (ax_info->ctl_urb != NULL) {
- /* no need to unlink, since there should not be any ctl URBs
- pending at this point */
- usb_free_urb(ax_info->ctl_urb);
- }
-
- kfree(ax_info);
-
-exit_err:
- err("%s: Failed to initialize\n", __FUNCTION__);
- return -EIO;
-}
-
-static void ax8817x_disconnect(struct usb_interface *intf)
-{
- struct ax8817x_info *ax_info = usb_get_intfdata(intf);
-
- usb_set_intfdata(intf, NULL);
- if (ax_info) {
- ax_info->drv_state = AX_DRV_STATE_EXITING;
-
- if (ax_info->int_urb != NULL) {
- usb_unlink_urb(ax_info->int_urb);
- usb_free_urb(ax_info->int_urb);
- kfree(ax_info->int_buf);
- }
-
- unregister_netdev(ax_info->net);
-
- /* XXX: hmmm... need to go through and clear out the ctl queue, too... */
- if (ax_info->ctl_urb != NULL) {
- usb_unlink_urb(ax_info->ctl_urb);
- usb_free_urb(ax_info->ctl_urb);
- }
-
- kfree(ax_info);
- }
-}
-
-static struct usb_driver ax8817x_driver = {
- .owner = THIS_MODULE,
- .name = DRIVER_NAME,
- .probe = ax8817x_bind,
- .disconnect = ax8817x_disconnect,
- .id_table = ax8817x_id_table,
-};
-
-static int __init ax8817x_init(void)
-{
- int ret;
-
- if (n_rx_urbs < 1)
- n_rx_urbs = AX_RX_URBS_DEFAULT;
-
- ret = usb_register(&ax8817x_driver);
- if (ret < 0) {
- err("%s: Failed to register\n", __FUNCTION__);
- } else {
- info(DRIVER_DESC " " DRIVER_VERSION);
- }
-
- return ret;
-}
-
-static void __exit ax8817x_exit(void)
-{
- usb_deregister(&ax8817x_driver);
-}
-
-module_init(ax8817x_init);
-module_exit(ax8817x_exit);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index d9abf8afdcad..07f227d3c64d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -594,8 +594,6 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
timeout = schedule_timeout(timeout);
- set_current_state( TASK_RUNNING );
-
remove_wait_queue( q, &wait );
return( timeout );
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ef813e60a286..95d984b0f8d1 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -17,6 +17,11 @@
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
*
+ * (21/Sep/2003) Ian Abbott
+ * Added VID/PID for Omnidirectional Control Technology US101 USB to
+ * RS-232 adapter (also rebadged as Dick Smith Electronics XH6381).
+ * VID/PID supplied by Donald Gordon.
+ *
* (19/Aug/2003) Ian Abbott
* Freed urb's transfer buffer in write bulk callback.
* Omitted some paranoid checks in write bulk callback that don't matter.
@@ -334,6 +339,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0, 0x3ff) },
{ } /* Terminating entry */
};
@@ -406,6 +412,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0x400, 0xffff) },
{ } /* Terminating entry */
};
@@ -491,6 +498,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
+ { USB_DEVICE(OCT_VID, OCT_US101_PID) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
{ } /* Terminating entry */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index ae5e8df54a99..64ad4790fe86 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -133,6 +133,13 @@
#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */
#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */
+/*
+ * Definitions for Omnidirectional Control Technology, Inc. devices
+ */
+#define OCT_VID 0x0B39 /* OCT vendor ID */
+/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
+#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index e9a4282d89c7..96747544c788 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1019,10 +1019,10 @@ int usb_serial_probe(struct usb_interface *interface,
retval = type->probe (serial, id_pattern);
module_put(type->owner);
- if (retval < 0) {
+ if (retval) {
dbg ("sub driver rejected device");
kfree (serial);
- return -ENODEV;
+ return retval;
}
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 81e6c62a28ee..abbb98ce53e3 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1074,7 +1074,6 @@ static int usb_stor_reset_common(struct us_data *us,
up(&us->dev_semaphore);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ*6);
- set_current_state(TASK_RUNNING);
down(&us->dev_semaphore);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("Reset interrupted by disconnect\n");