diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-20 04:18:59 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-20 04:18:59 -0700 |
| commit | 834ae7f12afa0d4350e3874a135aa5a4c24a87d7 (patch) | |
| tree | 59478adff11dc8cd1aa0654dc5475a8216b29e80 | |
| parent | 4f3a1d592e8dc6d7327fc7ca915b9b764883d5b7 (diff) | |
| parent | 24a2d11aa804699923077b0e13d1b65e36217db0 (diff) | |
Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
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(®s->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"); |
