summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.osdl.org>2003-09-20 04:18:59 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-09-20 04:18:59 -0700
commit834ae7f12afa0d4350e3874a135aa5a4c24a87d7 (patch)
tree59478adff11dc8cd1aa0654dc5475a8216b29e80
parent4f3a1d592e8dc6d7327fc7ca915b9b764883d5b7 (diff)
parent24a2d11aa804699923077b0e13d1b65e36217db0 (diff)
Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--Documentation/networking/bonding.txt4
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/input/evdev.c12
-rw-r--r--drivers/input/input.c6
-rw-r--r--drivers/input/joystick/db9.c313
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c5
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c6
-rw-r--r--drivers/input/keyboard/Kconfig3
-rw-r--r--drivers/input/keyboard/atkbd.c173
-rw-r--r--drivers/input/mouse/Kconfig20
-rw-r--r--drivers/input/mouse/psmouse-base.c103
-rw-r--r--drivers/input/mouse/psmouse.h22
-rw-r--r--drivers/input/mouse/synaptics.c363
-rw-r--r--drivers/input/mouse/synaptics.h27
-rw-r--r--drivers/input/serio/serio.c31
-rw-r--r--drivers/net/3c501.c6
-rw-r--r--drivers/net/3c505.c12
-rw-r--r--drivers/net/3c515.c1
-rw-r--r--drivers/net/Space.c4
-rw-r--r--drivers/net/acenic.c3
-rw-r--r--drivers/net/bonding/bond_alb.c150
-rw-r--r--drivers/net/bonding/bond_alb.h8
-rw-r--r--drivers/net/bonding/bond_main.c1078
-rw-r--r--drivers/net/bonding/bonding.h4
-rw-r--r--drivers/net/cs89x0.c1
-rw-r--r--drivers/net/depca.c942
-rw-r--r--drivers/net/e1000/e1000_main.c13
-rw-r--r--drivers/net/eepro.c6
-rw-r--r--drivers/net/ewrk3.c5
-rw-r--r--drivers/net/hamradio/baycom_par.c1
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c1
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c1
-rw-r--r--drivers/net/hamradio/hdlcdrv.c1
-rw-r--r--drivers/net/hamradio/scc.c208
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/ibmlana.c1
-rw-r--r--drivers/net/irda/Kconfig24
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/ali-ircc.c84
-rw-r--r--drivers/net/irda/donauboe.c50
-rw-r--r--drivers/net/irda/irda-usb.c44
-rw-r--r--drivers/net/irda/nsc-ircc.c78
-rw-r--r--drivers/net/irda/sir_kthread.c4
-rw-r--r--drivers/net/irda/smc-ircc.c1258
-rw-r--r--drivers/net/irda/toshoboe.c957
-rw-r--r--drivers/net/irda/via-ircc.c92
-rw-r--r--drivers/net/irda/w83977af_ir.c54
-rw-r--r--drivers/net/lance.c10
-rw-r--r--drivers/net/mace.c1
-rw-r--r--drivers/net/ne2.c1
-rw-r--r--drivers/net/ni5010.c5
-rw-r--r--drivers/net/ni52.c5
-rw-r--r--drivers/net/ni65.c1
-rw-r--r--drivers/net/ns83820.c10
-rw-r--r--drivers/net/pcmcia/com20020_cs.c41
-rw-r--r--drivers/net/rcpci45.c4
-rw-r--r--drivers/net/rrunner.c17
-rw-r--r--drivers/net/rrunner.h1
-rw-r--r--drivers/net/sb1000.c1
-rw-r--r--drivers/net/sis900.c1
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h4
-rw-r--r--drivers/net/sk98lin/skge.c1
-rw-r--r--drivers/net/sk_mca.h2
-rw-r--r--drivers/net/skfp/h/targetos.h1
-rw-r--r--drivers/net/smc9194.c1
-rw-r--r--drivers/net/tokenring/lanstreamer.h2
-rw-r--r--drivers/net/tokenring/proteon.c2
-rw-r--r--drivers/net/tokenring/skisa.c2
-rw-r--r--drivers/net/tokenring/smctr.c1
-rw-r--r--drivers/net/tokenring/tms380tr.c1
-rw-r--r--drivers/net/wan/comx-hw-comx.c1
-rw-r--r--drivers/net/wan/comx-hw-locomx.c1
-rw-r--r--drivers/net/wan/comx-hw-mixcom.c1
-rw-r--r--drivers/net/wan/comx-hw-munich.c1
-rw-r--r--drivers/net/wan/comx-proto-fr.c1
-rw-r--r--drivers/net/wan/comx-proto-lapb.c1
-rw-r--r--drivers/net/wan/comx-proto-ppp.c1
-rw-r--r--drivers/net/wan/comx.c1
-rw-r--r--drivers/net/wan/cycx_x25.c1
-rw-r--r--drivers/net/wan/dlci.c1
-rw-r--r--drivers/net/wan/dscc4.c1
-rw-r--r--drivers/net/wan/lmc/lmc_ver.h2
-rw-r--r--drivers/net/wan/pc300_drv.c1
-rw-r--r--drivers/net/wan/pc300_tty.c1
-rw-r--r--drivers/net/wan/sbni.c20
-rw-r--r--drivers/net/wan/sdla_chdlc.c1
-rw-r--r--drivers/net/wan/sdla_fr.c1
-rw-r--r--drivers/net/wan/sdla_ft1.c1
-rw-r--r--drivers/net/wan/sdla_ppp.c1
-rw-r--r--drivers/net/wan/sdla_x25.c1
-rw-r--r--drivers/net/wan/sdladrv.c1
-rw-r--r--drivers/net/wan/sdlamain.c1
-rw-r--r--drivers/net/wan/sealevel.c159
-rw-r--r--drivers/net/wan/wanpipe_multppp.c1
-rw-r--r--drivers/net/wd.c5
-rw-r--r--drivers/net/wireless/airo.c11
-rw-r--r--drivers/net/wireless/arlan-proc.c3
-rw-r--r--drivers/net/wireless/arlan.c1
-rw-r--r--drivers/net/wireless/arlan.h1
-rw-r--r--drivers/net/wireless/strip.c1
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/serio.h3
-rw-r--r--include/net/syncppp.h7
-rw-r--r--sound/oss/i810_audio.c11
105 files changed, 2590 insertions, 3960 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f6121f18c501..3a66d54c51e0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -788,6 +788,10 @@ running once the system is up.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
+ psmouse_resetafter=
+ [HW,MOUSE] Try to reset Synaptics Touchpad after so many
+ bad packets (0 = never).
+
pss= [HW,OSS] Personal Sound System (ECHO ESC614)
Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 0687f435ee89..32acbb0020f4 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -527,9 +527,9 @@ Verifying Bond Configuration
1) Bonding information files
----------------------------
-The bonding driver information files reside in the /proc/net/bond* directories.
+The bonding driver information files reside in the /proc/net/bonding directory.
-Sample contents of /proc/net/bond0/info after the driver is loaded with
+Sample contents of /proc/net/bonding/bond0 after the driver is loaded with
parameters of mode=0 and miimon=1000 is shown below.
Bonding Mode: load balancing (round-robin)
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 26c5df39f937..32347f8c9369 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -205,7 +205,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
INPUT_KEYCODE(dev, scancode) = keycode;
for (i = 0; i < dev->keycodemax; i++)
- if(INPUT_KEYCODE(dev, scancode) == oldkey)
+ if(keycode == oldkey)
break;
if (i == dev->keycodemax)
clear_bit(oldkey, dev->keybit);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 10a13ac90c48..ca56ac39e2b8 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -208,7 +208,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
- int i, t, u;
+ int i, t, u, v;
if (!evdev->exist) return -ENODEV;
@@ -239,14 +239,12 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCSKEYCODE:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+ if (get_user(v, ((int *) arg) + 1)) return -EFAULT;
u = INPUT_KEYCODE(dev, t);
- if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
-
- for (i = 0; i < dev->keycodemax; i++)
- if(INPUT_KEYCODE(dev, t) == u) break;
+ INPUT_KEYCODE(dev, t) = v;
+ for (i = 0; i < dev->keycodemax; i++) if (v == u) break;
if (i == dev->keycodemax) clear_bit(u, dev->keybit);
- set_bit(INPUT_KEYCODE(dev, t), dev->keybit);
-
+ set_bit(v, dev->keybit);
return 0;
case EVIOCSFF:
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 843c342864f5..45d9bdffdbe4 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -426,8 +426,10 @@ void input_register_device(struct input_dev *dev)
init_timer(&dev->timer);
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
- dev->rep[REP_DELAY] = HZ/4;
- dev->rep[REP_PERIOD] = HZ/33;
+ if (!dev->rep[REP_DELAY])
+ dev->rep[REP_DELAY] = HZ/4;
+ if (!dev->rep[REP_PERIOD])
+ dev->rep[REP_PERIOD] = HZ/33;
INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 091fe2e887fa..9d757ce3f8ec 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -55,7 +55,9 @@ MODULE_PARM(db9_3, "2i");
#define DB9_MULTI_0802 0x08
#define DB9_MULTI_0802_2 0x09
#define DB9_CD32_PAD 0x0A
-#define DB9_MAX_PAD 0x0B
+#define DB9_SATURN_DPP 0x0B
+#define DB9_SATURN_DPP_2 0x0C
+#define DB9_MAX_PAD 0x0D
#define DB9_UP 0x01
#define DB9_DOWN 0x02
@@ -69,10 +71,7 @@ MODULE_PARM(db9_3, "2i");
#define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08
-#define DB9_SATURN0 0x00
-#define DB9_SATURN1 0x02
-#define DB9_SATURN2 0x04
-#define DB9_SATURN3 0x06
+#define DB9_MAX_DEVICES 2
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
@@ -82,7 +81,7 @@ static int db9_2[] __initdata = { -1, 0 };
static int db9_3[] __initdata = { -1, 0 };
struct db9 {
- struct input_dev dev[2];
+ struct input_dev dev[DB9_MAX_DEVICES];
struct timer_list timer;
struct pardevice *pd;
int mode;
@@ -96,12 +95,247 @@ static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
-static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 };
+static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
- db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn };
+ db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
+ db9_cd32_btn, db9_cd32_btn };
static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
- "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad" };
+ "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
+
+static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
+static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
+static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
+static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
+static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
+
+/*
+ * Saturn controllers
+ */
+#define DB9_SATURN_DELAY 300
+static const int db9_saturn_byte[] = { 1, 1, 1, 2, 2, 2, 2, 2, 1 };
+static const unsigned char db9_saturn_mask[] = { 0x04, 0x01, 0x02, 0x40, 0x20, 0x10, 0x08, 0x80, 0x08 };
+
+/*
+ * db9_saturn_write_sub() writes 2 bit data.
+ */
+static void db9_saturn_write_sub(struct parport *port, int type, unsigned char data, int powered, int pwr_sub)
+{
+ unsigned char c;
+
+ switch (type) {
+ case 1: /* DPP1 */
+ c = 0x80 | 0x30 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | data;
+ parport_write_data(port, c);
+ break;
+ case 2: /* DPP2 */
+ c = 0x40 | data << 4 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | 0x03;
+ parport_write_data(port, c);
+ break;
+ case 0: /* DB9 */
+ c = ((((data & 2) ? 2 : 0) | ((data & 1) ? 4 : 0)) ^ 0x02) | !powered;
+ parport_write_control(port, c);
+ break;
+ }
+}
+
+/*
+ * gc_saturn_read_sub() reads 4 bit data.
+ */
+static unsigned char db9_saturn_read_sub(struct parport *port, int type)
+{
+ unsigned char data;
+
+ if (type) {
+ /* DPP */
+ data = parport_read_status(port) ^ 0x80;
+ return (data & 0x80 ? 1 : 0) | (data & 0x40 ? 2 : 0)
+ | (data & 0x20 ? 4 : 0) | (data & 0x10 ? 8 : 0);
+ } else {
+ /* DB9 */
+ data = parport_read_data(port) & 0x0f;
+ return (data & 0x8 ? 1 : 0) | (data & 0x4 ? 2 : 0)
+ | (data & 0x2 ? 4 : 0) | (data & 0x1 ? 8 : 0);
+ }
+}
+
+/*
+ * db9_saturn_read_analog() sends clock and reads 8 bit data.
+ */
+static unsigned char db9_saturn_read_analog(struct parport *port, int type, int powered)
+{
+ unsigned char data;
+
+ db9_saturn_write_sub(port, type, 0, powered, 0);
+ udelay(DB9_SATURN_DELAY);
+ data = db9_saturn_read_sub(port, type) << 4;
+ db9_saturn_write_sub(port, type, 2, powered, 0);
+ udelay(DB9_SATURN_DELAY);
+ data |= db9_saturn_read_sub(port, type);
+ return data;
+}
+
+/*
+ * db9_saturn_read_packet() reads whole saturn packet at connector
+ * and returns device identifier code.
+ */
+static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char *data, int type, int powered)
+{
+ int i, j;
+ unsigned char tmp;
+
+ db9_saturn_write_sub(port, type, 3, powered, 0);
+ data[0] = db9_saturn_read_sub(port, type);
+ switch (data[0] & 0x0f) {
+ case 0xf:
+ /* 1111 no pad */
+ return data[0] = 0xff;
+ case 0x4: case 0x4 | 0x8:
+ /* ?100 : digital controller */
+ db9_saturn_write_sub(port, type, 0, powered, 1);
+ data[2] = db9_saturn_read_sub(port, type) << 4;
+ db9_saturn_write_sub(port, type, 2, powered, 1);
+ data[1] = db9_saturn_read_sub(port, type) << 4;
+ db9_saturn_write_sub(port, type, 1, powered, 1);
+ data[1] |= db9_saturn_read_sub(port, type);
+ db9_saturn_write_sub(port, type, 3, powered, 1);
+ /* data[2] |= db9_saturn_read_sub(port, type); */
+ data[2] |= data[0];
+ return data[0] = 0x02;
+ case 0x1:
+ /* 0001 : analog controller or multitap */
+ db9_saturn_write_sub(port, type, 2, powered, 0);
+ udelay(DB9_SATURN_DELAY);
+ data[0] = db9_saturn_read_analog(port, type, powered);
+ if (data[0] != 0x41) {
+ /* read analog controller */
+ for (i = 0; i < (data[0] & 0x0f); i++)
+ data[i + 1] = db9_saturn_read_analog(port, type, powered);
+ db9_saturn_write_sub(port, type, 3, powered, 0);
+ return data[0];
+ } else {
+ /* read multitap */
+ if (db9_saturn_read_analog(port, type, powered) != 0x60)
+ return data[0] = 0xff;
+ for (i = 0; i < 60; i += 10) {
+ data[i] = db9_saturn_read_analog(port, type, powered);
+ if (data[i] != 0xff)
+ /* read each pad */
+ for (j = 0; j < (data[i] & 0x0f); j++)
+ data[i + j + 1] = db9_saturn_read_analog(port, type, powered);
+ }
+ db9_saturn_write_sub(port, type, 3, powered, 0);
+ return 0x41;
+ }
+ case 0x0:
+ /* 0000 : mouse */
+ db9_saturn_write_sub(port, type, 2, powered, 0);
+ udelay(DB9_SATURN_DELAY);
+ tmp = db9_saturn_read_analog(port, type, powered);
+ if (tmp == 0xff) {
+ for (i = 0; i < 3; i++)
+ data[i + 1] = db9_saturn_read_analog(port, type, powered);
+ db9_saturn_write_sub(port, type, 3, powered, 0);
+ return data[0] = 0xe3;
+ }
+ default:
+ return data[0];
+ }
+}
+
+/*
+ * db9_saturn_report() analyzes packet and reports.
+ */
+static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads)
+{
+ int tmp, i, j;
+
+ tmp = (id == 0x41) ? 60 : 10;
+ for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) {
+ switch (data[j]) {
+ case 0x16: /* multi controller (analog 4 axis) */
+ input_report_abs(dev + n, db9_abs[5], data[j + 6]);
+ case 0x15: /* mission stick (analog 3 axis) */
+ input_report_abs(dev + n, db9_abs[3], data[j + 4]);
+ input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+ case 0x13: /* racing controller (analog 1 axis) */
+ input_report_abs(dev + n, db9_abs[2], data[j + 3]);
+ case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
+ case 0x02: /* digital pad (digital 2 axis + buttons) */
+ input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+ input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+ for (i = 0; i < 9; i++)
+ input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+ break;
+ case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
+ input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+ input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+ for (i = 0; i < 9; i++)
+ input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+ input_report_abs(dev + n, db9_abs[2], data[j + 3]);
+ input_report_abs(dev + n, db9_abs[3], data[j + 4]);
+ input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+ /*
+ input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
+ input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
+ */
+ input_report_abs(dev + n, db9_abs[6], data[j + 7]);
+ input_report_abs(dev + n, db9_abs[7], data[j + 8]);
+ input_report_abs(dev + n, db9_abs[5], data[j + 9]);
+ break;
+ case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
+ input_report_key(dev + n, BTN_A, data[j + 3] & 0x80);
+ input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f);
+ break;
+ case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
+ input_report_key(dev + n, BTN_START, data[j + 1] & 0x08);
+ input_report_key(dev + n, BTN_A, data[j + 1] & 0x04);
+ input_report_key(dev + n, BTN_C, data[j + 1] & 0x02);
+ input_report_key(dev + n, BTN_B, data[j + 1] & 0x01);
+ input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80);
+ input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
+ break;
+ case 0xff:
+ default: /* no pad */
+ input_report_abs(dev + n, db9_abs[0], 0);
+ input_report_abs(dev + n, db9_abs[1], 0);
+ for (i = 0; i < 9; i++)
+ input_report_key(dev + n, db9_cd32_btn[i], 0);
+ break;
+ }
+ }
+ return n;
+}
+
+static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
+{
+ unsigned char id, data[60];
+ int type, n, max_pads;
+ int tmp, i;
+
+ switch (mode) {
+ case DB9_SATURN_PAD:
+ type = 0;
+ n = 1;
+ break;
+ case DB9_SATURN_DPP:
+ type = 1;
+ n = 1;
+ break;
+ case DB9_SATURN_DPP_2:
+ type = 1;
+ n = 2;
+ break;
+ default:
+ return -1;
+ }
+ max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
+ for (tmp = 0, i = 0; i < n; i++) {
+ id = db9_saturn_read_packet(port, data, type + i, 1);
+ tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
+ }
+ return 0;
+}
static void db9_timer(unsigned long private)
{
@@ -222,28 +456,10 @@ static void db9_timer(unsigned long private)
break;
case DB9_SATURN_PAD:
+ case DB9_SATURN_DPP:
+ case DB9_SATURN_DPP_2:
- parport_write_control(port, DB9_SATURN0);
- data = parport_read_data(port);
-
- input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
- input_report_key(dev, BTN_Z, ~data & DB9_DOWN);
- input_report_key(dev, BTN_TL, ~data & DB9_UP);
- input_report_key(dev, BTN_TR, ~data & DB9_RIGHT);
-
- parport_write_control(port, DB9_SATURN2);
- data = parport_read_data(port);
-
- input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
- input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
-
- parport_write_control(port, DB9_NORMAL);
- data = parport_read_data(port);
-
- input_report_key(dev, BTN_A, ~data & DB9_LEFT);
- input_report_key(dev, BTN_B, ~data & DB9_UP);
- input_report_key(dev, BTN_C, ~data & DB9_DOWN);
- input_report_key(dev, BTN_X, ~data & DB9_RIGHT);
+ db9_saturn(db9->mode, port, dev);
break;
case DB9_CD32_PAD:
@@ -279,8 +495,10 @@ static int db9_open(struct input_dev *dev)
if (!db9->used++) {
parport_claim(db9->pd);
parport_write_data(port, 0xff);
- parport_data_reverse(port);
- parport_write_control(port, DB9_NORMAL);
+ if (db9_reverse[db9->mode]) {
+ parport_data_reverse(port);
+ parport_write_control(port, DB9_NORMAL);
+ }
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}
@@ -321,11 +539,13 @@ static struct db9 __init *db9_probe(int *config)
return NULL;
}
- if (!(pp->modes & PARPORT_MODE_TRISTATE) && config[1] != DB9_MULTI_0802) {
- printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
- return NULL;
+ if (db9_bidirectional[config[1]]) {
+ if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
+ printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+ return NULL;
+ }
}
-
+
if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL)))
return NULL;
memset(db9, 0, sizeof(struct db9));
@@ -343,7 +563,7 @@ static struct db9 __init *db9_probe(int *config)
return NULL;
}
- for (i = 0; i < 1 + (db9->mode == DB9_MULTI_0802_2); i++) {
+ for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
@@ -359,14 +579,19 @@ static struct db9 __init *db9_probe(int *config)
db9->dev[i].id.version = 0x0100;
db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- db9->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
for (j = 0; j < db9_buttons[db9->mode]; j++)
set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
-
- db9->dev[i].absmin[ABS_X] = -1; db9->dev[i].absmax[ABS_X] = 1;
- db9->dev[i].absmin[ABS_Y] = -1; db9->dev[i].absmax[ABS_Y] = 1;
-
+ for (j = 0; j < db9_num_axis[db9->mode]; j++) {
+ set_bit(db9_abs[j], db9->dev[i].absbit);
+ if (j < 2) {
+ db9->dev[i].absmin[db9_abs[j]] = -1;
+ db9->dev[i].absmax[db9_abs[j]] = 1;
+ } else {
+ db9->dev[i].absmin[db9_abs[j]] = 1;
+ db9->dev[i].absmax[db9_abs[j]] = 255;
+ db9->dev[i].absflat[db9_abs[j]] = 0;
+ }
+ }
input_register_device(db9->dev + i);
printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
}
@@ -419,7 +644,7 @@ void __exit db9_exit(void)
for (i = 0; i < 3; i++)
if (db9_base[i]) {
- for (j = 0; j < 1 + (db9_base[i]->mode == DB9_MULTI_0802_2); j++)
+ for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
input_unregister_device(db9_base[i]->dev + j);
parport_unregister_device(db9_base[i]->pd);
}
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 176c5e889186..0c37044ef85a 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -166,8 +166,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
iforce->expect_packet = 0;
iforce->ecmd = cmd;
memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
- if (waitqueue_active(&iforce->wait))
- wake_up(&iforce->wait);
+ wake_up(&iforce->wait);
}
#endif
@@ -264,7 +263,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait);
- if (usb_submit_urb(iforce->ctrl, GFP_KERNEL)) {
+ if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
return -1;
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 0acb3f9b6c1d..a2cefd078385 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -116,8 +116,7 @@ static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
iforce_usb_xmit(iforce);
- if (waitqueue_active(&iforce->wait))
- wake_up(&iforce->wait);
+ wake_up(&iforce->wait);
}
static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
@@ -125,8 +124,7 @@ static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
struct iforce *iforce = urb->context;
if (urb->status) return;
iforce->ecmd = 0xff00 | urb->actual_length;
- if (waitqueue_active(&iforce->wait))
- wake_up(&iforce->wait);
+ wake_up(&iforce->wait);
}
static int iforce_usb_probe(struct usb_interface *intf,
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index d210fba2b127..9288a60dff5e 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -13,7 +13,8 @@ config INPUT_KEYBOARD
config KEYBOARD_ATKBD
tristate "AT keyboard support" if EMBEDDED || !X86
- default y
+ default y if INPUT=y && INPUT_KEYBOARD=y && SERIO=y
+ default m
depends on INPUT && INPUT_KEYBOARD && SERIO
help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 719def669f8f..9f7726d91402 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -18,6 +18,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
+#include <linux/timer.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
@@ -40,8 +41,8 @@ static int atkbd_reset = 1;
static unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85,
0, 56, 42,182, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
- 0, 46, 45, 32, 18, 5, 4, 91, 0, 57, 47, 33, 20, 19, 6, 0,
- 0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
+ 0, 46, 45, 32, 18, 5, 4, 91, 90, 57, 47, 33, 20, 19, 6, 0,
+ 91, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0,
85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121, 0,123,
@@ -87,10 +88,10 @@ static unsigned char atkbd_set3_keycode[512] = {
#define ATKBD_CMD_GSCANSET 0x11f0
#define ATKBD_CMD_SSCANSET 0x10f0
#define ATKBD_CMD_GETID 0x02f2
+#define ATKBD_CMD_SETREP 0x10f3
#define ATKBD_CMD_ENABLE 0x00f4
#define ATKBD_CMD_RESET_DIS 0x00f5
#define ATKBD_CMD_RESET_BAT 0x02ff
-#define ATKBD_CMD_SETALL_MB 0x00f8
#define ATKBD_CMD_RESEND 0x00fe
#define ATKBD_CMD_EX_ENABLE 0x10ea
#define ATKBD_CMD_EX_SETLEDS 0x20eb
@@ -114,12 +115,14 @@ struct atkbd {
unsigned char keycode[512];
struct input_dev dev;
struct serio *serio;
+ struct timer_list timer;
char name[64];
char phys[32];
unsigned char cmdbuf[4];
unsigned char cmdcnt;
unsigned char set;
unsigned char release;
+ int lastkey;
volatile signed char ack;
unsigned char emul;
unsigned short id;
@@ -142,6 +145,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
#endif
+#if !defined(__i386__) && !defined (__x86_64__)
if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
printk("atkbd.c: frame/parity error: %02x\n", flags);
serio_write(serio, ATKBD_CMD_RESEND);
@@ -151,6 +155,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (!flags)
atkbd->resend = 0;
+#endif
switch (code) {
case ATKBD_RET_ACK:
@@ -195,6 +200,14 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->set, code, serio->phys, atkbd->release ? "released" : "pressed");
break;
default:
+
+ if (!atkbd->release) {
+ mod_timer(&atkbd->timer,
+ jiffies + (test_bit(atkbd->keycode[code],
+ atkbd->dev.key) ? HZ/33 : HZ/4) + HZ/100);
+ atkbd->lastkey = atkbd->keycode[code];
+ }
+
input_regs(&atkbd->dev, regs);
input_report_key(&atkbd->dev, atkbd->keycode[code], !atkbd->release);
input_sync(&atkbd->dev);
@@ -205,6 +218,13 @@ out:
return IRQ_HANDLED;
}
+static void atkbd_force_key_up(unsigned long data)
+{
+ struct atkbd *atkbd = (void *) data;
+ input_report_key(&atkbd->dev, atkbd->lastkey, 0);
+ input_sync(&atkbd->dev);
+}
+
/*
* atkbd_sendbyte() sends a byte to the keyboard, and waits for
* acknowledge. It doesn't handle resends according to the keyboard
@@ -214,7 +234,7 @@ out:
static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte)
{
- int timeout = 10000; /* 100 msec */
+ int timeout = 20000; /* 200 msec */
atkbd->ack = 0;
#ifdef ATKBD_DEBUG
@@ -322,13 +342,50 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
}
/*
- * Enable keyboard.
+ * atkbd_probe() probes for an AT keyboard on a serio port.
*/
-static void atkbd_enable(struct atkbd *atkbd)
+
+static int atkbd_probe(struct atkbd *atkbd)
{
- if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE))
- printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
- atkbd->serio->phys);
+ unsigned char param[2];
+
+/*
+ * Some systems, where the bit-twiddling when testing the io-lines of the
+ * controller may confuse the keyboard need a full reset of the keyboard. On
+ * these systems the BIOS also usually doesn't do it for us.
+ */
+
+ if (atkbd_reset)
+ if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
+ printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys);
+
+/*
+ * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
+ * Some keyboards report different values, but the first byte is always 0xab or
+ * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
+ * should make sure we don't try to set the LEDs on it.
+ */
+
+ if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) {
+
+/*
+ * If the get ID command failed, we check if we can at least set the LEDs on
+ * the keyboard. This should work on every keyboard out there. It also turns
+ * the LEDs off, which we want anyway.
+ */
+ param[0] = 0;
+ if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+ return -1;
+ atkbd->id = 0xabba;
+ return 0;
+ }
+
+ if (param[0] != 0xab && param[0] != 0xac)
+ return -1;
+ atkbd->id = (param[0] << 8) | param[1];
+
+
+ return 0;
}
/*
@@ -365,103 +422,57 @@ static int atkbd_set_3(struct atkbd *atkbd)
return 4;
}
-/*
- * Try to set the set we want.
- */
+ if (atkbd_set != 3)
+ return 2;
- param[0] = atkbd_set;
+ param[0] = 3;
if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET))
return 2;
-/*
- * Read set number. Beware here. Some keyboards always send '2'
- * or some other number regardless into what mode they have been
- * attempted to be set. Other keyboards treat the '0' command as
- * 'set to set 0', and not 'report current set' as they should.
- * In that case we time out, and return 2.
- */
-
param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET))
return 2;
-/*
- * Here we return the set number the keyboard reports about
- * itself.
- */
+ if (param[0] != 3)
+ return 2;
- return (param[0] == 3) ? 3 : 2;
+ return 3;
}
-/*
- * atkbd_probe() probes for an AT keyboard on a serio port.
- */
-
-static int atkbd_probe(struct atkbd *atkbd)
+static int atkbd_enable(struct atkbd *atkbd)
{
- unsigned char param[2];
-
-/*
- * Some systems, where the bit-twiddling when testing the io-lines of the
- * controller may confuse the keyboard need a full reset of the keyboard. On
- * these systems the BIOS also usually doesn't do it for us.
- */
-
- if (atkbd_reset)
- if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
- printk(KERN_WARNING
- "atkbd.c: keyboard reset failed on %s\n",
- atkbd->serio->phys);
+ unsigned char param[1];
/*
- * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
- * Some keyboards report different values, but the first byte is always 0xab or
- * 0xac. Some old AT keyboards don't report anything.
+ * Set the LEDs to a defined state.
*/
- if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) {
+ param[0] = 0;
+ if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+ return -1;
/*
- * If the get ID command failed, we check if we can at least set the LEDs on
- * the keyboard. This should work on every keyboard out there. It also turns
- * the LEDs off, which we want anyway.
+ * Set autorepeat to fastest possible.
*/
- param[0] = 0;
- if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
- return -1;
- atkbd->id = 0xabba;
- return 0;
- }
- if (param[0] != 0xab && param[0] != 0xac)
+ param[0] = 0;
+ if (atkbd_command(atkbd, param, ATKBD_CMD_SETREP))
return -1;
- atkbd->id = (param[0] << 8) | param[1];
/*
- * Set the LEDs to a defined state.
+ * Enable the keyboard to receive keystrokes.
*/
- param[0] = 0;
- if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+ if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) {
+ printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
+ atkbd->serio->phys);
return -1;
+ }
return 0;
}
/*
- * Disable autorepeat. We don't need it, as we do it in software anyway,
- * because that way can get faster repeat, and have less system load (less
- * accesses to the slow ISA hardware). If this fails, we don't care, and will
- * just ignore the repeated keys.
- *
- * This command is for scancode set 3 only.
- */
-static void atkbd_disable_autorepeat(struct atkbd *atkbd)
-{
- atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB);
-}
-
-/*
* atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
* reboot.
*/
@@ -485,7 +496,7 @@ static void atkbd_disconnect(struct serio *serio)
}
/*
- * atkbd_connect() is called when the serio module finds an interface
+ * atkbd_connect() is called when the serio module finds and interface
* that isn't handled yet by an appropriate device driver. We check if
* there is an AT keyboard out there and if yes, we register ourselves
* to the input module.
@@ -513,6 +524,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
} else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ atkbd->dev.rep[REP_DELAY] = HZ/4 + HZ/50;
+ atkbd->dev.rep[REP_PERIOD] = HZ/33;
+
atkbd->serio = serio;
init_input_dev(&atkbd->dev);
@@ -525,6 +539,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
serio->private = atkbd;
+ init_timer(&atkbd->timer);
+ atkbd->timer.data = (long) atkbd;
+ atkbd->timer.function = atkbd_force_key_up;
+
if (serio_open(serio, dev)) {
kfree(atkbd);
return;
@@ -539,9 +557,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
}
atkbd->set = atkbd_set_3(atkbd);
- if (atkbd->set == 3)
- atkbd_disable_autorepeat(atkbd);
atkbd_enable(atkbd);
+
} else {
atkbd->set = 2;
atkbd->id = 0xab00;
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index a6b481994163..9105f6c697b3 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -19,9 +19,7 @@ config MOUSE_PS2
Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
- compatible. Support for Synaptics TouchPads is also included.
- For Synaptics TouchPad support in XFree86 you'll need this XFree86
- driver: http://w1.894.telia.com/~u89404340/touchpad/index.html
+ compatible.
If unsure, say Y.
@@ -30,6 +28,22 @@ config MOUSE_PS2
The module will be called psmouse. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+config MOUSE_PS2_SYNAPTICS
+ bool "Synaptics TouchPad"
+ default n
+ depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
+ ---help---
+ Say Y here if you have a Synaptics TouchPad connected to your system.
+ This touchpad is found on many modern laptop computers.
+
+ Note that you also need a user space driver to interpret the data
+ generated by the kernel. A compatible driver for XFree86 is available
+ from http://w1.894.telia.com/~u89404340/touchpad/index.html
+
+ The gpm program is not yet able to interpret the data from this
+ driver, so if you need to use the touchpad in the console, you have to
+ say N for now.
+
config MOUSE_SERIAL
tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE && SERIO
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 030d23149e2e..4ed0da4e7d7e 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -17,6 +17,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
+#include <linux/pm.h>
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
@@ -29,6 +30,8 @@ MODULE_PARM(psmouse_resolution, "i");
MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
MODULE_PARM(psmouse_smartscroll, "i");
MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+MODULE_PARM(psmouse_resetafter, "i");
+MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
MODULE_LICENSE("GPL");
#define PSMOUSE_LOGITECH_SMARTSCROLL 1
@@ -36,11 +39,12 @@ MODULE_LICENSE("GPL");
static int psmouse_noext;
int psmouse_resolution;
int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
+unsigned int psmouse_resetafter;
-static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"};
+static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
/*
- * psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
+ * psmouse_process_packet() analyzes the PS/2 mouse packet contents and
* reports relevant events to the input module.
*/
@@ -108,6 +112,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
{
struct psmouse *psmouse = serio->private;
+ if (psmouse->state == PSMOUSE_IGNORE)
+ goto out;
+
if (psmouse->acking) {
switch (data) {
case PSMOUSE_RET_ACK:
@@ -132,20 +139,35 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
}
if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
- printk(KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n", psmouse->pktcnt);
+ printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->pktcnt = 0;
}
psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data;
- if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
- psmouse_process_packet(psmouse, regs);
- psmouse->pktcnt = 0;
- goto out;
+ if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
+ if (psmouse->pktcnt == 1)
+ goto out;
+
+ if (psmouse->pktcnt == 2) {
+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {
+ psmouse->state = PSMOUSE_IGNORE;
+ serio_rescan(serio);
+ goto out;
+ }
+ if (psmouse->type == PSMOUSE_SYNAPTICS) {
+ /* neither 0xAA nor 0x00 are valid first bytes
+ * for a packet in absolute mode
+ */
+ psmouse->pktcnt = 0;
+ goto out;
+ }
+ }
}
- if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) {
+ if (psmouse->type == PSMOUSE_SYNAPTICS) {
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
@@ -155,8 +177,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out;
}
- if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) {
- serio_rescan(serio);
+ if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
+ psmouse_process_packet(psmouse, regs);
+ psmouse->pktcnt = 0;
goto out;
}
out:
@@ -200,7 +223,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
psmouse->cmdcnt = receive;
if (command == PSMOUSE_CMD_RESET_BAT)
- timeout = 2000000; /* 2 sec */
+ timeout = 4000000; /* 4 sec */
if (command & 0xff)
if (psmouse_sendbyte(psmouse, command & 0xff))
@@ -227,7 +250,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
for (i = 0; i < receive; i++)
param[i] = psmouse->cmdbuf[(receive - 1) - i];
- if (psmouse->cmdcnt)
+ if (psmouse->cmdcnt)
return (psmouse->cmdcnt = 0) - 1;
return 0;
@@ -450,14 +473,18 @@ static void psmouse_initialize(struct psmouse *psmouse)
*/
psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
+}
/*
- * Last, we enable the mouse so that we get reports from it.
+ * psmouse_activate() enables the mouse so that we get motion reports from it.
*/
+static void psmouse_activate(struct psmouse *psmouse)
+{
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
+ psmouse->state = PSMOUSE_ACTIVATED;
}
/*
@@ -478,13 +505,39 @@ static void psmouse_cleanup(struct serio *serio)
static void psmouse_disconnect(struct serio *serio)
{
struct psmouse *psmouse = serio->private;
+
+ psmouse->state = PSMOUSE_IGNORE;
+ synaptics_disconnect(psmouse);
input_unregister_device(&psmouse->dev);
serio_close(serio);
- synaptics_disconnect(psmouse);
kfree(psmouse);
}
/*
+ * Reinitialize mouse hardware after software suspend.
+ */
+
+static int psmouse_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
+{
+ struct psmouse *psmouse = dev->data;
+ struct serio_dev *ser_dev = psmouse->serio->dev;
+
+ synaptics_disconnect(psmouse);
+
+ /* We need to reopen the serio port to reinitialize the i8042 controller */
+ serio_close(psmouse->serio);
+ serio_open(psmouse->serio, ser_dev);
+
+ /* Probe and re-initialize the mouse */
+ psmouse_probe(psmouse);
+ psmouse_initialize(psmouse);
+ synaptics_pt_init(psmouse);
+ psmouse_activate(psmouse);
+
+ return 0;
+}
+
+/*
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
@@ -492,8 +545,10 @@ static void psmouse_disconnect(struct serio *serio)
static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
{
struct psmouse *psmouse;
+ struct pm_dev *pmdev;
- if ((serio->type & SERIO_TYPE) != SERIO_8042)
+ if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
+ (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
return;
if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
@@ -506,6 +561,7 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ psmouse->state = PSMOUSE_NEW_DEVICE;
psmouse->serio = serio;
psmouse->dev.private = psmouse;
@@ -522,6 +578,12 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return;
}
+ pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
+ if (pmdev) {
+ psmouse->dev.pm_dev = pmdev;
+ pmdev->data = psmouse;
+ }
+
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0",
@@ -539,6 +601,10 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
psmouse_initialize(psmouse);
+
+ synaptics_pt_init(psmouse);
+
+ psmouse_activate(psmouse);
}
static struct serio_dev psmouse_dev = {
@@ -567,9 +633,16 @@ static int __init psmouse_smartscroll_setup(char *str)
return 1;
}
+static int __init psmouse_resetafter_setup(char *str)
+{
+ get_option(&str, &psmouse_resetafter);
+ return 1;
+}
+
__setup("psmouse_noext", psmouse_noext_setup);
__setup("psmouse_resolution=", psmouse_resolution_setup);
__setup("psmouse_smartscroll=", psmouse_smartscroll_setup);
+__setup("psmouse_resetafter=", psmouse_resetafter_setup);
#endif
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 05a24de18d7d..a69cb72d8a80 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -13,9 +13,15 @@
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
+#define PSMOUSE_RET_ID 0x00
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
+/* psmouse states */
+#define PSMOUSE_NEW_DEVICE 0
+#define PSMOUSE_ACTIVATED 1
+#define PSMOUSE_IGNORE 2
+
struct psmouse {
void *private;
struct input_dev dev;
@@ -29,6 +35,7 @@ struct psmouse {
unsigned char type;
unsigned char model;
unsigned long last;
+ unsigned char state;
char acking;
volatile char ack;
char error;
@@ -36,16 +43,17 @@ struct psmouse {
char phys[32];
};
-#define PSMOUSE_PS2 1
-#define PSMOUSE_PS2PP 2
-#define PSMOUSE_PS2TPP 3
-#define PSMOUSE_GENPS 4
-#define PSMOUSE_IMPS 5
-#define PSMOUSE_IMEX 6
-#define PSMOUSE_SYNAPTICS 7
+#define PSMOUSE_PS2 1
+#define PSMOUSE_PS2PP 2
+#define PSMOUSE_PS2TPP 3
+#define PSMOUSE_GENPS 4
+#define PSMOUSE_IMPS 5
+#define PSMOUSE_IMEX 6
+#define PSMOUSE_SYNAPTICS 7
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
extern int psmouse_smartscroll;
+extern unsigned int psmouse_resetafter;
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 5fa695eb774e..9ba48609d77e 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1,6 +1,9 @@
/*
* Synaptics TouchPad PS/2 mouse driver
*
+ * 2003 Dmitry Torokhov <dtor@mail.ru>
+ * Added support for pass-through port
+ *
* 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure.
*
@@ -21,6 +24,7 @@
#include <linux/module.h>
#include <linux/input.h>
+#include <linux/serio.h>
#include "psmouse.h"
#include "synaptics.h"
@@ -71,7 +75,7 @@ static int synaptics_set_mode(struct psmouse *psmouse, unsigned char mode)
if (synaptics_special_cmd(psmouse, mode))
return -1;
- param[0] = 0x14;
+ param[0] = SYN_PS_SET_MODE2;
if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE))
return -1;
return 0;
@@ -83,7 +87,7 @@ static int synaptics_reset(struct psmouse *psmouse)
if (psmouse_command(psmouse, r, PSMOUSE_CMD_RESET_BAT))
return -1;
- if (r[0] == 0xAA && r[1] == 0x00)
+ if (r[0] == PSMOUSE_RET_BAT && r[1] == PSMOUSE_RET_ID)
return 0;
return -1;
}
@@ -106,16 +110,25 @@ static int synaptics_model_id(struct psmouse *psmouse, unsigned long int *model_
* Read the capability-bits from the touchpad
* see also the SYN_CAP_* macros
*/
-static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability)
+static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability, unsigned long int *ext_cap)
{
unsigned char cap[3];
if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
return -1;
*capability = (cap[0]<<16) | (cap[1]<<8) | cap[2];
- if (SYN_CAP_VALID(*capability))
- return 0;
- return -1;
+ *ext_cap = 0;
+ if (!SYN_CAP_VALID(*capability))
+ return -1;
+
+ if (SYN_EXT_CAP_REQUESTS(*capability)) {
+ if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
+ printk(KERN_ERR "Synaptics claims to have extended capabilities,"
+ " but I'm not able to read them.");
+ } else
+ *ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2];
+ }
+ return 0;
}
/*
@@ -134,19 +147,11 @@ static int synaptics_identify(struct psmouse *psmouse, unsigned long int *ident)
return -1;
}
-static int synaptics_enable_device(struct psmouse *psmouse)
-{
- if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
- return -1;
- return 0;
-}
-
static void print_ident(struct synaptics_data *priv)
{
printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity));
- printk(KERN_INFO " Firware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
+ printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
SYN_ID_MINOR(priv->identity));
-
if (SYN_MODEL_ROT180(priv->model_id))
printk(KERN_INFO " 180 degree mounted touchpad\n");
if (SYN_MODEL_PORTRAIT(priv->model_id))
@@ -159,12 +164,17 @@ static void print_ident(struct synaptics_data *priv)
if (SYN_CAP_EXTENDED(priv->capabilities)) {
printk(KERN_INFO " Touchpad has extended capability bits\n");
- if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
+ if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+ printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
+ (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
+ else if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
printk(KERN_INFO " -> four buttons\n");
if (SYN_CAP_MULTIFINGER(priv->capabilities))
printk(KERN_INFO " -> multifinger detection\n");
if (SYN_CAP_PALMDETECT(priv->capabilities))
printk(KERN_INFO " -> palm detection\n");
+ if (SYN_CAP_PASS_THROUGH(priv->capabilities))
+ printk(KERN_INFO " -> pass-through port\n");
}
}
@@ -172,6 +182,7 @@ static int query_hardware(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
int retries = 0;
+ int mode;
while ((retries++ < 3) && synaptics_reset(psmouse))
printk(KERN_ERR "synaptics reset failed\n");
@@ -180,17 +191,107 @@ static int query_hardware(struct psmouse *psmouse)
return -1;
if (synaptics_model_id(psmouse, &priv->model_id))
return -1;
- if (synaptics_capability(psmouse, &priv->capabilities))
+ if (synaptics_capability(psmouse, &priv->capabilities, &priv->ext_cap))
return -1;
- if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE |
- SYN_BIT_HIGH_RATE |
- SYN_BIT_DISABLE_GESTURE |
- SYN_BIT_W_MODE)))
+
+ mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
+ if (SYN_ID_MAJOR(priv->identity) >= 4)
+ mode |= SYN_BIT_DISABLE_GESTURE;
+ if (SYN_CAP_EXTENDED(priv->capabilities))
+ mode |= SYN_BIT_W_MODE;
+ if (synaptics_set_mode(psmouse, mode))
return -1;
- synaptics_enable_device(psmouse);
+ return 0;
+}
- print_ident(priv);
+/*****************************************************************************
+ * Synaptics pass-through PS/2 port support
+ ****************************************************************************/
+static int synaptics_pt_open(struct serio *port)
+{
+ return 0;
+}
+
+static void synaptics_pt_close(struct serio *port)
+{
+}
+
+static int synaptics_pt_write(struct serio *port, unsigned char c)
+{
+ struct psmouse *parent = port->driver;
+ char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
+
+ if (synaptics_special_cmd(parent, c))
+ return -1;
+ if (psmouse_command(parent, &rate_param, PSMOUSE_CMD_SETRATE))
+ return -1;
+ return 0;
+}
+
+static inline int synaptics_is_pt_packet(unsigned char *buf)
+{
+ return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
+}
+
+static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
+{
+ struct psmouse *child = ptport->private;
+
+ if (child) {
+ if (child->state == PSMOUSE_ACTIVATED) {
+ serio_interrupt(ptport, packet[1], 0, NULL);
+ serio_interrupt(ptport, packet[4], 0, NULL);
+ serio_interrupt(ptport, packet[5], 0, NULL);
+ if (child->type >= PSMOUSE_GENPS)
+ serio_interrupt(ptport, packet[2], 0, NULL);
+ } else if (child->state != PSMOUSE_IGNORE) {
+ serio_interrupt(ptport, packet[1], 0, NULL);
+ }
+ }
+}
+
+int synaptics_pt_init(struct psmouse *psmouse)
+{
+ struct synaptics_data *priv = psmouse->private;
+ struct serio *port;
+ struct psmouse *child;
+
+ if (psmouse->type != PSMOUSE_SYNAPTICS)
+ return -1;
+ if (!SYN_CAP_EXTENDED(priv->capabilities))
+ return -1;
+ if (!SYN_CAP_PASS_THROUGH(priv->capabilities))
+ return -1;
+
+ priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!port) {
+ printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n");
+ return -1;
+ }
+
+ memset(port, 0, sizeof(struct serio));
+ port->type = SERIO_PS_PSTHRU;
+ port->name = "Synaptics pass-through";
+ port->phys = "synaptics-pt/serio0";
+ port->write = synaptics_pt_write;
+ port->open = synaptics_pt_open;
+ port->close = synaptics_pt_close;
+ port->driver = psmouse;
+
+ printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys);
+ serio_register_slave_port(port);
+
+ /* adjust the touchpad to child's choice of protocol */
+ child = port->private;
+ if (child && child->type >= PSMOUSE_GENPS) {
+ if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE |
+ SYN_BIT_HIGH_RATE |
+ SYN_BIT_DISABLE_GESTURE |
+ SYN_BIT_FOUR_BYTE_CLIENT |
+ SYN_BIT_W_MODE)))
+ printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
+ }
return 0;
}
@@ -213,22 +314,27 @@ int synaptics_init(struct psmouse *psmouse)
{
struct synaptics_data *priv;
+#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
+ return -1;
+#endif
psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv)
return -1;
memset(priv, 0, sizeof(struct synaptics_data));
- priv->inSync = 1;
+ priv->out_of_sync = 0;
if (query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
goto init_fail;
}
+ print_ident(priv);
+
/*
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
* which says that they should be valid regardless of the actual size of
- * the senser.
+ * the sensor.
*/
set_bit(EV_ABS, psmouse->dev.evbit);
set_abs_params(&psmouse->dev, ABS_X, 1472, 5472, 0, 0);
@@ -243,7 +349,24 @@ int synaptics_init(struct psmouse *psmouse)
set_bit(BTN_RIGHT, psmouse->dev.keybit);
set_bit(BTN_FORWARD, psmouse->dev.keybit);
set_bit(BTN_BACK, psmouse->dev.keybit);
-
+ if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+ switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
+ default:
+ printk(KERN_ERR "This touchpad reports more than 8 multi-buttons, don't know how to handle.\n");
+ case 8:
+ set_bit(BTN_7, psmouse->dev.keybit);
+ set_bit(BTN_6, psmouse->dev.keybit);
+ case 6:
+ set_bit(BTN_5, psmouse->dev.keybit);
+ set_bit(BTN_4, psmouse->dev.keybit);
+ case 4:
+ set_bit(BTN_3, psmouse->dev.keybit);
+ set_bit(BTN_2, psmouse->dev.keybit);
+ case 2:
+ set_bit(BTN_1, psmouse->dev.keybit);
+ set_bit(BTN_0, psmouse->dev.keybit);
+ break;
+ }
clear_bit(EV_REL, psmouse->dev.evbit);
clear_bit(REL_X, psmouse->dev.relbit);
clear_bit(REL_Y, psmouse->dev.relbit);
@@ -259,42 +382,85 @@ void synaptics_disconnect(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
- kfree(priv);
+ if (psmouse->type == PSMOUSE_SYNAPTICS && priv) {
+ synaptics_set_mode(psmouse, 0);
+ if (priv->ptport) {
+ serio_unregister_slave_port(priv->ptport);
+ kfree(priv->ptport);
+ }
+ kfree(priv);
+ }
}
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
-static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw)
+static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
{
- unsigned char *buf = priv->proto_buf;
-
- hw->x = (((buf[3] & 0x10) << 8) |
- ((buf[1] & 0x0f) << 8) |
- buf[4]);
- hw->y = (((buf[3] & 0x20) << 7) |
- ((buf[1] & 0xf0) << 4) |
- buf[5]);
-
- hw->z = buf[2];
- hw->w = (((buf[0] & 0x30) >> 2) |
- ((buf[0] & 0x04) >> 1) |
- ((buf[3] & 0x04) >> 2));
-
- hw->left = (buf[0] & 0x01) ? 1 : 0;
- hw->right = (buf[0] & 0x2) ? 1 : 0;
hw->up = 0;
hw->down = 0;
+ hw->b0 = 0;
+ hw->b1 = 0;
+ hw->b2 = 0;
+ hw->b3 = 0;
+ hw->b4 = 0;
+ hw->b5 = 0;
+ hw->b6 = 0;
+ hw->b7 = 0;
+
+ if (SYN_MODEL_NEWABS(priv->model_id)) {
+ hw->x = (((buf[3] & 0x10) << 8) |
+ ((buf[1] & 0x0f) << 8) |
+ buf[4]);
+ hw->y = (((buf[3] & 0x20) << 7) |
+ ((buf[1] & 0xf0) << 4) |
+ buf[5]);
+
+ hw->z = buf[2];
+ hw->w = (((buf[0] & 0x30) >> 2) |
+ ((buf[0] & 0x04) >> 1) |
+ ((buf[3] & 0x04) >> 2));
+
+ hw->left = (buf[0] & 0x01) ? 1 : 0;
+ hw->right = (buf[0] & 0x02) ? 1 : 0;
+ if (SYN_CAP_EXTENDED(priv->capabilities) &&
+ (SYN_CAP_FOUR_BUTTON(priv->capabilities))) {
+ hw->up = ((buf[3] & 0x01)) ? 1 : 0;
+ if (hw->left)
+ hw->up = !hw->up;
+ hw->down = ((buf[3] & 0x02)) ? 1 : 0;
+ if (hw->right)
+ hw->down = !hw->down;
+ }
+ if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
+ ((buf[3] & 2) ? !hw->right : hw->right)) {
+ switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
+ default:
+ ; /* we did comment while initialising... */
+ case 8:
+ hw->b7 = ((buf[5] & 0x08)) ? 1 : 0;
+ hw->b6 = ((buf[4] & 0x08)) ? 1 : 0;
+ case 6:
+ hw->b5 = ((buf[5] & 0x04)) ? 1 : 0;
+ hw->b4 = ((buf[4] & 0x04)) ? 1 : 0;
+ case 4:
+ hw->b3 = ((buf[5] & 0x02)) ? 1 : 0;
+ hw->b2 = ((buf[4] & 0x02)) ? 1 : 0;
+ case 2:
+ hw->b1 = ((buf[5] & 0x01)) ? 1 : 0;
+ hw->b0 = ((buf[4] & 0x01)) ? 1 : 0;
+ }
+ }
+ } else {
+ hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
+ hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
+
+ hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
+ hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
- if (SYN_CAP_EXTENDED(priv->capabilities) &&
- (SYN_CAP_FOUR_BUTTON(priv->capabilities))) {
- hw->up = ((buf[3] & 0x01)) ? 1 : 0;
- if (hw->left)
- hw->up = !hw->up;
- hw->down = ((buf[3] & 0x02)) ? 1 : 0;
- if (hw->right)
- hw->down = !hw->down;
+ hw->left = (buf[0] & 0x01) ? 1 : 0;
+ hw->right = (buf[0] & 0x02) ? 1 : 0;
}
}
@@ -307,7 +473,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct synaptics_data *priv = psmouse->private;
struct synaptics_hw_state hw;
- synaptics_parse_hw_state(priv, &hw);
+ synaptics_parse_hw_state(psmouse->packet, priv, &hw);
if (hw.z > 0) {
int w_ok = 0;
@@ -347,7 +513,24 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_key(dev, BTN_RIGHT, hw.right);
input_report_key(dev, BTN_FORWARD, hw.up);
input_report_key(dev, BTN_BACK, hw.down);
-
+ if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+ switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
+ default:
+ ; /* we did comment while initialising... */
+ case 8:
+ input_report_key(dev, BTN_7, hw.b7);
+ input_report_key(dev, BTN_6, hw.b6);
+ case 6:
+ input_report_key(dev, BTN_5, hw.b5);
+ input_report_key(dev, BTN_4, hw.b4);
+ case 4:
+ input_report_key(dev, BTN_3, hw.b3);
+ input_report_key(dev, BTN_2, hw.b2);
+ case 2:
+ input_report_key(dev, BTN_1, hw.b1);
+ input_report_key(dev, BTN_0, hw.b0);
+ break;
+ }
input_sync(dev);
}
@@ -355,35 +538,59 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
struct input_dev *dev = &psmouse->dev;
struct synaptics_data *priv = psmouse->private;
- unsigned char *pBuf = priv->proto_buf;
- unsigned char u = psmouse->packet[0];
+ unsigned char data = psmouse->packet[psmouse->pktcnt - 1];
+ int newabs = SYN_MODEL_NEWABS(priv->model_id);
input_regs(dev, regs);
- pBuf[priv->proto_buf_tail++] = u;
-
- /* check first byte */
- if ((priv->proto_buf_tail == 1) && ((u & 0xC8) != 0x80)) {
- priv->inSync = 0;
- priv->proto_buf_tail = 0;
- printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
- return;
- }
+ switch (psmouse->pktcnt) {
+ case 1:
+ if (newabs ? ((data & 0xC8) != 0x80) : ((data & 0xC0) != 0xC0)) {
+ printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
+ goto bad_sync;
+ }
+ break;
+ case 2:
+ if (!newabs && ((data & 0x60) != 0x00)) {
+ printk(KERN_WARNING "Synaptics driver lost sync at 2nd byte\n");
+ goto bad_sync;
+ }
+ break;
+ case 4:
+ if (newabs ? ((data & 0xC8) != 0xC0) : ((data & 0xC0) != 0x80)) {
+ printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
+ goto bad_sync;
+ }
+ break;
+ case 5:
+ if (!newabs && ((data & 0x60) != 0x00)) {
+ printk(KERN_WARNING "Synaptics driver lost sync at 5th byte\n");
+ goto bad_sync;
+ }
+ break;
+ default:
+ if (psmouse->pktcnt >= 6) { /* Full packet received */
+ if (priv->out_of_sync) {
+ priv->out_of_sync = 0;
+ printk(KERN_NOTICE "Synaptics driver resynced.\n");
+ }
- /* check 4th byte */
- if ((priv->proto_buf_tail == 4) && ((u & 0xc8) != 0xc0)) {
- priv->inSync = 0;
- priv->proto_buf_tail = 0;
- printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
- return;
- }
+ if (priv->ptport && synaptics_is_pt_packet(psmouse->packet))
+ synaptics_pass_pt_packet(priv->ptport, psmouse->packet);
+ else
+ synaptics_process_packet(psmouse);
- if (priv->proto_buf_tail >= 6) { /* Full packet received */
- if (!priv->inSync) {
- priv->inSync = 1;
- printk(KERN_NOTICE "Synaptics driver resynced.\n");
+ psmouse->pktcnt = 0;
}
- synaptics_process_packet(psmouse);
- priv->proto_buf_tail = 0;
+ break;
+ }
+ return;
+
+ bad_sync:
+ priv->out_of_sync++;
+ psmouse->pktcnt = 0;
+ if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) {
+ psmouse->state = PSMOUSE_IGNORE;
+ serio_rescan(psmouse->serio);
}
}
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 6e3e029a3bdd..4dad98abd54e 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -12,6 +12,7 @@
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_init(struct psmouse *psmouse);
+extern int synaptics_pt_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics queries */
@@ -22,12 +23,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08
+#define SYN_QUE_EXT_CAPAB 0x09
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
#define SYN_BIT_HIGH_RATE (1 << 6)
#define SYN_BIT_SLEEP_MODE (1 << 3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2)
+#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)
#define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */
@@ -42,11 +45,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
+#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
+#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1)
+#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -62,6 +68,10 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
+/* synaptics special commands */
+#define SYN_PS_SET_MODE2 0x14
+#define SYN_PS_CLIENT_CMD 0x28
+
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
@@ -75,21 +85,28 @@ struct synaptics_hw_state {
int right;
int up;
int down;
+ int b0;
+ int b1;
+ int b2;
+ int b3;
+ int b4;
+ int b5;
+ int b6;
+ int b7;
};
struct synaptics_data {
/* Data read from the touchpad */
unsigned long int model_id; /* Model-ID */
unsigned long int capabilities; /* Capabilities */
+ unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */
/* Data for normal processing */
- unsigned char proto_buf[6]; /* Buffer for Packet */
- unsigned char last_byte; /* last received byte */
- int inSync; /* Packets in sync */
- int proto_buf_tail;
-
+ unsigned int out_of_sync; /* # of packets out of sync */
int old_w; /* Previous w value */
+
+ struct serio *ptport; /* pass-through port */
};
#endif /* _SYNAPTICS_H */
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 78c51d96dea6..7c818a32628a 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -49,7 +49,9 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(serio_register_port);
+EXPORT_SYMBOL(serio_register_slave_port);
EXPORT_SYMBOL(serio_unregister_port);
+EXPORT_SYMBOL(serio_unregister_slave_port);
EXPORT_SYMBOL(serio_register_device);
EXPORT_SYMBOL(serio_unregister_device);
EXPORT_SYMBOL(serio_open);
@@ -166,6 +168,17 @@ void serio_register_port(struct serio *serio)
up(&serio_sem);
}
+/*
+ * Same as serio_register_port but does not try to acquire serio_sem.
+ * Should be used when registering a serio from other input device's
+ * connect() function.
+ */
+void serio_register_slave_port(struct serio *serio)
+{
+ list_add_tail(&serio->node, &serio_list);
+ serio_find_dev(serio);
+}
+
void serio_unregister_port(struct serio *serio)
{
down(&serio_sem);
@@ -175,6 +188,18 @@ void serio_unregister_port(struct serio *serio)
up(&serio_sem);
}
+/*
+ * Same as serio_unregister_port but does not try to acquire serio_sem.
+ * Should be used when unregistering a serio from other input device's
+ * disconnect() function.
+ */
+void serio_unregister_slave_port(struct serio *serio)
+{
+ list_del_init(&serio->node);
+ if (serio->dev && serio->dev->disconnect)
+ serio->dev->disconnect(serio);
+}
+
void serio_register_device(struct serio_dev *dev)
{
struct serio *serio;
@@ -204,9 +229,11 @@ void serio_unregister_device(struct serio_dev *dev)
/* called from serio_dev->connect/disconnect methods under serio_sem */
int serio_open(struct serio *serio, struct serio_dev *dev)
{
- if (serio->open(serio))
- return -1;
serio->dev = dev;
+ if (serio->open(serio)) {
+ serio->dev = NULL;
+ return -1;
+ }
return 0;
}
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index f5a5b8cd31a4..b5b199eef9d2 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -123,6 +123,7 @@ static const char version[] =
#include <linux/config.h> /* for CONFIG_IP_MULTICAST */
#include <linux/spinlock.h>
#include <linux/ethtool.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -241,7 +242,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
if (dev->irq < 2)
{
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
irq_mask = probe_irq_on();
inb(RX_STATUS); /* Clear pending interrupts. */
@@ -250,8 +251,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
outb(0x00, AX_CMD);
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
autoirq = probe_irq_off(irq_mask);
if (autoirq == 0)
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 44e86a1355d4..d1607cabd3e2 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -298,17 +298,13 @@ inline static void adapter_reset(struct net_device *dev)
set_hsf(dev, HSF_PCB_NAK);
}
outb_control(adapter->hcr_val | ATTN | DIR, dev);
- timeout = jiffies + 1*HZ/100;
- while (time_before_eq(jiffies, timeout));
+ mdelay(10);
outb_control(adapter->hcr_val & ~ATTN, dev);
- timeout = jiffies + 1*HZ/100;
- while (time_before_eq(jiffies, timeout));
+ mdelay(10);
outb_control(adapter->hcr_val | FLSH, dev);
- timeout = jiffies + 1*HZ/100;
- while (time_before_eq(jiffies, timeout));
+ mdelay(10);
outb_control(adapter->hcr_val & ~FLSH, dev);
- timeout = jiffies + 1*HZ/100;
- while (time_before_eq(jiffies, timeout));
+ mdelay(10);
outb_control(orig_hcr, dev);
if (!start_receive(dev, &adapter->tx_pcb))
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 9ef643420408..d3e3d819b9cb 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -59,7 +59,6 @@ static int max_interrupt_work = 20;
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/isapnp.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 673ebcced980..651ffca8a9be 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -58,7 +58,6 @@ extern int at1500_probe(struct net_device *);
extern int at1700_probe(struct net_device *);
extern int fmv18x_probe(struct net_device *);
extern int eth16i_probe(struct net_device *);
-extern int depca_probe(struct net_device *);
extern int i82596_probe(struct net_device *);
extern int ewrk3_probe(struct net_device *);
extern int el1_probe(struct net_device *);
@@ -252,9 +251,6 @@ static struct devprobe isa_probes[] __initdata = {
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
{eepro_probe, 0},
#endif
-#ifdef CONFIG_DEPCA /* DEC DEPCA */
- {depca_probe, 0},
-#endif
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
{ewrk3_probe, 0},
#endif
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 3350a70c2103..eaa214a5a518 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -1757,7 +1757,8 @@ static int __init ace_init(struct net_device *dev)
* Wait for the firmware to spin up - max 3 seconds.
*/
myjif = jiffies + 3 * HZ;
- while (time_before(jiffies, myjif) && !ap->fw_running);
+ while (time_before(jiffies, myjif) && !ap->fw_running)
+ cpu_relax();
if (!ap->fw_running) {
printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f0399fc818b0..284c405a8030 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -24,10 +24,15 @@
* 2003/06/25 - Shmulik Hen <shmulik.hen at intel dot com>
* - Fixed signed/unsigned calculation errors that caused load sharing
* to collapse to one slave under very heavy UDP Tx stress.
+ *
+ * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
+ * - Add support for setting bond's MAC address with special
+ * handling required for ALB/TLB.
*/
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include <linux/pkt_sched.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
@@ -943,10 +948,11 @@ alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
}
/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the hw as well as the hw address of the net_device
+ * set the hw address of the device as well as the hw address of the
+ * net_device
*/
static int
-alb_set_mac_addr(struct slave *slave, u8 addr[], int hw)
+alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
{
struct net_device *dev = NULL;
struct sockaddr s_addr;
@@ -954,16 +960,16 @@ alb_set_mac_addr(struct slave *slave, u8 addr[], int hw)
dev = slave->dev;
if (!hw) {
- memcpy(dev->dev_addr, addr, ETH_ALEN);
+ memcpy(dev->dev_addr, addr, dev->addr_len);
return 0;
}
/* for rlb each slave must have a unique hw mac addresses so that */
/* each slave will receive packets destined to a different mac */
- memcpy(s_addr.sa_data, addr, ETH_ALEN);
+ memcpy(s_addr.sa_data, addr, dev->addr_len);
s_addr.sa_family = dev->type;
if (dev->set_mac_address(dev, &s_addr)) {
- printk(KERN_DEBUG "bonding: Error: alb_set_mac_addr:"
+ printk(KERN_DEBUG "bonding: Error: alb_set_slave_mac_addr:"
" dev->set_mac_address of dev %s failed!"
" ALB mode requires that the base driver"
" support setting the hw address also when"
@@ -987,8 +993,8 @@ alb_swap_mac_addr(struct bonding *bond,
slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
- alb_set_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
- alb_set_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
/* fasten the change in the switch */
if (SLAVE_IS_OK(slave1)) {
@@ -1153,8 +1159,8 @@ alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
}
if (tmp_slave1) {
- alb_set_mac_addr(slave, tmp_slave1->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, tmp_slave1->perm_hwaddr,
+ bond->alb_info.rlb_enabled);
printk(KERN_WARNING "bonding: Warning: the hw address "
"of slave %s is in use by the bond; "
@@ -1172,6 +1178,67 @@ alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
return 0;
}
+/**
+ * alb_set_mac_address
+ * @bond:
+ * @addr:
+ *
+ * In TLB mode all slaves are configured to the bond's hw address, but set
+ * their dev_addr field to different addresses (based on their permanent hw
+ * addresses).
+ *
+ * For each slave, this function sets the interface to the new address and then
+ * changes its dev_addr field to its previous value.
+ *
+ * Unwinding assumes bond's mac address has not yet changed.
+ */
+static inline int
+alb_set_mac_address(struct bonding *bond, void *addr)
+{
+ struct sockaddr sa;
+ struct slave *slave;
+ char tmp_addr[ETH_ALEN];
+ int error;
+
+ if (bond->alb_info.rlb_enabled) {
+ return 0;
+ }
+
+ slave = bond_get_first_slave(bond);
+ for (; slave; slave = bond_get_next_slave(bond, slave)) {
+ if (slave->dev->set_mac_address == NULL) {
+ error = -EOPNOTSUPP;
+ goto unwind;
+ }
+
+ /* save net_device's current hw address */
+ memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
+
+ error = slave->dev->set_mac_address(slave->dev, addr);
+
+ /* restore net_device's hw address */
+ memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+
+ if (error) {
+ goto unwind;
+ }
+ }
+
+ return 0;
+
+unwind:
+ memcpy(sa.sa_data, bond->device->dev_addr, bond->device->addr_len);
+ sa.sa_family = bond->device->type;
+ slave = bond_get_first_slave(bond);
+ for (; slave; slave = bond_get_next_slave(bond, slave)) {
+ memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
+ slave->dev->set_mac_address(slave->dev, &sa);
+ memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+ }
+
+ return error;
+}
+
/************************ exported alb funcions ************************/
int
@@ -1262,16 +1329,15 @@ bond_alb_xmit(struct sk_buff *skb, struct net_device *dev)
hash_size = 16;
break;
-#ifdef FIXME
case ETH_P_IPX:
- if (skb->nh.ipxh->ipx_checksum !=
+ if (ipx_hdr(skb)->ipx_checksum !=
__constant_htons(IPX_NO_CHECKSUM)) {
/* something is wrong with this packet */
do_tx_balance = 0;
break;
}
- if (skb->nh.ipxh->ipx_type !=
+ if (ipx_hdr(skb)->ipx_type !=
__constant_htons(IPX_TYPE_NCP)) {
/* The only protocol worth balancing in
* this family since it has an "ARP" like
@@ -1284,7 +1350,6 @@ bond_alb_xmit(struct sk_buff *skb, struct net_device *dev)
hash_start = (char*)eth_data->h_dest;
hash_size = ETH_ALEN;
break;
-#endif
case ETH_P_ARP:
do_tx_balance = 0;
@@ -1444,8 +1509,8 @@ bond_alb_init_slave(struct bonding *bond, struct slave *slave)
{
int err = 0;
- err = alb_set_mac_addr(slave, slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ err = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
+ bond->alb_info.rlb_enabled);
if (err) {
return err;
}
@@ -1569,10 +1634,61 @@ bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave)
alb_swap_mac_addr(bond, swap_slave, new_slave);
} else {
/* set the new_slave to the bond mac address */
- alb_set_mac_addr(new_slave, bond->device->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(new_slave, bond->device->dev_addr,
+ bond->alb_info.rlb_enabled);
/* fasten bond mac on new current slave */
alb_send_learning_packets(new_slave, bond->device->dev_addr);
}
}
+int
+bond_alb_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct bonding *bond = dev->priv;
+ struct sockaddr *sa = addr;
+ struct slave *swap_slave = NULL;
+ int error = 0;
+
+ if (!is_valid_ether_addr(sa->sa_data)) {
+ return -EADDRNOTAVAIL;
+ }
+
+ error = alb_set_mac_address(bond, addr);
+ if (error) {
+ return error;
+ }
+
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+ /* If there is no current_slave there is nothing else to do.
+ * Otherwise we'll need to pass the new address to it and handle
+ * duplications.
+ */
+ if (bond->current_slave == NULL) {
+ return 0;
+ }
+
+ swap_slave = bond_get_first_slave(bond);
+ while (swap_slave) {
+ if (!memcmp(swap_slave->dev->dev_addr, dev->dev_addr, ETH_ALEN)) {
+ break;
+ }
+ swap_slave = bond_get_next_slave(bond, swap_slave);
+ }
+
+ if (swap_slave) {
+ alb_swap_mac_addr(bond, swap_slave, bond->current_slave);
+ } else {
+ alb_set_slave_mac_addr(bond->current_slave, dev->dev_addr,
+ bond->alb_info.rlb_enabled);
+
+ alb_send_learning_packets(bond->current_slave, dev->dev_addr);
+ if (bond->alb_info.rlb_enabled) {
+ /* inform clients mac address has changed */
+ rlb_req_update_slave_clients(bond, bond->current_slave);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 8b69c8a8f4b9..d3f4291706ef 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -17,6 +17,13 @@
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
+ *
+ *
+ * Changes:
+ *
+ * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
+ * - Add support for setting bond's MAC address with special
+ * handling required for ALB/TLB.
*/
#ifndef __BOND_ALB_H__
@@ -122,6 +129,7 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
void bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave);
int bond_alb_xmit(struct sk_buff *skb, struct net_device *dev);
void bond_alb_monitor(struct bonding *bond);
+int bond_alb_set_mac_address(struct net_device *dev, void *addr);
#endif /* __BOND_ALB_H__ */
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 356c27ec5423..949c58d469c7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -408,6 +408,24 @@
* and free it separately; use standard list operations instead
* of pre-allocated array of bonds.
* Version to 2.3.0.
+ *
+ * 2003/08/07 - Jay Vosburgh <fubar at us dot ibm dot com>,
+ * Amir Noam <amir.noam at intel dot com> and
+ * Shmulik Hen <shmulik.hen at intel dot com>
+ * - Propagating master's settings: Distinguish between modes that
+ * use a primary slave from those that don't, and propagate settings
+ * accordingly; Consolidate change_active opeartions and add
+ * reselect_active and find_best opeartions; Decouple promiscuous
+ * handling from the multicast mode setting; Add support for changing
+ * HW address and MTU with proper unwind; Consolidate procfs code,
+ * add CHANGENAME handler; Enhance netdev notification handling.
+ * Version to 2.4.0.
+ *
+ * 2003/09/15 - Stephen Hemminger <shemminger at osdl dot org>,
+ * Amir Noam <amir.noam at intel dot com>
+ * - Convert /proc to seq_file interface.
+ * Change /proc/net/bondX/info to /proc/net/bonding/bondX.
+ * Set version to 2.4.1.
*/
#include <linux/config.h>
@@ -441,6 +459,8 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/if_bonding.h>
#include <linux/smp.h>
@@ -452,8 +472,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "2.3.0"
-#define DRV_RELDATE "August 6, 2003"
+#define DRV_VERSION "2.4.1"
+#define DRV_RELDATE "September 15, 2003"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -473,6 +493,11 @@ DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n";
#define MAX_ARP_IP_TARGETS 16
#endif
+#define USES_PRIMARY(mode) \
+ (((mode) == BOND_MODE_ACTIVEBACKUP) || \
+ ((mode) == BOND_MODE_TLB) || \
+ ((mode) == BOND_MODE_ALB))
+
struct bond_parm_tbl {
char *modename;
int mode;
@@ -536,6 +561,9 @@ static struct bond_parm_tbl bond_lacp_tbl[] = {
};
static LIST_HEAD(bond_dev_list);
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *bond_proc_dir = NULL;
+#endif
MODULE_PARM(max_bonds, "i");
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -567,7 +595,6 @@ static struct net_device_stats *bond_get_stats(struct net_device *dev);
static void bond_mii_monitor(struct net_device *dev);
static void loadbalance_arp_monitor(struct net_device *dev);
static void activebackup_arp_monitor(struct net_device *dev);
-static int bond_event(struct notifier_block *this, unsigned long event, void *ptr);
static void bond_mc_list_destroy(struct bonding *bond);
static void bond_mc_add(bonding_t *bond, void *addr, int alen);
static void bond_mc_delete(bonding_t *bond, void *addr, int alen);
@@ -581,22 +608,17 @@ static int bond_enslave(struct net_device *master, struct net_device *slave);
static int bond_release(struct net_device *master, struct net_device *slave);
static int bond_release_all(struct net_device *master);
static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
+static void change_active_interface(struct bonding *bond, struct slave *new);
+static void reselect_active_interface(struct bonding *bond);
+static struct slave *find_best_interface(struct bonding *bond);
-/* Caller must hold bond->ptrlock for write */
-static inline struct slave*
-bond_assign_current_slave(struct bonding *bond,struct slave *newslave)
-{
- if ((bond_mode == BOND_MODE_TLB) ||
- (bond_mode == BOND_MODE_ALB)) {
- bond_alb_assign_current_slave(bond, newslave);
- } else {
- bond->current_slave = newslave;
- }
-
- return bond->current_slave;
-}
/* #define BONDING_DEBUG 1 */
+#ifdef BONDING_DEBUG
+#define dprintk(x...) printk(x...)
+#else /* BONDING_DEBUG */
+#define dprintk(x...) do {} while (0)
+#endif /* BONDING_DEBUG */
/* several macros */
@@ -691,7 +713,7 @@ update_slave_cnt(bonding_t *bond, int incr)
* belongs to <bond>. It returns <slave> in case it's needed.
* Nothing is freed on return, structures are just unchained.
* If the bond->current_slave pointer was pointing to <slave>,
- * it's replaced with bond->next, or NULL if not applicable.
+ * it should be changed by the calling function.
*
* bond->lock held for writing by caller.
*/
@@ -725,17 +747,6 @@ bond_detach_slave(bonding_t *bond, slave_t *slave)
update_slave_cnt(bond, -1);
- /* no need to hold ptrlock since bond lock is
- * already held for writing
- */
- if (slave == bond->current_slave) {
- if ( bond->next != (slave_t *)bond) { /* found one slave */
- bond_assign_current_slave(bond, bond->next);
- } else {
- bond_assign_current_slave(bond, NULL);
- }
- }
-
return slave;
}
@@ -1167,23 +1178,22 @@ static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
}
/*
- * Push the promiscuity flag down to all slaves
+ * Push the promiscuity flag down to appropriate slaves
*/
static void bond_set_promiscuity(bonding_t *bond, int inc)
{
slave_t *slave;
- switch (multicast_mode) {
- case BOND_MULTICAST_ACTIVE :
- /* write lock already acquired */
- if (bond->current_slave != NULL)
+
+ if (USES_PRIMARY(bond_mode)) {
+ if (bond->current_slave) {
dev_set_promiscuity(bond->current_slave->dev, inc);
- break;
- case BOND_MULTICAST_ALL :
- for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+ }
+
+ } else {
+ for (slave = bond->prev; slave != (slave_t*)bond;
+ slave = slave->prev) {
dev_set_promiscuity(slave->dev, inc);
- break;
- case BOND_MULTICAST_DISABLED :
- break;
+ }
}
}
@@ -1229,20 +1239,23 @@ static void set_multicast_list(struct net_device *master)
bonding_t *bond = master->priv;
struct dev_mc_list *dmi;
- if (multicast_mode == BOND_MULTICAST_DISABLED)
- return;
- /*
- * Lock the private data for the master
- */
write_lock_bh(&bond->lock);
- /* set promiscuity flag to slaves */
+ /*
+ * Do promisc before checking multicast_mode
+ */
if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
bond_set_promiscuity(bond, 1);
if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) )
bond_set_promiscuity(bond, -1);
+ if (multicast_mode == BOND_MULTICAST_DISABLED) {
+ bond->flags = master->flags;
+ write_unlock_bh(&bond->lock);
+ return;
+ }
+
/* set allmulti flag to slaves */
if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) )
bond_set_allmulti(bond, 1);
@@ -1274,32 +1287,40 @@ static void set_multicast_list(struct net_device *master)
/*
* Update the mc list and multicast-related flags for the new and
- * old active slaves (if any) according to the multicast mode
+ * old active slaves (if any) according to the multicast mode, and
+ * promiscuous flags unconditionally.
*/
static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
{
struct dev_mc_list *dmi;
- switch(multicast_mode) {
- case BOND_MULTICAST_ACTIVE :
+ if (USES_PRIMARY(bond_mode)) {
if (bond->device->flags & IFF_PROMISC) {
- if (old != NULL && new != old)
+ if (old)
dev_set_promiscuity(old->dev, -1);
- dev_set_promiscuity(new->dev, 1);
+ if (new)
+ dev_set_promiscuity(new->dev, 1);
}
+ }
+
+ switch(multicast_mode) {
+ case BOND_MULTICAST_ACTIVE :
if (bond->device->flags & IFF_ALLMULTI) {
- if (old != NULL && new != old)
+ if (old)
dev_set_allmulti(old->dev, -1);
- dev_set_allmulti(new->dev, 1);
+ if (new)
+ dev_set_allmulti(new->dev, 1);
}
/* first remove all mc addresses from old slave if any,
and _then_ add them to new active slave */
- if (old != NULL && new != old) {
+ if (old) {
for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
- for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
- dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+ if (new) {
+ for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
+ dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+ }
break;
case BOND_MULTICAST_ALL :
/* nothing to do: mc list is already up-to-date on all slaves */
@@ -1415,7 +1436,7 @@ static int bond_enslave(struct net_device *master_dev,
* The application already set the master's
* mac address to that of the first slave
*/
- memcpy(addr.sa_data, master_dev->dev_addr, ETH_ALEN);
+ memcpy(addr.sa_data, master_dev->dev_addr, master_dev->addr_len);
addr.sa_family = slave_dev->type;
err = slave_dev->set_mac_address(slave_dev, &addr);
if (err) {
@@ -1461,11 +1482,19 @@ static int bond_enslave(struct net_device *master_dev,
}
}
- if (multicast_mode == BOND_MULTICAST_ALL) {
- /* set promiscuity level to new slave */
- if (master_dev->flags & IFF_PROMISC)
+ /* set promiscuity level to new slave */
+ if (master_dev->flags & IFF_PROMISC) {
+ /* If the mode USES_PRIMARY, then the new slave gets the
+ * master's promisc (and mc) settings only if it becomes the
+ * current_slave, and that is taken care of later when calling
+ * bond_change_active()
+ */
+ if (!USES_PRIMARY(bond_mode)) {
dev_set_promiscuity(slave_dev, 1);
+ }
+ }
+ if (multicast_mode == BOND_MULTICAST_ALL) {
/* set allmulti level to new slave */
if (master_dev->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, 1);
@@ -1578,9 +1607,7 @@ static int bond_enslave(struct net_device *master_dev,
#endif
/* first slave or no active slave yet, and this link
is OK, so make this interface the active one */
- bond_assign_current_slave(bond, new_slave);
- bond_set_slave_active_flags(new_slave);
- bond_mc_update(bond, new_slave, NULL);
+ change_active_interface(bond, new_slave);
}
else {
#ifdef BONDING_DEBUG
@@ -1630,7 +1657,7 @@ static int bond_enslave(struct net_device *master_dev,
/* first slave or no active slave yet, and this link
* is OK, so make this interface the active one
*/
- bond_assign_current_slave(bond, new_slave);
+ change_active_interface(bond, new_slave);
}
/* if there is a primary slave, remember it */
@@ -1645,8 +1672,13 @@ static int bond_enslave(struct net_device *master_dev,
#endif
/* always active in trunk mode */
new_slave->state = BOND_STATE_ACTIVE;
+
+ /* In trunking mode there is little meaning to current_slave
+ * anyway (it holds no special properties of the bond device),
+ * so we can change it without calling change_active_interface()
+ */
if (bond->current_slave == NULL)
- bond_assign_current_slave(bond, new_slave);
+ bond->current_slave = new_slave;
}
write_unlock_bh(&bond->lock);
@@ -1737,6 +1769,13 @@ static int bond_change_active(struct net_device *master_dev, struct net_device *
return -ENODEV;
}
+ /* Verify that master_dev is indeed the master of slave_dev */
+ if (!(slave_dev->flags & IFF_SLAVE) ||
+ (slave_dev->master != master_dev)) {
+
+ return -EINVAL;
+ }
+
bond = (struct bonding *) master_dev->priv;
write_lock_bh(&bond->lock);
slave = (slave_t *)bond;
@@ -1761,16 +1800,7 @@ static int bond_change_active(struct net_device *master_dev, struct net_device *
(oldactive != NULL)&&
(newactive->link == BOND_LINK_UP)&&
IS_UP(newactive->dev)) {
- if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
- bond_set_slave_inactive_flags(oldactive);
- bond_set_slave_active_flags(newactive);
- }
-
- bond_mc_update(bond, newactive, oldactive);
- bond_assign_current_slave(bond, newactive);
- printk("%s : activate %s(old : %s)\n",
- master_dev->name, newactive->dev->name,
- oldactive->dev->name);
+ change_active_interface(bond, newactive);
} else {
ret = -EINVAL;
}
@@ -1778,47 +1808,26 @@ static int bond_change_active(struct net_device *master_dev, struct net_device *
return ret;
}
-/* Choose a new valid interface from the pool, set it active
- * and make it the current slave. If no valid interface is
- * found, the oldest slave in BACK state is choosen and
- * activated. If none is found, it's considered as no
- * interfaces left so the current slave is set to NULL.
- * The result is a pointer to the current slave.
- *
- * Since this function sends messages tails through printk, the caller
- * must have started something like `printk(KERN_INFO "xxxx ");'.
+/**
+ * find_best_interface - select the best available slave to be the active one
+ * @bond: our bonding struct
*
* Warning: Caller must hold ptrlock for writing.
*/
-slave_t *change_active_interface(bonding_t *bond)
+static struct slave *find_best_interface(struct bonding *bond)
{
- slave_t *newslave, *oldslave;
- slave_t *bestslave = NULL;
+ struct slave *newslave, *oldslave;
+ struct slave *bestslave = NULL;
int mintime;
newslave = oldslave = bond->current_slave;
if (newslave == NULL) { /* there were no active slaves left */
if (bond->next != (slave_t *)bond) { /* found one slave */
- newslave = bond_assign_current_slave(bond, bond->next);
+ newslave = bond->next;
} else {
-
- printk (" but could not find any %s interface.\n",
- (bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
- bond_assign_current_slave(bond, NULL);
return NULL; /* still no slave, return NULL */
}
- } else if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
- /* make sure oldslave doesn't send arps - this could
- * cause a ping-pong effect between interfaces since they
- * would be able to tx arps - in active backup only one
- * slave should be able to tx arps, and that should be
- * the current_slave; the only exception is when all
- * slaves have gone down, then only one non-current slave can
- * send arps at a time; clearing oldslaves' mc list is handled
- * later in this function.
- */
- bond_set_slave_inactive_flags(oldslave);
}
mintime = updelay;
@@ -1833,22 +1842,12 @@ slave_t *change_active_interface(bonding_t *bond)
newslave = bond->primary_slave;
}
+ /* remember where to stop iterating over the slaves */
+ oldslave = newslave;
+
do {
if (IS_UP(newslave->dev)) {
if (newslave->link == BOND_LINK_UP) {
- /* this one is immediately usable */
- if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
- bond_set_slave_active_flags(newslave);
- bond_mc_update(bond, newslave, oldslave);
- printk (" and making interface %s the active one.\n",
- newslave->dev->name);
- }
- else {
- printk (" and setting pointer to interface %s.\n",
- newslave->dev->name);
- }
-
- bond_assign_current_slave(bond, newslave);
return newslave;
}
else if (newslave->link == BOND_LINK_BACK) {
@@ -1861,46 +1860,105 @@ slave_t *change_active_interface(bonding_t *bond)
}
} while ((newslave = newslave->next) != oldslave);
- /* no usable backup found, we'll see if we at least got a link that was
- coming back for a long time, and could possibly already be usable.
- */
-
- if (bestslave != NULL) {
- /* early take-over. */
- printk (" and making interface %s the active one %d ms earlier.\n",
- bestslave->dev->name,
- (updelay - bestslave->delay)*miimon);
-
- bestslave->delay = 0;
- bestslave->link = BOND_LINK_UP;
- bestslave->jiffies = jiffies;
- bond_set_slave_active_flags(bestslave);
- bond_mc_update(bond, bestslave, oldslave);
- bond_assign_current_slave(bond, bestslave);
- return bestslave;
- }
-
- if ((bond_mode == BOND_MODE_ACTIVEBACKUP) &&
- (multicast_mode == BOND_MULTICAST_ACTIVE) &&
- (oldslave != NULL)) {
- /* flush bonds (master's) mc_list from oldslave since it wasn't
- * updated (and deleted) above
- */
- bond_mc_list_flush(oldslave->dev, bond->device);
- if (bond->device->flags & IFF_PROMISC) {
- dev_set_promiscuity(oldslave->dev, -1);
+ return bestslave;
+}
+
+/**
+ * change_active_interface - change the active slave into the specified one
+ * @bond: our bonding struct
+ * @new: the new slave to make the active one
+ *
+ * Set the new slave to the bond's settings and unset them on the old
+ * current_slave.
+ * Setting include flags, mc-list, promiscuity, allmulti, etc.
+ *
+ * If @new's link state is %BOND_LINK_BACK we'll set it to %BOND_LINK_UP,
+ * because it is apparently the best available slave we have, even though its
+ * updelay hasn't timed out yet.
+ *
+ * Warning: Caller must hold ptrlock for writing.
+ */
+static void change_active_interface(struct bonding *bond, struct slave *new)
+{
+ struct slave *old = bond->current_slave;
+
+ if (old == new) {
+ return;
+ }
+
+ if (new) {
+ if (new->link == BOND_LINK_BACK) {
+ if (USES_PRIMARY(bond_mode)) {
+ printk (KERN_INFO
+ "%s: making interface %s the new "
+ "active one %d ms earlier.\n",
+ bond->device->name, new->dev->name,
+ (updelay - new->delay) * miimon);
+ }
+
+ new->delay = 0;
+ new->link = BOND_LINK_UP;
+ new->jiffies = jiffies;
+
+ if (bond_mode == BOND_MODE_8023AD) {
+ bond_3ad_handle_link_change(new, BOND_LINK_UP);
+ }
+
+ if ((bond_mode == BOND_MODE_TLB) ||
+ (bond_mode == BOND_MODE_ALB)) {
+ bond_alb_handle_link_change(bond, new, BOND_LINK_UP);
+ }
+ } else {
+ if (USES_PRIMARY(bond_mode)) {
+ printk (KERN_INFO
+ "%s: making interface %s the new active one.\n",
+ bond->device->name, new->dev->name);
+ }
}
- if (bond->device->flags & IFF_ALLMULTI) {
- dev_set_allmulti(oldslave->dev, -1);
+ }
+
+ if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+ if (old) {
+ bond_set_slave_inactive_flags(old);
+ }
+
+ if (new) {
+ bond_set_slave_active_flags(new);
}
}
- printk (" but could not find any %s interface.\n",
- (bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
-
- /* absolutely nothing found. let's return NULL */
- bond_assign_current_slave(bond, NULL);
- return NULL;
+ if (USES_PRIMARY(bond_mode)) {
+ bond_mc_update(bond, new, old);
+ }
+
+ if ((bond_mode == BOND_MODE_TLB) ||
+ (bond_mode == BOND_MODE_ALB)) {
+ bond_alb_assign_current_slave(bond, new);
+ } else {
+ bond->current_slave = new;
+ }
+}
+
+/**
+ * reselect_active_interface - select a new active slave, if needed
+ * @bond: our bonding struct
+ *
+ * This functions shoud be called when one of the following occurs:
+ * - The old current_slave has been released or lost its link.
+ * - The primary_slave has got its link back.
+ * - A slave has got its link back and there's no old current_slave.
+ *
+ * Warning: Caller must hold ptrlock for writing.
+ */
+static void reselect_active_interface(struct bonding *bond)
+{
+ struct slave *best_slave;
+
+ best_slave = find_best_interface(bond);
+
+ if (best_slave != bond->current_slave) {
+ change_active_interface(bond, best_slave);
+ }
}
/*
@@ -1949,12 +2007,12 @@ static int bond_release(struct net_device *master, struct net_device *slave)
"of %s to a different address "
"to avoid conflicts.\n",
slave->name,
- slave->dev_addr[0],
- slave->dev_addr[1],
- slave->dev_addr[2],
- slave->dev_addr[3],
- slave->dev_addr[4],
- slave->dev_addr[5],
+ our_slave->perm_hwaddr[0],
+ our_slave->perm_hwaddr[1],
+ our_slave->perm_hwaddr[2],
+ our_slave->perm_hwaddr[3],
+ our_slave->perm_hwaddr[4],
+ our_slave->perm_hwaddr[5],
bond->device->name,
slave->name);
}
@@ -1967,6 +2025,11 @@ static int bond_release(struct net_device *master, struct net_device *slave)
bond_3ad_unbind_slave(our_slave);
}
+ printk (KERN_INFO "%s: releasing %s interface %s\n",
+ master->name,
+ (our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+ slave->name);
+
/* release the slave from its bond */
bond_detach_slave(bond, our_slave);
@@ -1974,18 +2037,11 @@ static int bond_release(struct net_device *master, struct net_device *slave)
bond->primary_slave = NULL;
}
- printk (KERN_INFO "%s: releasing %s interface %s",
- master->name,
- (our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
- slave->name);
-
- if (our_slave == old_current) {
- /* find a new interface and be verbose */
- change_active_interface(bond);
- } else {
- printk(".\n");
+ if (bond->current_slave == our_slave) {
+ change_active_interface(bond, NULL);
+ reselect_active_interface(bond);
}
-
+
if (bond->current_slave == NULL) {
printk(KERN_INFO
"%s: now running without any active interface !\n",
@@ -2013,16 +2069,22 @@ static int bond_release(struct net_device *master, struct net_device *slave)
return -EINVAL;
}
+ /* unset promiscuity level from slave */
+ if (master->flags & IFF_PROMISC) {
+ /* If the mode USES_PRIMARY, then we should only remove its
+ * promisc settings if it was the current_slave, but that was
+ * already taken care of above when we detached the slave
+ */
+ if (!USES_PRIMARY(bond_mode)) {
+ dev_set_promiscuity(slave, -1);
+ }
+ }
+
/* undo settings and restore original values */
-
if (multicast_mode == BOND_MULTICAST_ALL) {
/* flush master's mc_list from slave */
bond_mc_list_flush (slave, master);
- /* unset promiscuity level from slave */
- if (master->flags & IFF_PROMISC)
- dev_set_promiscuity(slave, -1);
-
/* unset allmulti level from slave */
if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave, -1);
@@ -2089,7 +2151,7 @@ static int bond_release_all(struct net_device *master)
}
old_current = bond->current_slave;
- bond_assign_current_slave(bond, NULL);
+ change_active_interface(bond, NULL);
bond->current_arp_slave = NULL;
bond->primary_slave = NULL;
@@ -2118,17 +2180,17 @@ static int bond_release_all(struct net_device *master)
*/
write_unlock_bh(&bond->lock);
- if (multicast_mode == BOND_MULTICAST_ALL
- || (multicast_mode == BOND_MULTICAST_ACTIVE
- && old_current == our_slave)) {
+ /* unset promiscuity level from slave */
+ if (master->flags & IFF_PROMISC) {
+ if (!USES_PRIMARY(bond_mode)) {
+ dev_set_promiscuity(slave_dev, -1);
+ }
+ }
+ if (multicast_mode == BOND_MULTICAST_ALL) {
/* flush master's mc_list from slave */
bond_mc_list_flush (slave_dev, master);
- /* unset promiscuity level from slave */
- if (master->flags & IFF_PROMISC)
- dev_set_promiscuity(slave_dev, -1);
-
/* unset allmulti level from slave */
if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, -1);
@@ -2274,9 +2336,7 @@ static void bond_mii_monitor(struct net_device *master)
write_lock(&bond->ptrlock);
if (slave == bond->current_slave) {
/* find a new interface and be verbose */
- change_active_interface(bond);
- } else {
- printk(".\n");
+ reselect_active_interface(bond);
}
write_unlock(&bond->ptrlock);
slave_died = 1;
@@ -2372,7 +2432,7 @@ static void bond_mii_monitor(struct net_device *master)
write_lock(&bond->ptrlock);
if ( (bond->primary_slave != NULL)
&& (slave == bond->primary_slave) )
- change_active_interface(bond);
+ reselect_active_interface(bond);
write_unlock(&bond->ptrlock);
}
else
@@ -2418,40 +2478,8 @@ static void bond_mii_monitor(struct net_device *master)
/* no active interface at the moment or need to bring up the primary */
if (oldcurrent == NULL) { /* no active interface at the moment */
if (bestslave != NULL) { /* last chance to find one ? */
- if (bestslave->link == BOND_LINK_UP) {
- printk (KERN_INFO
- "%s: making interface %s the new active one.\n",
- master->name, bestslave->dev->name);
- } else {
- printk (KERN_INFO
- "%s: making interface %s the new "
- "active one %d ms earlier.\n",
- master->name, bestslave->dev->name,
- (updelay - bestslave->delay) * miimon);
-
- bestslave->delay = 0;
- bestslave->link = BOND_LINK_UP;
- bestslave->jiffies = jiffies;
-
- /* notify ad that the link status has changed */
- if (bond_mode == BOND_MODE_8023AD) {
- bond_3ad_handle_link_change(bestslave, BOND_LINK_UP);
- }
-
- if ((bond_mode == BOND_MODE_TLB) ||
- (bond_mode == BOND_MODE_ALB)) {
- bond_alb_handle_link_change(bond, bestslave, BOND_LINK_UP);
- }
- }
-
- if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
- bond_set_slave_active_flags(bestslave);
- bond_mc_update(bond, bestslave, NULL);
- } else if (bond_mode != BOND_MODE_8023AD) {
- bestslave->state = BOND_STATE_ACTIVE;
- }
write_lock(&bond->ptrlock);
- bond_assign_current_slave(bond, bestslave);
+ change_active_interface(bond, bestslave);
write_unlock(&bond->ptrlock);
} else if (slave_died) {
/* print this message only once a slave has just died */
@@ -2535,7 +2563,7 @@ static void loadbalance_arp_monitor(struct net_device *master)
"for interface %s, ",
master->name,
slave->dev->name);
- change_active_interface(bond);
+ reselect_active_interface(bond);
} else {
printk(KERN_INFO
"%s: interface %s is now up\n",
@@ -2567,7 +2595,7 @@ static void loadbalance_arp_monitor(struct net_device *master)
write_lock(&bond->ptrlock);
if (slave == bond->current_slave) {
- change_active_interface(bond);
+ reselect_active_interface(bond);
}
write_unlock(&bond->ptrlock);
}
@@ -2645,9 +2673,7 @@ static void activebackup_arp_monitor(struct net_device *master)
if ((bond->current_slave == NULL) &&
((jiffies - slave->dev->trans_start) <=
the_delta_in_ticks)) {
- bond_assign_current_slave(bond, slave);
- bond_set_slave_active_flags(slave);
- bond_mc_update(bond, slave, NULL);
+ change_active_interface(bond, slave);
bond->current_arp_slave = NULL;
} else if (bond->current_slave != slave) {
/* this slave has just come up but we
@@ -2737,7 +2763,8 @@ static void activebackup_arp_monitor(struct net_device *master)
master->name,
slave->dev->name);
write_lock(&bond->ptrlock);
- slave = change_active_interface(bond);
+ reselect_active_interface(bond);
+ slave = bond->current_slave;
write_unlock(&bond->ptrlock);
bond->current_arp_slave = slave;
if (slave != NULL) {
@@ -2756,13 +2783,10 @@ static void activebackup_arp_monitor(struct net_device *master)
bond->primary_slave->dev->name);
/* primary is up so switch to it */
- bond_set_slave_inactive_flags(slave);
- bond_mc_update(bond, bond->primary_slave, slave);
write_lock(&bond->ptrlock);
- bond_assign_current_slave(bond, bond->primary_slave);
+ change_active_interface(bond, bond->primary_slave);
write_unlock(&bond->ptrlock);
slave = bond->primary_slave;
- bond_set_slave_active_flags(slave);
slave->jiffies = jiffies;
} else {
bond->current_arp_slave = NULL;
@@ -2805,7 +2829,7 @@ static void activebackup_arp_monitor(struct net_device *master)
/* if the link state is up at this point, we
* mark it down - this can happen if we have
* simultaneous link failures and
- * change_active_interface doesn't make this
+ * reselect_active_interface doesn't make this
* one the current slave so it is still marked
* up when it is actually down
*/
@@ -3050,15 +3074,9 @@ static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
case SIOCBONDRELEASE:
ret = bond_release(master_dev, slave_dev);
break;
- case BOND_SETHWADDR_OLD:
- case SIOCBONDSETHWADDR:
- ret = bond_sethwaddr(master_dev, slave_dev);
- break;
case BOND_CHANGE_ACTIVE_OLD:
case SIOCBONDCHANGEACTIVE:
- if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
- (bond_mode == BOND_MODE_TLB) ||
- (bond_mode == BOND_MODE_ALB)) {
+ if (USES_PRIMARY(bond_mode)) {
ret = bond_change_active(master_dev, slave_dev);
}
else {
@@ -3180,7 +3198,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev)
dev_queue_xmit(skb);
write_lock(&bond->ptrlock);
- bond_assign_current_slave(bond, slave->next);
+ bond->current_slave = slave->next;
write_unlock(&bond->ptrlock);
read_unlock(&bond->lock);
@@ -3367,162 +3385,480 @@ static struct net_device_stats *bond_get_stats(struct net_device *dev)
}
#ifdef CONFIG_PROC_FS
-static int bond_read_proc(char *buf, char **start, off_t off, int count, int *eof, void *data)
+
+#define SEQ_START_TOKEN ((void *)1)
+
+static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
{
- struct bonding *bond = (struct bonding *) data;
- int len = 0;
- u16 link;
- slave_t *slave = NULL;
+ struct bonding *bond = seq->private;
+ loff_t off = 0;
+ struct slave *slave;
/* make sure the bond won't be taken away */
read_lock(&dev_base_lock);
+ read_lock_bh(&bond->lock);
- len += sprintf(buf + len, "%s\n", version);
-
- /*
- * This function locks the mutex, so we can't lock it until
- * afterwards
- */
- link = bond_check_mii_link(bond);
+ if (*pos == 0) {
+ return SEQ_START_TOKEN;
+ }
- len += sprintf(buf + len, "Bonding Mode: %s\n",
- bond_mode_name());
+ for (slave = bond->prev; slave != (slave_t *)bond;
+ slave = slave->prev) {
- if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
- (bond_mode == BOND_MODE_TLB) ||
- (bond_mode == BOND_MODE_ALB)) {
- read_lock_bh(&bond->lock);
- read_lock(&bond->ptrlock);
- if (bond->current_slave != NULL) {
- len += sprintf(buf + len,
- "Currently Active Slave: %s\n",
- bond->current_slave->dev->name);
+ if (++off == *pos) {
+ return slave;
}
- read_unlock(&bond->ptrlock);
- read_unlock_bh(&bond->lock);
}
- len += sprintf(buf + len, "MII Status: ");
- len += sprintf(buf + len,
- link == BMSR_LSTATUS ? "up\n" : "down\n");
- len += sprintf(buf + len, "MII Polling Interval (ms): %d\n",
- miimon);
- len += sprintf(buf + len, "Up Delay (ms): %d\n",
- updelay * miimon);
- len += sprintf(buf + len, "Down Delay (ms): %d\n",
- downdelay * miimon);
- len += sprintf(buf + len, "Multicast Mode: %s\n",
- multicast_mode_name());
+ return NULL;
+}
+
+static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct bonding *bond = seq->private;
+ struct slave *slave = v;
- read_lock_bh(&bond->lock);
+ ++*pos;
+ if (v == SEQ_START_TOKEN) {
+ slave = bond->prev;
+ } else {
+ slave = slave->prev;
+ }
+
+ return (slave == (struct slave *) bond) ? NULL : slave;
+}
+
+static void bond_info_seq_stop(struct seq_file *seq, void *v)
+{
+ struct bonding *bond = seq->private;
+
+ read_unlock_bh(&bond->lock);
+ read_unlock(&dev_base_lock);
+}
+
+static void bond_info_show_master(struct seq_file *seq, struct bonding *bond)
+{
+ struct slave *curr;
+
+ read_lock(&bond->ptrlock);
+ curr = bond->current_slave;
+ read_unlock(&bond->ptrlock);
+
+ seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name());
+
+ if (USES_PRIMARY(bond_mode)) {
+ if (curr) {
+ seq_printf(seq,
+ "Currently Active Slave: %s\n",
+ curr->dev->name);
+ }
+ }
+
+ seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
+ seq_printf(seq, "MII Polling Interval (ms): %d\n", miimon);
+ seq_printf(seq, "Up Delay (ms): %d\n", updelay * miimon);
+ seq_printf(seq, "Down Delay (ms): %d\n", downdelay * miimon);
+ seq_printf(seq, "Multicast Mode: %s\n", multicast_mode_name());
if (bond_mode == BOND_MODE_8023AD) {
struct ad_info ad_info;
- len += sprintf(buf + len, "\n802.3ad info\n");
+ seq_puts(seq, "\n802.3ad info\n");
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
- len += sprintf(buf + len, "bond %s has no active aggregator\n", bond->device->name);
+ seq_printf(seq, "bond %s has no active aggregator\n",
+ bond->device->name);
} else {
- len += sprintf(buf + len, "Active Aggregator Info:\n");
+ seq_printf(seq, "Active Aggregator Info:\n");
+
+ seq_printf(seq, "\tAggregator ID: %d\n",
+ ad_info.aggregator_id);
+ seq_printf(seq, "\tNumber of ports: %d\n",
+ ad_info.ports);
+ seq_printf(seq, "\tActor Key: %d\n",
+ ad_info.actor_key);
+ seq_printf(seq, "\tPartner Key: %d\n",
+ ad_info.partner_key);
+ seq_printf(seq, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ad_info.partner_system[0],
+ ad_info.partner_system[1],
+ ad_info.partner_system[2],
+ ad_info.partner_system[3],
+ ad_info.partner_system[4],
+ ad_info.partner_system[5]);
+ }
+ }
+}
+
+static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
+{
+ seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
+ seq_printf(seq, "MII Status: %s\n",
+ (slave->link == BOND_LINK_UP) ? "up" : "down");
+ seq_printf(seq, "Link Failure Count: %d\n",
+ slave->link_failure_count);
+
+ if (app_abi_ver >= 1) {
+ seq_printf(seq,
+ "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ slave->perm_hwaddr[0],
+ slave->perm_hwaddr[1],
+ slave->perm_hwaddr[2],
+ slave->perm_hwaddr[3],
+ slave->perm_hwaddr[4],
+ slave->perm_hwaddr[5]);
+ }
- len += sprintf(buf + len, "\tAggregator ID: %d\n", ad_info.aggregator_id);
- len += sprintf(buf + len, "\tNumber of ports: %d\n", ad_info.ports);
- len += sprintf(buf + len, "\tActor Key: %d\n", ad_info.actor_key);
- len += sprintf(buf + len, "\tPartner Key: %d\n", ad_info.partner_key);
- len += sprintf(buf + len, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
- ad_info.partner_system[0],
- ad_info.partner_system[1],
- ad_info.partner_system[2],
- ad_info.partner_system[3],
- ad_info.partner_system[4],
- ad_info.partner_system[5]);
+ if (bond_mode == BOND_MODE_8023AD) {
+ const struct aggregator *agg
+ = SLAVE_AD_INFO(slave).port.aggregator;
+
+ if (agg) {
+ seq_printf(seq, "Aggregator ID: %d\n",
+ agg->aggregator_identifier);
+ } else {
+ seq_puts(seq, "Aggregator ID: N/A\n");
}
}
+}
- for (slave = bond->prev; slave != (slave_t *)bond;
+static int bond_info_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "%s\n", version);
+ bond_info_show_master(seq, seq->private);
+ } else {
+ bond_info_show_slave(seq, v);
+ }
+
+ return 0;
+}
+
+static struct seq_operations bond_info_seq_ops = {
+ .start = bond_info_seq_start,
+ .next = bond_info_seq_next,
+ .stop = bond_info_seq_stop,
+ .show = bond_info_seq_show,
+};
+
+static int bond_info_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int rc;
+
+ rc = seq_open(file, &bond_info_seq_ops);
+ if (!rc) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+ return rc;
+}
+
+static struct file_operations bond_info_fops = {
+ .owner = THIS_MODULE,
+ .open = bond_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int bond_create_proc_info(struct bonding *bond)
+{
+ struct net_device *dev = bond->device;
+
+ if (bond_proc_dir) {
+ bond->bond_proc_file = create_proc_entry(dev->name,
+ S_IRUGO,
+ bond_proc_dir);
+ if (bond->bond_proc_file == NULL) {
+ printk(KERN_WARNING
+ "%s: Cannot create /proc/net/bonding/%s\n",
+ dev->name, dev->name);
+ } else {
+ bond->bond_proc_file->data = bond;
+ bond->bond_proc_file->proc_fops = &bond_info_fops;
+ bond->bond_proc_file->owner = THIS_MODULE;
+ memcpy(bond->procdir_name, dev->name, IFNAMSIZ);
+ }
+ }
+
+ return 0;
+}
+
+static void bond_destroy_proc_info(struct bonding *bond)
+{
+ if (bond_proc_dir && bond->bond_proc_file) {
+ remove_proc_entry(bond->procdir_name, bond_proc_dir);
+ memset(bond->procdir_name, 0, IFNAMSIZ);
+ bond->bond_proc_file = NULL;
+ }
+}
+#endif /* CONFIG_PROC_FS */
+
+/*
+ * Change HW address
+ *
+ * Note that many devices must be down to change the HW address, and
+ * downing the master releases all slaves. We can make bonds full of
+ * bonding devices to test this, however.
+ */
+static inline int
+bond_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct bonding *bond = dev->priv;
+ struct sockaddr *sa = addr, tmp_sa;
+ struct slave *slave;
+ int error;
+
+ dprintk(KERN_INFO "bond_set_mac_address %p %s\n", dev,
+ dev->name);
+
+ if (!is_valid_ether_addr(sa->sa_data)) {
+ return -EADDRNOTAVAIL;
+ }
+
+ for (slave = bond->prev; slave != (struct slave *)bond;
slave = slave->prev) {
- len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);
+ dprintk(KERN_INFO "bond_set_mac: slave %p %s\n", slave,
+ slave->dev->name);
+ if (slave->dev->set_mac_address == NULL) {
+ error = -EOPNOTSUPP;
+ dprintk(KERN_INFO "bond_set_mac EOPNOTSUPP %s\n",
+ slave->dev->name);
+ goto unwind;
+ }
- len += sprintf(buf + len, "MII Status: ");
+ error = slave->dev->set_mac_address(slave->dev, addr);
+ if (error) {
+ /* TODO: consider downing the slave
+ * and retry ?
+ * User should expect communications
+ * breakage anyway until ARP finish
+ * updating, so...
+ */
+ dprintk(KERN_INFO "bond_set_mac err %d %s\n",
+ error, slave->dev->name);
+ goto unwind;
+ }
+ }
- len += sprintf(buf + len,
- slave->link == BOND_LINK_UP ?
- "up\n" : "down\n");
- len += sprintf(buf + len, "Link Failure Count: %d\n",
- slave->link_failure_count);
+ /* success */
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+ return 0;
- if (app_abi_ver >= 1) {
- len += sprintf(buf + len,
- "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
- slave->perm_hwaddr[0],
- slave->perm_hwaddr[1],
- slave->perm_hwaddr[2],
- slave->perm_hwaddr[3],
- slave->perm_hwaddr[4],
- slave->perm_hwaddr[5]);
+unwind:
+ memcpy(tmp_sa.sa_data, dev->dev_addr, dev->addr_len);
+ tmp_sa.sa_family = dev->type;
+
+ for (slave = slave->next; slave != bond->next;
+ slave = slave->next) {
+ int tmp_error;
+
+ tmp_error = slave->dev->set_mac_address(slave->dev, &tmp_sa);
+ if (tmp_error) {
+ dprintk(KERN_INFO "bond_set_mac_address: "
+ "unwind err %d dev %s\n",
+ tmp_error, slave->dev->name);
}
+ }
- if (bond_mode == BOND_MODE_8023AD) {
- struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
+ return error;
+}
- if (agg) {
- len += sprintf(buf + len, "Aggregator ID: %d\n",
- agg->aggregator_identifier);
- } else {
- len += sprintf(buf + len, "Aggregator ID: N/A\n");
- }
+/*
+ * Change the MTU of all of a master's slaves to match the master
+ */
+static inline int
+bond_change_mtu(struct net_device *dev, int newmtu)
+{
+ bonding_t *bond = dev->priv;
+ slave_t *slave;
+ int error;
+
+ dprintk(KERN_INFO "CM: b %p nm %d\n", bond, newmtu);
+ for (slave = bond->prev; slave != (slave_t *)bond;
+ slave = slave->prev) {
+ dprintk(KERN_INFO "CM: s %p s->p %p c_m %p\n", slave,
+ slave->prev, slave->dev->change_mtu);
+ if (slave->dev->change_mtu) {
+ error = slave->dev->change_mtu(slave->dev, newmtu);
+ } else {
+ slave->dev->mtu = newmtu;
+ error = 0;
+ }
+
+ if (error) {
+ /* If we failed to set the slave's mtu to the new value
+ * we must abort the operation even in ACTIVE_BACKUP
+ * mode, because if we allow the backup slaves to have
+ * different mtu values than the active slave we'll
+ * need to change their mtu when doing a failover. That
+ * means changing their mtu from timer context, which
+ * is probably not a good idea.
+ */
+ dprintk(KERN_INFO "bond_change_mtu err %d %s\n",
+ error, slave->dev->name);
+ goto unwind;
}
}
- read_unlock_bh(&bond->lock);
- /*
- * Figure out the calcs for the /proc/net interface
- */
- if (len <= off + count) {
- *eof = 1;
+ dev->mtu = newmtu;
+ return 0;
+
+
+unwind:
+ for (slave = slave->next; slave != bond->next;
+ slave = slave->next) {
+
+ if (slave->dev->change_mtu) {
+ slave->dev->change_mtu(slave->dev, dev->mtu);
+ } else {
+ slave->dev->mtu = dev->mtu;
+ }
}
- *start = buf + off;
- len -= off;
- if (len > count) {
- len = count;
+
+ return error;
+}
+
+/*
+ * Change device name
+ */
+static inline int bond_event_changename(struct bonding *bond)
+{
+#ifdef CONFIG_PROC_FS
+ bond_destroy_proc_info(bond);
+ bond_create_proc_info(bond);
+#endif
+
+ return NOTIFY_DONE;
+}
+
+static int bond_master_netdev_event(unsigned long event, struct net_device *event_dev)
+{
+ struct bonding *bond, *event_bond = NULL;
+
+ list_for_each_entry(bond, &bond_dev_list, bond_list) {
+ if (bond == event_dev->priv) {
+ event_bond = bond;
+ break;
+ }
}
- if (len < 0) {
- len = 0;
+
+ if (event_bond == NULL) {
+ return NOTIFY_DONE;
}
- read_unlock(&dev_base_lock);
+ switch (event) {
+ case NETDEV_CHANGENAME:
+ return bond_event_changename(event_bond);
+ case NETDEV_UNREGISTER:
+ /*
+ * TODO: remove a bond from the list?
+ */
+ break;
+ default:
+ break;
+ }
- return len;
+ return NOTIFY_DONE;
}
-#endif /* CONFIG_PROC_FS */
-static int bond_event(struct notifier_block *this, unsigned long event,
- void *ptr)
+static int bond_slave_netdev_event(unsigned long event, struct net_device *event_dev)
{
- struct net_device *event_dev = (struct net_device *)ptr;
struct net_device *master = event_dev->master;
- if ((event == NETDEV_UNREGISTER) && (master != NULL)) {
- bond_release(master, event_dev);
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ if (master != NULL) {
+ bond_release(master, event_dev);
+ }
+ break;
+ case NETDEV_CHANGE:
+ /*
+ * TODO: is this what we get if somebody
+ * sets up a hierarchical bond, then rmmod's
+ * one of the slave bonding devices?
+ */
+ break;
+ case NETDEV_DOWN:
+ /*
+ * ... Or is it this?
+ */
+ break;
+ case NETDEV_CHANGEMTU:
+ /*
+ * TODO: Should slaves be allowed to
+ * independently alter their MTU? For
+ * an active-backup bond, slaves need
+ * not be the same type of device, so
+ * MTUs may vary. For other modes,
+ * slaves arguably should have the
+ * same MTUs. To do this, we'd need to
+ * take over the slave's change_mtu
+ * function for the duration of their
+ * servitude.
+ */
+ break;
+ case NETDEV_CHANGENAME:
+ /*
+ * TODO: handle changing the primary's name
+ */
+ break;
+ default:
+ break;
}
return NOTIFY_DONE;
}
+/*
+ * bond_netdev_event: handle netdev notifier chain events.
+ *
+ * This function receives events for the netdev chain. The caller (an
+ * ioctl handler calling notifier_call_chain) holds the necessary
+ * locks for us to safely manipulate the slave devices (RTNL lock,
+ * dev_probe_lock).
+ */
+static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = (struct net_device *)ptr;
+ unsigned short flags;
+ int res = NOTIFY_DONE;
+
+ dprintk(KERN_INFO "bond_netdev_event n_b %p ev %lx ptr %p\n",
+ this, event, ptr);
+
+ flags = event_dev->flags & (IFF_MASTER | IFF_SLAVE);
+ switch (flags) {
+ case IFF_MASTER:
+ res = bond_master_netdev_event(event, event_dev);
+ break;
+ case IFF_SLAVE:
+ res = bond_slave_netdev_event(event, event_dev);
+ break;
+ default:
+ /* A master that is also a slave ? */
+ break;
+ }
+
+ return res;
+}
+
static struct notifier_block bond_netdev_notifier = {
- .notifier_call = bond_event,
+ .notifier_call = bond_netdev_event,
};
-static void bond_deinit(struct net_device *dev)
+static inline void bond_deinit(struct net_device *dev)
{
struct bonding *bond = dev->priv;
list_del(&bond->bond_list);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("info", bond->bond_proc_dir);
- remove_proc_entry(dev->name, proc_net);
+ bond_destroy_proc_info(bond);
#endif
}
@@ -3535,10 +3871,21 @@ static void bond_free_all(void)
unregister_netdev(dev);
bond_deinit(dev);
- kfree(dev);
+ free_netdev(dev);
+ }
+
+#ifdef CONFIG_PROC_FS
+ if (bond_proc_dir) {
+ remove_proc_entry(DRV_NAME, proc_net);
+ bond_proc_dir = NULL;
}
+#endif
}
+/*
+ * Does not allocate but creates a /proc entry.
+ * Allowed to fail.
+ */
static int __init bond_init(struct net_device *dev)
{
struct bonding *bond;
@@ -3553,12 +3900,15 @@ static int __init bond_init(struct net_device *dev)
rwlock_init(&bond->lock);
rwlock_init(&bond->ptrlock);
+ /* Initialize pointers */
bond->next = bond->prev = (slave_t *)bond;
bond->current_slave = NULL;
bond->current_arp_slave = NULL;
bond->device = dev;
/* Initialize the device structure. */
+ dev->set_mac_address = bond_set_mac_address;
+
switch (bond_mode) {
case BOND_MODE_ACTIVEBACKUP:
dev->hard_start_xmit = bond_xmit_activebackup;
@@ -3578,6 +3928,7 @@ static int __init bond_init(struct net_device *dev)
case BOND_MODE_TLB:
case BOND_MODE_ALB:
dev->hard_start_xmit = bond_alb_xmit;
+ dev->set_mac_address = bond_alb_set_mac_address;
break;
default:
printk(KERN_ERR "Unknown bonding mode %d\n", bond_mode);
@@ -3589,7 +3940,7 @@ static int __init bond_init(struct net_device *dev)
dev->stop = bond_close;
dev->set_multicast_list = set_multicast_list;
dev->do_ioctl = bond_ioctl;
-
+ dev->change_mtu = bond_change_mtu;
dev->tx_queue_len = 0;
dev->flags |= IFF_MASTER|IFF_MULTICAST;
#ifdef CONFIG_NET_FASTROUTE
@@ -3616,27 +3967,10 @@ static int __init bond_init(struct net_device *dev)
} else {
printk("out ARP monitoring\n");
}
-
+
#ifdef CONFIG_PROC_FS
- bond->bond_proc_dir = proc_mkdir(dev->name, proc_net);
- if (bond->bond_proc_dir == NULL) {
- printk(KERN_ERR "%s: Cannot init /proc/net/%s/\n",
- dev->name, dev->name);
- return -ENOMEM;
- }
- bond->bond_proc_dir->owner = THIS_MODULE;
-
- bond->bond_proc_info_file =
- create_proc_read_entry("info", 0, bond->bond_proc_dir,
- bond_read_proc, bond);
- if (bond->bond_proc_info_file == NULL) {
- printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n",
- dev->name, dev->name);
- remove_proc_entry(dev->name, proc_net);
- return -ENOMEM;
- }
- bond->bond_proc_info_file->owner = THIS_MODULE;
-#endif /* CONFIG_PROC_FS */
+ bond_create_proc_info(bond);
+#endif
list_add_tail(&bond->bond_list, &bond_dev_list);
@@ -3693,6 +4027,12 @@ static int __init bonding_init(void)
}
}
+ if (USES_PRIMARY(bond_mode)) {
+ multicast_mode = BOND_MULTICAST_ACTIVE;
+ } else {
+ multicast_mode = BOND_MULTICAST_ALL;
+ }
+
if (multicast) {
multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
if (multicast_mode == -1) {
@@ -3905,9 +4245,7 @@ static int __init bonding_init(void)
"link failures! see bonding.txt for details.\n");
}
- if ((primary != NULL) && (bond_mode != BOND_MODE_ACTIVEBACKUP) &&
- (bond_mode != BOND_MODE_TLB) &&
- (bond_mode != BOND_MODE_ALB)){
+ if ((primary != NULL) && !USES_PRIMARY(bond_mode)) {
/* currently, using a primary only makes sense
* in active backup, TLB or ALB modes
*/
@@ -3918,6 +4256,16 @@ static int __init bonding_init(void)
primary = NULL;
}
+#ifdef CONFIG_PROC_FS
+ bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
+ if (bond_proc_dir == NULL) {
+ printk(KERN_WARNING
+ "bonding_init(): can not create /proc/net/" DRV_NAME);
+ } else {
+ bond_proc_dir->owner = THIS_MODULE;
+ }
+#endif
+
rtnl_lock();
err = 0;
@@ -3932,7 +4280,7 @@ static int __init bonding_init(void)
err = dev_alloc_name(dev, "bond%d");
if (err < 0) {
- kfree(dev);
+ free_netdev(dev);
goto out_err;
}
@@ -3942,7 +4290,7 @@ static int __init bonding_init(void)
*/
err = bond_init(dev);
if (err < 0) {
- kfree(dev);
+ free_netdev(dev);
goto out_err;
}
@@ -3951,7 +4299,7 @@ static int __init bonding_init(void)
err = register_netdevice(dev);
if (err < 0) {
bond_deinit(dev);
- kfree(dev);
+ free_netdev(dev);
goto out_err;
}
}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a8aa800a7421..8358c8085542 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -101,8 +101,8 @@ typedef struct bonding {
struct timer_list arp_timer;
struct net_device_stats stats;
#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *bond_proc_dir;
- struct proc_dir_entry *bond_proc_info_file;
+ struct proc_dir_entry *bond_proc_file;
+ char procdir_name[IFNAMSIZ];
#endif /* CONFIG_PROC_FS */
struct list_head bond_list;
struct net_device *device;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 343bf90f27e1..af8b183799b0 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -90,7 +90,6 @@
or override something. */
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
/*
* Set this to zero to disable DMA code
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 623b9b54d796..e9700be21569 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -1,4 +1,4 @@
-/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
+/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
Written 1994, 1995 by David C. Davies.
@@ -253,7 +253,8 @@
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/ctype.h>
-#include <linux/mca-legacy.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -265,7 +266,6 @@
#endif
#ifdef CONFIG_EISA
-#include <linux/device.h>
#include <linux/eisa.h>
#endif
@@ -305,21 +305,21 @@ static int depca_debug = 1;
** EISA bus defines
*/
#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */
-#define MAX_EISA_SLOTS 16
-#define EISA_SLOT_INC 0x1000
/*
** ISA Bus defines
*/
#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
-#define DEPCA_IO_PORTS {0x300, 0x200, 0}
#define DEPCA_TOTAL_SIZE 0x10
-static short mem_chkd;
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE212_ID 0x6def
+static struct {
+ u_long iobase;
+ struct platform_device *device;
+} depca_io_ports[] = {
+ { 0x300, NULL },
+ { 0x200, NULL },
+ { 0 , NULL },
+};
/*
** Name <-> Adapter mapping
@@ -330,34 +330,86 @@ static short mem_chkd;
"DE210","DE212",\
"DE422",\
""}
-static enum {
+
+static char* __initdata depca_signature[] = DEPCA_SIGNATURE;
+
+enum depca_type {
DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
-} adapter;
+};
+
+static char depca_string[] = "depca";
+
+static int depca_device_remove (struct device *device);
#ifdef CONFIG_EISA
struct eisa_device_id depca_eisa_ids[] = {
- { "DEC4220" },
+ { "DEC4220", de422 },
{ "" }
};
static int depca_eisa_probe (struct device *device);
-static int depca_eisa_remove (struct device *device);
struct eisa_driver depca_eisa_driver = {
.id_table = depca_eisa_ids,
.driver = {
- .name = "depca",
+ .name = depca_string,
.probe = depca_eisa_probe,
- .remove = __devexit_p (depca_eisa_remove)
+ .remove = __devexit_p (depca_device_remove)
}
};
#endif
+#ifdef CONFIG_MCA
+/*
+** Adapter ID for the MCA EtherWORKS DE210/212 adapter
+*/
+#define DE210_ID 0x628d
+#define DE212_ID 0x6def
+
+static short depca_mca_adapter_ids[] = {
+ DE210_ID,
+ DE212_ID,
+ 0x0000
+};
+
+static char *depca_mca_adapter_name[] = {
+ "DEC EtherWORKS MC Adapter (DE210)",
+ "DEC EtherWORKS MC Adapter (DE212)",
+ NULL
+};
+
+static enum depca_type depca_mca_adapter_type[] = {
+ de210,
+ de212,
+ 0
+};
+
+static int depca_mca_probe (struct device *);
+
+static struct mca_driver depca_mca_driver = {
+ .id_table = depca_mca_adapter_ids,
+ .driver = {
+ .name = depca_string,
+ .bus = &mca_bus_type,
+ .probe = depca_mca_probe,
+ .remove = __devexit_p(depca_device_remove),
+ },
+};
+#endif
+
+static int depca_isa_probe (struct device *);
+
+static struct device_driver depca_isa_driver = {
+ .name = depca_string,
+ .bus = &platform_bus_type,
+ .probe = depca_isa_probe,
+ .remove = __devexit_p(depca_device_remove),
+};
+
/*
** Miscellaneous info...
*/
#define DEPCA_STRLEN 16
-#define MAX_NUM_DEPCAS 2
/*
** Memory Alignment. Each descriptor is 4 longwords long. To force a
@@ -402,10 +454,13 @@ struct depca_init {
#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you
increase DEPCA_PKT_STAT_SZ */
struct depca_private {
- char devname[DEPCA_STRLEN]; /* Device Product String */
char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */
- char adapter; /* Adapter type */
- char mca_slot; /* MCA slot, if MCA else -1 */
+ enum depca_type adapter; /* Adapter type */
+ enum {
+ DEPCA_BUS_MCA = 1,
+ DEPCA_BUS_ISA,
+ DEPCA_BUS_EISA,
+ } depca_bus; /* type of bus */
struct depca_init init_block; /* Shadow Initialization block */
/* CPU address space fields */
struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */
@@ -467,45 +522,39 @@ static void set_multicast_list(struct net_device *dev);
/*
** Private functions
*/
-static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
static void depca_init_ring(struct net_device *dev);
static int depca_rx(struct net_device *dev);
static int depca_tx(struct net_device *dev);
static void LoadCSRs(struct net_device *dev);
static int InitRestartDepca(struct net_device *dev);
-static void DepcaSignature(char *name, u_long paddr);
+static int DepcaSignature(char *name, u_long paddr);
static int DevicePresent(u_long ioaddr);
static int get_hw_addr(struct net_device *dev);
static void SetMulticastFilter(struct net_device *dev);
-static void isa_probe(struct net_device *dev, u_long iobase);
-#ifdef CONFIG_MCA
-static void mca_probe(struct net_device *dev, u_long iobase);
-#endif
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static int depca_dev_index(char *s);
-static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
static int load_packet(struct net_device *dev, struct sk_buff *skb);
static void depca_dbg_open(struct net_device *dev);
-#ifdef MODULE
-static int autoprobed = 1, loading_module = 1;
-# else
static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
static u_char *depca_irq;
-static int autoprobed, loading_module;
-#endif /* MODULE */
-static char name[DEPCA_STRLEN];
-static int num_depcas, num_eth;
+static int irq;
+static int io;
+static char *adapter_name;
static int mem; /* For loadable module assignment
use insmod mem=0x????? .... */
-static char *adapter_name; /* = '\0'; If no PROM when loadable module
- use insmod adapter_name=DE??? ...
- bss initializes this to zero
- */
+module_param (irq, int, 0);
+module_param (io, int, 0);
+module_param (adapter_name, charp, 0);
+module_param (mem, int, 0);
+MODULE_PARM_DESC(irq, "DEPCA IRQ number");
+MODULE_PARM_DESC(io, "DEPCA I/O base address");
+MODULE_PARM_DESC(adapter_name, "DEPCA adapter name");
+MODULE_PARM_DESC(mem, "DEPCA shared memory address");
+MODULE_LICENSE("GPL");
+
/*
** Miscellaneous defines...
*/
@@ -513,52 +562,30 @@ static char *adapter_name; /* = '\0'; If no PROM when loadable module
outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA)
-int __init depca_probe(struct net_device *dev)
-{
- int tmp = num_depcas, status = -ENODEV;
- u_long iobase = dev->base_addr;
-
- SET_MODULE_OWNER(dev);
-
- if ((iobase == 0) && loading_module) {
- printk("Autoprobing is not supported when loading a module based driver.\n");
- status = -EIO;
- } else {
-#ifdef CONFIG_MCA
- mca_probe(dev, iobase);
-#endif
- isa_probe(dev, iobase);
-#ifdef CONFIG_EISA
- eisa_driver_register (&depca_eisa_driver);
-#endif
-
- if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
- printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
- }
-
- /*
- ** Walk the device list to check that at least one device
- ** initialised OK
- */
- for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
-
- if (dev->priv)
- status = 0;
- if (iobase == 0)
- autoprobed = 1;
- }
-
- return status;
-}
-
-static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
+static int __init depca_hw_init (struct net_device *dev, struct device *device)
{
struct depca_private *lp;
int i, j, offset, netRAM, mem_len, status = 0;
s16 nicsr;
- u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
- int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS);
+ u_long ioaddr;
+ u_long mem_start;
+ /*
+ * We are now supposed to enter this function with the
+ * following fields filled with proper values :
+ *
+ * dev->base_addr
+ * lp->mem_start
+ * lp->depca_bus
+ * lp->adapter
+ *
+ * dev->irq can be set if known from device configuration (on
+ * MCA or EISA) or module option. Otherwise, it will be auto
+ * detected.
+ */
+
+ ioaddr = dev->base_addr;
+
STOP_DEPCA;
nicsr = inb(DEPCA_NICSR);
@@ -569,24 +596,34 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
return -ENXIO;
}
- do {
- strcpy(name, (adapter_name ? adapter_name : ""));
- mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]);
- DepcaSignature(name, mem_start);
- } while (!mem && mem_base[mem_chkd] && (adapter == unknown));
+ lp = (struct depca_private *) dev->priv;
+ mem_start = lp->mem_start;
- if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */
+ if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
return -ENXIO;
- }
- dev->base_addr = ioaddr;
+ printk ("%s: %s at 0x%04lx",
+ device->bus_id, depca_signature[lp->adapter], ioaddr);
+
+ switch (lp->depca_bus) {
+#ifdef CONFIG_MCA
+ case DEPCA_BUS_MCA:
+ printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
+ break;
+#endif
- if (mca_slot != -1) {
- printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
- } else if (is_eisa) { /* EISA slot address */
- printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
- } else { /* ISA port address */
- printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
+#ifdef CONFIG_EISA
+ case DEPCA_BUS_EISA:
+ printk(" (EISA slot %d)", to_eisa_device(device)->slot);
+ break;
+#endif
+
+ case DEPCA_BUS_ISA:
+ break;
+
+ default:
+ printk("Unknown DEPCA bus %d\n", lp->depca_bus);
+ return -ENXIO;
}
printk(", h/w address ");
@@ -601,18 +638,20 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
printk("%2.2x", dev->dev_addr[i]);
/* Set up the maximum amount of network RAM(kB) */
- netRAM = ((adapter != DEPCA) ? 64 : 48);
- if ((nicsr & _128KB) && (adapter == de422))
+ netRAM = ((lp->adapter != DEPCA) ? 64 : 48);
+ if ((nicsr & _128KB) && (lp->adapter == de422))
netRAM = 128;
- offset = 0x0000;
/* Shared Memory Base Address */
if (nicsr & BUF) {
- offset = 0x8000; /* 32kbyte RAM offset */
nicsr &= ~BS; /* DEPCA RAM in top 32k */
netRAM -= 32;
+
+ /* Only EISA/ISA needs start address to be re-computed */
+ if (lp->depca_bus != DEPCA_BUS_MCA)
+ mem_start += 0x8000;
}
- mem_start += offset; /* (E)ISA start address */
+
if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
> (netRAM << 10)) {
printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
@@ -622,23 +661,14 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start);
/* Enable the shadow RAM. */
- if (adapter != DEPCA) {
+ if (lp->adapter != DEPCA) {
nicsr |= SHE;
outb(nicsr, DEPCA_NICSR);
}
- /* Define the device private memory */
- if (!is_eisa) {
- dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- }
- lp = (struct depca_private *) dev->priv;
- memset((char *) dev->priv, 0, sizeof(struct depca_private));
- lp->adapter = adapter;
- lp->mca_slot = mca_slot;
lp->lock = SPIN_LOCK_UNLOCKED;
- sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
+ sprintf(lp->adapter_name, "%s (%s)",
+ depca_signature[lp->adapter], device->bus_id);
status = -EBUSY;
/* Initialisation Block */
@@ -702,7 +732,6 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
/* To auto-IRQ we enable the initialization-done and DMA err,
interrupts. For now we will always get a DMA error. */
if (dev->irq < 2) {
-#ifndef MODULE
unsigned char irqnum;
unsigned long irq_mask, delay;
@@ -725,6 +754,9 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
case de422:
depca_irq = de422_irq;
break;
+
+ default:
+ break; /* Not reached */
}
/* Trigger an initialization just for the interrupt. */
@@ -733,6 +765,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
delay = jiffies + HZ/50;
while (time_before(jiffies, delay))
yield();
+
irqnum = probe_irq_off(irq_mask);
status = -ENXIO;
@@ -746,13 +779,11 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
printk(" and uses IRQ%d.\n", dev->irq);
}
- status = -ENXIO;
if (!dev->irq) {
printk(" but incorrect IRQ line detected.\n");
- goto out_priv;
+ return -ENXIO;
}
}
-#endif /* MODULE */
} else {
printk(" and assigned IRQ%d.\n", dev->irq);
}
@@ -773,17 +804,14 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
dev->mem_start = 0;
- /* Fill in the generic field of the device structure. */
- if (!is_eisa)
- ether_setup(dev);
+ device->driver_data = dev;
+ SET_NETDEV_DEV (dev, device);
+
+ register_netdev (dev);
return 0;
- out_priv:
- if (!is_eisa) {
- kfree(dev->priv);
- dev->priv = NULL;
- } else {
- unregister_netdev (dev);
- }
+
+ out_priv:
+
return status;
}
@@ -1284,215 +1312,265 @@ static void SetMulticastFilter(struct net_device *dev)
return;
}
+static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
+{
+ int status = 0;
+
+ if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
+ status = -EBUSY;
+ goto out;
+ }
+
+ if (DevicePresent(ioaddr)) {
+ status = -ENODEV;
+ goto out_release;
+ }
+
+ if (!(*devp = alloc_etherdev (sizeof (struct depca_private)))) {
+ status = -ENOMEM;
+ goto out_release;
+ }
+
+ return 0;
+
+ out_release:
+ release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+ return status;
+}
+
#ifdef CONFIG_MCA
/*
** Microchannel bus I/O device probe
*/
-static void __init mca_probe(struct net_device *dev, u_long ioaddr)
+static int __init depca_mca_probe(struct device *device)
{
unsigned char pos[2];
unsigned char where;
- unsigned long iobase;
- int irq;
- int slot = 0;
+ unsigned long iobase, mem_start;
+ int irq, err;
+ struct mca_device *mdev = to_mca_device (device);
+ struct net_device *dev;
+ struct depca_private *lp;
/*
- ** See if we've been here before.
- */
- if ((!ioaddr && autoprobed) || (ioaddr && !loading_module))
- return;
-
- if (MCA_bus) {
- /*
- ** Search for the adapter. If an address has been given, search
- ** specifically for the card at that address. Otherwise find the
- ** first card in the system.
- */
- while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
- pos[0] = mca_read_stored_pos(slot, 2);
- pos[1] = mca_read_stored_pos(slot, 3);
-
- /*
- ** IO of card is handled by bits 1 and 2 of pos0.
- **
- ** bit2 bit1 IO
- ** 0 0 0x2c00
- ** 0 1 0x2c10
- ** 1 0 0x2c20
- ** 1 1 0x2c30
- */
- where = (pos[0] & 6) >> 1;
- iobase = 0x2c00 + (0x10 * where);
-
- if ((ioaddr) && (ioaddr != iobase)) {
- /*
- ** Card was found, but not at the right IO location. Continue
- ** scanning from the next MCA slot up for another card.
- */
- slot++;
- continue;
- }
-
- /*
- ** Found the adapter we were looking for. Now start setting it up.
- **
- ** First work on decoding the IRQ. It's stored in the lower 4 bits
- ** of pos1. Bits are as follows (from the ADF file):
- **
- ** Bits
- ** 3 2 1 0 IRQ
- ** --------------------
- ** 0 0 1 0 5
- ** 0 0 0 1 9
- ** 0 1 0 0 10
- ** 1 0 0 0 11
- * */
- where = pos[1] & 0x0f;
- switch (where) {
- case 1:
- irq = 9;
- break;
- case 2:
- irq = 5;
- break;
- case 4:
- irq = 10;
- break;
- case 8:
- irq = 11;
- break;
- default:
- printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where);
- return;
- }
+ ** Search for the adapter. If an address has been given, search
+ ** specifically for the card at that address. Otherwise find the
+ ** first card in the system.
+ */
+
+ pos[0] = mca_device_read_stored_pos(mdev, 2);
+ pos[1] = mca_device_read_stored_pos(mdev, 3);
- /*
- ** Shared memory address of adapter is stored in bits 3-5 of pos0.
- ** They are mapped as follows:
- **
- ** Bit
- ** 5 4 3 Memory Addresses
- ** 0 0 0 C0000-CFFFF (64K)
- ** 1 0 0 C8000-CFFFF (32K)
- ** 0 0 1 D0000-DFFFF (64K)
- ** 1 0 1 D8000-DFFFF (32K)
- ** 0 1 0 E0000-EFFFF (64K)
- ** 1 1 0 E8000-EFFFF (32K)
- */
- where = (pos[0] & 0x18) >> 3;
- mem = 0xc0000 + (where * 0x10000);
- if (pos[0] & 0x20) {
- mem += 0x8000;
- }
+ /*
+ ** IO of card is handled by bits 1 and 2 of pos0.
+ **
+ ** bit2 bit1 IO
+ ** 0 0 0x2c00
+ ** 0 1 0x2c10
+ ** 1 0 0x2c20
+ ** 1 1 0x2c30
+ */
+ where = (pos[0] & 6) >> 1;
+ iobase = 0x2c00 + (0x10 * where);
- /*
- ** Get everything allocated and initialized... (almost just
- ** like the ISA and EISA probes)
- */
- if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
- if (autoprobed)
- printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
- goto next;
- }
- if (DevicePresent(iobase) != 0) {
- /*
- ** If the MCA configuration says the card should be here,
- ** it really should be here.
- */
- printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
- goto release_next;
- }
+ /*
+ ** Found the adapter we were looking for. Now start setting it up.
+ **
+ ** First work on decoding the IRQ. It's stored in the lower 4 bits
+ ** of pos1. Bits are as follows (from the ADF file):
+ **
+ ** Bits
+ ** 3 2 1 0 IRQ
+ ** --------------------
+ ** 0 0 1 0 5
+ ** 0 0 0 1 9
+ ** 0 1 0 0 10
+ ** 1 0 0 0 11
+ */
+ where = pos[1] & 0x0f;
+ switch (where) {
+ case 1:
+ irq = 9;
+ break;
+ case 2:
+ irq = 5;
+ break;
+ case 4:
+ irq = 10;
+ break;
+ case 8:
+ irq = 11;
+ break;
+ default:
+ printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where);
+ return -EINVAL;
+ }
- if (!(dev = alloc_device(dev, iobase)))
- goto release_next;
+ /*
+ ** Shared memory address of adapter is stored in bits 3-5 of pos0.
+ ** They are mapped as follows:
+ **
+ ** Bit
+ ** 5 4 3 Memory Addresses
+ ** 0 0 0 C0000-CFFFF (64K)
+ ** 1 0 0 C8000-CFFFF (32K)
+ ** 0 0 1 D0000-DFFFF (64K)
+ ** 1 0 1 D8000-DFFFF (32K)
+ ** 0 1 0 E0000-EFFFF (64K)
+ ** 1 1 0 E8000-EFFFF (32K)
+ */
+ where = (pos[0] & 0x18) >> 3;
+ mem_start = 0xc0000 + (where * 0x10000);
+ if (pos[0] & 0x20) {
+ mem_start += 0x8000;
+ }
- num_eth++;
- dev->irq = irq;
- if (depca_hw_init(dev, iobase, slot))
- goto release_next;
+ /* claim the slot */
+ strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
+ sizeof(mdev->name));
+ mca_device_set_claim(mdev, 1);
+
+ /*
+ ** Get everything allocated and initialized... (almost just
+ ** like the ISA and EISA probes)
+ */
+ irq = mca_device_transform_irq(mdev, irq);
+ iobase = mca_device_transform_ioport(mdev, iobase);
+
+ if ((err = depca_common_init (iobase, &dev)))
+ goto out_unclaim;
+
+ dev->irq = irq;
+ dev->base_addr = iobase;
+ lp = dev->priv;
+ lp->depca_bus = DEPCA_BUS_MCA;
+ lp->adapter = depca_mca_adapter_type[mdev->index];
+ lp->mem_start = mem_start;
+
+ if ((err = depca_hw_init(dev, device)))
+ goto out_free;
- /*
- ** Adapter initialized correctly: Name it in
- ** /proc/mca.
- */
- mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
- mca_mark_as_used(slot);
- num_depcas++;
-
- /*
- ** If this is a probe by a module, return after setting up the
- ** given card.
- */
- if (ioaddr)
- return;
-
- /*
- ** Set up to check the next slot and loop.
- */
- slot++;
- continue;
+ return 0;
- release_next:
- release_region (iobase, DEPCA_TOTAL_SIZE);
- next:
- slot++;
- }
- }
+ out_free:
+ free_netdev (dev);
+ release_region (iobase, DEPCA_TOTAL_SIZE);
+ out_unclaim:
+ mca_device_set_claim(mdev, 0);
- return;
+ return err;;
}
#endif
/*
** ISA bus I/O device probe
*/
-static void __init isa_probe(struct net_device *dev, u_long ioaddr)
+
+static void depca_platform_release (struct device *device)
{
- int i = num_depcas, maxSlots;
- s32 ports[] = DEPCA_IO_PORTS;
-
- if (!ioaddr && autoprobed)
- return; /* Been here before ! */
- if (ioaddr > 0x400)
- return; /* EISA Address */
- if (i >= MAX_NUM_DEPCAS)
- return; /* Too many ISA adapters */
-
- if (ioaddr == 0) { /* Autoprobing */
- maxSlots = MAX_NUM_DEPCAS;
- } else { /* Probe a specific location */
- ports[i] = ioaddr;
- maxSlots = i + 1;
- }
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device (device);
+ kfree (pldev);
+}
+
+static void __init depca_platform_probe (void)
+{
+ int i;
+ struct platform_device *pldev;
- for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
- if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) {
- if (autoprobed)
- printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
+ for (i = 0; depca_io_ports[i].iobase; i++) {
+ depca_io_ports[i].device = NULL;
+
+ /* if an address has been specified on the command
+ * line, use it (if valid) */
+ if (io && io != depca_io_ports[i].iobase)
continue;
- }
+
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL)))
+ continue;
+
+ memset (pldev, 0, sizeof (*pldev));
+ pldev->name = depca_string;
+ pldev->id = i;
+ pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
+ pldev->dev.release = depca_platform_release;
+ depca_io_ports[i].device = pldev;
- if (DevicePresent(ports[i])) {
- release_region (ports[i], DEPCA_TOTAL_SIZE);
+ if (platform_device_register (pldev)) {
+ kfree (pldev);
+ depca_io_ports[i].device = NULL;
continue;
}
- if (!(dev = alloc_device(dev, ports[i]))) {
- release_region (ports[i], DEPCA_TOTAL_SIZE);
- continue;
+ if (!pldev->dev.driver) {
+ /* The driver was not bound to this device, there was
+ * no hardware at this address. Unregister it, as the
+ * release fuction will take care of freeing the
+ * allocated structure */
+
+ depca_io_ports[i].device = NULL;
+ platform_device_unregister (pldev);
}
+ }
+}
- num_eth++;
+static enum depca_type __init depca_shmem_probe (ulong *mem_start)
+{
+ u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
+ enum depca_type adapter = unknown;
+ int i;
- if (depca_hw_init(dev, ports[i], -1)) {
- release_region (ports[i], DEPCA_TOTAL_SIZE);
- continue;
- }
+ for (i = 0; mem_base[i]; i++) {
+ *mem_start = mem ? mem : mem_base[i];
+ adapter = DepcaSignature (adapter_name, *mem_start);
+ if (adapter != unknown)
+ break;
+ }
+
+ return adapter;
+}
- num_depcas++;
+static int __init depca_isa_probe (struct device *device)
+{
+ struct net_device *dev;
+ struct depca_private *lp;
+ u_long ioaddr, mem_start = 0;
+ enum depca_type adapter = unknown;
+ int status = 0;
+
+ ioaddr = (u_long) device->platform_data;
+
+ if ((status = depca_common_init (ioaddr, &dev)))
+ goto out;
+
+ adapter = depca_shmem_probe (&mem_start);
+
+ if (adapter == unknown) {
+ status = -ENODEV;
+ goto out_free;
}
- return;
+ dev->base_addr = ioaddr;
+ dev->irq = irq; /* Use whatever value the user gave
+ * us, and 0 if he didn't. */
+ lp = dev->priv;
+ lp->depca_bus = DEPCA_BUS_ISA;
+ lp->adapter = adapter;
+ lp->mem_start = mem_start;
+
+ if ((status = depca_hw_init(dev, device)))
+ goto out_free;
+
+ return 0;
+
+ out_free:
+ free_netdev (dev);
+ release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+ return status;
}
/*
@@ -1504,202 +1582,120 @@ static int __init depca_eisa_probe (struct device *device)
{
struct eisa_device *edev;
struct net_device *dev;
- u_long iobase;
+ struct depca_private *lp;
+ u_long ioaddr, mem_start;
int status = 0;
edev = to_eisa_device (device);
- iobase = edev->base_addr + DEPCA_EISA_IO_PORTS;
+ ioaddr = edev->base_addr + DEPCA_EISA_IO_PORTS;
- if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
- status = -EBUSY;
+ if ((status = depca_common_init (ioaddr, &dev)))
goto out;
- }
-
- if (DevicePresent(iobase)) {
- status = -ENODEV;
- goto out_release;
- }
- if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) {
- status = -ENOMEM;
- goto out_release;
- }
-
- eisa_set_drvdata (edev, dev);
+ /* It would have been nice to get card configuration from the
+ * card. Unfortunately, this register is write-only (shares
+ * it's address with the ethernet prom)... As we don't parse
+ * the EISA configuration structures (yet... :-), just rely on
+ * the ISA probing to sort it out... */
+
+ depca_shmem_probe (&mem_start);
- if ((status = depca_hw_init(dev, iobase, -1)))
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+ lp = dev->priv;
+ lp->depca_bus = DEPCA_BUS_EISA;
+ lp->adapter = edev->id.driver_data;
+ lp->mem_start = mem_start;
+
+ if ((status = depca_hw_init(dev, device)))
goto out_free;
-
- num_depcas++;
+
return 0;
out_free:
- kfree (dev);
- out_release:
- release_region (iobase, DEPCA_TOTAL_SIZE);
+ free_netdev (dev);
+ release_region (ioaddr, DEPCA_TOTAL_SIZE);
out:
return status;
}
+#endif
-static int __devexit depca_eisa_remove (struct device *device)
+static int __devexit depca_device_remove (struct device *device)
{
struct net_device *dev;
- struct eisa_device *edev;
struct depca_private *lp;
+ int bus;
- edev = to_eisa_device (device);
- dev = eisa_get_drvdata (edev);
+ dev = device->driver_data;
lp = dev->priv;
unregister_netdev (dev);
iounmap (lp->sh_mem);
release_mem_region (lp->mem_start, lp->mem_len);
release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
- kfree (dev);
+ bus = lp->depca_bus;
+ free_netdev (dev);
return 0;
}
-#endif
-
-/*
-** Search the entire 'eth' device list for a fixed probe. If a match isn't
-** found then check for an autoprobe or unused device location. If they
-** are not available then insert a new device structure at the end of
-** the current list.
-*/
-static struct net_device *__init alloc_device(struct net_device *dev, u_long iobase)
-{
- struct net_device *adev = NULL;
- int fixed = 0, new_dev = 0;
-
- num_eth = depca_dev_index(dev->name);
- if (loading_module)
- return dev;
-
- while (1) {
- if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) {
- adev = dev;
- } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
- fixed = 1;
- } else {
- if (dev->next == NULL) {
- new_dev = 1;
- } else if (strncmp(dev->next->name, "eth", 3) != 0) {
- new_dev = 1;
- }
- }
- if ((dev->next == NULL) || new_dev || fixed)
- break;
- dev = dev->next;
- num_eth++;
- }
- if (adev && !fixed) {
- dev = adev;
- num_eth = depca_dev_index(dev->name);
- new_dev = 0;
- }
-
- if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) {
- num_eth++; /* New device */
- dev = insert_device(dev, iobase, depca_probe);
- }
-
- return dev;
-}
-
-/*
-** If at end of eth device list and can't use current entry, malloc
-** one up. If memory could not be allocated, print an error message.
-*/
-static struct net_device *__init insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
-{
- struct net_device *new;
-
- new = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if (new == NULL) {
- printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
- return NULL;
- } else {
- new->next = dev->next;
- dev->next = new;
- dev = dev->next; /* point to the new device */
- if (num_eth > 9999) {
- sprintf(dev->name, "eth????"); /* New device name */
- } else {
- sprintf(dev->name, "eth%d", num_eth); /* New device name */
- }
- dev->base_addr = iobase; /* assign the io address */
- dev->init = init; /* initialisation routine */
- }
-
- return dev;
-}
-
-static int __init depca_dev_index(char *s)
-{
- int i = 0, j = 0;
-
- for (; *s; s++) {
- if (isdigit(*s)) {
- j = 1;
- i = (i * 10) + (*s - '0');
- } else if (j)
- break;
- }
-
- return i;
-}
/*
** Look for a particular board name in the on-board Remote Diagnostics
** and Boot (readb) ROM. This will also give us a clue to the network RAM
** base address.
*/
-static void __init DepcaSignature(char *name, u_long paddr)
+static int __init DepcaSignature(char *name, u_long base_addr)
{
u_int i, j, k;
- const char *signatures[] = DEPCA_SIGNATURE;
void *ptr;
char tmpstr[16];
+ u_long prom_addr = base_addr + 0xc000;
+ u_long mem_addr = base_addr + 0x8000; /* 32KB */
+
+ /* Can't reserve the prom region, it is already marked as
+ * used, at least on x86. Instead, reserve a memory region a
+ * board would certainly use. If it works, go ahead. If not,
+ * run like hell... */
+
+ if (!request_mem_region (mem_addr, 16, depca_string))
+ return unknown;
/* Copy the first 16 bytes of ROM */
- ptr = ioremap(paddr + 0xc000, 16);
+
+ ptr = ioremap(prom_addr, 16);
if (ptr == NULL) {
- printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr + 0xc000);
- adapter = unknown;
- return;
+ printk(KERN_ERR "depca: I/O remap failed at %lx\n", prom_addr);
+ return unknown;
}
for (i = 0; i < 16; i++) {
tmpstr[i] = readb(ptr + i);
}
iounmap(ptr);
+ release_mem_region (mem_addr, 16);
+
/* Check if PROM contains a valid string */
- for (i = 0; *signatures[i] != '\0'; i++) {
- for (j = 0, k = 0; j < 16 && k < strlen(signatures[i]); j++) {
- if (signatures[i][k] == tmpstr[j]) { /* track signature */
+ for (i = 0; *depca_signature[i] != '\0'; i++) {
+ for (j = 0, k = 0; j < 16 && k < strlen(depca_signature[i]); j++) {
+ if (depca_signature[i][k] == tmpstr[j]) { /* track signature */
k++;
} else { /* lost signature; begin search again */
k = 0;
}
}
- if (k == strlen(signatures[i]))
+ if (k == strlen(depca_signature[i]))
break;
}
/* Check if name string is valid, provided there's no PROM */
- if (*name && (i == unknown)) {
- for (i = 0; *signatures[i] != '\0'; i++) {
- if (strcmp(name, signatures[i]) == 0)
+ if (name && *name && (i == unknown)) {
+ for (i = 0; *depca_signature[i] != '\0'; i++) {
+ if (strcmp(name, depca_signature[i]) == 0)
break;
}
}
- /* Update search results */
- strcpy(name, signatures[i]);
- adapter = i;
-
- return;
+ return i;
}
/*
@@ -1773,10 +1769,11 @@ static int __init DevicePresent(u_long ioaddr)
static int __init get_hw_addr(struct net_device *dev)
{
u_long ioaddr = dev->base_addr;
+ struct depca_private *lp = dev->priv;
int i, k, tmp, status = 0;
u_short j, x, chksum;
- x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);
+ x = (((lp->adapter == de100) || (lp->adapter == de101)) ? 1 : 0);
for (i = 0, k = 0, j = 0; j < 3; j++) {
k <<= 1;
@@ -2083,55 +2080,40 @@ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return status;
}
-#ifdef MODULE
-static struct net_device thisDepca;
-static int irq = 7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */
-static int io = 0x200; /* Or use the irq= io= options to insmod */
-MODULE_PARM(irq, "i");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(irq, "DEPCA IRQ number");
-MODULE_PARM_DESC(io, "DEPCA I/O base address");
-
-/* See depca_probe() for autoprobe messages when a module */
-int init_module(void)
+static int __init depca_module_init (void)
{
- thisDepca.irq = irq;
- thisDepca.base_addr = io;
- thisDepca.init = depca_probe;
+ int err = 0;
- if (register_netdev(&thisDepca) != 0)
- return -EIO;
-
- return 0;
+#if CONFIG_MCA
+ err = mca_register_driver (&depca_mca_driver);
+#endif
+#ifdef CONFIG_EISA
+ err |= eisa_driver_register (&depca_eisa_driver);
+#endif
+ err |= driver_register (&depca_isa_driver);
+ depca_platform_probe ();
+
+ return err;
}
-void cleanup_module(void)
+static void __exit depca_module_exit (void)
{
- struct depca_private *lp = thisDepca.priv;
-
- unregister_netdev(&thisDepca);
- if (lp) {
- iounmap(lp->sh_mem);
- release_mem_region (lp->mem_start, lp->mem_len);
-#ifdef CONFIG_MCA
- if (lp->mca_slot != -1)
- mca_mark_as_unused(lp->mca_slot);
+ int i;
+#if CONFIG_MCA
+ mca_unregister_driver (&depca_mca_driver);
#endif
- kfree(lp);
- thisDepca.priv = NULL;
- }
- thisDepca.irq = 0;
+#ifdef CONFIG_EISA
+ eisa_driver_unregister (&depca_eisa_driver);
+#endif
+ driver_unregister (&depca_isa_driver);
- release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
+ for (i = 0; depca_io_ports[i].iobase; i++) {
+ if (depca_io_ports[i].device) {
+ platform_device_unregister (depca_io_ports[i].device);
+ depca_io_ports[i].device = NULL;
+ }
+ }
}
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- *
- * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- * End:
- */
+module_init (depca_module_init);
+module_exit (depca_module_exit);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 4bf0772ee632..168d89fa8cb4 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1536,19 +1536,24 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
struct e1000_buffer *buffer_info;
unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int offset = 0, size, count = 0, i;
+#ifdef NETIF_F_TSO
+ unsigned int mss;
+#endif
+ unsigned int nr_frags;
+ unsigned int f;
#ifdef NETIF_F_TSO
- unsigned int mss = skb_shinfo(skb)->tso_size;
+ mss = skb_shinfo(skb)->tso_size;
/* The controller does a simple calculation to
* make sure there is enough room in the FIFO before
* initiating the DMA for each buffer. The calc is:
* 4 = ceil(buffer len/mss). To make sure we don't
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
- if(mss) max_per_txd = min(mss << 2, max_per_txd);
+ if (mss)
+ max_per_txd = min(mss << 2, max_per_txd);
#endif
- unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
- unsigned int f;
+ nr_frags = skb_shinfo(skb)->nr_frags;
len -= skb->data_len;
i = tx_ring->next_to_use;
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 93a29e4a94a6..a9a45c144b81 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -897,14 +897,12 @@ static int eepro_grab_irq(struct net_device *dev)
eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != EBUSY) {
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
/* Twinkle the interrupt, and check if it's seen */
irq_mask = probe_irq_on();
eepro_diag(ioaddr); /* RESET the 82595 */
-
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
if (*irqp == probe_irq_off(irq_mask)) /* It's a good IRQ line */
break;
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index bc2402359aee..af7e100facc1 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -564,7 +564,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
if (dev->irq < 2) {
#ifndef MODULE
u_char irqnum;
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
irq_mask = probe_irq_on();
@@ -578,8 +578,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
irqnum = irq[((icr & IRQ_SEL) >> 4)];
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
dev->irq = probe_irq_off(irq_mask);
if ((dev->irq) && (irqnum == dev->irq)) {
printk(" and uses IRQ%d.\n", dev->irq);
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index f36ba3e63c7c..14e472b5dfae 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -68,7 +68,6 @@
/*****************************************************************************/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index dc69693d7f21..17dc08f263c3 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -71,7 +71,6 @@
/*****************************************************************************/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/string.h>
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index 50b5a38afb9d..daf34e2361ce 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -61,7 +61,6 @@
/*****************************************************************************/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/string.h>
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 980dbbe807f5..c05577280b56 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -43,7 +43,6 @@
/*****************************************************************************/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/net.h>
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index bc0cca8c8463..cee45d0cebbf 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -171,6 +171,7 @@
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <net/ax25.h>
@@ -202,8 +203,8 @@ static void scc_key_trx (struct scc_channel *scc, char tx);
static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void scc_init_timer(struct scc_channel *scc);
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev);
-static int scc_net_init(struct net_device *dev);
+static int scc_net_alloc(const char *name, struct scc_channel *scc);
+static void scc_net_setup(struct net_device *dev);
static int scc_net_open(struct net_device *dev);
static int scc_net_close(struct net_device *dev);
static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
@@ -235,7 +236,7 @@ static io_port Vector_Latch;
/* These provide interrupt save 2-step access to the Z8530 registers */
-static spinlock_t iolock; /* Guards paired accesses */
+static spinlock_t iolock = SPIN_LOCK_UNLOCKED; /* Guards paired accesses */
static inline unsigned char InReg(io_port port, unsigned char reg)
{
@@ -1512,34 +1513,28 @@ static void z8530_init(void)
* Allocate device structure, err, instance, and register driver
*/
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev)
+static int scc_net_alloc(const char *name, struct scc_channel *scc)
{
+ int err;
struct net_device *dev;
- if (dev_get(name))
- {
- printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
- return -EEXIST;
- }
-
- if ((scc->dev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL)
+ dev = alloc_netdev(0, name, scc_net_setup);
+ if (!dev)
return -ENOMEM;
- dev = scc->dev;
- memset(dev, 0, sizeof(struct net_device));
-
- strcpy(dev->name, name);
- dev->priv = (void *) scc;
- dev->init = scc_net_init;
-
+ dev->priv = scc;
+ scc->dev = dev;
spin_lock_init(&scc->lock);
-
- if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0) {
- kfree(dev);
- return -EIO;
- }
- SET_MODULE_OWNER(dev);
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR "%s: can't register network device (%d)\n",
+ name, err);
+ free_netdev(dev);
+ scc->dev = NULL;
+ return err;
+ }
+
return 0;
}
@@ -1556,8 +1551,9 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] =
/* ----> Initialize device <----- */
-static int scc_net_init(struct net_device *dev)
+static void scc_net_setup(struct net_device *dev)
{
+ SET_MODULE_OWNER(dev);
dev->tx_queue_len = 16; /* should be enough... */
dev->open = scc_net_open;
@@ -1581,7 +1577,6 @@ static int scc_net_init(struct net_device *dev)
dev->mtu = AX25_DEF_PACLEN;
dev->addr_len = AX25_ADDR_LEN;
- return 0;
}
/* ----> open network device <---- */
@@ -1719,10 +1714,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct scc_mem_config memcfg;
struct scc_hw_config hwcfg;
struct scc_calibrate cal;
+ struct scc_channel *scc;
int chan;
- unsigned char device_name[10];
+ unsigned char device_name[IFNAMSIZ];
void *arg;
- struct scc_channel *scc;
scc = (struct scc_channel *) dev->priv;
arg = (void *) ifr->ifr_data;
@@ -1828,8 +1823,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
- if (Nchips+chan != 0)
- scc_net_setup(&SCC_Info[2*Nchips+chan], device_name, 1);
+ if (Nchips+chan != 0 &&
+ scc_net_alloc(device_name,
+ &SCC_Info[2*Nchips+chan]))
+ return -EINVAL;
}
}
@@ -1978,39 +1975,58 @@ static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
/* * dump statistics to /proc/net/z8530drv * */
/* ******************************************************************** */
+#ifdef CONFIG_PROC_FS
-static int scc_net_get_info(char *buffer, char **start, off_t offset, int length)
+static inline struct scc_channel *scc_net_seq_idx(loff_t pos)
{
- struct scc_channel *scc;
- struct scc_kiss *kiss;
- struct scc_stat *stat;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
int k;
- len += sprintf(buffer, "z8530drv-"VERSION"\n");
-
- if (!Driver_Initialized)
- {
- len += sprintf(buffer+len, "not initialized\n");
- goto done;
+ for (k = 0; k < Nchips*2; ++k) {
+ if (!SCC_Info[k].init)
+ continue;
+ if (pos-- == 0)
+ return &SCC_Info[k];
}
+ return NULL;
+}
- if (!Nchips)
- {
- len += sprintf(buffer+len, "chips missing\n");
- goto done;
+static void *scc_net_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos ? scc_net_seq_idx(*pos - 1) : SEQ_START_TOKEN;
+
+}
+
+static void *scc_net_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ unsigned k;
+ struct scc_channel *scc = v;
+ ++*pos;
+
+ for (k = (v == SEQ_START_TOKEN) ? 0 : (scc - SCC_Info)+1;
+ k < Nchips*2; ++k) {
+ if (SCC_Info[k].init)
+ return &SCC_Info[k];
}
+ return NULL;
+}
- for (k = 0; k < Nchips*2; k++)
- {
- scc = &SCC_Info[k];
- stat = &scc->stat;
- kiss = &scc->kiss;
+static void scc_net_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int scc_net_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(seq, "z8530drv-"VERSION"\n");
+ } else if (!Driver_Initialized) {
+ seq_puts(seq, "not initialized\n");
+ } else if (!Nchips) {
+ seq_puts(seq, "chips missing\n");
+ } else {
+ const struct scc_channel *scc = v;
+ const struct scc_stat *stat = &scc->stat;
+ const struct scc_kiss *kiss = &scc->kiss;
- if (!scc->init)
- continue;
/* dev data ctrl irq clock brand enh vector special option
* baud nrz clocksrc softdcd bufsize
@@ -2021,24 +2037,24 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length
* R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
*/
- len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
+ seq_printf(seq, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
scc->dev->name,
scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
scc->enhanced, Vector_Latch, scc->special,
scc->option);
- len += sprintf(buffer+len, "\t%lu %d %d %d %d\n",
+ seq_printf(seq, "\t%lu %d %d %d %d\n",
scc->modem.speed, scc->modem.nrz,
scc->modem.clocksrc, kiss->softdcd,
stat->bufsize);
- len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n",
+ seq_printf(seq, "\t%lu %lu %lu %lu\n",
stat->rxints, stat->txints, stat->exints, stat->spints);
- len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
+ seq_printf(seq, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
stat->rxframes, stat->rxerrs, stat->rx_over,
stat->txframes, stat->txerrs, stat->tx_under,
stat->nospace, stat->tx_state);
#define K(x) kiss->x
- len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
+ seq_printf(seq, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
K(txdelay), K(persist), K(slottime), K(tailtime),
K(fulldup), K(waittime), K(mintime), K(maxkeyup),
K(idletime), K(maxdefer), K(tx_inhibit), K(group));
@@ -2047,43 +2063,49 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length
{
int reg;
- len += sprintf(buffer+len, "\tW ");
+ seq_printf(seq, "\tW ");
for (reg = 0; reg < 16; reg++)
- len += sprintf(buffer+len, "%2.2x ", scc->wreg[reg]);
- len += sprintf(buffer+len, "\n");
+ seq_printf(seq, "%2.2x ", scc->wreg[reg]);
+ seq_printf(seq, "\n");
- len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
+ seq_printf(seq, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
for (reg = 3; reg < 8; reg++)
- len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
- len += sprintf(buffer+len, "XX ");
+ seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
+ seq_printf(seq, "XX ");
for (reg = 9; reg < 16; reg++)
- len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
- len += sprintf(buffer+len, "\n");
+ seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
+ seq_printf(seq, "\n");
}
#endif
- len += sprintf(buffer+len, "\n");
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length)
- break;
+ seq_putc(seq, '\n');
}
-done:
+ return 0;
+}
- *start = buffer + (offset - begin);
- len -= (offset - begin);
+static struct seq_operations scc_net_seq_ops = {
+ .start = scc_net_seq_start,
+ .next = scc_net_seq_next,
+ .stop = scc_net_seq_stop,
+ .show = scc_net_seq_show,
+};
- if (len > length) len = length;
- return len;
+static int scc_net_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &scc_net_seq_ops);
}
+static struct file_operations scc_net_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = scc_net_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+#endif /* CONFIG_PROC_FS */
+
/* ******************************************************************** */
/* * Init SCC driver * */
@@ -2091,23 +2113,18 @@ done:
static int __init scc_init_driver (void)
{
- int result;
- char devname[10];
+ char devname[IFNAMSIZ];
printk(banner);
- spin_lock_init(&iolock);
-
sprintf(devname,"%s0", SCC_DriverName);
- result = scc_net_setup(SCC_Info, devname, 0);
- if (result)
- {
+ if (scc_net_alloc(devname, SCC_Info)) {
printk(KERN_ERR "z8530drv: cannot initialize module\n");
- return result;
+ return -EIO;
}
- proc_net_create("z8530drv", 0, scc_net_get_info);
+ proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
return 0;
}
@@ -2117,11 +2134,12 @@ static void __exit scc_cleanup_driver(void)
io_port ctrl;
int k;
struct scc_channel *scc;
+ struct net_device *dev;
- if (Nchips == 0)
+ if (Nchips == 0 && (dev = SCC_Info[0].dev))
{
- unregister_netdev(SCC_Info[0].dev);
- free_netdev(SCC_Info[0].dev);
+ unregister_netdev(dev);
+ free_netdev(dev);
}
/* Guard against chip prattle */
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index e7046c031bb5..58c0a07039e2 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -74,7 +74,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/version.h>
#include <asm/uaccess.h>
#include <linux/init.h>
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 15f1460cb5c3..9c846746e921 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -74,7 +74,6 @@ History:
*************************************************************************/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index ca62b7cec493..12547d2d2d7f 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -254,18 +254,6 @@ config WINBOND_FIR
<file:Documentation/modules.txt>. The module will be called
w83977af_ir.
-config TOSHIBA_OLD
- tristate "Toshiba Type-O IR Port (old driver)"
- depends on IRDA && BROKEN_ON_SMP
- help
- Say Y here if you want to build support for the Toshiba Type-O IR
- chipset. This chipset is used by the Toshiba Libretto 100CT, and
- many more laptops. This driver is obsolete, will no more be
- maintained and will be removed in favor of the new driver.
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>.
- The module will be called toshoboe.
-
config TOSHIBA_FIR
tristate "Toshiba Type-O IR Port"
depends on IRDA
@@ -281,18 +269,6 @@ config AU1000_FIR
tristate "Alchemy Au1000 SIR/FIR"
depends on MIPS_AU1000 && IRDA
-config SMC_IRCC_OLD
- tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
- depends on EXPERIMENTAL && IRDA && ISA
- help
- Say Y here if you want to build support for the SMC Infrared
- Communications Controller. It is used in the Fujitsu Lifebook 635t
- and Sony PCG-505TX. This driver is obsolete, will no more be
- maintained and will be removed in favor of the new driver.
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. The module will be
- called smc-ircc.
-
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA && ISA
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index a05395e2dcd1..c0a59b3855c8 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -12,9 +12,7 @@ obj-$(CONFIG_USB_IRDA) += irda-usb.o
obj-$(CONFIG_NSC_FIR) += nsc-ircc.o
obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o
-obj-$(CONFIG_TOSHIBA_OLD) += toshoboe.o
obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o
-obj-$(CONFIG_SMC_IRCC_OLD) += smc-ircc.o irport.o
obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index c4866c84fbc0..380f6488745b 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -89,7 +89,6 @@ static int ali_ircc_close(struct ali_ircc_cb *self);
static int ali_ircc_setup(chipio_t *info);
static int ali_ircc_is_receiving(struct ali_ircc_cb *self);
-static int ali_ircc_net_init(struct net_device *dev);
static int ali_ircc_net_open(struct net_device *dev);
static int ali_ircc_net_close(struct net_device *dev);
static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -255,14 +254,14 @@ static int ali_ircc_open(int i, chipio_t *info)
if ((ali_ircc_setup(info)) == -1)
return -1;
- /* Allocate new instance of the driver */
- self = kmalloc(sizeof(struct ali_ircc_cb), GFP_KERNEL);
- if (self == NULL)
- {
+ dev = alloc_netdev(sizeof(*self), "irda%d", irda_device_setup);
+ if (dev == NULL) {
ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
return -ENOMEM;
}
- memset(self, 0, sizeof(struct ali_ircc_cb));
+
+ self = dev->priv;
+ self->netdev = dev;
spin_lock_init(&self->lock);
/* Need to store self somewhere */
@@ -282,9 +281,8 @@ static int ali_ircc_open(int i, chipio_t *info)
if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
self->io.fir_base);
- dev_self[i] = NULL;
- kfree(self);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_out1;
}
/* Initialize QoS for this device */
@@ -307,19 +305,17 @@ static int ali_ircc_open(int i, chipio_t *info)
/* Allocate memory if needed */
self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
GFP_KERNEL |GFP_DMA);
- if (self->rx_buff.head == NULL)
- {
- kfree(self);
- return -ENOMEM;
+ if (self->rx_buff.head == NULL) {
+ err = -ENOMEM;
+ goto err_out2;
}
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL|GFP_DMA);
if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out3;
}
memset(self->tx_buff.head, 0, self->tx_buff.truesize);
@@ -332,28 +328,21 @@ static int ali_ircc_open(int i, chipio_t *info)
self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
self->tx_fifo.tail = self->tx_buff.head;
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
- return -ENOMEM;
- }
-
- dev->priv = (void *) self;
- self->netdev = dev;
+ /* Keep track of module usage */
+ SET_MODULE_OWNER(dev);
+
/* Override the network functions we need to use */
- dev->init = ali_ircc_net_init;
dev->hard_start_xmit = ali_ircc_sir_hard_xmit;
dev->open = ali_ircc_net_open;
dev->stop = ali_ircc_net_close;
dev->do_ioctl = ali_ircc_net_ioctl;
dev->get_stats = ali_ircc_net_get_stats;
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
+ err = register_netdev(dev);
if (err) {
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
- return -1;
+ goto err_out4;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
@@ -370,6 +359,17 @@ static int ali_ircc_open(int i, chipio_t *info)
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0;
+
+ err_out4:
+ kfree(self->tx_buff.head);
+ err_out3:
+ kfree(self->rx_buff.head);
+ err_out2:
+ release_region(self->io.fir_base, self->io.fir_ext);
+ err_out1:
+ dev_self[i] = NULL;
+ free_netdev(dev);
+ return err;
}
@@ -390,8 +390,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
iobase = self->io.fir_base;
/* Remove netdevice */
- if (self->netdev)
- unregister_netdev(self->netdev);
+ unregister_netdev(self->netdev);
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", __FUNCTION__, self->io.fir_base);
@@ -404,7 +403,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
kfree(self->rx_buff.head);
dev_self[self->index] = NULL;
- kfree(self);
+ free_netdev(self->netdev);
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
@@ -1291,29 +1290,6 @@ static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
}
/*
- * Function ali_ircc_net_init (dev)
- *
- * Initialize network device
- *
- */
-static int ali_ircc_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );
-
- return 0;
-}
-
-/*
* Function ali_ircc_net_open (dev)
*
* Start the device
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index db20dcc0ef7b..11ff089e616b 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1396,20 +1396,6 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<');
return IRQ_HANDLED;
}
-static int
-toshoboe_net_init (struct net_device *dev)
-{
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup (dev);
-
- /* Insert overrides below this line! */
- return 0;
-}
static int
toshoboe_net_open (struct net_device *dev)
@@ -1589,14 +1575,13 @@ toshoboe_close (struct pci_dev *pci_dev)
self->rx_bufs[i] = NULL;
}
- if (self->netdev)
- unregister_netdev(self->netdev);
+ unregister_netdev(self->netdev);
kfree (self->ringbuf);
self->ringbuf = NULL;
self->ring = NULL;
- return;
+ free_netdev(self->netdev);
}
static int
@@ -1613,17 +1598,17 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
if ((err=pci_enable_device(pci_dev)))
return err;
- self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
-
- if (self == NULL)
+ dev = alloc_netdev(sizeof (struct toshoboe_cb), "irda%d",
+ irda_device_setup);
+ if (dev == NULL)
{
printk (KERN_ERR DRIVER_NAME ": can't allocate memory for "
"IrDA control block\n");
return -ENOMEM;
}
- memset (self, 0, sizeof (struct toshoboe_cb));
-
+ self = dev->priv;
+ self->netdev = dev;
self->pdev = pci_dev;
self->base = pci_resource_start(pci_dev,0);
@@ -1732,33 +1717,20 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
}
#endif
- if (!(dev = dev_alloc ("irda%d", &err)))
- {
- printk (KERN_ERR DRIVER_NAME ": dev_alloc() failed\n");
- err = -ENOMEM;
- goto freebufs;
- }
-
- dev->priv = (void *) self;
- self->netdev = dev;
-
- printk (KERN_INFO "IrDA: Registered device %s\n", dev->name);
-
- dev->init = toshoboe_net_init;
+ SET_MODULE_OWNER(dev);
dev->hard_start_xmit = toshoboe_hard_xmit;
dev->open = toshoboe_net_open;
dev->stop = toshoboe_net_close;
dev->do_ioctl = toshoboe_net_ioctl;
- rtnl_lock ();
- err = register_netdevice (dev);
- rtnl_unlock ();
+ err = register_netdev(dev);
if (err)
{
printk (KERN_ERR DRIVER_NAME ": register_netdev() failed\n");
err = -ENOMEM;
goto freebufs;
}
+ printk (KERN_INFO "IrDA: Registered device %s\n", dev->name);
pci_set_drvdata(pci_dev,self);
@@ -1779,7 +1751,7 @@ freeregion:
release_region (self->io.fir_base, self->io.fir_ext);
freeself:
- kfree (self);
+ free_netdev(dev);
return err;
}
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 164f8b32c5f3..4b0c4fde5f37 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -112,7 +112,6 @@ static int irda_usb_close(struct irda_usb_cb *self);
static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
-static int irda_usb_net_init(struct net_device *dev);
static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -901,24 +900,6 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
* be dealt with below...
*/
-/*------------------------------------------------------------------*/
-/*
- * Callback when a new IrDA device is created.
- */
-static int irda_usb_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Set up to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- return 0;
-}
/*------------------------------------------------------------------*/
/*
@@ -1195,15 +1176,18 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
/* Create a network device for us */
- if (!(netdev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
- return -1;
+ netdev = alloc_netdev(0, "irda%d", irda_device_setup);
+ if (!netdev) {
+ ERROR("%s(), alloc_net_dev() failed!\n", __FUNCTION__);
+ return -ENOMEM;
}
+
+ SET_MODULE_OWNER(dev);
+
self->netdev = netdev;
netdev->priv = (void *) self;
/* Override the network functions we need to use */
- netdev->init = irda_usb_net_init;
netdev->hard_start_xmit = irda_usb_hard_xmit;
netdev->tx_timeout = irda_usb_net_timeout;
netdev->watchdog_timeo = 250*HZ/1000; /* 250 ms > USB timeout */
@@ -1212,12 +1196,12 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
netdev->get_stats = irda_usb_net_get_stats;
netdev->do_ioctl = irda_usb_net_ioctl;
- rtnl_lock();
- err = register_netdevice(netdev);
- rtnl_unlock();
+ err = register_netdev(netdev);
if (err) {
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
- return -1;
+ self->netdev = NULL;
+ free_netdev(netdev);
+ return err;
}
MESSAGE("IrDA: Registered device %s\n", netdev->name);
@@ -1236,9 +1220,11 @@ static inline int irda_usb_close(struct irda_usb_cb *self)
ASSERT(self != NULL, return -1;);
/* Remove netdevice */
- if (self->netdev)
+ if (self->netdev) {
unregister_netdev(self->netdev);
- self->netdev = NULL;
+ free_netdev(self->netdev);
+ self->netdev = NULL;
+ }
/* Remove the speed buffer */
if (self->speed_buff != NULL) {
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 11bb1143f23a..af88184cd759 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -143,7 +143,6 @@ static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
static int nsc_ircc_read_dongle_id (int iobase);
static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
-static int nsc_ircc_net_init(struct net_device *dev);
static int nsc_ircc_net_open(struct net_device *dev);
static int nsc_ircc_net_close(struct net_device *dev);
static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -261,14 +260,16 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
- /* Allocate new instance of the driver */
- self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
- if (self == NULL) {
+ dev = alloc_netdev(sizeof(struct nsc_ircc_cb), "irda%d",
+ irda_device_setup);
+ if (dev == NULL) {
ERROR("%s(), can't allocate memory for "
"control block!\n", __FUNCTION__);
return -ENOMEM;
}
- memset(self, 0, sizeof(struct nsc_ircc_cb));
+
+ self = dev->priv;
+ self->netdev = dev;
spin_lock_init(&self->lock);
/* Need to store self somewhere */
@@ -288,9 +289,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
if (!ret) {
WARNING("%s(), can't get iobase of 0x%03x\n",
__FUNCTION__, self->io.fir_base);
- dev_self[i] = NULL;
- kfree(self);
- return -ENODEV;
+ err = -ENODEV;
+ goto out1;
}
/* Initialize QoS for this device */
@@ -313,17 +313,17 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
GFP_KERNEL|GFP_DMA);
if (self->rx_buff.head == NULL) {
- kfree(self);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out2;
+
}
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL|GFP_DMA);
if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out3;
}
memset(self->tx_buff.head, 0, self->tx_buff.truesize);
@@ -336,28 +336,18 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
self->tx_fifo.tail = self->tx_buff.head;
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
- return -ENOMEM;
- }
-
- dev->priv = (void *) self;
- self->netdev = dev;
-
/* Override the network functions we need to use */
- dev->init = nsc_ircc_net_init;
+ SET_MODULE_OWNER(dev);
dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
dev->open = nsc_ircc_net_open;
dev->stop = nsc_ircc_net_close;
dev->do_ioctl = nsc_ircc_net_ioctl;
dev->get_stats = nsc_ircc_net_get_stats;
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
+ err = register_netdev(dev);
if (err) {
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
- return -1;
+ goto out4;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
@@ -380,6 +370,16 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
pmdev->data = self;
return 0;
+ out4:
+ kfree(self->tx_buff.head);
+ out3:
+ kfree(self->rx_buff.head);
+ out2:
+ release_region(self->io.fir_base, self->io.fir_ext);
+ out1:
+ free_netdev(dev);
+ dev_self[i] = NULL;
+ return err;
}
/*
@@ -399,8 +399,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
iobase = self->io.fir_base;
/* Remove netdevice */
- if (self->netdev)
- unregister_netdev(self->netdev);
+ unregister_netdev(self->netdev);
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, "%s(), Releasing Region %03x\n",
@@ -414,7 +413,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
kfree(self->rx_buff.head);
dev_self[self->index] = NULL;
- kfree(self);
+ free_netdev(self->netdev);
return 0;
}
@@ -1991,27 +1990,6 @@ static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
}
/*
- * Function nsc_ircc_net_init (dev)
- *
- * Initialize network device
- *
- */
-static int nsc_ircc_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- return 0;
-}
-
-/*
* Function nsc_ircc_net_open (dev)
*
* Start the device
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index 5e7f455432c2..620b524bd80e 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -132,7 +132,7 @@ static int irda_thread(void *startup)
if (list_empty(&irda_rq_queue.request_list))
schedule();
else
- set_task_state(current, TASK_RUNNING);
+ __set_task_state(current, TASK_RUNNING);
remove_wait_queue(&irda_rq_queue.kick, &wait);
/* make swsusp happy with our thread */
@@ -165,7 +165,7 @@ static void flush_irda_queue(void)
if (atomic_read(&irda_rq_queue.num_pending))
schedule();
else
- set_task_state(current, TASK_RUNNING);
+ __set_task_state(current, TASK_RUNNING);
remove_wait_queue(&irda_rq_queue.done, &wait);
}
}
diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c
deleted file mode 100644
index 91f476547a83..000000000000
--- a/drivers/net/irda/smc-ircc.c
+++ /dev/null
@@ -1,1258 +0,0 @@
-/*********************************************************************
- *
- * Filename: smc-ircc.c
- * Version: 0.4
- * Description: Driver for the SMC Infrared Communications Controller
- * Status: Experimental.
- * Author: Thomas Davis (tadavis@jps.net)
- * Created at:
- * Modified at: Tue Feb 22 10:05:06 2000
- * Modified by: Dag Brattli <dag@brattli.net>
- * Modified at: Tue Jun 26 2001
- * Modified by: Stefani Seibold <stefani@seibold.net>
- * Modified at: Thur Apr 18 2002
- * Modified by: Jeff Snyder <je4d@pobox.com>
- *
- * Copyright (c) 2001 Stefani Seibold
- * Copyright (c) 1999-2001 Dag Brattli
- * Copyright (c) 1998-1999 Thomas Davis,
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * SIO's: all SIO documentet by SMC (June, 2001)
- * Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX,
- * Dell Inspiron 8000
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/rtnetlink.h>
-#include <linux/serial_reg.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-
-#include <linux/pm.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irda_device.h>
-#include <net/irda/smc-ircc.h>
-#include <net/irda/irport.h>
-
-struct smc_chip {
- char *name;
- u16 flags;
- u8 devid;
- u8 rev;
-};
-typedef struct smc_chip smc_chip_t;
-
-static const char *driver_name = "smc-ircc";
-
-#define DIM(x) (sizeof(x)/(sizeof(*(x))))
-
-#define CHIP_IO_EXTENT 8
-
-static struct ircc_cb *dev_self[] = { NULL, NULL};
-
-/* Some prototypes */
-static int ircc_open(unsigned int iobase, unsigned int board_addr);
-static int ircc_dma_receive(struct ircc_cb *self, int iobase);
-static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
-static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs);
-static void ircc_change_speed(void *priv, u32 speed);
-static irqreturn_t ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int ircc_net_open(struct net_device *dev);
-static int ircc_net_close(struct net_device *dev);
-static int ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-#define KEY55_1 0 /* SuperIO Configuration mode with Key <0x55> */
-#define KEY55_2 1 /* SuperIO Configuration mode with Key <0x55,0x55> */
-#define NoIRDA 2 /* SuperIO Chip has no IRDA Port */
-#define SIR 0 /* SuperIO Chip has only slow IRDA */
-#define FIR 4 /* SuperIO Chip has fast IRDA */
-#define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
-
-/* These are the currently known SMC SuperIO chipsets */
-static smc_chip_t __initdata fdc_chips_flat[]=
-{
- /* Base address 0x3f0 or 0x370 */
- { "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip can not detected */
- { "37C665GT", KEY55_2|NoIRDA, 0x65, 0x01 },
- { "37C665GT", KEY55_2|NoIRDA, 0x66, 0x01 },
- { "37C669", KEY55_2|SIR|SERx4, 0x03, 0x02 },
- { "37C669", KEY55_2|SIR|SERx4, 0x04, 0x02 }, /* ID? */
- { "37C78", KEY55_2|NoIRDA, 0x78, 0x00 },
- { "37N769", KEY55_1|FIR|SERx4, 0x28, 0x00 },
- { "37N869", KEY55_1|FIR|SERx4, 0x29, 0x00 },
- { NULL }
-};
-
-static smc_chip_t __initdata fdc_chips_paged[]=
-{
- /* Base address 0x3f0 or 0x370 */
- { "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 },
- { "37B77X", KEY55_1|SIR|SERx4, 0x43, 0x00 },
- { "37B78X", KEY55_1|SIR|SERx4, 0x44, 0x00 },
- { "37B80X", KEY55_1|SIR|SERx4, 0x42, 0x00 },
- { "37C67X", KEY55_1|FIR|SERx4, 0x40, 0x00 },
- { "37C93X", KEY55_2|SIR|SERx4, 0x02, 0x01 },
- { "37C93XAPM", KEY55_1|SIR|SERx4, 0x30, 0x01 },
- { "37C93XFR", KEY55_2|FIR|SERx4, 0x03, 0x01 },
- { "37M707", KEY55_1|SIR|SERx4, 0x42, 0x00 },
- { "37M81X", KEY55_1|SIR|SERx4, 0x4d, 0x00 },
- { "37N958FR", KEY55_1|FIR|SERx4, 0x09, 0x04 },
- { "37N971", KEY55_1|FIR|SERx4, 0x0a, 0x00 },
- { "37N972", KEY55_1|FIR|SERx4, 0x0b, 0x00 },
- { NULL }
-};
-
-static smc_chip_t __initdata lpc_chips_flat[]=
-{
- /* Base address 0x2E or 0x4E */
- { "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 },
- { "47N267", KEY55_1|FIR|SERx4, 0x5e, 0x00 },
- { NULL }
-};
-
-static smc_chip_t __initdata lpc_chips_paged[]=
-{
- /* Base address 0x2E or 0x4E */
- { "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 },
- { "47B37X", KEY55_1|SIR|SERx4, 0x52, 0x00 },
- { "47M10X", KEY55_1|SIR|SERx4, 0x59, 0x00 },
- { "47M120", KEY55_1|NoIRDA|SERx4, 0x5c, 0x00 },
- { "47M13X", KEY55_1|SIR|SERx4, 0x59, 0x00 },
- { "47M14X", KEY55_1|SIR|SERx4, 0x5f, 0x00 },
- { "47N252", KEY55_1|FIR|SERx4, 0x0e, 0x00 },
- { "47S42X", KEY55_1|SIR|SERx4, 0x57, 0x00 },
- { NULL }
-};
-
-static int ircc_irq=255;
-static int ircc_dma=255;
-static int ircc_fir=0;
-static int ircc_sir=0;
-static int ircc_cfg=0;
-
-static unsigned short dev_count=0;
-
-static inline void register_bank(int iobase, int bank)
-{
- outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
- iobase+IRCC_MASTER);
-}
-
-static int __init smc_access(unsigned short cfg_base,unsigned char reg)
-{
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-
- outb(reg, cfg_base);
-
- if (inb(cfg_base)!=reg)
- return -1;
-
- return 0;
-}
-
-static const smc_chip_t * __init smc_probe(unsigned short cfg_base,u8 reg,const smc_chip_t *chip,char *type)
-{
- u8 devid,xdevid,rev;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-
- /* Leave configuration */
-
- outb(0xaa, cfg_base);
-
- if (inb(cfg_base)==0xaa) /* not a smc superio chip */
- return NULL;
-
- outb(reg, cfg_base);
-
- xdevid=inb(cfg_base+1);
-
- /* Enter configuration */
-
- outb(0x55, cfg_base);
-
- if (smc_access(cfg_base,0x55)) /* send second key and check */
- return NULL;
-
- /* probe device ID */
-
- if (smc_access(cfg_base,reg))
- return NULL;
-
- devid=inb(cfg_base+1);
-
- if (devid==0) /* typical value for unused port */
- return NULL;
-
- if (devid==0xff) /* typical value for unused port */
- return NULL;
-
- /* probe revision ID */
-
- if (smc_access(cfg_base,reg+1))
- return NULL;
-
- rev=inb(cfg_base+1);
-
- if (rev>=128) /* i think this will make no sense */
- return NULL;
-
- if (devid==xdevid) /* protection against false positives */
- return NULL;
-
- /* Check for expected device ID; are there others? */
-
- while(chip->devid!=devid) {
-
- chip++;
-
- if (chip->name==NULL)
- return NULL;
- }
- if (chip->rev>rev)
- return NULL;
-
- MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
-
- if (chip->flags&NoIRDA)
- MESSAGE("chipset does not support IRDA\n");
-
- return chip;
-}
-
-/*
- * Function smc_superio_flat (chip, base, type)
- *
- * Try get configuration of a smc SuperIO chip with flat register model
- *
- */
-static int __init smc_superio_flat(const smc_chip_t *chips, unsigned short cfg_base, char *type)
-{
- unsigned short fir_io;
- unsigned short sir_io;
- u8 mode;
- int ret = -ENODEV;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-
- if (smc_probe(cfg_base,0xD,chips,type)==NULL)
- return ret;
-
- outb(0x0c, cfg_base);
-
- mode = inb(cfg_base+1);
- mode = (mode & 0x38) >> 3;
-
- /* Value for IR port */
- if (mode && mode < 4) {
- /* SIR iobase */
- outb(0x25, cfg_base);
- sir_io = inb(cfg_base+1) << 2;
-
- /* FIR iobase */
- outb(0x2b, cfg_base);
- fir_io = inb(cfg_base+1) << 3;
-
- if (fir_io) {
- if (ircc_open(fir_io, sir_io) == 0)
- ret=0;
- }
- }
-
- /* Exit configuration */
- outb(0xaa, cfg_base);
-
- return ret;
-}
-
-/*
- * Function smc_superio_paged (chip, base, type)
- *
- * Try get configuration of a smc SuperIO chip with paged register model
- *
- */
-static int __init smc_superio_paged(const smc_chip_t *chips, unsigned short cfg_base, char *type)
-{
- unsigned short fir_io;
- unsigned short sir_io;
- int ret = -ENODEV;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-
- if (smc_probe(cfg_base,0x20,chips,type)==NULL)
- return ret;
-
- /* Select logical device (UART2) */
- outb(0x07, cfg_base);
- outb(0x05, cfg_base + 1);
-
- /* SIR iobase */
- outb(0x60, cfg_base);
- sir_io = inb(cfg_base + 1) << 8;
- outb(0x61, cfg_base);
- sir_io |= inb(cfg_base + 1);
-
- /* Read FIR base */
- outb(0x62, cfg_base);
- fir_io = inb(cfg_base + 1) << 8;
- outb(0x63, cfg_base);
- fir_io |= inb(cfg_base + 1);
- outb(0x2b, cfg_base); /* ??? */
-
- if (fir_io) {
- if (ircc_open(fir_io, sir_io) == 0)
- ret=0;
- }
-
- /* Exit configuration */
- outb(0xaa, cfg_base);
-
- return ret;
-}
-
-static int __init smc_superio_fdc(unsigned short cfg_base)
-{
- if (check_region(cfg_base, 2) < 0) {
- IRDA_DEBUG(0, "%s: can't get cfg_base of 0x%03x\n", __FUNCTION__ ,
- cfg_base);
- return -1;
- }
-
- if (!smc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
- return 0;
-
- return -1;
-}
-
-static int __init smc_superio_lpc(unsigned short cfg_base)
-{
-#if 0
- if (check_region(cfg_base, 2) < 0) {
- IRDA_DEBUG(0, "%s: can't get cfg_base of 0x%03x\n", __FUNCTION__ ,
- cfg_base);
- return -1;
- }
-#endif
-
- if (!smc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
- return 0;
-
- return -1;
-}
-
-/*
- * Function ircc_init ()
- *
- * Initialize chip. Just try to find out how many chips we are dealing with
- * and where they are
- */
-int __init ircc_init(void)
-{
- int ret=-ENODEV;
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- dev_count=0;
-
- if ((ircc_fir>0)&&(ircc_sir>0)) {
- MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
- MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
-
- if (ircc_open(ircc_fir, ircc_sir) == 0)
- return 0;
-
- return -ENODEV;
- }
-
- /* try user provided configuration register base address */
- if (ircc_cfg>0) {
- MESSAGE(" Overriding configuration address 0x%04x\n", ircc_cfg);
- if (!smc_superio_fdc(ircc_cfg))
- ret=0;
- }
-
- /* Trys to open for all the SMC chipsets we know about */
-
- IRDA_DEBUG(0,
- "%s Try to open all known SMC chipsets\n", __FUNCTION__ );
-
- if (!smc_superio_fdc(0x3f0))
- ret=0;
- if (!smc_superio_fdc(0x370))
- ret=0;
- if (!smc_superio_fdc(0xe0))
- ret=0;
- if (!smc_superio_lpc(0x2e))
- ret=0;
- if (!smc_superio_lpc(0x4e))
- ret=0;
-
- return ret;
-}
-
-/*
- * Function ircc_open (iobase, irq)
- *
- * Try to open driver instance
- *
- */
-static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
-{
- struct ircc_cb *self;
- struct irport_cb *irport;
- unsigned char low, high, chip, config, dma, irq, version;
- unsigned long flags;
-
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- if (check_region(fir_base, CHIP_IO_EXTENT) < 0) {
- IRDA_DEBUG(0, "%s: can't get fir_base of 0x%03x\n", __FUNCTION__ ,
- fir_base);
- return -ENODEV;
- }
-#if POSSIBLE_USED_BY_SERIAL_DRIVER
- if (check_region(sir_base, CHIP_IO_EXTENT) < 0) {
- IRDA_DEBUG(0, "%s: can't get sir_base of 0x%03x\n", __FUNCTION__ ,
- sir_base);
- return -ENODEV;
- }
-#endif
-
- register_bank(fir_base, 3);
-
- high = inb(fir_base+IRCC_ID_HIGH);
- low = inb(fir_base+IRCC_ID_LOW);
- chip = inb(fir_base+IRCC_CHIP_ID);
- version = inb(fir_base+IRCC_VERSION);
- config = inb(fir_base+IRCC_INTERFACE);
-
- irq = config >> 4 & 0x0f;
- dma = config & 0x0f;
-
- if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
- IRDA_DEBUG(0,
- "%s(), addr 0x%04x - no device found!\n", __FUNCTION__ , fir_base);
- return -ENODEV;
- }
- MESSAGE("SMC IrDA Controller found\n IrCC version %d.%d, "
- "firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
- chip & 0x0f, version, fir_base, sir_base, dma, irq);
-
- if (dev_count >= DIM(dev_self)) {
- IRDA_DEBUG(0,
- "%s(), to many devices!\n", __FUNCTION__ );
- return -ENOMEM;
- }
-
- /*
- * Allocate new instance of the driver
- */
- self = kmalloc(sizeof(struct ircc_cb), GFP_KERNEL);
- if (self == NULL) {
- ERROR("%s, Can't allocate memory for control block!\n",
- driver_name);
- return -ENOMEM;
- }
- memset(self, 0, sizeof(struct ircc_cb));
-
- /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
- self->rx_buff.truesize = 4000;
- self->tx_buff.truesize = 4000;
-
- self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL) {
- ERROR("%s, Can't allocate memory for receive buffer!\n",
- driver_name);
- kfree(self);
- return -ENOMEM;
- }
-
- self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->tx_buff.head == NULL) {
- ERROR("%s, Can't allocate memory for transmit buffer!\n",
- driver_name);
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENOMEM;
- }
-
- irport = irport_open(dev_count, sir_base, irq);
- if (!irport) {
- kfree(self->tx_buff.head);
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENODEV;
- }
-
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
-
- /* Need to store self somewhere */
- dev_self[dev_count++] = self;
-
- /* Steal the network device from irport */
- self->netdev = irport->netdev;
- self->irport = irport;
-
- irport->priv = self;
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(self->netdev);
-
- /* Initialize IO */
- self->io = &irport->io;
- self->io->fir_base = fir_base;
- self->io->sir_base = sir_base; /* Used by irport */
- self->io->fir_ext = CHIP_IO_EXTENT;
- self->io->sir_ext = 8; /* Used by irport */
-
- if (ircc_irq < 255) {
- if (ircc_irq!=irq)
- MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
- driver_name, irq, ircc_irq);
- self->io->irq = ircc_irq;
- }
- else
- self->io->irq = irq;
- if (ircc_dma < 255) {
- if (ircc_dma!=dma)
- MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
- driver_name, dma, ircc_dma);
- self->io->dma = ircc_dma;
- }
- else
- self->io->dma = dma;
-
- request_region(self->io->fir_base, CHIP_IO_EXTENT, driver_name);
-
- /* Don't allow irport to change under us - Jean II */
- spin_lock_irqsave(&self->irport->lock, flags);
-
- /* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&irport->qos);
-
- /* The only value we must override it the baudrate */
- irport->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
- IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-
- irport->qos.min_turn_time.bits = 0x07;
- irport->qos.window_size.bits = 0x01;
- irda_qos_bits_to_value(&irport->qos);
-
- irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
-
-
- self->rx_buff.in_frame = FALSE;
- self->rx_buff.state = OUTSIDE_FRAME;
- self->tx_buff.data = self->tx_buff.head;
- self->rx_buff.data = self->rx_buff.head;
-
- /* Override the speed change function, since we must control it now */
- irport->change_speed = &ircc_change_speed;
- irport->interrupt = &ircc_interrupt;
- self->netdev->open = &ircc_net_open;
- self->netdev->stop = &ircc_net_close;
-
- irport_start(self->irport);
- spin_unlock_irqrestore(&self->irport->lock, flags);
-
- self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ircc_pmproc);
- if (self->pmdev)
- self->pmdev->data = self;
-
- /* Power on device */
-
- outb(0x00, fir_base+IRCC_MASTER);
-
- return 0;
-}
-
-/*
- * Function ircc_change_speed (self, baud)
- *
- * Change the speed of the device
- *
- * This function should be called with irq off and spin-lock.
- */
-static void ircc_change_speed(void *priv, u32 speed)
-{
- int iobase, ir_mode, ctrl, fast;
- struct ircc_cb *self = (struct ircc_cb *) priv;
- struct net_device *dev;
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- ASSERT(self != NULL, return;);
-
- dev = self->netdev;
- iobase = self->io->fir_base;
-
- /* Update accounting for new speed */
- self->io->speed = speed;
-
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
-
- switch (speed) {
- default:
- IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", __FUNCTION__ ,
- speed);
- /* FALLTHROUGH */
- case 9600:
- case 19200:
- case 38400:
- case 57600:
- case 115200:
- ir_mode = IRCC_CFGA_IRDA_SIR_A;
- ctrl = 0;
- fast = 0;
- break;
- case 576000:
- ir_mode = IRCC_CFGA_IRDA_HDLC;
- ctrl = IRCC_CRC;
- fast = 0;
- IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__ );
- break;
- case 1152000:
- ir_mode = IRCC_CFGA_IRDA_HDLC;
- ctrl = IRCC_1152 | IRCC_CRC;
- fast = 0;
- IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __FUNCTION__ );
- break;
- case 4000000:
- ir_mode = IRCC_CFGA_IRDA_4PPM;
- ctrl = IRCC_CRC;
- fast = IRCC_LCR_A_FAST;
- IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __FUNCTION__ );
- break;
- }
-
- register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
- /* Make special FIR init if necessary */
- if (speed > 115200) {
- /* No need to lock, already locked - Jean II */
- irport_stop(self->irport);
-
- /* Install FIR transmit handler */
- dev->hard_start_xmit = &ircc_hard_xmit;
-
- /*
- * Don't know why we have to do this, but FIR interrupts
- * stops working if we remove it.
- */
- /* outb(UART_MCR_OUT2, self->io->sir_base + UART_MCR); */
-
- /* Be ready for incoming frames */
- ircc_dma_receive(self, iobase);
- } else {
- /* Install SIR transmit handler */
- dev->hard_start_xmit = &irport_hard_xmit;
- /* No need to lock, already locked - Jean II */
- irport_start(self->irport);
-
- IRDA_DEBUG(0,
- "%s(), using irport to change speed to %d\n", __FUNCTION__ , speed);
- irport_change_speed(self->irport, speed);
- }
-
- register_bank(iobase, 1);
- outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode),
- iobase+IRCC_SCE_CFGA);
-
-#ifdef SMC_669 /* Uses pin 88/89 for Rx/Tx */
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
- iobase+IRCC_SCE_CFGB);
-#else
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
- iobase+IRCC_SCE_CFGB);
-#endif
- (void) inb(iobase+IRCC_FIFO_THRESHOLD);
- outb(64, iobase+IRCC_FIFO_THRESHOLD);
-
- register_bank(iobase, 4);
- outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
-
- register_bank(iobase, 0);
- outb(fast, iobase+IRCC_LCR_A);
-
- netif_start_queue(dev);
-}
-
-/*
- * Function ircc_hard_xmit (skb, dev)
- *
- * Transmit the frame!
- *
- */
-static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct irport_cb *irport;
- struct ircc_cb *self;
- unsigned long flags;
- s32 speed;
- int iobase;
- int mtt;
-
- irport = (struct irport_cb *) dev->priv;
- self = (struct ircc_cb *) irport->priv;
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io->fir_base;
-
- netif_stop_queue(dev);
-
- /* Make sure tests *& speed change are atomic */
- spin_lock_irqsave(&self->irport->lock, flags);
-
- /* Note : you should make sure that speed changes are not going
- * to corrupt any outgoing frame. Look at nsc-ircc for the gory
- * details - Jean II */
-
- /* Check if we need to change the speed after this frame */
- speed = irda_get_next_speed(skb);
- if ((speed != self->io->speed) && (speed != -1)) {
- /* Check for empty frame */
- if (!skb->len) {
- ircc_change_speed(self, speed);
- dev->trans_start = jiffies;
- spin_unlock_irqrestore(&self->irport->lock, flags);
- dev_kfree_skb(skb);
- return 0;
- } else
- self->new_speed = speed;
- }
-
- memcpy(self->tx_buff.head, skb->data, skb->len);
-
- self->tx_buff.len = skb->len;
- self->tx_buff.data = self->tx_buff.head;
-
- mtt = irda_get_mtt(skb);
- if (mtt) {
- int bofs;
-
- /*
- * Compute how many BOFs (STA or PA's) we need to waste the
- * min turn time given the speed of the link.
- */
- bofs = mtt * (self->io->speed / 1000) / 8000;
- if (bofs > 4095)
- bofs = 4095;
-
- ircc_dma_xmit(self, iobase, bofs);
- } else {
- /* Transmit frame */
- ircc_dma_xmit(self, iobase, 0);
- }
- dev->trans_start = jiffies;
- spin_unlock_irqrestore(&self->irport->lock, flags);
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-/*
- * Function ircc_dma_xmit (self, iobase)
- *
- * Transmit data using DMA
- *
- */
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs)
-{
- u8 ctrl;
-
- IRDA_DEBUG(2, "%s\n", __FUNCTION__ );
-#if 0
- /* Disable Rx */
- register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
-#endif
- register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
-
- self->io->direction = IO_XMIT;
-
- /* Set BOF additional count for generating the min turn time */
- register_bank(iobase, 4);
- outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
- ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
- outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
-
- /* Set max Tx frame size */
- outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
- outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
-
- /* Setup DMA controller (must be done after enabling chip DMA) */
- setup_dma(self->io->dma, self->tx_buff.data, self->tx_buff.len,
- DMA_TX_MODE);
-
- outb(UART_MCR_OUT2, self->io->sir_base + UART_MCR);
- /* Enable burst mode chip Tx DMA */
- register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
-
- /* Enable interrupt */
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
- register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
-
- /* Enable transmit */
- outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
-}
-
-/*
- * Function ircc_dma_xmit_complete (self)
- *
- * The transfer of a frame in finished. This function will only be called
- * by the interrupt handler
- *
- */
-static void ircc_dma_xmit_complete(struct ircc_cb *self, int iobase)
-{
- IRDA_DEBUG(2, "%s\n", __FUNCTION__ );
-#if 0
- /* Disable Tx */
- register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
-#endif
- register_bank(self->io->fir_base, 1);
- outb(inb(self->io->fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- self->io->fir_base+IRCC_SCE_CFGB);
-
- /* Check for underrrun! */
- register_bank(iobase, 0);
- if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
- self->irport->stats.tx_errors++;
- self->irport->stats.tx_fifo_errors++;
-
- /* Reset error condition */
- register_bank(iobase, 0);
- outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
- } else {
- self->irport->stats.tx_packets++;
- self->irport->stats.tx_bytes += self->tx_buff.len;
- }
-
- /* Check if it's time to change the speed */
- if (self->new_speed) {
- ircc_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
- netif_wake_queue(self->netdev);
-}
-
-/*
- * Function ircc_dma_receive (self)
- *
- * Get ready for receiving a frame. The device will initiate a DMA
- * if it starts to receive a frame.
- *
- */
-static int ircc_dma_receive(struct ircc_cb *self, int iobase)
-{
-#if 0
- /* Turn off chip DMA */
- register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
-#endif
- setup_dma(self->io->dma, self->rx_buff.data, self->rx_buff.truesize,
- DMA_RX_MODE);
-
- /* Set max Rx frame size */
- register_bank(iobase, 4);
- outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
- outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
-
- self->io->direction = IO_RECV;
- self->rx_buff.data = self->rx_buff.head;
-
- /* Setup DMA controller */
-
- /* Enable receiver */
- register_bank(iobase, 0);
- outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
- iobase+IRCC_LCR_B);
-
- /* Enable burst mode chip Rx DMA */
- register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
-
- return 0;
-}
-
-/*
- * Function ircc_dma_receive_complete (self)
- *
- * Finished with receiving frames
- *
- */
-static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
-{
- struct sk_buff *skb;
- int len, msgcnt;
-
- IRDA_DEBUG(2, "%s\n", __FUNCTION__ );
-#if 0
- /* Disable Rx */
- register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
-#endif
- register_bank(iobase, 0);
- msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
-
- IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__ ,
- get_dma_residue(self->io->dma));
-
- len = self->rx_buff.truesize - get_dma_residue(self->io->dma);
-
- /* Remove CRC */
- if (self->io->speed < 4000000)
- len -= 2;
- else
- len -= 4;
-
- if ((len < 2) || (len > 2050)) {
- WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
- return;
- }
- IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__ , msgcnt, len);
-
- skb = dev_alloc_skb(len+1);
- if (!skb) {
- WARNING("%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
- return;
- }
- /* Make sure IP header gets aligned */
- skb_reserve(skb, 1);
-
- memcpy(skb_put(skb, len), self->rx_buff.data, len);
- self->irport->stats.rx_packets++;
- self->irport->stats.rx_bytes += len;
-
- skb->dev = self->netdev;
- skb->mac.raw = skb->data;
- skb->protocol = htons(ETH_P_IRDA);
- netif_rx(skb);
- self->netdev->last_rx = jiffies;
-}
-
-/*
- * Function ircc_interrupt (irq, dev_id, regs)
- *
- * An interrupt from the chip has arrived. Time to do some work
- *
- */
-static irqreturn_t ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct irport_cb *irport;
- struct ircc_cb *self;
- int iobase, iir;
-
- if (dev == NULL) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
- return IRQ_NONE;
- }
- irport = (struct irport_cb *) dev->priv;
- ASSERT(irport != NULL, return IRQ_NONE;);
- self = (struct ircc_cb *) irport->priv;
- ASSERT(self != NULL, return IRQ_NONE;);
-
- /* Check if we should use the SIR interrupt handler */
- if (self->io->speed < 576000) {
- /* Will spinlock itself - Jean II */
- irport_interrupt(irq, dev_id, regs);
- return IRQ_HANDLED;
- }
- iobase = self->io->fir_base;
-
- spin_lock(&self->irport->lock);
-
- register_bank(iobase, 0);
- iir = inb(iobase+IRCC_IIR);
-
- /* Disable interrupts */
- outb(0, iobase+IRCC_IER);
-
- IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__ , iir);
-
- if (iir & IRCC_IIR_EOM) {
- if (self->io->direction == IO_RECV)
- ircc_dma_receive_complete(self, iobase);
- else
- ircc_dma_xmit_complete(self, iobase);
-
- ircc_dma_receive(self, iobase);
- }
-
- /* Enable interrupts again */
- register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
-
- spin_unlock(&self->irport->lock);
- return IRQ_HANDLED;
-}
-
-#if 0 /* unused */
-/*
- * Function ircc_is_receiving (self)
- *
- * Return TRUE is we are currently receiving a frame
- *
- */
-static int ircc_is_receiving(struct ircc_cb *self)
-{
- int status = FALSE;
- /* int iobase; */
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- ASSERT(self != NULL, return FALSE;);
-
- IRDA_DEBUG(0, "%s: dma count = %d\n", __FUNCTION__ ,
- get_dma_residue(self->io->dma));
-
- status = (self->rx_buff.state != OUTSIDE_FRAME);
-
- return status;
-}
-#endif /* unused */
-
-/*
- * Function ircc_net_open (dev)
- *
- * Start the device
- *
- */
-static int ircc_net_open(struct net_device *dev)
-{
- struct irport_cb *irport;
- struct ircc_cb *self;
- int iobase;
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- ASSERT(dev != NULL, return -1;);
- irport = (struct irport_cb *) dev->priv;
- self = (struct ircc_cb *) irport->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io->fir_base;
-
- irport_net_open(dev); /* irport allocates the irq */
-
- /*
- * Always allocate the DMA channel after the IRQ,
- * and clean up on failure.
- */
- if (request_dma(self->io->dma, dev->name)) {
- irport_net_close(dev);
-
- WARNING("%s(), unable to allocate DMA=%d\n", __FUNCTION__, self->io->dma);
- return -EAGAIN;
- }
-
- return 0;
-}
-
-/*
- * Function ircc_net_close (dev)
- *
- * Stop the device
- *
- */
-static int ircc_net_close(struct net_device *dev)
-{
- struct irport_cb *irport;
- struct ircc_cb *self;
- int iobase;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
-
- ASSERT(dev != NULL, return -1;);
- irport = (struct irport_cb *) dev->priv;
- self = (struct ircc_cb *) irport->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io->fir_base;
-
- irport_net_close(dev);
-
- disable_dma(self->io->dma);
-
- free_dma(self->io->dma);
-
- return 0;
-}
-
-static void ircc_suspend(struct ircc_cb *self)
-{
- MESSAGE("%s, Suspending\n", driver_name);
-
- if (self->io->suspended)
- return;
-
- ircc_net_close(self->netdev);
-
- self->io->suspended = 1;
-}
-
-static void ircc_wakeup(struct ircc_cb *self)
-{
- if (!self->io->suspended)
- return;
-
- /* The code was doing a "cli()" here, but this can't be right.
- * If you need protection, do it in net_open with a spinlock
- * or give a good reason. - Jean II */
-
- ircc_net_open(self->netdev);
-
- MESSAGE("%s, Waking up\n", driver_name);
-}
-
-static int ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct ircc_cb *self = (struct ircc_cb*) dev->data;
- if (self) {
- switch (rqst) {
- case PM_SUSPEND:
- ircc_suspend(self);
- break;
- case PM_RESUME:
- ircc_wakeup(self);
- break;
- }
- }
- return 0;
-}
-
-/*
- * Function ircc_close (self)
- *
- * Close driver instance
- *
- */
-static int __exit ircc_close(struct ircc_cb *self)
-{
- int iobase;
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- ASSERT(self != NULL, return -1;);
-
- iobase = self->irport->io.fir_base;
-
- if (self->pmdev)
- pm_unregister(self->pmdev);
-
- /* This will destroy irport */
- irport_close(self->irport);
-
- /* Stop interrupts */
- register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
-#if 0
- /* Reset to SIR mode */
- register_bank(iobase, 1);
- outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
- outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
-#endif
-
- /* Release the PORT that this driver is using */
- IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__ , iobase);
-
- release_region(iobase, CHIP_IO_EXTENT);
-
- if (self->tx_buff.head)
- kfree(self->tx_buff.head);
-
- if (self->rx_buff.head)
- kfree(self->rx_buff.head);
-
- kfree(self);
-
- return 0;
-}
-
-static int __init smc_init(void)
-{
- return ircc_init();
-}
-
-void __exit smc_cleanup(void)
-{
- int i;
-
- IRDA_DEBUG(0, "%s\n", __FUNCTION__ );
-
- for (i=0; i < 2; i++) {
- if (dev_self[i])
- ircc_close(dev_self[i]);
- }
-}
-
-module_init(smc_init);
-module_exit(smc_cleanup);
-
-MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
-MODULE_DESCRIPTION("SMC IrCC controller driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(ircc_dma, "1i");
-MODULE_PARM_DESC(ircc_dma, "DMA channel");
-MODULE_PARM(ircc_irq, "1i");
-MODULE_PARM_DESC(ircc_irq, "IRQ line");
-MODULE_PARM(ircc_fir, "1-4i");
-MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
-MODULE_PARM(ircc_sir, "1-4i");
-MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
-MODULE_PARM(ircc_cfg, "1-4i");
-MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
deleted file mode 100644
index ab9a604f3887..000000000000
--- a/drivers/net/irda/toshoboe.c
+++ /dev/null
@@ -1,957 +0,0 @@
-/*********************************************************************
- *
- * Filename: toshoboe.c
- * Version: 0.1
- * Description: Driver for the Toshiba OBOE (or type-O or 700 or 701)
- * FIR Chipset.
- * Status: Experimental.
- * Author: James McKenzie <james@fishsoup.dhs.org>
- * Created at: Sat May 8 12:35:27 1999
- * Modified: Paul Bristow <paul.bristow@technologist.com>
- * Modified: Mon Nov 11 19:10:05 1999
- *
- * Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Neither James McKenzie nor Cambridge University admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- * Applicable Models : Libretto 100CT. and many more
- * Toshiba refers to this chip as the type-O IR port.
- *
- ********************************************************************/
-
-/* This driver is experimental, I have only three ir devices */
-/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
-/* an hp printer, this works fine at 4MBPS with my HP printer */
-
-static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
-
-/* Define this to have only one frame in the XMIT or RECV queue */
-/* Toshiba's drivers do this, but it disables back to back tansfers */
-/* I think that the chip may have some problems certainly, I have */
-/* seen it jump over tasks in the taskfile->xmit with this turned on */
-#define ONETASK
-
-/* To adjust the number of tasks in use edit toshoboe.h */
-
-/* Define this to enable FIR and MIR support */
-#define ENABLE_FAST
-
-/* Size of IO window */
-#define CHIP_IO_EXTENT 0x1f
-
-/* Transmit and receive buffer sizes, adjust at your peril */
-#define RX_BUF_SZ 4196
-#define TX_BUF_SZ 4196
-
-/* No user servicable parts below here */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/rtnetlink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irda_device.h>
-
-#include <linux/pm.h>
-
-#include <net/irda/toshoboe.h>
-
-#define PCI_DEVICE_ID_FIR701b 0x0d01
-
-static struct pci_device_id toshoboe_pci_tbl[] = {
- { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701b, PCI_ANY_ID, PCI_ANY_ID, },
- { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
-
-static const char *driver_name = "toshoboe";
-
-static int max_baud = 4000000;
-
-/* Shutdown the chip and point the taskfile reg somewhere else */
-static void
-toshoboe_stopchip (struct toshoboe_cb *self)
-{
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- outb_p (0x0e, OBOE_REG_11);
-
- outb_p (0x00, OBOE_RST);
- outb_p (0x3f, OBOE_TFP2); /*Write the taskfile address */
- outb_p (0xff, OBOE_TFP1);
- outb_p (0xff, OBOE_TFP0);
- outb_p (0x0f, OBOE_REG_1B);
- outb_p (0xff, OBOE_REG_1A);
- outb_p (0x00, OBOE_ISR); /*FIXME: should i do this to disbale ints */
- outb_p (0x80, OBOE_RST);
- outb_p (0xe, OBOE_LOCK);
-
-}
-
-/*Set the baud rate */
-static void
-toshoboe_setbaud (struct toshoboe_cb *self, int baud)
-{
- unsigned long flags;
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud);
-
- save_flags (flags);
- cli ();
- switch (baud)
- {
- case 2400:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0xbf, OBOE_UDIV);
- break;
- case 4800:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0x5f, OBOE_UDIV);
- break;
- case 9600:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0x2f, OBOE_UDIV);
- break;
- case 19200:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0x17, OBOE_UDIV);
- break;
- case 38400:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0xb, OBOE_UDIV);
- break;
- case 57600:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0x7, OBOE_UDIV);
- break;
- case 115200:
- outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
- outb_p (0x3, OBOE_UDIV);
- break;
- case 1152000:
- outb_p (OBOE_PMDL_MIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_MIR, OBOE_SMDL);
- outb_p (0x1, OBOE_UDIV);
- break;
- case 4000000:
- outb_p (OBOE_PMDL_FIR, OBOE_PMDL);
- outb_p (OBOE_SMDL_FIR, OBOE_SMDL);
- outb_p (0x0, OBOE_UDIV);
- break;
- }
-
- restore_flags (flags);
-
- outb_p (0x00, OBOE_RST);
- outb_p (0x80, OBOE_RST);
- outb_p (0x01, OBOE_REG_9);
-
- self->io.speed = baud;
-}
-
-/* Wake the chip up and get it looking at the taskfile */
-static void
-toshoboe_startchip (struct toshoboe_cb *self)
-{
- __u32 physaddr;
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
-
- outb_p (0, OBOE_LOCK);
- outb_p (0, OBOE_RST);
- outb_p (OBOE_NTR_VAL, OBOE_NTR);
- outb_p (0xf0, OBOE_REG_D);
- outb_p (0xff, OBOE_ISR);
- outb_p (0x0f, OBOE_REG_1B);
- outb_p (0xff, OBOE_REG_1A);
-
-
- physaddr = virt_to_bus (self->taskfile);
-
- outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0);
- outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1);
- outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
-
- outb_p (0x0e, OBOE_REG_11);
- outb_p (0x80, OBOE_RST);
-
- toshoboe_setbaud (self, 9600);
-
-}
-
-/*Let the chip look at memory */
-static void
-toshoboe_enablebm (struct toshoboe_cb *self)
-{
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
- pci_set_master (self->pdev);
-}
-
-/*Don't let the chip look at memory */
-static void
-toshoboe_disablebm (struct toshoboe_cb *self)
-{
- __u8 command;
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
- command &= ~PCI_COMMAND_MASTER;
- pci_write_config_byte (self->pdev, PCI_COMMAND, command);
-
-}
-
-/*setup the taskfile */
-static void
-toshoboe_initbuffs (struct toshoboe_cb *self)
-{
- int i;
- unsigned long flags;
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- save_flags (flags);
- cli ();
-
- for (i = 0; i < TX_SLOTS; ++i)
- {
- self->taskfile->xmit[i].len = 0;
- self->taskfile->xmit[i].control = 0x00;
- self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]);
- }
-
- for (i = 0; i < RX_SLOTS; ++i)
- {
- self->taskfile->recv[i].len = 0;
- self->taskfile->recv[i].control = 0x83;
- self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
- }
-
- restore_flags (flags);
-}
-
-/*Transmit something */
-static int
-toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
-{
- struct toshoboe_cb *self;
- __s32 speed;
- int mtt, len;
-
- self = (struct toshoboe_cb *) dev->priv;
-
- ASSERT (self != NULL, return 0;
- );
-
- /* Check if we need to change the speed */
- speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
- /* Check for empty frame */
- if (!skb->len) {
- toshoboe_setbaud(self, speed);
- dev_kfree_skb(skb);
- return 0;
- } else
- self->new_speed = speed;
- }
-
- netif_stop_queue(dev);
-
- if (self->stopped) {
- dev_kfree_skb(skb);
- return 0;
- }
-
-#ifdef ONETASK
- if (self->txpending)
- return -EBUSY;
-
- self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
-
- self->txs &= 0x3f;
-
-#endif
-
- if (self->taskfile->xmit[self->txs].control)
- return -EBUSY;
-
-
- if (inb_p (OBOE_RST) & OBOE_RST_WRAP)
- {
- len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ);
- }
- else
- {
- len = skb->len;
- memcpy (self->xmit_bufs[self->txs], skb->data, len);
- }
- self->taskfile->xmit[self->txs].len = len & 0x0fff;
-
-
-
- outb_p (0, OBOE_RST);
- outb_p (0x1e, OBOE_REG_11);
-
- self->taskfile->xmit[self->txs].control = 0x84;
-
- mtt = irda_get_mtt (skb);
- if (mtt)
- udelay (mtt);
-
- self->txpending++;
-
- /*FIXME: ask about busy,media_busy stuff, for the moment */
- /*busy means can't queue any more */
-#ifndef ONETASK
- if (self->txpending != TX_SLOTS)
- {
- netif_wake_queue(dev);
- }
-#endif
-
- outb_p (0x80, OBOE_RST);
- outb_p (1, OBOE_REG_9);
-
- self->txs++;
- self->txs %= TX_SLOTS;
-
- dev_kfree_skb (skb);
-
- return 0;
-}
-
-/*interrupt handler */
-static irqreturn_t
-toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
-{
- struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
- __u8 irqstat;
- struct sk_buff *skb;
-
- if (self == NULL)
- {
- printk (KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
- return IRQ_NONE;
- }
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- irqstat = inb_p (OBOE_ISR);
-
-/* woz it us */
- if (!(irqstat & 0xf8))
- return IRQ_NONE;
-
- outb_p (irqstat, OBOE_ISR); /*Acknologede it */
-
-
-/* Txdone */
- if (irqstat & OBOE_ISR_TXDONE)
- {
- self->txpending--;
-
- self->stats.tx_packets++;
-
- if (self->new_speed) {
- toshoboe_setbaud(self, self->new_speed);
-
- self->new_speed = 0;
- }
- /* Tell network layer that we want more frames */
- netif_wake_queue(self->netdev);
- }
-
- if (irqstat & OBOE_ISR_RXDONE)
- {
-
-#ifdef ONETASK
- self->rxs = inb_p (OBOE_RCVT);
- self->rxs += (RX_SLOTS - 1);
- self->rxs %= RX_SLOTS;
-#else
- while (self->taskfile->recv[self->rxs].control == 0)
-#endif
- {
- int len = self->taskfile->recv[self->rxs].len;
-
- if (len > 2)
- len -= 2;
-
- skb = dev_alloc_skb (len + 1);
- if (skb)
- {
- skb_reserve (skb, 1);
-
- skb_put (skb, len);
- memcpy (skb->data, self->recv_bufs[self->rxs], len);
-
- self->stats.rx_packets++;
- skb->dev = self->netdev;
- skb->mac.raw = skb->data;
- skb->protocol = htons (ETH_P_IRDA);
- }
- else
- {
- printk (KERN_INFO
- "%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
- }
-
- self->taskfile->recv[self->rxs].control = 0x83;
- self->taskfile->recv[self->rxs].len = 0x0;
-
- self->rxs++;
- self->rxs %= RX_SLOTS;
-
- if (skb) {
- netif_rx (skb);
- self->netdev->last_rx = jiffies;
- }
-
- }
-
- }
-
- if (irqstat & OBOE_ISR_20)
- {
- printk (KERN_WARNING "Oboe_irq: 20\n");
- }
- if (irqstat & OBOE_ISR_10)
- {
- printk (KERN_WARNING "Oboe_irq: 10\n");
- }
- if (irqstat & 0x8)
- {
- /*FIXME: I think this is a TX or RX error of some sort */
-
- self->stats.tx_errors++;
- self->stats.rx_errors++;
-
- }
- return IRQ_HANDLED;
-}
-
-static int
-toshoboe_net_init (struct net_device *dev)
-{
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup (dev);
-
- /* Insert overrides below this line! */
- return 0;
-}
-
-
-static void
-toshoboe_initptrs (struct toshoboe_cb *self)
-{
-
- unsigned long flags;
- save_flags (flags);
- cli ();
-
- /*FIXME: need to test this carefully to check which one */
- /*of the two possible startup logics the chip uses */
- /*although it won't make any difference if no-one xmits durining init */
- /*and none what soever if using ONETASK */
-
- self->rxs = inb_p (OBOE_RCVT);
- self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
-
-#if 0
- self->rxs = 0;
- self->txs = 0;
-#endif
-#if 0
- self->rxs = RX_SLOTS - 1;
- self->txs = 0;
-#endif
-
-
- self->txpending = 0;
-
- restore_flags (flags);
-
-}
-
-
-static int
-toshoboe_net_open (struct net_device *dev)
-{
- struct toshoboe_cb *self;
- char hwname[32];
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- ASSERT (dev != NULL, return -1;
- );
- self = (struct toshoboe_cb *) dev->priv;
-
- ASSERT (self != NULL, return 0;
- );
-
- if (self->stopped)
- return 0;
-
- if (request_irq (self->io.irq, toshoboe_interrupt,
- SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
- {
-
- return -EAGAIN;
- }
-
- toshoboe_initbuffs (self);
- toshoboe_enablebm (self);
- toshoboe_startchip (self);
- toshoboe_initptrs (self);
-
- /* Ready to play! */
- netif_start_queue(dev);
- /* Give self a hardware name */
- sprintf(hwname, "Toshiba-FIR @ 0x%03x", self->base);
- /*
- * Open new IrLAP layer instance, now that everything should be
- * initialized properly
- */
- self->irlap = irlap_open(dev, &self->qos, hwname);
-
- self->open = 1;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-
-}
-
-static int
-toshoboe_net_close (struct net_device *dev)
-{
- struct toshoboe_cb *self;
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- ASSERT (dev != NULL, return -1;
- );
- self = (struct toshoboe_cb *) dev->priv;
-
- /* Stop device */
- netif_stop_queue(dev);
-
- /* Stop and remove instance of IrLAP */
- if (self->irlap)
- irlap_close(self->irlap);
- self->irlap = NULL;
-
- self->open = 0;
-
- free_irq (self->io.irq, (void *) self);
-
- if (!self->stopped)
- {
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
- }
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-
-}
-
-/*
- * Function toshoboe_net_ioctl (dev, rq, cmd)
- *
- * Process IOCTL commands for this device
- *
- */
-static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct if_irda_req *irq = (struct if_irda_req *) rq;
- struct toshoboe_cb *self;
- unsigned long flags;
- int ret = 0;
-
- ASSERT(dev != NULL, return -1;);
-
- self = dev->priv;
-
- ASSERT(self != NULL, return -1;);
-
- IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__ , dev->name, cmd);
-
- /* Disable interrupts & save flags */
- save_flags(flags);
- cli();
- switch (cmd) {
- case SIOCSBANDWIDTH: /* Set bandwidth */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- goto out;
- }
- /* toshoboe_setbaud(self, irq->ifr_baudrate); */
- /* Just change speed once - inserted by Paul Bristow */
- self->new_speed = irq->ifr_baudrate;
- break;
- case SIOCSMEDIABUSY: /* Set media busy */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- goto out;
- }
- irda_device_set_media_busy(self->netdev, TRUE);
- break;
- case SIOCGRECEIVING: /* Check if we are receiving right now */
- irq->ifr_receiving = 0; /* Can't tell */
- break;
- default:
- ret = -EOPNOTSUPP;
- }
-out:
- restore_flags(flags);
- return ret;
-}
-
-MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");
-MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM (max_baud, "i");
-MODULE_PARM_DESC(max_baus, "Maximum baud rate");
-
-static void
-toshoboe_remove (struct pci_dev *pci_dev)
-{
- int i;
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- ASSERT (self != NULL, return;
- );
-
- if (!self->stopped)
- {
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
- }
-
- release_region (self->io.sir_base, self->io.sir_ext);
-
-
- for (i = 0; i < TX_SLOTS; ++i)
- {
- kfree (self->xmit_bufs[i]);
- self->xmit_bufs[i] = NULL;
- }
-
- for (i = 0; i < RX_SLOTS; ++i)
- {
- kfree (self->recv_bufs[i]);
- self->recv_bufs[i] = NULL;
- }
-
- if (self->netdev)
- unregister_netdev(self->netdev);
-
- kfree (self->taskfilebuf);
- self->taskfilebuf = NULL;
- self->taskfile = NULL;
-
- return;
-
-}
-
-static int
-toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
-{
- struct toshoboe_cb *self;
- struct net_device *dev;
- int i = 0;
- int ok = 0;
- int err;
-
- IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
-
- if ((err=pci_enable_device(pci_dev)))
- return err;
-
- self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
-
- if (self == NULL)
- {
- printk (KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
- return -ENOMEM;
- }
-
- memset (self, 0, sizeof (struct toshoboe_cb));
-
- self->open = 0;
- self->stopped = 0;
- self->pdev = pci_dev;
- self->base = pci_resource_start(pci_dev,0);
-
- self->io.sir_base = self->base;
- self->io.irq = pci_dev->irq;
- self->io.sir_ext = CHIP_IO_EXTENT;
- self->io.speed = 9600;
-
- /* Lock the port that we need */
- if (NULL==request_region (self->io.sir_base, self->io.sir_ext, driver_name))
- {
- IRDA_DEBUG (0, "%s(), can't get iobase of 0x%03x\n", __FUNCTION__ ,
- self->io.sir_base);
-
- err = -EBUSY;
- goto freeself;
- }
-
- irda_init_max_qos_capabilies (&self->qos);
- self->qos.baud_rate.bits = 0;
-
- if (max_baud >= 2400)
- self->qos.baud_rate.bits |= IR_2400;
- /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
- if (max_baud >= 9600)
- self->qos.baud_rate.bits |= IR_9600;
- if (max_baud >= 19200)
- self->qos.baud_rate.bits |= IR_19200;
- if (max_baud >= 115200)
- self->qos.baud_rate.bits |= IR_115200;
-#ifdef ENABLE_FAST
- if (max_baud >= 576000)
- self->qos.baud_rate.bits |= IR_576000;
- if (max_baud >= 1152000)
- self->qos.baud_rate.bits |= IR_1152000;
- if (max_baud >= 4000000)
- self->qos.baud_rate.bits |= (IR_4000000 << 8);
-#endif
-
-
- self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
-
- irda_qos_bits_to_value (&self->qos);
-
- self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
-
-#ifdef ENABLE_FAST
- if (max_baud >= 576000)
- self->flags |= IFF_FIR;
-#endif
-
- /* Now setup the endless buffers we need */
-
- self->txs = 0;
- self->rxs = 0;
-
- self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL);
- if (!self->taskfilebuf)
- {
- printk (KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
- err = -ENOMEM;
- goto freeregion;
- }
-
-
- memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
-
- /*We need to align the taskfile on a taskfile size boundary */
- {
- __u32 addr;
-
- addr = (__u32) self->taskfilebuf;
- addr &= ~(sizeof (struct OboeTaskFile) - 1);
- addr += sizeof (struct OboeTaskFile);
-
- self->taskfile = (struct OboeTaskFile *) addr;
- }
-
- for (i = 0; i < TX_SLOTS; ++i)
- {
- self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
- if (self->xmit_bufs[i])
- ok++;
- }
-
- for (i = 0; i < RX_SLOTS; ++i)
- {
- self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
- if (self->recv_bufs[i])
- ok++;
- }
-
- if (ok != RX_SLOTS + TX_SLOTS)
- {
- printk (KERN_ERR "toshoboe: kmalloc for buffers failed()\n");
- err = -ENOMEM;
- goto freebufs;
-
- }
-
-
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
- err = -ENOMEM;
- goto freebufs;
- }
- dev->priv = (void *) self;
- self->netdev = dev;
-
- MESSAGE("IrDA: Registered device %s\n", dev->name);
-
- dev->init = toshoboe_net_init;
- dev->hard_start_xmit = toshoboe_hard_xmit;
- dev->open = toshoboe_net_open;
- dev->stop = toshoboe_net_close;
- dev->do_ioctl = toshoboe_net_ioctl;
-
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
- if (err) {
- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
- /* XXX there is not freeing for dev? */
- goto freebufs;
- }
- pci_set_drvdata(pci_dev,self);
-
- printk (KERN_WARNING "ToshOboe: Using ");
-#ifdef ONETASK
- printk ("single");
-#else
- printk ("multiple");
-#endif
- printk (" tasks, version %s\n", rcsid);
-
- return (0);
-freebufs:
- for (i = 0; i < TX_SLOTS; ++i)
- if (self->xmit_bufs[i])
- kfree (self->xmit_bufs[i]);
- for (i = 0; i < RX_SLOTS; ++i)
- if (self->recv_bufs[i])
- kfree (self->recv_bufs[i]);
- kfree(self->taskfilebuf);
-freeregion:
- release_region (self->io.sir_base, self->io.sir_ext);
-freeself:
- kfree (self);
- return err;
-}
-
-static int
-toshoboe_suspend (struct pci_dev *pci_dev, u32 crap)
-{
- int i = 10;
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
-
- printk (KERN_WARNING "ToshOboe: suspending\n");
-
- if (!self || self->stopped)
- return 0;
-
- self->stopped = 1;
-
- if (!self->open)
- return 0;
-
-/*FIXME: can't sleep here wait one second */
-
- while ((i--) && (self->txpending))
- udelay (100);
-
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
-
- self->txpending = 0;
- return 0;
-}
-
-
-static int
-toshoboe_resume (struct pci_dev *pci_dev)
-{
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
- unsigned long flags;
-
- if (!self)
- return 0;
-
- if (!self->stopped)
- return 0;
-
- if (!self->open)
- {
- self->stopped = 0;
- return 0;
- }
-
- save_flags (flags);
- cli ();
-
- toshoboe_initbuffs (self);
- toshoboe_enablebm (self);
- toshoboe_startchip (self);
-
- toshoboe_setbaud (self, self->io.speed);
-
- toshoboe_initptrs (self);
-
- netif_wake_queue(self->netdev);
- restore_flags (flags);
- printk (KERN_WARNING "ToshOboe: waking up\n");
- return 0;
-}
-
-static struct pci_driver toshoboe_pci_driver = {
- .name = "toshoboe",
- .id_table = toshoboe_pci_tbl,
- .probe = toshoboe_probe,
- .remove = toshoboe_remove,
- .suspend = toshoboe_suspend,
- .resume = toshoboe_resume
-};
-
-int __init
-toshoboe_init (void)
-{
- return pci_module_init(&toshoboe_pci_driver);
-}
-
-void
-toshoboe_cleanup (void)
-{
- pci_unregister_driver(&toshoboe_pci_driver);
-}
-
-module_init(toshoboe_init);
-module_exit(toshoboe_cleanup);
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 66b133fdccbf..a6e100b51799 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -94,7 +94,6 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id,
static int via_ircc_is_receiving(struct via_ircc_cb *self);
static int via_ircc_read_dongle_id(int iobase);
-static int via_ircc_net_init(struct net_device *dev);
static int via_ircc_net_open(struct net_device *dev);
static int via_ircc_net_close(struct net_device *dev);
static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
@@ -330,18 +329,19 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
{
struct net_device *dev;
struct via_ircc_cb *self;
- int ret;
int err;
if ((via_ircc_setup(info, id)) == -1)
return -1;
/* Allocate new instance of the driver */
- self = kmalloc(sizeof(struct via_ircc_cb), GFP_KERNEL);
- if (self == NULL) {
+ dev = alloc_netdev(sizeof(struct via_ircc_cb), "irda%d",
+ irda_device_setup);
+ if (dev == NULL)
return -ENOMEM;
- }
- memset(self, 0, sizeof(struct via_ircc_cb));
+
+ self = dev->priv;
+ self->netdev = dev;
spin_lock_init(&self->lock);
/* Need to store self somewhere */
@@ -360,14 +360,12 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
self->RxDataReady = 0;
/* Reserve the ioports that we need */
- ret = check_region(self->io.fir_base, self->io.fir_ext);
- if (ret < 0) {
+ if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
// WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",self->io.fir_base);
- dev_self[i] = NULL;
- kfree(self);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_out1;
}
- request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
/* The only value we must override it the baudrate */
@@ -391,17 +389,16 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
self->rx_buff.head =
(__u8 *) kmalloc(self->rx_buff.truesize, GFP_KERNEL | GFP_DMA);
if (self->rx_buff.head == NULL) {
- kfree(self);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out2;
}
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head =
(__u8 *) kmalloc(self->tx_buff.truesize, GFP_KERNEL | GFP_DMA);
if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out3;
}
memset(self->tx_buff.head, 0, self->tx_buff.truesize);
@@ -414,30 +411,20 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
self->tx_fifo.tail = self->tx_buff.head;
- if (!(dev = dev_alloc("irda%d", &err))) {
- kfree(self->tx_buff.head);
- kfree(self->rx_buff.head);
- kfree(self);
- return -ENOMEM;
- }
-
- dev->priv = (void *) self;
- self->netdev = dev;
+ /* Keep track of module usage */
+ SET_MODULE_OWNER(dev);
/* Override the network functions we need to use */
- dev->init = via_ircc_net_init;
dev->hard_start_xmit = via_ircc_hard_xmit_sir;
dev->open = via_ircc_net_open;
dev->stop = via_ircc_net_close;
dev->do_ioctl = via_ircc_net_ioctl;
dev->get_stats = via_ircc_net_get_stats;
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
- if (err) {
- return -1;
- }
+ err = register_netdev(dev);
+ if (err)
+ goto err_out4;
+
MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Check if user has supplied the dongle id or not */
@@ -448,6 +435,16 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
self->io.dongle_id);
return 0;
+ err_out4:
+ kfree(self->tx_buff.head);
+ err_out3:
+ kfree(self->rx_buff.head);
+ err_out2:
+ release_region(self->io.fir_base, self->io.fir_ext);
+ err_out1:
+ free_netdev(dev);
+ dev_self[i] = NULL;
+ return err;
}
/*
@@ -468,11 +465,7 @@ static int __exit via_ircc_close(struct via_ircc_cb *self)
ResetChip(iobase, 5); //hardware reset.
/* Remove netdevice */
- if (self->netdev) {
- rtnl_lock();
- unregister_netdevice(self->netdev);
- rtnl_unlock();
- }
+ unregister_netdev(self->netdev);
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, "%s(), Releasing Region %03x\n",
@@ -483,7 +476,8 @@ static int __exit via_ircc_close(struct via_ircc_cb *self)
if (self->rx_buff.head)
kfree(self->rx_buff.head);
dev_self[self->index] = NULL;
- kfree(self);
+
+ free_netdev(self->netdev);
return 0;
}
@@ -1456,26 +1450,6 @@ static int via_ircc_is_receiving(struct via_ircc_cb *self)
return status;
}
-/*
- * Function via_ircc_net_init (dev)
- *
- * Initialize network device
- *
- */
-static int via_ircc_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- return 0;
-}
/*
* Function via_ircc_net_open (dev)
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index f23ce614504b..ea5cfd850485 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -99,7 +99,6 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase);
static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed);
static int w83977af_is_receiving(struct w83977af_ir *self);
-static int w83977af_net_init(struct net_device *dev);
static int w83977af_net_open(struct net_device *dev);
static int w83977af_net_close(struct net_device *dev);
static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -171,14 +170,16 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
/*
* Allocate new instance of the driver
*/
- self = kmalloc(sizeof(struct w83977af_ir), GFP_KERNEL);
- if (self == NULL) {
+ dev = alloc_netdev(sizeof(struct w83977af_ir), "irda%d",
+ irda_device_setup);
+ if (dev == NULL) {
printk( KERN_ERR "IrDA: Can't allocate memory for "
"IrDA control block!\n");
err = -ENOMEM;
goto err_out;
}
- memset(self, 0, sizeof(struct w83977af_ir));
+
+ self = dev->priv;
spin_lock_init(&self->lock);
@@ -230,29 +231,21 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
self->rx_buff.state = OUTSIDE_FRAME;
self->tx_buff.data = self->tx_buff.head;
self->rx_buff.data = self->rx_buff.head;
-
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
- err = -ENOMEM;
- goto err_out3;
- }
- dev->priv = (void *) self;
self->netdev = dev;
+ /* Keep track of module usage */
+ SET_MODULE_OWNER(dev);
+
/* Override the network functions we need to use */
- dev->init = w83977af_net_init;
dev->hard_start_xmit = w83977af_hard_xmit;
dev->open = w83977af_net_open;
dev->stop = w83977af_net_close;
dev->do_ioctl = w83977af_net_ioctl;
dev->get_stats = w83977af_net_get_stats;
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
+ err = register_netdev(dev);
if (err) {
ERROR("%s(), register_netdevice() failed!\n", __FUNCTION__);
- err = -1;
goto err_out3;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
@@ -266,7 +259,7 @@ err_out3:
err_out2:
kfree(self->rx_buff.head);
err_out1:
- kfree(self);
+ free_netdev(dev);
err_out:
release_region(iobase, CHIP_IO_EXTENT);
return err;
@@ -299,8 +292,7 @@ static int w83977af_close(struct w83977af_ir *self)
#endif /* CONFIG_USE_W977_PNP */
/* Remove netdevice */
- if (self->netdev)
- unregister_netdev(self->netdev);
+ unregister_netdev(self->netdev);
/* Release the PORT that this driver is using */
IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n",
@@ -313,7 +305,7 @@ static int w83977af_close(struct w83977af_ir *self)
if (self->rx_buff.head)
kfree(self->rx_buff.head);
- kfree(self);
+ free_netdev(self->netdev);
return 0;
}
@@ -1187,28 +1179,6 @@ static int w83977af_is_receiving(struct w83977af_ir *self)
}
/*
- * Function w83977af_net_init (dev)
- *
- *
- *
- */
-static int w83977af_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-
- /* Keep track of module usage */
- SET_MODULE_OWNER(dev);
-
- /* Set up to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- return 0;
-}
-
-
-/*
* Function w83977af_net_open (dev)
*
* Start the device
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 56cc884228a8..a6862d60c398 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -543,7 +543,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
if (dev->irq >= 2)
printk(" assigned IRQ %d", dev->irq);
else if (lance_version != 0) { /* 7990 boards need DMA detection first. */
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
/* To auto-IRQ we enable the initialization-done and DMA error
interrupts. For ISA boards we get a DMA error, but VLB and PCI
@@ -553,8 +553,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
/* Trigger an initialization just for the interrupt. */
outw(0x0041, ioaddr+LANCE_DATA);
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
dev->irq = probe_irq_off(irq_mask);
if (dev->irq)
printk(", probed IRQ %d", dev->irq);
@@ -621,13 +620,12 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
if (lance_version == 0 && dev->irq == 0) {
/* We may auto-IRQ now that we have a DMA channel. */
/* Trigger an initialization just for the interrupt. */
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
irq_mask = probe_irq_on();
outw(0x0041, ioaddr+LANCE_DATA);
- delay = jiffies + HZ/25;
- while (time_before(jiffies, delay)) ;
+ mdelay(40);
dev->irq = probe_irq_off(irq_mask);
if (dev->irq == 0) {
printk(" Failed to detect the 7990 IRQ line.\n");
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 135af8ee8965..43eccb42921b 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -7,7 +7,6 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 15f5739b1e56..32e59fd124b4 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -60,7 +60,6 @@
static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index e9c07dba7c6e..19dedf118748 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -255,14 +255,13 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
if (dev->irq == 0xff)
;
else if (dev->irq < 2) {
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
PRINTK2((KERN_DEBUG "%s: I/O #5 passed!\n", dev->name));
irq_mask = probe_irq_on();
trigger_irq(ioaddr);
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
dev->irq = probe_irq_off(irq_mask);
PRINTK2((KERN_DEBUG "%s: I/O #6 passed!\n", dev->name));
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 67f857fc37ae..f5d04d487d3a 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -492,14 +492,13 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr)
if(dev->irq < 2)
{
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
irq_mask = probe_irq_on();
ni_reset586();
ni_attn586();
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
dev->irq = probe_irq_off(irq_mask);
if(!dev->irq)
{
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3ddc5e07ae24..cd9aebbf5a2a 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -72,7 +72,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <asm/bitops.h>
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 0e315b8d3753..67d71fc92eb5 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1833,13 +1833,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
if (err) {
printk(KERN_INFO "ns83820: unable to register irq %d\n",
pci_dev->irq);
- goto out_unmap;
+ goto out_disable;
}
err = register_netdev(&dev->net_dev);
if (err) {
printk(KERN_INFO "ns83820: unable to register netdev: %d\n", err);
- goto out_unmap;
+ goto out_free_irq;
}
printk("%s: ns83820.c: 0x22c: %08x, subsystem: %04x:%04x\n",
@@ -2025,9 +2025,11 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
return 0;
-out_unmap:
- iounmap(dev->base);
+out_free_irq:
+ free_irq(pci_dev->irq, dev);
out_disable:
+ if (dev->base)
+ iounmap(dev->base);
pci_free_consistent(pci_dev, 4 * DESC_SIZE * NR_TX_DESC, dev->tx_descs, dev->tx_phy_descs);
pci_free_consistent(pci_dev, 4 * DESC_SIZE * NR_RX_DESC, dev->rx_info.descs, dev->rx_info.phy_descs);
pci_disable_device(pci_dev);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 7e5a91a4510b..2d1341705429 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -145,6 +145,20 @@ typedef struct com20020_dev_t {
dev_node_t node;
} com20020_dev_t;
+static void com20020_setup(struct net_device *dev)
+{
+ struct arcnet_local *lp = dev->priv;
+
+ lp->timeout = timeout;
+ lp->backplane = backplane;
+ lp->clockp = clockp;
+ lp->clockm = clockm & 3;
+ lp->hw.owner = THIS_MODULE;
+
+ /* fill in our module parameters as defaults */
+ dev->dev_addr[0] = node;
+}
+
/*======================================================================
com20020_attach() creates an "instance" of the driver, allocating
@@ -173,18 +187,14 @@ static dev_link_t *com20020_attach(void)
if (!info)
goto fail_alloc_info;
- lp = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
- if (!lp)
- goto fail_alloc_lp;
-
- dev = dev_alloc("arc%d", &ret);
+ dev = alloc_netdev(sizeof(struct arcnet_local), "arc%d",
+ com20020_setup);
if (!dev)
goto fail_alloc_dev;
memset(info, 0, sizeof(struct com20020_dev_t));
- memset(lp, 0, sizeof(struct arcnet_local));
memset(link, 0, sizeof(struct dev_link_t));
- dev->priv = lp;
+ lp = dev->priv;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts1 = 16;
@@ -201,13 +211,6 @@ static dev_link_t *com20020_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- /* fill in our module parameters as defaults */
- dev->dev_addr[0] = node;
- lp->timeout = timeout;
- lp->backplane = backplane;
- lp->clockp = clockp;
- lp->clockm = clockm & 3;
- lp->hw.owner = THIS_MODULE;
link->irq.Instance = info->dev = dev;
link->priv = info;
@@ -234,8 +237,6 @@ static dev_link_t *com20020_attach(void)
return link;
fail_alloc_dev:
- kfree(lp);
-fail_alloc_lp:
kfree(info);
fail_alloc_info:
kfree(link);
@@ -303,11 +304,9 @@ static void com20020_detach(dev_link_t *link)
/* ...but I/O ports are done automatically by card services */
unregister_netdev(dev);
- MOD_DEC_USE_COUNT;
}
DEBUG(1,"kfree...\n");
- kfree(dev->priv);
free_netdev(dev);
}
DEBUG(1,"kfree2...\n");
@@ -361,7 +360,6 @@ static void com20020_config(dev_link_t *link)
/* Configure card */
link->state |= DEV_CONFIG;
- strcpy(info->node.dev_name, dev->name);
DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
i = !CS_SUCCESS;
@@ -407,13 +405,11 @@ static void com20020_config(dev_link_t *link)
goto failed;
}
- MOD_INC_USE_COUNT;
-
lp = dev->priv;
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
- i = com20020_found(dev, 0);
+ i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
@@ -421,6 +417,7 @@ static void com20020_config(dev_link_t *link)
}
info->dev_configured = 1;
+ strcpy(info->node.dev_name, dev->name);
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
index e7e1a9f2d71a..b1bb757ed01e 100644
--- a/drivers/net/rcpci45.c
+++ b/drivers/net/rcpci45.c
@@ -259,10 +259,12 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->set_config = &RCconfig;
if ((error = register_netdev(dev)))
- goto err_out_free_region;
+ goto err_out_iounmap;
return 0; /* success */
+err_out_iounmap:
+ iounmap((void *) dev->base_addr);
err_out_free_region:
pci_release_regions (pdev);
err_out_free_msgbuf:
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 87c980ff9112..fd8e0c45f74f 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -30,7 +30,6 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -124,7 +123,6 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
rrpriv->pci_dev = pdev;
spin_lock_init(&rrpriv->lock);
- sprintf(rrpriv->name, "RoadRunner serial HIPPI");
dev->irq = pdev->irq;
dev->open = &rr_open;
@@ -228,7 +226,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, NULL);
}
out2:
- kfree(dev);
+ free_netdev(dev);
out3:
return ret;
}
@@ -236,9 +234,10 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
static void __devexit rr_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct rr_private *rr = (struct rr_private *)dev->priv;
if (dev) {
+ struct rr_private *rr = dev->priv;
+
if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){
printk(KERN_ERR "%s: trying to unload running NIC\n",
dev->name);
@@ -721,7 +720,8 @@ static int rr_init1(struct net_device *dev)
* Give the FirmWare time to chew on the `get running' command.
*/
myjif = jiffies + 5 * HZ;
- while (time_before(jiffies, myjif) && !rrpriv->fw_running);
+ while (time_before(jiffies, myjif) && !rrpriv->fw_running)
+ cpu_relax();
netif_start_queue(dev);
@@ -1201,8 +1201,7 @@ static int rr_open(struct net_device *dev)
readl(&regs->HostCtrl);
spin_unlock_irqrestore(&rrpriv->lock, flags);
- if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))
- {
+ if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, dev->name, dev)) {
printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
dev->name, dev->irq);
ecode = -EAGAIN;
@@ -1222,7 +1221,6 @@ static int rr_open(struct net_device *dev)
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
return ecode;
error:
@@ -1414,7 +1412,6 @@ static int rr_close(struct net_device *dev)
free_irq(dev->irq, dev);
spin_unlock_irqrestore(&rrpriv->lock, flags);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1727,7 +1724,7 @@ static struct pci_driver rr_driver = {
.name = "rrunner",
.id_table = rr_pci_tbl,
.probe = rr_init_one,
- .remove = rr_remove_one,
+ .remove = __devexit_p(rr_remove_one),
};
static int __init rr_init_module(void)
diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h
index 4927fe937c43..1049131ed89c 100644
--- a/drivers/net/rrunner.h
+++ b/drivers/net/rrunner.h
@@ -820,7 +820,6 @@ struct rr_private
u32 tx_full;
u32 fw_rev;
volatile short fw_running;
- char name[24]; /* The assigned name */
struct net_device_stats stats;
struct pci_dev *pci_dev;
};
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 5326dee62c74..dae4c5463973 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -35,7 +35,6 @@
static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/interrupt.h>
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 6422eb2a4208..15cef66f3a73 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -47,7 +47,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
index d8b3172e9cc0..8b60183652df 100644
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ b/drivers/net/sk98lin/h/skdrv1st.h
@@ -107,9 +107,6 @@
#ifndef __INC_SKDRV1ST_H
#define __INC_SKDRV1ST_H
-/* Check kernel version */
-#include <linux/version.h>
-
typedef struct s_AC SK_AC;
/* Set card versions */
@@ -135,7 +132,6 @@ typedef struct s_AC SK_AC;
#error You must compile this driver with "-O".
#endif
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index a38036f73346..3fce1a398217 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -361,7 +361,6 @@
* <linux/module.h>
*
* "h/skdrv1st.h"
- * <linux/version.h>
* <linux/types.h>
* <linux/kernel.h>
* <linux/string.h>
diff --git a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h
index cb29200514ed..d1b5250d153a 100644
--- a/drivers/net/sk_mca.h
+++ b/drivers/net/sk_mca.h
@@ -1,3 +1,5 @@
+#include <linux/version.h>
+
#ifndef _SK_MCA_INCLUDE_
#define _SK_MCA_INCLUDE_
diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/skfp/h/targetos.h
index 7c6c1bd85bca..94a81eede792 100644
--- a/drivers/net/skfp/h/targetos.h
+++ b/drivers/net/skfp/h/targetos.h
@@ -43,7 +43,6 @@
#undef ADDR
-#include <linux/version.h>
#include <asm/io.h>
#include <linux/netdevice.h>
#include <linux/fddidevice.h>
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 7d9d24d5d326..4d24343c1799 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -58,7 +58,6 @@ static const char version[] =
"smc9194.c:v0.14 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h
index bd7df5afa857..932cb70c4a7d 100644
--- a/drivers/net/tokenring/lanstreamer.h
+++ b/drivers/net/tokenring/lanstreamer.h
@@ -60,6 +60,8 @@
*
*/
+#include <linux/version.h>
+
#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include <asm/ioctl.h>
#define IOCTL_PRINT_RX_BUFS SIOCDEVPRIVATE
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 4c4b4dd034ab..fe9bc7a426f3 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -410,7 +410,7 @@ int init_module(void)
}
} else {
for(i = 0; num < ISATR_MAX_ADAPTERS && portlist[i]; i++) {
- if (setup_card(portlist[i], irq[i], dma[i]))
+ if (setup_card(portlist[i], irq[num], dma[num]) == 0)
num++;
}
}
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index da77f8bdb53f..b0bc243ac9e8 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -423,7 +423,7 @@ int init_module(void)
}
} else {
for(i = 0; num < ISATR_MAX_ADAPTERS && portlist[i]; i++) {
- if (setup_card(portlist[i], irq[i], dma[i]))
+ if (setup_card(portlist[i], irq[num], dma[num]) == 0)
num++;
}
}
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index ef5a3714dd1b..0761bc72691b 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -29,7 +29,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index e1062b3d654b..1931a5b05b3f 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -77,7 +77,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
#endif
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
diff --git a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c
index 17d797e727b1..a62fe5514470 100644
--- a/drivers/net/wan/comx-hw-comx.c
+++ b/drivers/net/wan/comx-hw-comx.c
@@ -51,7 +51,6 @@
#define VERSION "0.87"
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
diff --git a/drivers/net/wan/comx-hw-locomx.c b/drivers/net/wan/comx-hw-locomx.c
index 45bf7f870848..1d20fed5f6ee 100644
--- a/drivers/net/wan/comx-hw-locomx.c
+++ b/drivers/net/wan/comx-hw-locomx.c
@@ -38,7 +38,6 @@
#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
diff --git a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c
index 0881f7e17563..c6fb9ac67c21 100644
--- a/drivers/net/wan/comx-hw-mixcom.c
+++ b/drivers/net/wan/comx-hw-mixcom.c
@@ -41,7 +41,6 @@
#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
diff --git a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c
index a3a0f400e5a5..35328059a66a 100644
--- a/drivers/net/wan/comx-hw-munich.c
+++ b/drivers/net/wan/comx-hw-munich.c
@@ -30,7 +30,6 @@
#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
diff --git a/drivers/net/wan/comx-proto-fr.c b/drivers/net/wan/comx-proto-fr.c
index e1c83300548d..c9551366b74b 100644
--- a/drivers/net/wan/comx-proto-fr.c
+++ b/drivers/net/wan/comx-proto-fr.c
@@ -37,7 +37,6 @@
#define VERSION "0.73"
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c
index ae0f5fde7519..30c818601ecf 100644
--- a/drivers/net/wan/comx-proto-lapb.c
+++ b/drivers/net/wan/comx-proto-lapb.c
@@ -24,7 +24,6 @@
#define VERSION "0.80"
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
diff --git a/drivers/net/wan/comx-proto-ppp.c b/drivers/net/wan/comx-proto-ppp.c
index 991110142d1d..3f4501014739 100644
--- a/drivers/net/wan/comx-proto-ppp.c
+++ b/drivers/net/wan/comx-proto-ppp.c
@@ -34,7 +34,6 @@
#define VERSION "0.23"
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c
index 1418fd1e7b38..e296504cb02e 100644
--- a/drivers/net/wan/comx.c
+++ b/drivers/net/wan/comx.c
@@ -55,7 +55,6 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/jiffies.h>
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index a66e1a729689..cd1cd85691e8 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -78,7 +78,6 @@
#define CYCLOMX_X25_DEBUG 1
-#include <linux/version.h>
#include <linux/errno.h> /* return codes */
#include <linux/if_arp.h> /* ARPHRD_HWX25 */
#include <linux/kernel.h> /* printk(), and other useful stuff */
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index e16e4b79a5c3..6d3d2d461a75 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -40,7 +40,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 9d38514a9920..f1dfc6df73cd 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -80,7 +80,6 @@
* - misc crapectomy.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
diff --git a/drivers/net/wan/lmc/lmc_ver.h b/drivers/net/wan/lmc/lmc_ver.h
index 3e171caeee82..75ea93765c7c 100644
--- a/drivers/net/wan/lmc/lmc_ver.h
+++ b/drivers/net/wan/lmc/lmc_ver.h
@@ -1,3 +1,5 @@
+#include <linux/version.h>
+
#ifndef _IF_LMC_LINUXVER_
#define _IF_LMC_LINUXVER_
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 21d1deffca33..3fa5e3d61007 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -227,7 +227,6 @@ static char rcsid[] =
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#include <linux/if.h>
-#include <linux/version.h>
#include <net/syncppp.h>
#include <net/arp.h>
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index d683c01f0542..a07c82a57771 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -37,7 +37,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/errno.h>
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 81b2f271036c..6c620805fe92 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -53,6 +53,7 @@
#include <linux/skbuff.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <net/arp.h>
@@ -337,13 +338,12 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
outb( 0, ioaddr + CSR0 );
if( irq < 2 ) {
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
irq_mask = probe_irq_on();
outb( EN_INT | TR_REQ, ioaddr + CSR0 );
outb( PR_RES, ioaddr + CSR1 );
- delay = jiffies + HZ/20;
- while (time_before(jiffies, delay)) ;
+ mdelay(50);
irq = probe_irq_off(irq_mask);
outb( 0, ioaddr + CSR0 );
@@ -1562,13 +1562,13 @@ __setup( "sbni=", sbni_setup );
static u32
calc_crc32( u32 crc, u8 *p, u32 len )
{
- register u32 _crc __asm ( "ax" );
+ register u32 _crc;
_crc = crc;
__asm __volatile (
"xorl %%ebx, %%ebx\n"
- "movl %1, %%esi\n"
- "movl %2, %%ecx\n"
+ "movl %2, %%esi\n"
+ "movl %3, %%ecx\n"
"movl $crc32tab, %%edi\n"
"shrl $2, %%ecx\n"
"jz 1f\n"
@@ -1604,7 +1604,7 @@ calc_crc32( u32 crc, u8 *p, u32 len )
"jnz 0b\n"
"1:\n"
- "movl %2, %%ecx\n"
+ "movl %3, %%ecx\n"
"andl $3, %%ecx\n"
"jz 2f\n"
@@ -1629,9 +1629,9 @@ calc_crc32( u32 crc, u8 *p, u32 len )
"xorb 2(%%esi), %%bl\n"
"xorl (%%edi,%%ebx,4), %%eax\n"
"2:\n"
- :
- : "a" (_crc), "g" (p), "g" (len)
- : "ax", "bx", "cx", "dx", "si", "di"
+ : "=a" (_crc)
+ : "0" (_crc), "g" (p), "g" (len)
+ : "bx", "cx", "dx", "si", "di"
);
return _crc;
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index 5ca0ef0599b3..1e71ffda7cfc 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -49,7 +49,6 @@
*****************************************************************************/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 1a86e09ff325..a755df6cdef8 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -139,7 +139,6 @@
*****************************************************************************/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
index 490baed9fbab..5e3124856eb0 100644
--- a/drivers/net/wan/sdla_ft1.c
+++ b/drivers/net/wan/sdla_ft1.c
@@ -21,7 +21,6 @@
*****************************************************************************/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
index f68d3abca0fc..1761cb68ab48 100644
--- a/drivers/net/wan/sdla_ppp.c
+++ b/drivers/net/wan/sdla_ppp.c
@@ -91,7 +91,6 @@
*****************************************************************************/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index a963ef3debf3..3f2bbe8fbfbc 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -82,7 +82,6 @@
*=====================================================*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index 6610ed33e6ba..16f590614e53 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -91,7 +91,6 @@
#if defined(_LINUX_) /****** Linux *******************************/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
index de695ac6ff6e..c469c05ff658 100644
--- a/drivers/net/wan/sdlamain.c
+++ b/drivers/net/wan/sdlamain.c
@@ -46,7 +46,6 @@
* Jan 02, 1997 Gene Kozin Initial version.
*****************************************************************************/
-#include <linux/version.h>
#include <linux/config.h> /* OS configuration options */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index 2f337392ef91..250f5ea9bb75 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -31,7 +31,6 @@
struct slvl_device
{
- void *if_ptr; /* General purpose pointer (used by SPPP) */
struct z8530_channel *chan;
struct ppp_device netdev;
int channel;
@@ -40,7 +39,7 @@ struct slvl_device
struct slvl_board
{
- struct slvl_device dev[2];
+ struct slvl_device *dev[2];
struct z8530_dev board;
int iobase;
};
@@ -119,7 +118,6 @@ static int sealevel_open(struct net_device *d)
* Go go go
*/
netif_start_queue(d);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -153,7 +151,6 @@ static int sealevel_close(struct net_device *d)
z8530_sync_close(d, slvl->chan);
break;
}
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -202,48 +199,79 @@ static int sealevel_neigh_setup_dev(struct net_device *dev, struct neigh_parms *
return 0;
}
+
+static void slvl_setup(struct net_device *d)
+{
+ d->open = sealevel_open;
+ d->stop = sealevel_close;
+ d->hard_start_xmit = sealevel_queue_xmit;
+ d->get_stats = sealevel_get_stats;
+ d->set_multicast_list = NULL;
+ d->do_ioctl = sealevel_ioctl;
+ d->neigh_setup = sealevel_neigh_setup_dev;
+ d->set_mac_address = NULL;
+
+}
+
+static inline struct slvl_device *slvl_alloc(int iobase, int irq)
+{
+ struct net_device *d;
+ struct slvl_device *sv;
+
+ d = alloc_netdev(sizeof(struct slvl_device), "hdlc%d",
+ slvl_setup);
+
+ if (!d)
+ return NULL;
+
+ sv = d->priv;
+ sv->netdev.dev = d;
+ d->base_addr = iobase;
+ d->irq = irq;
+
+ sppp_attach(&sv->netdev);
+ return sv;
+}
+
+
/*
- * Description block for a Comtrol Hostess SV11 card
+ * Allocate and setup Sealevel board.
*/
-static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow)
+static __init struct slvl_board *slvl_init(int iobase, int irq,
+ int txdma, int rxdma, int slow)
{
struct z8530_dev *dev;
- struct slvl_device *sv;
struct slvl_board *b;
- int u;
/*
* Get the needed I/O space
*/
-
+
if(!request_region(iobase, 8, "Sealevel 4021"))
{
printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase);
return NULL;
}
- b=(struct slvl_board *)kmalloc(sizeof(struct slvl_board), GFP_KERNEL);
+ b = kmalloc(sizeof(struct slvl_board), GFP_KERNEL);
if(!b)
goto fail3;
-
- memset(b, 0, sizeof(*sv));
-
- b->dev[0].chan = &b->board.chanA;
- b->dev[0].if_ptr = &b->dev[0].netdev;
- b->dev[0].netdev.dev=(struct net_device *)
- kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if(!b->dev[0].netdev.dev)
+
+ memset(b, 0, sizeof(*b));
+ if (!(b->dev[0]= slvl_alloc(iobase, irq)))
goto fail2;
- b->dev[1].chan = &b->board.chanB;
- b->dev[1].if_ptr = &b->dev[1].netdev;
- b->dev[1].netdev.dev=(struct net_device *)
- kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if(!b->dev[1].netdev.dev)
+ b->dev[0]->chan = &b->board.chanA;
+ b->dev[0]->channel = 0;
+
+ if (!(b->dev[1] = slvl_alloc(iobase, irq)))
goto fail1_0;
- dev=&b->board;
+ b->dev[1]->chan = &b->board.chanB;
+ b->dev[1]->channel = 1;
+
+ dev = &b->board;
/*
* Stuff in the I/O addressing
@@ -287,8 +315,8 @@ static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, i
dev->irq=irq;
dev->chanA.private=&b->dev[0];
dev->chanB.private=&b->dev[1];
- dev->chanA.netdevice=b->dev[0].netdev.dev;
- dev->chanB.netdevice=b->dev[1].netdev.dev;
+ dev->chanA.netdevice=b->dev[0]->netdev.dev;
+ dev->chanB.netdevice=b->dev[1]->netdev.dev;
dev->chanA.dev=dev;
dev->chanB.dev=dev;
@@ -329,55 +357,18 @@ static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, i
enable_irq(irq);
- for(u=0; u<2; u++)
- {
- sv=&b->dev[u];
- sv->channel = u;
-
- if(dev_alloc_name(sv->chan->netdevice,"hdlc%d")>=0)
- {
- struct net_device *d=sv->chan->netdevice;
-
- /*
- * Initialise the PPP components
- */
- sppp_attach(&sv->netdev);
-
- /*
- * Local fields
- */
-
- d->base_addr = iobase;
- d->irq = irq;
- d->priv = sv;
- d->init = NULL;
-
- d->open = sealevel_open;
- d->stop = sealevel_close;
- d->hard_start_xmit = sealevel_queue_xmit;
- d->get_stats = sealevel_get_stats;
- d->set_multicast_list = NULL;
- d->do_ioctl = sealevel_ioctl;
- d->neigh_setup = sealevel_neigh_setup_dev;
- d->set_mac_address = NULL;
+ if (register_netdev(b->dev[0]->netdev.dev))
+ goto dmafail2;
- if(register_netdev(d)==-1)
- {
- printk(KERN_ERR "%s: unable to register device.\n",
- d->name);
- goto fail_unit;
- }
+ if (register_netdev(b->dev[1]->netdev.dev))
+ goto fail_unit;
- break;
- }
- }
z8530_describe(dev, "I/O", iobase);
dev->active=1;
return b;
fail_unit:
- if(u==1)
- unregister_netdev(b->dev[0].chan->netdevice);
+ unregister_netdev(b->dev[0]->netdev.dev);
dmafail2:
free_dma(dev->chanA.rxdma);
@@ -386,9 +377,9 @@ dmafail:
fail:
free_irq(irq, dev);
fail1_1:
- kfree(b->dev[1].netdev.dev);
+ free_netdev(b->dev[1]->netdev.dev);
fail1_0:
- kfree(b->dev[0].netdev.dev);
+ free_netdev(b->dev[0]->netdev.dev);
fail2:
kfree(b);
fail3:
@@ -396,7 +387,7 @@ fail3:
return NULL;
}
-static void slvl_shutdown(struct slvl_board *b)
+static void __exit slvl_shutdown(struct slvl_board *b)
{
int u;
@@ -404,8 +395,11 @@ static void slvl_shutdown(struct slvl_board *b)
for(u=0; u<2; u++)
{
- sppp_detach(b->dev[u].netdev.dev);
- unregister_netdev(b->dev[u].netdev.dev);
+ struct net_device *d = b->dev[u]->netdev.dev;
+ sppp_detach(d);
+
+ unregister_netdev(d);
+ free_netdev(d);
}
free_irq(b->board.irq, &b->board);
@@ -416,7 +410,6 @@ static void slvl_shutdown(struct slvl_board *b)
release_region(b->iobase, 8);
}
-#ifdef MODULE
static int io=0x238;
static int txdma=1;
@@ -441,20 +434,22 @@ MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021");
static struct slvl_board *slvl_unit;
-int init_module(void)
+static int __init slvl_init_module(void)
{
+#ifdef MODULE
printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.02.\n");
- printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");
- if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL)
- return -ENODEV;
- return 0;
+ printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");
+#endif
+ slvl_unit = slvl_init(io, irq, txdma, rxdma, slow);
+
+ return slvl_unit ? 0 : -ENODEV;
}
-void cleanup_module(void)
+static void __exit slvl_cleanup_module(void)
{
if(slvl_unit)
slvl_shutdown(slvl_unit);
}
-#endif
-
+module_init(slvl_init_module);
+module_exit(slvl_cleanup_module);
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
index 0eeb51c7105f..6aa6987d96cb 100644
--- a/drivers/net/wan/wanpipe_multppp.c
+++ b/drivers/net/wan/wanpipe_multppp.c
@@ -18,7 +18,6 @@
*****************************************************************************/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 411a448d2f2f..cebcdbbfc7f6 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -235,7 +235,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
int reg4 = inb(ioaddr+4);
if (ancient || reg1 == 0xff) { /* Ack!! No way to read the IRQ! */
short nic_addr = ioaddr+WD_NIC_OFFSET;
- unsigned long irq_mask, delay;
+ unsigned long irq_mask;
/* We have an old-style ethercard that doesn't report its IRQ
line. Do autoirq to find the IRQ line. Note that this IS NOT
@@ -248,8 +248,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
outb_p(0x00, nic_addr + EN0_RCNTLO);
outb_p(0x00, nic_addr + EN0_RCNTHI);
outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
- delay = jiffies + HZ/50;
- while (time_before(jiffies, delay)) ;
+ mdelay(20);
dev->irq = probe_irq_off(irq_mask);
outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 4b78dce165f5..41a35807b6cd 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -18,7 +18,6 @@
======================================================================*/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -42,7 +41,6 @@
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
-#include <linux/config.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
@@ -1435,7 +1433,7 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
int i,j;
u32 counter;
- u8 *cipher;
+ u8 *cipher, plain[16];
struct scatterlist sg[1];
crypto_cipher_setkey(tfm, pkey, 16);
@@ -1446,8 +1444,9 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
aes_counter[13] = (u8)(counter >> 16);
aes_counter[12] = (u8)(counter >> 24);
counter++;
- sg[0].page = virt_to_page(aes_counter);
- sg[0].offset = ((long) aes_counter & ~PAGE_MASK);
+ memcpy (plain, aes_counter, 16);
+ sg[0].page = virt_to_page(plain);
+ sg[0].offset = ((long) plain & ~PAGE_MASK);
sg[0].length = 16;
crypto_cipher_encrypt(tfm, sg, sg, 16);
cipher = kmap(sg[0].page) + sg[0].offset;
@@ -4624,7 +4623,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
return -ENODEV;
pci_set_drvdata(pdev, dev);
- clear_bit (FLAG_PCI, &((struct airo_info *)dev->priv)->flags);
+ set_bit (FLAG_PCI, &((struct airo_info *)dev->priv)->flags);
return 0;
}
diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c
index ccd6e2ea3848..18f055132858 100644
--- a/drivers/net/wireless/arlan-proc.c
+++ b/drivers/net/wireless/arlan-proc.c
@@ -5,9 +5,6 @@
#ifdef CONFIG_PROC_FS
-
-#include <linux/version.h>
-
/* void enableReceive(struct net_device* dev);
*/
diff --git a/drivers/net/wireless/arlan.c b/drivers/net/wireless/arlan.c
index 0de038cd8275..4c72ab91fbd7 100644
--- a/drivers/net/wireless/arlan.c
+++ b/drivers/net/wireless/arlan.c
@@ -5,6 +5,7 @@
* This module provides support for the Arlan 655 card made by Aironet
*/
+#include <linux/version.h>
#include <linux/config.h>
#include "arlan.h"
diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h
index 3a6fe9c6b6ca..aacef0d77a56 100644
--- a/drivers/net/wireless/arlan.h
+++ b/drivers/net/wireless/arlan.h
@@ -3,7 +3,6 @@
* Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
* GNU General Public License applies
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/config.h>
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 7a49e54c2379..57463d81c457 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -83,7 +83,6 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/include/linux/input.h b/include/linux/input.h
index da49f7ee0f18..c98e6fc575fe 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -751,7 +751,7 @@ struct ff_effect {
#define LONG(x) ((x)/BITS_PER_LONG)
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
- ((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
+ ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
diff --git a/include/linux/serio.h b/include/linux/serio.h
index f1c67ff70f2a..66fdaf9b1be5 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio);
irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
void serio_register_port(struct serio *serio);
+void serio_register_slave_port(struct serio *serio);
void serio_unregister_port(struct serio *serio);
+void serio_unregister_slave_port(struct serio *serio);
void serio_register_device(struct serio_dev *dev);
void serio_unregister_device(struct serio_dev *dev);
@@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_RS232 0x02000000UL
#define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PC9800 0x04000000UL
+#define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_PROTO 0xFFUL
#define SERIO_MSC 0x01
diff --git a/include/net/syncppp.h b/include/net/syncppp.h
index 07214226b4e3..f2032606419e 100644
--- a/include/net/syncppp.h
+++ b/include/net/syncppp.h
@@ -57,8 +57,11 @@ struct ppp_device
struct sppp sppp; /* Synchronous PPP */
};
-#define sppp_of(dev) \
- (&((struct ppp_device *)(*(unsigned long *)((dev)->priv)))->sppp)
+static inline struct sppp *sppp_of(struct net_device *dev)
+{
+ struct ppp_device *ppp = dev->priv;
+ return &ppp->sppp;
+}
#define PP_KEEPALIVE 0x01 /* use keepalive protocol */
#define PP_CISCO 0x02 /* use Cisco protocol instead of PPP */
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index 1006ad599d35..40af7a1c4633 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -2728,7 +2728,7 @@ static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec
i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
/* wait for analog ready */
- for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
+ for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
{
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/20);
@@ -3091,10 +3091,17 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
return -EIO;
if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) {
- printk(KERN_ERR "intel810: architecture does not support"
+ printk(KERN_ERR "i810_audio: architecture does not support"
" 32bit PCI busmaster DMA\n");
return -ENODEV;
}
+
+ if( pci_resource_start(pci_dev, 1) == 0)
+ {
+ /* MMIO only ICH5 .. here be dragons .. */
+ printk(KERN_ERR "i810_audio: Pure MMIO interfaces not yet supported.\n");
+ return -ENODEV;
+ }
if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "i810_audio: out of memory\n");