From e9c8862f19958846dd0c7b39d0f6216aad6c7bee Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 00:20:47 -0400 Subject: Input: remove accept method from input_dev This method used to enforce exclusive access to iforce devices, but presenlty there are no known users of this method. Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 4 ---- drivers/input/input.c | 9 --------- 2 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a29d5ce..2426a5d 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -127,14 +127,10 @@ static int evdev_open(struct inode * inode, struct file * file) { struct evdev_list *list; int i = iminor(inode) - EVDEV_MINOR_BASE; - int accept_err; if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist) return -ENODEV; - if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) - return accept_err; - if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL))) return -ENOMEM; diff --git a/drivers/input/input.c b/drivers/input/input.c index a90486f..c2e4d9b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -197,15 +197,6 @@ static void input_repeat_key(unsigned long data) mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); } -int input_accept_process(struct input_handle *handle, struct file *file) -{ - if (handle->dev->accept) - return handle->dev->accept(handle->dev, file); - - return 0; -} -EXPORT_SYMBOL(input_accept_process); - int input_grab_device(struct input_handle *handle) { if (handle->dev->grab) -- cgit v1.1 From c7e8dc6ee6d59bf72f5478fa6355a27750e6c7d2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 00:21:03 -0400 Subject: Input: add start() method to input handlers The new start() method is called immediately after connect() and also when "grabbed" device is released by its owner. This will allow input handlers to re-synchronize state of once-grabbed device with the rest of devices. Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 39 ++++++++++++++++++++------------------- drivers/input/input.c | 12 ++++++++++-- 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 056ebe8..38de44b 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -988,7 +988,7 @@ static inline unsigned char getleds(void) * interrupt routines for this thing allows us to easily mask * this when we don't want any of the above to happen. * This allows for easy and efficient race-condition prevention - * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ... + * for kbd_start => input_event(dev, EV_LED, ...) => ... */ static void kbd_bh(unsigned long dummy) @@ -1011,23 +1011,6 @@ static void kbd_bh(unsigned long dummy) DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); -/* - * This allows a newly plugged keyboard to pick the LED state. - */ -static void kbd_refresh_leds(struct input_handle *handle) -{ - unsigned char leds = ledstate; - - tasklet_disable(&keyboard_tasklet); - if (leds != 0xff) { - input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); - input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_sync(handle->dev); - } - tasklet_enable(&keyboard_tasklet); -} - #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ @@ -1307,7 +1290,6 @@ static struct input_handle *kbd_connect(struct input_handler *handler, handle->name = "kbd"; input_open_device(handle); - kbd_refresh_leds(handle); return handle; } @@ -1318,6 +1300,24 @@ static void kbd_disconnect(struct input_handle *handle) kfree(handle); } +/* + * Start keyboard handler on the new keyboard by refreshing LED state to + * match the rest of the system. + */ +static void kbd_start(struct input_handle *handle) +{ + unsigned char leds = ledstate; + + tasklet_disable(&keyboard_tasklet); + if (leds != 0xff) { + input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); + input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_sync(handle->dev); + } + tasklet_enable(&keyboard_tasklet); +} + static struct input_device_id kbd_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, @@ -1338,6 +1338,7 @@ static struct input_handler kbd_handler = { .event = kbd_event, .connect = kbd_connect, .disconnect = kbd_disconnect, + .start = kbd_start, .name = "kbd", .id_table = kbd_ids, }; diff --git a/drivers/input/input.c b/drivers/input/input.c index c2e4d9b..7aeebb9 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -209,8 +209,13 @@ EXPORT_SYMBOL(input_grab_device); void input_release_device(struct input_handle *handle) { - if (handle->dev->grab == handle) + if (handle->dev->grab == handle) { handle->dev->grab = NULL; + + list_for_each_entry(handle, &handle->dev->h_list, d_node) + if (handle->handler->start) + handle->handler->start(handle); + } } EXPORT_SYMBOL(input_release_device); @@ -954,8 +959,11 @@ int input_register_device(struct input_dev *dev) list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) + if ((handle = handler->connect(handler, dev, id))) { input_link_handle(handle); + if (handler->start) + handler->start(handle); + } input_wakeup_procfs_readers(); -- cgit v1.1 From 0e739d28762e78c746cad8edd33223550a1c6a3f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 00:22:43 -0400 Subject: Input: introduce input_inject_event() function Create input_inject_event() function which is to be used by input handlers as opposed to input_event() which is reserved for drivers implementing input devices. The difference is that if device is "grabbed" by some process input_inject_event() will ignore events unless sent from the handle that is currently owns the device. Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 36 ++++++++++++++++++------------------ drivers/input/evdev.c | 6 +++--- drivers/input/input.c | 27 +++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 38de44b..1e946f5 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -223,13 +223,13 @@ static void kd_nosound(unsigned long ignored) { struct list_head *node; - list_for_each(node,&kbd_handler.h_list) { + list_for_each(node, &kbd_handler.h_list) { struct input_handle *handle = to_handle_h(node); if (test_bit(EV_SND, handle->dev->evbit)) { if (test_bit(SND_TONE, handle->dev->sndbit)) - input_event(handle->dev, EV_SND, SND_TONE, 0); + input_inject_event(handle, EV_SND, SND_TONE, 0); if (test_bit(SND_BELL, handle->dev->sndbit)) - input_event(handle->dev, EV_SND, SND_BELL, 0); + input_inject_event(handle, EV_SND, SND_BELL, 0); } } } @@ -247,11 +247,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks) struct input_handle *handle = to_handle_h(node); if (test_bit(EV_SND, handle->dev->evbit)) { if (test_bit(SND_TONE, handle->dev->sndbit)) { - input_event(handle->dev, EV_SND, SND_TONE, hz); + input_inject_event(handle, EV_SND, SND_TONE, hz); break; } if (test_bit(SND_BELL, handle->dev->sndbit)) { - input_event(handle->dev, EV_SND, SND_BELL, 1); + input_inject_event(handle, EV_SND, SND_BELL, 1); break; } } @@ -272,15 +272,15 @@ int kbd_rate(struct kbd_repeat *rep) unsigned int d = 0; unsigned int p = 0; - list_for_each(node,&kbd_handler.h_list) { + list_for_each(node, &kbd_handler.h_list) { struct input_handle *handle = to_handle_h(node); struct input_dev *dev = handle->dev; if (test_bit(EV_REP, dev->evbit)) { if (rep->delay > 0) - input_event(dev, EV_REP, REP_DELAY, rep->delay); + input_inject_event(handle, EV_REP, REP_DELAY, rep->delay); if (rep->period > 0) - input_event(dev, EV_REP, REP_PERIOD, rep->period); + input_inject_event(handle, EV_REP, REP_PERIOD, rep->period); d = dev->rep[REP_DELAY]; p = dev->rep[REP_PERIOD]; } @@ -988,7 +988,7 @@ static inline unsigned char getleds(void) * interrupt routines for this thing allows us to easily mask * this when we don't want any of the above to happen. * This allows for easy and efficient race-condition prevention - * for kbd_start => input_event(dev, EV_LED, ...) => ... + * for kbd_start => input_inject_event(dev, EV_LED, ...) => ... */ static void kbd_bh(unsigned long dummy) @@ -998,11 +998,11 @@ static void kbd_bh(unsigned long dummy) if (leds != ledstate) { list_for_each(node, &kbd_handler.h_list) { - struct input_handle * handle = to_handle_h(node); - input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); - input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_sync(handle->dev); + struct input_handle *handle = to_handle_h(node); + input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); + input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_inject_event(handle, EV_SYN, SYN_REPORT, 0); } } @@ -1310,10 +1310,10 @@ static void kbd_start(struct input_handle *handle) tasklet_disable(&keyboard_tasklet); if (leds != 0xff) { - input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); - input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_sync(handle->dev); + input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); + input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_inject_event(handle, EV_SYN, SYN_REPORT, 0); } tasklet_enable(&keyboard_tasklet); } diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2426a5d..4bf4818 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -256,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ if (evdev_event_from_user(buffer + retval, &event)) return -EFAULT; - input_event(list->evdev->handle.dev, event.type, event.code, event.value); + input_inject_event(&list->evdev->handle, event.type, event.code, event.value); retval += evdev_event_size(); } @@ -424,8 +424,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, if (get_user(v, ip + 1)) return -EFAULT; - input_event(dev, EV_REP, REP_DELAY, u); - input_event(dev, EV_REP, REP_PERIOD, v); + input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); + input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); return 0; diff --git a/drivers/input/input.c b/drivers/input/input.c index 7aeebb9..e209139 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -35,6 +35,16 @@ static LIST_HEAD(input_handler_list); static struct input_handler *input_table[8]; +/** + * input_event() - report new input event + * @handle: device that generated the event + * @type: type of the event + * @code: event code + * @value: value of the event + * + * This function should be used by drivers implementing various input devices + * See also input_inject_event() + */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handle; @@ -183,6 +193,23 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in } EXPORT_SYMBOL(input_event); +/** + * input_inject_event() - send input event from input handler + * @handle: input handle to send event through + * @type: type of the event + * @code: event code + * @value: value of the event + * + * Similar to input_event() but will ignore event if device is "grabbed" and handle + * injecting event is not the one that owns the device. + */ +void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) +{ + if (!handle->dev->grab || handle->dev->grab == handle) + input_event(handle->dev, type, code, value); +} +EXPORT_SYMBOL(input_inject_event); + static void input_repeat_key(unsigned long data) { struct input_dev *dev = (void *) data; -- cgit v1.1 From c7948989f84ee6e9c68cc643f8c6a635eb7a904b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 6 Jul 2006 00:23:38 -0400 Subject: Input: wistron - fix section reference mismatches Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index ccf0fae..a8efc1a 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -94,7 +94,7 @@ static void call_bios(struct regs *regs) static ssize_t __init locate_wistron_bios(void __iomem *base) { - static const unsigned char __initdata signature[] = + static unsigned char __initdata signature[] = { 0x42, 0x21, 0x55, 0x30 }; ssize_t offset; @@ -259,11 +259,11 @@ static int __init dmi_matched(struct dmi_system_id *dmi) return 1; } -static struct key_entry keymap_empty[] = { +static struct key_entry keymap_empty[] __initdata = { { KE_END, 0 } }; -static struct key_entry keymap_fs_amilo_pro_v2000[] = { +static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { { KE_KEY, 0x01, KEY_HELP }, { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, @@ -273,7 +273,7 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = { { KE_END, 0 } }; -static struct key_entry keymap_fujitsu_n3510[] = { +static struct key_entry keymap_fujitsu_n3510[] __initdata = { { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, { KE_KEY, 0x36, KEY_WWW }, @@ -285,7 +285,7 @@ static struct key_entry keymap_fujitsu_n3510[] = { { KE_END, 0 } }; -static struct key_entry keymap_wistron_ms2111[] = { +static struct key_entry keymap_wistron_ms2111[] __initdata = { { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, { KE_KEY, 0x13, KEY_PROG3 }, @@ -294,7 +294,7 @@ static struct key_entry keymap_wistron_ms2111[] = { { KE_END, 0 } }; -static struct key_entry keymap_wistron_ms2141[] = { +static struct key_entry keymap_wistron_ms2141[] __initdata = { { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, { KE_WIFI, 0x30, 0 }, @@ -307,7 +307,7 @@ static struct key_entry keymap_wistron_ms2141[] = { { KE_END, 0 } }; -static struct key_entry keymap_acer_aspire_1500[] = { +static struct key_entry keymap_acer_aspire_1500[] __initdata = { { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, { KE_WIFI, 0x30, 0 }, @@ -317,7 +317,7 @@ static struct key_entry keymap_acer_aspire_1500[] = { { KE_END, 0 } }; -static struct key_entry keymap_acer_travelmate_240[] = { +static struct key_entry keymap_acer_travelmate_240[] __initdata = { { KE_KEY, 0x31, KEY_MAIL }, { KE_KEY, 0x36, KEY_WWW }, { KE_KEY, 0x11, KEY_PROG1 }, @@ -327,7 +327,7 @@ static struct key_entry keymap_acer_travelmate_240[] = { { KE_END, 0 } }; -static struct key_entry keymap_aopen_1559as[] = { +static struct key_entry keymap_aopen_1559as[] __initdata = { { KE_KEY, 0x01, KEY_HELP }, { KE_KEY, 0x06, KEY_PROG3 }, { KE_KEY, 0x11, KEY_PROG1 }, @@ -343,7 +343,7 @@ static struct key_entry keymap_aopen_1559as[] = { * a list of buttons and their key codes (reported when loading this module * with force=1) and the output of dmidecode to $MODULE_AUTHOR. */ -static struct dmi_system_id dmi_ids[] = { +static struct dmi_system_id dmi_ids[] __initdata = { { .callback = dmi_matched, .ident = "Fujitsu-Siemens Amilo Pro V2000", -- cgit v1.1 From 699756199d65700e8deed59ae250439ca8684686 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 23:54:30 -0400 Subject: Input: fm801-gp - fix use after free Fixes Coverity #id 916 Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/fm801-gp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 47e93da..90de5af 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device gp->gameport = port; gp->res_port = request_region(port->io, 0x10, "FM801 GP"); if (!gp->res_port) { - kfree(gp); - gameport_free_port(port); printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n", port->io, port->io + 0x0f); + gameport_free_port(port); + kfree(gp); return -EBUSY; } -- cgit v1.1 From 95349fe8144b7d18f04bdca1c2d3fb85789de4fb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 23:54:48 -0400 Subject: Input: libps2 - warn instead of oopsing when passed bad arguments This is more user-friendly and also fixes Coverity #id 249 Signed-off-by: Dmitry Torokhov --- drivers/input/serio/libps2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 61a6f97..ed202f2 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -177,6 +177,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) return -1; } + if (send && !param) { + WARN_ON(1); + return -1; + } + mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING); serio_pause_rx(ps2dev->serio); -- cgit v1.1 From 8d64d3722c6abbb43bccd518ececc5559e1962b4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 6 Jul 2006 23:55:00 -0400 Subject: Input: iforce - check array bounds before accessing elements Fixes Coverity #id 864 Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 6d99e3c..dc6cfea 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -222,22 +222,22 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id) int err = 0; struct iforce_core_effect* core_effect; - /* Check who is trying to erase this effect */ - if (iforce->core_effects[effect_id].owner != current->pid) { - printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner); - return -EACCES; - } - if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) return -EINVAL; - core_effect = iforce->core_effects + effect_id; + core_effect = &iforce->core_effects[effect_id]; + + /* Check who is trying to erase this effect */ + if (core_effect->owner != current->pid) { + printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner); + return -EACCES; + } if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) - err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk)); + err = release_resource(&core_effect->mod1_chunk); if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) - err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk)); + err = release_resource(&core_effect->mod2_chunk); /*TODO: remember to change that if more FF_MOD* bits are added */ core_effect->flags[0] = 0; -- cgit v1.1 From b53174fb5a0e47a19e10b8ef74ab0c12a19f92dc Mon Sep 17 00:00:00 2001 From: Przemek Iskra Date: Sat, 15 Jul 2006 01:16:21 -0400 Subject: Input: iforce - add Trust Force Feedback Race Master support Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index dc6cfea..b4914e7 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -79,6 +79,7 @@ static struct iforce_device iforce_device[] = { { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? + { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; -- cgit v1.1 From a2b2ed2ce20ae6c335a27ae5bf8580f385014e70 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 15 Jul 2006 01:17:38 -0400 Subject: Input: fix list iteration in input_release_device() Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index e209139..9c98b6d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -236,10 +236,12 @@ EXPORT_SYMBOL(input_grab_device); void input_release_device(struct input_handle *handle) { - if (handle->dev->grab == handle) { - handle->dev->grab = NULL; + struct input_dev *dev = handle->dev; + + if (dev->grab == handle) { + dev->grab = NULL; - list_for_each_entry(handle, &handle->dev->h_list, d_node) + list_for_each_entry(handle, &dev->h_list, d_node) if (handle->handler->start) handle->handler->start(handle); } -- cgit v1.1 From cb78623517ca08a035a3f69c0ca6d68a0123e649 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 15 Jul 2006 01:17:54 -0400 Subject: Input: HID - fix potential out-of-bound array access Fixes Coverity #id 978 Signed-off-by: Dmitry Torokhov --- drivers/usb/input/hid-input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 028e1ad..7208839 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -607,7 +607,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } - if (usage->hat_min < usage->hat_max || usage->hat_dir) { + if (usage->type == EV_ABS && + (usage->hat_min < usage->hat_max || usage->hat_dir)) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { input_set_abs_params(input, i, -1, 1, 0, 0); -- cgit v1.1 From b6d786dbe6fc19b51edd6cf6de84fd65b702c800 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 Jul 2006 01:08:51 -0400 Subject: Input: add missing handler->start() call The start() method need to be called every time we create a new handle. This includes not only registering new devices but also when registering new handlers. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index 9c98b6d..9cb4b9a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1056,8 +1056,11 @@ void input_register_handler(struct input_handler *handler) list_for_each_entry(dev, &input_dev_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) + if ((handle = handler->connect(handler, dev, id))) { input_link_handle(handle); + if (handler->start) + handler->start(handle); + } input_wakeup_procfs_readers(); } -- cgit v1.1 From 826d598242d9200ddee63fce96f03793fddee4fc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 Jul 2006 01:09:10 -0400 Subject: Input: hiddev - use standard list implementation Fixes Coverity #id 303 Signed-off-by: Dmitry Torokhov --- drivers/usb/input/hiddev.c | 72 ++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 70477f0..f6b839c 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -49,7 +49,7 @@ struct hiddev { int open; wait_queue_head_t wait; struct hid_device *hid; - struct hiddev_list *list; + struct list_head list; }; struct hiddev_list { @@ -59,7 +59,7 @@ struct hiddev_list { unsigned flags; struct fasync_struct *fasync; struct hiddev *hiddev; - struct hiddev_list *next; + struct list_head node; }; static struct hiddev *hiddev_table[HIDDEV_MINORS]; @@ -73,12 +73,15 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS]; static struct hid_report * hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) { - unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; struct hid_report_enum *report_enum; + struct hid_report *report; struct list_head *list; if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; + rinfo->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (rinfo->report_type - HID_REPORT_TYPE_MIN); @@ -88,21 +91,25 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) break; case HID_REPORT_ID_FIRST: - list = report_enum->report_list.next; - if (list == &report_enum->report_list) + if (list_empty(&report_enum->report_list)) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + list = report_enum->report_list.next; + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; case HID_REPORT_ID_NEXT: - list = (struct list_head *) - report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; - if (list == NULL) + report = report_enum->report_id_hash[rid]; + if (!report) return NULL; - list = list->next; + + list = report->list.next; if (list == &report_enum->report_list) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; + + report = list_entry(list, struct hid_report, list); + rinfo->report_id = report->id; break; default: @@ -125,12 +132,13 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) struct hid_field *field; if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) return NULL; + uref->report_type > HID_REPORT_TYPE_MAX) + return NULL; report_enum = hid->report_enum + (uref->report_type - HID_REPORT_TYPE_MIN); - list_for_each_entry(report, &report_enum->report_list, list) + list_for_each_entry(report, &report_enum->report_list, list) { for (i = 0; i < report->maxfield; i++) { field = report->field[i]; for (j = 0; j < field->maxusage; j++) { @@ -142,6 +150,7 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) } } } + } return NULL; } @@ -150,9 +159,9 @@ static void hiddev_send_event(struct hid_device *hid, struct hiddev_usage_ref *uref) { struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list = hiddev->list; + struct hiddev_list *list; - while (list) { + list_for_each_entry(list, &hiddev->list, node) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { list->buffer[list->head] = *uref; @@ -160,8 +169,6 @@ static void hiddev_send_event(struct hid_device *hid, (HIDDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } - - list = list->next; } wake_up_interruptible(&hiddev->wait); @@ -180,7 +187,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = field->report->id; uref.field_index = field->index; uref.usage_index = (usage - field->usage); @@ -200,7 +207,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); uref.report_id = report->id; uref.field_index = HID_FIELD_INDEX_NONE; @@ -213,7 +220,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) { int retval; struct hiddev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } @@ -224,14 +233,9 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; - struct hiddev_list **listptr; - listptr = &list->hiddev->list; hiddev_fasync(-1, file, 0); - - while (*listptr && (*listptr != list)) - listptr = &((*listptr)->next); - *listptr = (*listptr)->next; + list_del(&list->node); if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -248,7 +252,8 @@ static int hiddev_release(struct inode * inode, struct file * file) /* * open file op */ -static int hiddev_open(struct inode * inode, struct file * file) { +static int hiddev_open(struct inode *inode, struct file *file) +{ struct hiddev_list *list; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -260,9 +265,7 @@ static int hiddev_open(struct inode * inode, struct file * file) { return -ENOMEM; list->hiddev = hiddev_table[i]; - list->next = hiddev_table[i]->list; - hiddev_table[i]->list = list; - + list_add_tail(&list->node, &hiddev_table[i]->list); file->private_data = list; if (!list->hiddev->open++) @@ -362,6 +365,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun static unsigned int hiddev_poll(struct file *file, poll_table *wait) { struct hiddev_list *list = file->private_data; + poll_wait(file, &list->hiddev->wait, wait); if (list->head != list->tail) return POLLIN | POLLRDNORM; @@ -382,7 +386,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; - struct hiddev_usage_ref_multi *uref_multi=NULL; + struct hiddev_usage_ref_multi *uref_multi = NULL; struct hiddev_usage_ref *uref; struct hiddev_devinfo dinfo; struct hid_report *report; @@ -764,15 +768,15 @@ int hiddev_connect(struct hid_device *hid) } init_waitqueue_head(&hiddev->wait); - - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; - + INIT_LIST_HEAD(&hiddev->list); hiddev->hid = hid; hiddev->exist = 1; hid->minor = hid->intf->minor; hid->hiddev = hiddev; + hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + return 0; } -- cgit v1.1 From 2b192908b8e74ce0753c7dff92d244735d1eeed9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 Jul 2006 01:13:26 -0400 Subject: Input: keyboard - remove static variable and clean up initialization Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 1e946f5..1120586 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals); struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct kbd_struct *kbd = kbd_table; -static struct kbd_struct kbd0; int spawnpid, spawnsig; @@ -1347,15 +1346,15 @@ int __init kbd_init(void) { int i; - kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; - kbd0.ledmode = LED_SHOW_FLAGS; - kbd0.lockstate = KBD_DEFLOCK; - kbd0.slockstate = 0; - kbd0.modeflags = KBD_DEFMODE; - kbd0.kbdmode = VC_XLATE; - - for (i = 0 ; i < MAX_NR_CONSOLES ; i++) - kbd_table[i] = kbd0; + for (i = 0; i < MAX_NR_CONSOLES; i++) { + kbd_table[i].ledflagstate = KBD_DEFLEDS; + kbd_table[i].default_ledflagstate = KBD_DEFLEDS; + kbd_table[i].ledmode = LED_SHOW_FLAGS; + kbd_table[i].lockstate = KBD_DEFLOCK; + kbd_table[i].slockstate = 0; + kbd_table[i].modeflags = KBD_DEFMODE; + kbd_table[i].kbdmode = VC_XLATE; + } input_register_handler(&kbd_handler); -- cgit v1.1 From 896cdc7b802c972d625351eb47d4add22d1fccb6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 19 Jul 2006 01:14:25 -0400 Subject: Input: keyboard - simplify emulate_raw() implementation Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 1120586..30a7454 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1025,7 +1025,7 @@ static const unsigned short x86_keycodes[256] = 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92, - 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, + 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339, 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349, 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355, 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361, @@ -1047,38 +1047,55 @@ extern void sun_do_break(void); static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) { - if (keycode > 255 || !x86_keycodes[keycode]) - return -1; + int code; switch (keycode) { case KEY_PAUSE: put_queue(vc, 0xe1); put_queue(vc, 0x1d | up_flag); put_queue(vc, 0x45 | up_flag); - return 0; + break; + case KEY_HANGEUL: if (!up_flag) put_queue(vc, 0xf2); - return 0; + break; + case KEY_HANJA: if (!up_flag) put_queue(vc, 0xf1); - return 0; - } + break; - if (keycode == KEY_SYSRQ && sysrq_alt) { - put_queue(vc, 0x54 | up_flag); - return 0; - } + case KEY_SYSRQ: + /* + * Real AT keyboards (that's what we're trying + * to emulate here emit 0xe0 0x2a 0xe0 0x37 when + * pressing PrtSc/SysRq alone, but simply 0x54 + * when pressing Alt+PrtSc/SysRq. + */ + if (sysrq_alt) { + put_queue(vc, 0x54 | up_flag); + } else { + put_queue(vc, 0xe0); + put_queue(vc, 0x2a | up_flag); + put_queue(vc, 0xe0); + put_queue(vc, 0x37 | up_flag); + } + break; + + default: + if (keycode > 255) + return -1; - if (x86_keycodes[keycode] & 0x100) - put_queue(vc, 0xe0); + code = x86_keycodes[keycode]; + if (!code) + return -1; - put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag); + if (code & 0x100) + put_queue(vc, 0xe0); + put_queue(vc, (code & 0x7f) | up_flag); - if (keycode == KEY_SYSRQ) { - put_queue(vc, 0xe0); - put_queue(vc, 0x37 | up_flag); + break; } return 0; -- cgit v1.1 From 2c1dd69d28cba5a51e838897e0335f82a292f366 Mon Sep 17 00:00:00 2001 From: Nick Martin Date: Wed, 19 Jul 2006 01:14:44 -0400 Subject: Input: spaceball - make 4000FLX Lefty work Although the Spaceball 4000FLX Lefty is already supported by the spaceball driver, it does not register properly due to SPACEBALL_MAX_ID being set too low. Increment SPACEBALL_MAX_ID such that the 4000FLX Lefty is properly recognized. Signed-off-by: Nick Martin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/spaceball.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 75eb5ca..7a19ee0 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -50,7 +50,7 @@ MODULE_LICENSE("GPL"); */ #define SPACEBALL_MAX_LENGTH 128 -#define SPACEBALL_MAX_ID 8 +#define SPACEBALL_MAX_ID 9 #define SPACEBALL_1003 1 #define SPACEBALL_2003B 3 -- cgit v1.1 From 73b59a3b1c09e4bfc678400b77b96134dcfbf112 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 19 Jul 2006 01:14:55 -0400 Subject: Input: serio/gameport - check whether driver core calls succeeded Signed-off-by: Randy Dunlap Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 66 +++++++++++++++++++++++++++++---------- drivers/input/serio/serio.c | 65 +++++++++++++++++++++++++++++--------- 2 files changed, 100 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 36644bf..3f47ae5 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -53,6 +53,7 @@ static LIST_HEAD(gameport_list); static struct bus_type gameport_bus; +static void gameport_add_driver(struct gameport_driver *drv); static void gameport_add_port(struct gameport *gameport); static void gameport_destroy_port(struct gameport *gameport); static void gameport_reconnect_port(struct gameport *gameport); @@ -211,8 +212,14 @@ static void gameport_release_driver(struct gameport *gameport) static void gameport_find_driver(struct gameport *gameport) { + int error; + down_write(&gameport_bus.subsys.rwsem); - device_attach(&gameport->dev); + error = device_attach(&gameport->dev); + if (error < 0) + printk(KERN_WARNING + "gameport: device_attach() failed for %s (%s), error: %d\n", + gameport->phys, gameport->name, error); up_write(&gameport_bus.subsys.rwsem); } @@ -316,7 +323,6 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) spin_unlock_irqrestore(&gameport_event_lock, flags); } - static struct gameport_event *gameport_get_event(void) { struct gameport_event *event; @@ -342,7 +348,6 @@ static struct gameport_event *gameport_get_event(void) static void gameport_handle_event(void) { struct gameport_event *event; - struct gameport_driver *gameport_drv; mutex_lock(&gameport_mutex); @@ -369,8 +374,7 @@ static void gameport_handle_event(void) break; case GAMEPORT_REGISTER_DRIVER: - gameport_drv = event->object; - driver_register(&gameport_drv->driver); + gameport_add_driver(event->object); break; default: @@ -532,6 +536,7 @@ static void gameport_init_port(struct gameport *gameport) if (gameport->parent) gameport->dev.parent = &gameport->parent->dev; + INIT_LIST_HEAD(&gameport->node); spin_lock_init(&gameport->timer_lock); init_timer(&gameport->poll_timer); gameport->poll_timer.function = gameport_run_poll_handler; @@ -544,6 +549,8 @@ static void gameport_init_port(struct gameport *gameport) */ static void gameport_add_port(struct gameport *gameport) { + int error; + if (gameport->parent) gameport->parent->child = gameport; @@ -558,8 +565,13 @@ static void gameport_add_port(struct gameport *gameport) printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n", gameport->name, gameport->phys, gameport->speed); - device_add(&gameport->dev); - gameport->registered = 1; + error = device_add(&gameport->dev); + if (error) + printk(KERN_ERR + "gameport: device_add() failed for %s (%s), error: %d\n", + gameport->phys, gameport->name, error); + else + gameport->registered = 1; } /* @@ -583,10 +595,11 @@ static void gameport_destroy_port(struct gameport *gameport) if (gameport->registered) { device_del(&gameport->dev); - list_del_init(&gameport->node); gameport->registered = 0; } + list_del_init(&gameport->node); + gameport_remove_pending_events(gameport); put_device(&gameport->dev); } @@ -704,11 +717,22 @@ static int gameport_driver_remove(struct device *dev) } static struct bus_type gameport_bus = { - .name = "gameport", - .probe = gameport_driver_probe, - .remove = gameport_driver_remove, + .name = "gameport", + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, }; +static void gameport_add_driver(struct gameport_driver *drv) +{ + int error; + + error = driver_register(&drv->driver); + if (error) + printk(KERN_ERR + "gameport: driver_register() failed for %s, error: %d\n", + drv->driver.name, error); +} + void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) { drv->driver.bus = &gameport_bus; @@ -778,16 +802,24 @@ void gameport_close(struct gameport *gameport) static int __init gameport_init(void) { - gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); - if (IS_ERR(gameport_task)) { - printk(KERN_ERR "gameport: Failed to start kgameportd\n"); - return PTR_ERR(gameport_task); - } + int error; gameport_bus.dev_attrs = gameport_device_attrs; gameport_bus.drv_attrs = gameport_driver_attrs; gameport_bus.match = gameport_bus_match; - bus_register(&gameport_bus); + error = bus_register(&gameport_bus); + if (error) { + printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); + return error; + } + + gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); + if (IS_ERR(gameport_task)) { + bus_unregister(&gameport_bus); + error = PTR_ERR(gameport_task); + printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error); + return error; + } return 0; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 6521034..3e76ad7 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -62,6 +62,7 @@ static LIST_HEAD(serio_list); static struct bus_type serio_bus; +static void serio_add_driver(struct serio_driver *drv); static void serio_add_port(struct serio *serio); static void serio_destroy_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); @@ -140,8 +141,14 @@ static void serio_release_driver(struct serio *serio) static void serio_find_driver(struct serio *serio) { + int error; + down_write(&serio_bus.subsys.rwsem); - device_attach(&serio->dev); + error = device_attach(&serio->dev); + if (error < 0) + printk(KERN_WARNING + "serio: device_attach() failed for %s (%s), error: %d\n", + serio->phys, serio->name, error); up_write(&serio_bus.subsys.rwsem); } @@ -272,7 +279,6 @@ static struct serio_event *serio_get_event(void) static void serio_handle_event(void) { struct serio_event *event; - struct serio_driver *serio_drv; mutex_lock(&serio_mutex); @@ -304,8 +310,7 @@ static void serio_handle_event(void) break; case SERIO_REGISTER_DRIVER: - serio_drv = event->object; - driver_register(&serio_drv->driver); + serio_add_driver(event->object); break; default: @@ -525,6 +530,7 @@ static void serio_init_port(struct serio *serio) __module_get(THIS_MODULE); + INIT_LIST_HEAD(&serio->node); spin_lock_init(&serio->lock); mutex_init(&serio->drv_mutex); device_initialize(&serio->dev); @@ -542,6 +548,8 @@ static void serio_init_port(struct serio *serio) */ static void serio_add_port(struct serio *serio) { + int error; + if (serio->parent) { serio_pause_rx(serio->parent); serio->parent->child = serio; @@ -551,9 +559,19 @@ static void serio_add_port(struct serio *serio) list_add_tail(&serio->node, &serio_list); if (serio->start) serio->start(serio); - device_add(&serio->dev); - sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); - serio->registered = 1; + error = device_add(&serio->dev); + if (error) + printk(KERN_ERR + "serio: device_add() failed for %s (%s), error: %d\n", + serio->phys, serio->name, error); + else { + serio->registered = 1; + error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); + if (error) + printk(KERN_ERR + "serio: sysfs_create_group() failed for %s (%s), error: %d\n", + serio->phys, serio->name, error); + } } /* @@ -583,10 +601,10 @@ static void serio_destroy_port(struct serio *serio) if (serio->registered) { sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); device_del(&serio->dev); - list_del_init(&serio->node); serio->registered = 0; } + list_del_init(&serio->node); serio_remove_pending_events(serio); put_device(&serio->dev); } @@ -756,6 +774,17 @@ static struct bus_type serio_bus = { .remove = serio_driver_remove, }; +static void serio_add_driver(struct serio_driver *drv) +{ + int error; + + error = driver_register(&drv->driver); + if (error) + printk(KERN_ERR + "serio: driver_register() failed for %s, error: %d\n", + drv->driver.name, error); +} + void __serio_register_driver(struct serio_driver *drv, struct module *owner) { drv->driver.bus = &serio_bus; @@ -903,18 +932,26 @@ irqreturn_t serio_interrupt(struct serio *serio, static int __init serio_init(void) { - serio_task = kthread_run(serio_thread, NULL, "kseriod"); - if (IS_ERR(serio_task)) { - printk(KERN_ERR "serio: Failed to start kseriod\n"); - return PTR_ERR(serio_task); - } + int error; serio_bus.dev_attrs = serio_device_attrs; serio_bus.drv_attrs = serio_driver_attrs; serio_bus.match = serio_bus_match; serio_bus.uevent = serio_uevent; serio_bus.resume = serio_resume; - bus_register(&serio_bus); + error = bus_register(&serio_bus); + if (error) { + printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); + return error; + } + + serio_task = kthread_run(serio_thread, NULL, "kseriod"); + if (IS_ERR(serio_task)) { + bus_unregister(&serio_bus); + error = PTR_ERR(serio_task); + printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error); + return error; + } return 0; } -- cgit v1.1 From 061b623c54c5722fbb55fddbbdacbf97e8a82701 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Mon, 10 Jul 2006 03:34:14 -0300 Subject: V4L/DVB (4291): Add dvbpll i2c device check. Some cards have multiple possible addresses for their PLLs, with no other way to tell if a PLL is present or not apart from probing to see if an i2c device is present. This adds a quick check to see if an i2c device is present at the given i2c address. Signed-off-by: Andrew de Quincey Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index a189683..b9a3388 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -613,7 +613,20 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) { + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = pll_addr, .flags = 0, .buf = NULL, .len = 0 }, + { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; struct dvb_pll_priv *priv = NULL; + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer (i2c, msg, 2); + if (ret != 2) + return -1; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); if (priv == NULL) -- cgit v1.1 From 04c56d0e5b27f1f65e4d20b46731d55341d42a6a Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Mon, 10 Jul 2006 03:34:14 -0300 Subject: V4L/DVB (4292): Fix DISEQC regression The changes to add frontend reinitialisation moved the position where the init() op is called into the frontend thread. Unfortunately, since DISEQC operations do not use the frontend thread, this meant that DISEQC could be called against an uninitalised frontend, leading to all sorts of trouble. Patch fixes this by reinstating the original fronted intialisation call. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 59ac35d..57b34cd 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -526,7 +526,9 @@ static int dvb_frontend_thread(void *data) fepriv->delay = 3*HZ; fepriv->status = 0; fepriv->wakeup = 0; - fepriv->reinitialise = 1; + fepriv->reinitialise = 0; + + dvb_frontend_init(fe); while (1) { up(&fepriv->sem); /* is locked when we enter the thread... */ @@ -1013,17 +1015,18 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) return ret; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + + /* normal tune mode when opened R/W */ + fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; + fepriv->tone = -1; + fepriv->voltage = -1; + ret = dvb_frontend_start (fe); if (ret) dvb_generic_release (inode, file); /* empty event queue */ fepriv->events.eventr = fepriv->events.eventw = 0; - - /* normal tune mode when opened R/W */ - fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; - fepriv->tone = -1; - fepriv->voltage = -1; } return ret; -- cgit v1.1 From f2813093810276a2a3c1f116f23baf2ab7a669bd Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Mon, 10 Jul 2006 03:34:15 -0300 Subject: V4L/DVB (4293): Fix unstable DISEQC behaviour on budget cards. Use the stv0299 native DISEQC implementation instead of the bitbanging one as required by the ves1893. This was originally found by Oliver Endriss. Signed-off-by: Andrew de Quincey Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 35761f1..1b4d884 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -375,9 +375,6 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; - budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } break; -- cgit v1.1 From 93e2b1ae97dedd66ca0cb8ac1a5ceb4904631091 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Mon, 10 Jul 2006 03:34:15 -0300 Subject: V4L/DVB (4294): Fix broken tda665x PLL definition. It was pointed out on the mailing list that this PLL definition is broken. I went back to the original dibusb driver and confirmed it used to use these settings, as well as consulting the datasheet. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b9a3388..fce5c42 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -194,11 +194,11 @@ struct dvb_pll_desc dvb_pll_tda665x = { { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, - { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ }, - { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ }, - { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, - { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ }, + { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, + { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, + { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, + { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, } }; EXPORT_SYMBOL(dvb_pll_tda665x); -- cgit v1.1 From 6a85774741f1ef1a47ba0670e99c97e892930cad Mon Sep 17 00:00:00 2001 From: Marco Schluessler Date: Mon, 10 Jul 2006 03:34:16 -0300 Subject: V4L/DVB (4295): Fix typo in comment for TDA9819 Fix typo in comment for TDA9819 Signed-off-by: Marco Schluessler Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 4 ++-- drivers/media/dvb/ttpci/av7110_v4l.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 500f15c..4506165 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2203,8 +2203,8 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params; /* set TDA9819 into DVB mode */ - saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) - saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) /* tuner on this needs a slower i2c bus speed */ av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 6405546..6ffe53f 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -272,8 +272,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) if (ves1820_writereg(dev, 0x09, 0x0f, 0x60)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF) + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF) } if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1) dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num); @@ -308,8 +308,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) if (ves1820_writereg(dev, 0x09, 0x0f, 0x20)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) } } @@ -750,8 +750,8 @@ int av7110_init_analog_module(struct av7110 *av7110) if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) - saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) } /* init the saa7113 */ -- cgit v1.1 From 6ba475042f0ca54bf055ce94b2a1e4656ed143f9 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Mon, 10 Jul 2006 03:34:16 -0300 Subject: V4L/DVB (4296): Remove stradis MODULE_DEVICE_INFO definition To prevent autoloading of the driver, as it then conflicts with every other saa7146 device in existence. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stradis.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index b36ba9f..5686547 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -2181,7 +2181,6 @@ static struct pci_device_id stradis_pci_tbl[] = { { 0 } }; -MODULE_DEVICE_TABLE(pci, stradis_pci_tbl); static struct pci_driver stradis_driver = { .name = "stradis", -- cgit v1.1 From c526e224e4075eff788a992f59bc4a9006b12923 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 15 Jul 2006 09:08:26 -0300 Subject: V4L/DVB (4298): Check all __must_check warnings in bttv. Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 5764a89..63e8316 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3909,6 +3909,8 @@ static void bttv_unregister_video(struct bttv *btv) /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { + int ret; + if (no_overlay <= 0) { bttv_video_template.type |= VID_TYPE_OVERLAY; } else { @@ -3923,7 +3925,10 @@ static int __devinit bttv_register_video(struct bttv *btv) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", btv->c.nr,btv->video_dev->minor & 0x1f); - video_device_create_file(btv->video_dev, &class_device_attr_card); + ret = video_device_create_file(btv->video_dev, &class_device_attr_card); + if (ret < 0) + printk(KERN_WARNING "bttv: video_device_create_file error: " + "%d\n", ret); /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); @@ -4287,6 +4292,8 @@ static struct pci_driver bttv_pci_driver = { static int bttv_init_module(void) { + int ret; + bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", @@ -4308,7 +4315,11 @@ static int bttv_init_module(void) bttv_check_chipset(); - bus_register(&bttv_sub_bus_type); + ret = bus_register(&bttv_sub_bus_type); + if (ret < 0) { + printk(KERN_WARNING "bttv: bus_register error: %d\n", ret); + return ret; + } return pci_register_driver(&bttv_pci_driver); } -- cgit v1.1 From d5fdd1354e04658ea25150cc152a395bb6ecb6da Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Sat, 15 Jul 2006 09:45:34 -0300 Subject: V4L/DVB (4306): Support non interlaced capture by default for saa713x This patch just sets the option noninterlaced to 1 by default since it has no known disadvantages. It is still possibe to get the old behaviour by setting noninterlaced=0. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index e4156ec..8277958 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -40,7 +40,7 @@ static unsigned int video_debug = 0; static unsigned int gbuffers = 8; -static unsigned int noninterlaced = 0; +static unsigned int noninterlaced = 1; static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; module_param(video_debug, int, 0644); @@ -48,7 +48,7 @@ MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); module_param(gbuffers, int, 0444); MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32"); module_param(noninterlaced, int, 0644); -MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced"); +MODULE_PARM_DESC(noninterlaced,"capture non interlaced video"); #define dprintk(fmt, arg...) if (video_debug) \ printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg) -- cgit v1.1 From 7845701820c420454bcfdc4902fad68901d9ff83 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 15 Jul 2006 15:19:56 -0300 Subject: V4L/DVB (4310): Saa7134: rename dmasound_{init, exit} Two different exports with the same name are not a good idea: $ grep -r EXPORT_SYMBOL\(dmasound_init\) * drivers/media/video/saa7134/saa7134-core.c:EXPORT_SYMBOL(dmasound_init); sound/oss/dmasound/dmasound_core.c:EXPORT_SYMBOL(dmasound_init); $ This patch renames the saa7134 dmasound_{init,exit} to saa7134_dmasound_{init,exit}. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-alsa.c | 10 +++++----- drivers/media/video/saa7134/saa7134-core.c | 16 ++++++++-------- drivers/media/video/saa7134/saa7134-oss.c | 10 +++++----- drivers/media/video/saa7134/saa7134.h | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index f1fd69e..d73cff1 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -997,9 +997,9 @@ static int saa7134_alsa_init(void) struct saa7134_dev *dev = NULL; struct list_head *list; - if (!dmasound_init && !dmasound_exit) { - dmasound_init = alsa_device_init; - dmasound_exit = alsa_device_exit; + if (!saa7134_dmasound_init && !saa7134_dmasound_exit) { + saa7134_dmasound_init = alsa_device_init; + saa7134_dmasound_exit = alsa_device_exit; } else { printk(KERN_WARNING "saa7134 ALSA: can't load, DMA sound handler already assigned (probably to OSS)\n"); return -EBUSY; @@ -1036,8 +1036,8 @@ static void saa7134_alsa_exit(void) snd_card_free(snd_saa7134_cards[idx]); } - dmasound_init = NULL; - dmasound_exit = NULL; + saa7134_dmasound_init = NULL; + saa7134_dmasound_exit = NULL; printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n"); return; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 6e97cc8..be3a81f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -95,8 +95,8 @@ LIST_HEAD(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; -int (*dmasound_init)(struct saa7134_dev *dev); -int (*dmasound_exit)(struct saa7134_dev *dev); +int (*saa7134_dmasound_init)(struct saa7134_dev *dev); +int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) @@ -1008,8 +1008,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* check for signal */ saa7134_irq_video_intl(dev); - if (dmasound_init && !dev->dmasound.priv_data) { - dmasound_init(dev); + if (saa7134_dmasound_init && !dev->dmasound.priv_data) { + saa7134_dmasound_init(dev); } return 0; @@ -1036,8 +1036,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) struct saa7134_mpeg_ops *mops; /* Release DMA sound modules if present */ - if (dmasound_exit && dev->dmasound.priv_data) { - dmasound_exit(dev); + if (saa7134_dmasound_exit && dev->dmasound.priv_data) { + saa7134_dmasound_exit(dev); } /* debugging ... */ @@ -1169,8 +1169,8 @@ EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ -EXPORT_SYMBOL(dmasound_init); -EXPORT_SYMBOL(dmasound_exit); +EXPORT_SYMBOL(saa7134_dmasound_init); +EXPORT_SYMBOL(saa7134_dmasound_exit); EXPORT_SYMBOL(saa7134_pgtable_free); EXPORT_SYMBOL(saa7134_pgtable_build); EXPORT_SYMBOL(saa7134_pgtable_alloc); diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 3895d05..2e3ba5f 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -993,9 +993,9 @@ static int saa7134_oss_init(void) struct saa7134_dev *dev = NULL; struct list_head *list; - if (!dmasound_init && !dmasound_exit) { - dmasound_init = oss_device_init; - dmasound_exit = oss_device_exit; + if (!saa7134_dmasound_init && !saa7134_dmasound_exit) { + saa7134_dmasound_init = oss_device_init; + saa7134_dmasound_exit = oss_device_exit; } else { printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n"); return -EBUSY; @@ -1037,8 +1037,8 @@ static void saa7134_oss_exit(void) } - dmasound_init = NULL; - dmasound_exit = NULL; + saa7134_dmasound_init = NULL; + saa7134_dmasound_exit = NULL; printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d5ee99c..c04ce61 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -586,8 +586,8 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); int saa7134_set_dmabits(struct saa7134_dev *dev); -extern int (*dmasound_init)(struct saa7134_dev *dev); -extern int (*dmasound_exit)(struct saa7134_dev *dev); +extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev); +extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); /* ----------------------------------------------------------- */ -- cgit v1.1 From a62c61d3820417e8efac8796f0a46d7ab337af8d Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 17 Jul 2006 16:34:27 -0300 Subject: V4L/DVB (4313): Bugfix for keycode calculation on NPG remotes Fix keycode calculations (all codes for this remote were wrong due to a lost + sign) Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 72b630a..c255646 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -89,7 +89,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) auxgpio = cx_read(MO_GP1_IO); /* Take out the parity part */ - gpio+=(gpio & 0x7fd) + (auxgpio & 0xef); + gpio=(gpio & 0x7fd) + (auxgpio & 0xef); } else auxgpio = gpio; -- cgit v1.1 From d9cd2d9b61898354f5dbabdc490dd6ef309ebbd4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 17 Jul 2006 17:15:26 -0300 Subject: V4L/DVB (4314): Set the Auxiliary Byte when tuning LG H06xF in analog mode With the LG H06xF tuners, an auxiliary byte must be sent after the standard four-byte i2c sequence. The code that does this is currently in the wrong place, causing random bytes to be written to the tuner over i2c in the set_type function. This patch moves this code from set_type to default_set_tv_freq. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 8 -------- drivers/media/video/tuner-simple.c | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index f7eb402..277d351 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -196,14 +196,6 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c, buffer, 4); default_tuner_init(c); break; - case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ - buffer[2] &= ~0x20; - buffer[2] |= 0x18; - buffer[3] = 0x20; - i2c_master_send(c, buffer, 4); - default_tuner_init(c); - break; case TUNER_PHILIPS_TD1316: buffer[0] = 0x0b; buffer[1] = 0xdc; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d071c5c..abe37cf 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -339,7 +339,20 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - if (t->type == TUNER_MICROTUNE_4042FI5) { + switch (t->type) { + case TUNER_LG_TDVS_H06XF: + /* Set the Auxiliary Byte. */ + buffer[0] = buffer[2]; + buffer[0] &= ~0x20; + buffer[0] |= 0x18; + buffer[1] = 0x20; + tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); + + if (2 != (rc = i2c_master_send(c,buffer,2))) + tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + break; + case TUNER_MICROTUNE_4042FI5: + { // FIXME - this may also work for other tuners unsigned long timeout = jiffies + msecs_to_jiffies(1); u8 status_byte = 0; @@ -364,10 +377,12 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[2] = config; buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0],buffer[1],buffer[2],buffer[3]); if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + break; + } } } -- cgit v1.1 From 3117beec7e43f91ce156cacf033a712c7e22737d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 19 Jul 2006 13:23:38 -0300 Subject: V4L/DVB (4316): Check __must_check warnings Check __must_check warnings for class_device_register and class_device_create_file video_device_create_file was declared as a void, but instead should return the int value of class_device_create_file. Move the check from bttv-driver.c into v4l2-dev.h, because all other callers of video_device_create_file must also be checked. Replace the call to class_device_create_file in videodev.c with video_device_create_file, as defined in v4l2-dev.h, so that the return value of class_device_create_file will be checked. Check the return value of class_device_register in videodev.c and pvrusb2-sysfs.c Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 8 ++----- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 33 ++++++++++++++++++++++++----- drivers/media/video/videodev.c | 11 +++++++--- 3 files changed, 38 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 63e8316..6db5e4e 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3909,8 +3909,6 @@ static void bttv_unregister_video(struct bttv *btv) /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { - int ret; - if (no_overlay <= 0) { bttv_video_template.type |= VID_TYPE_OVERLAY; } else { @@ -3925,10 +3923,8 @@ static int __devinit bttv_register_video(struct bttv *btv) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", btv->c.nr,btv->video_dev->minor & 0x1f); - ret = video_device_create_file(btv->video_dev, &class_device_attr_card); - if (ret < 0) - printk(KERN_WARNING "bttv: video_device_create_file error: " - "%d\n", ret); + + video_device_create_file(btv->video_dev, &class_device_attr_card); /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 6af55a8..ef46d4f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -600,6 +600,8 @@ static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) { struct pvr2_sysfs_debugifc *dip; + int ret; + dip = kmalloc(sizeof(*dip),GFP_KERNEL); if (!dip) return; memset(dip,0,sizeof(*dip)); @@ -613,8 +615,14 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip->attr_debuginfo.attr.mode = S_IRUGO; dip->attr_debuginfo.show = debuginfo_show; sfp->debugifc = dip; - class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); - class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); + ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); + if (ret < 0) + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); + if (ret < 0) + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); } @@ -709,6 +717,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp, { struct usb_device *usb_dev; struct class_device *class_dev; + int ret; + usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); if (!usb_dev) return; class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL); @@ -733,20 +743,33 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->class_dev = class_dev; class_dev->class_data = sfp; - class_device_register(class_dev); + ret = class_device_register(class_dev); + if (ret) { + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + kfree(class_dev); + return; + } sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; sfp->attr_v4l_minor_number.store = NULL; - class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); + ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); + if (ret < 0) + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.mode = S_IRUGO; sfp->attr_unit_number.show = unit_number_show; sfp->attr_unit_number.store = NULL; - class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); + ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); + if (ret < 0) + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); pvr2_sysfs_add_controls(sfp); #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index b26ebaf..4c3f926 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1512,6 +1512,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) int i=0; int base; int end; + int ret; char *name_base; switch(type) @@ -1571,9 +1572,13 @@ int video_register_device(struct video_device *vfd, int type, int nr) vfd->class_dev.class = &video_class; vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base); - class_device_register(&vfd->class_dev); - class_device_create_file(&vfd->class_dev, - &class_device_attr_name); + ret = class_device_register(&vfd->class_dev); + if (ret) { + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + return ret; + } + video_device_create_file(vfd, &class_device_attr_name); #if 1 /* needed until all drivers are fixed */ -- cgit v1.1 From 32e4c3a5622e832938aa0272e21a292564ff090a Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 18 Jul 2006 22:55:23 -0300 Subject: V4L/DVB (4323): [budget/budget-av/budget-ci/budget-patch drivers] fixed DMA start/stop code Fix bug reported by Andrew de Quincey: After cold boot the saa7146 DMA did not start if the demuxer was opened before the frontend has locked to the signal. DMA transfers will be started now if (and only if) the frontend is locked and data should be sent to the demuxer. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 3 ++ drivers/media/dvb/ttpci/budget-ci.c | 2 ++ drivers/media/dvb/ttpci/budget-core.c | 57 ++++++++++++++++++++++++++-------- drivers/media/dvb/ttpci/budget-patch.c | 2 ++ drivers/media/dvb/ttpci/budget.c | 2 ++ drivers/media/dvb/ttpci/budget.h | 7 +++-- 6 files changed, 57 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 5f111d4..2d21fec 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1303,6 +1303,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); ciintf_init(budget_av); + + ttpci_budget_init_hooks(&budget_av->budget); + return 0; } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 4b966ee..ffbbb3e 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1101,6 +1101,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_ci->budget.dvb_adapter.priv = budget_ci; frontend_init(budget_ci); + ttpci_budget_init_hooks(&budget_ci->budget); + return 0; } diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index e4cf777..e15562f 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -63,9 +63,6 @@ static int stop_ts_capture(struct budget *budget) { dprintk(2, "budget: %p\n", budget); - if (--budget->feeding) - return budget->feeding; - saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; @@ -77,8 +74,8 @@ static int start_ts_capture(struct budget *budget) dprintk(2, "budget: %p\n", budget); - if (budget->feeding) - return ++budget->feeding; + if (!budget->feeding || !budget->fe_synced) + return 0; saa7146_write(dev, MC1, MASK_20); // DMA3 off @@ -139,7 +136,33 @@ static int start_ts_capture(struct budget *budget) SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ - return ++budget->feeding; + return 0; +} + +static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + int synced; + int ret; + + if (budget->read_fe_status) + ret = budget->read_fe_status(fe, status); + else + ret = -EINVAL; + + if (!ret) { + synced = (*status & FE_HAS_LOCK); + if (synced != budget->fe_synced) { + budget->fe_synced = synced; + spin_lock(&budget->feedlock); + if (synced) + start_ts_capture(budget); + else + stop_ts_capture(budget); + spin_unlock(&budget->feedlock); + } + } + return ret; } static void vpeirq(unsigned long data) @@ -267,7 +290,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status; + int status = 0; dprintk(2, "budget: %p\n", budget); @@ -276,7 +299,8 @@ static int budget_start_feed(struct dvb_demux_feed *feed) spin_lock(&budget->feedlock); feed->pusi_seen = 0; /* have a clean section start */ - status = start_ts_capture(budget); + if (budget->feeding++ == 0) + status = start_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -285,12 +309,13 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status; + int status = 0; dprintk(2, "budget: %p\n", budget); spin_lock(&budget->feedlock); - status = stop_ts_capture(budget); + if (--budget->feeding == 0) + status = stop_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -470,6 +495,14 @@ err: return ret; } +void ttpci_budget_init_hooks(struct budget *budget) +{ + if (budget->dvb_frontend && !budget->read_fe_status) { + budget->read_fe_status = budget->dvb_frontend->ops.read_status; + budget->dvb_frontend->ops.read_status = budget_read_fe_status; + } +} + int ttpci_budget_deinit(struct budget *budget) { struct saa7146_dev *dev = budget->dev; @@ -508,11 +541,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) spin_lock(&budget->feedlock); budget->video_port = video_port; if (budget->feeding) { - int oldfeeding = budget->feeding; - budget->feeding = 1; stop_ts_capture(budget); start_ts_capture(budget); - budget->feeding = oldfeeding; } spin_unlock(&budget->feedlock); } @@ -520,6 +550,7 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) EXPORT_SYMBOL_GPL(ttpci_budget_debiread); EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite); EXPORT_SYMBOL_GPL(ttpci_budget_init); +EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks); EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index ee60ce9..5722744 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -617,6 +617,8 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte budget->dvb_adapter.priv = budget; frontend_init(budget); + ttpci_budget_init_hooks(budget); + return 0; } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 1b4d884..863dffb 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -471,6 +471,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ budget->dvb_adapter.priv = budget; frontend_init(budget); + ttpci_budget_init_hooks(budget); + return 0; } diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index ecea3a1..e8a5c79 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -52,9 +52,6 @@ struct budget { struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; - int fe_synced; - struct mutex pid_mutex; - int ci_present; int video_port; @@ -74,6 +71,9 @@ struct budget { struct dvb_adapter dvb_adapter; struct dvb_frontend *dvb_frontend; + int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status); + int fe_synced; + void *priv; }; @@ -106,6 +106,7 @@ static struct saa7146_pci_extension_data x_var = { \ extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, struct module *owner); +extern void ttpci_budget_init_hooks(struct budget *budget); extern int ttpci_budget_deinit(struct budget *budget); extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port); -- cgit v1.1 From e61b6fc58b4a0b07f1ccfc67bf2b84a2848fcb2c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 18 Jul 2006 22:42:18 -0300 Subject: V4L/DVB (4337): Refine dead code elimination in pvrusb2 Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 8 ++++++-- drivers/media/video/pvrusb2/pvrusb2-io.c | 9 ++++++--- drivers/media/video/pvrusb2/pvrusb2-io.h | 2 ++ drivers/media/video/pvrusb2/pvrusb2-ioread.c | 5 +++-- 4 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9b48abc..be1e5cc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -852,7 +852,6 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw) return hdw->serial_number; } - int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) { return hdw->unit_number; @@ -2318,7 +2317,6 @@ void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw) } } - /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) { @@ -2542,6 +2540,10 @@ static void pvr2_ctl_timeout(unsigned long data) } +/* Issue a command and get a response from the device. This extended + version includes a probe flag (which if set means that device errors + should not be logged or treated as fatal) and a timeout in jiffies. + This can be used to non-lethally probe the health of endpoint 1. */ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, void *write_data,unsigned int write_len, @@ -2970,6 +2972,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) } +/* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { int status; @@ -3068,6 +3071,7 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) } +/* Find I2C address of eeprom */ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) { int result; diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c index 681f79c..1e39376 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/drivers/media/video/pvrusb2/pvrusb2-io.c @@ -26,6 +26,8 @@ #include #include +static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state); + #define BUFFER_SIG 0x47653271 // #define SANITY_CHECK_BUFFERS @@ -515,6 +517,10 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp, } /* Query / set the nominal buffer count */ +int pvr2_stream_get_buffer_count(struct pvr2_stream *sp) +{ + return sp->buffer_target_count; +} int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt) { @@ -553,7 +559,6 @@ int pvr2_stream_get_ready_count(struct pvr2_stream *sp) return sp->r_count; } - void pvr2_stream_kill(struct pvr2_stream *sp) { struct pvr2_buffer *bp; @@ -607,7 +612,6 @@ int pvr2_buffer_queue(struct pvr2_buffer *bp) return ret; } - int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt) { int ret = 0; @@ -646,7 +650,6 @@ int pvr2_buffer_get_status(struct pvr2_buffer *bp) return bp->status; } - int pvr2_buffer_get_id(struct pvr2_buffer *bp) { return bp->id; diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h index 96285ad..93279cc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.h +++ b/drivers/media/video/pvrusb2/pvrusb2-io.h @@ -47,6 +47,7 @@ void pvr2_stream_set_callback(struct pvr2_stream *, void *data); /* Query / set the nominal buffer count */ +int pvr2_stream_get_buffer_count(struct pvr2_stream *); int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int); /* Get a pointer to a buffer that is either idle, ready, or is specified @@ -58,6 +59,7 @@ struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id); /* Find out how many buffers are idle or ready */ int pvr2_stream_get_ready_count(struct pvr2_stream *); + /* Kill all pending buffers and throw away any ready buffers as well */ void pvr2_stream_kill(struct pvr2_stream *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c index f7a2e22..b71f9a9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c @@ -213,7 +213,9 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) " pvr2_ioread_setup (tear-down) id=%p",cp); pvr2_ioread_stop(cp); pvr2_stream_kill(cp->stream); - pvr2_stream_set_buffer_count(cp->stream,0); + if (pvr2_stream_get_buffer_count(cp->stream)) { + pvr2_stream_set_buffer_count(cp->stream,0); + } cp->stream = NULL; } if (sp) { @@ -251,7 +253,6 @@ int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl) return ret; } - static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp) { int stat; -- cgit v1.1 From 55c05b6d226f68266d1f88dd81795b04d096b1c8 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Sun, 16 Jul 2006 19:41:41 -0300 Subject: V4L/DVB (4311): Fix possible dvb-pll oops Supplying a NULL i2c adapter to dvb_pll_attach is allowed, for example with mt352 demods. However, the pll i2c probe will segfault because it does not check for this. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index fce5c42..4c8a506 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -619,14 +619,16 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2 struct dvb_pll_priv *priv = NULL; int ret; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - ret = i2c_transfer (i2c, msg, 2); - if (ret != 2) - return -1; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + if (i2c != NULL) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer (i2c, msg, 2); + if (ret != 2) + return -1; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); if (priv == NULL) -- cgit v1.1 From 95faba22d8b81f0cd85b995232b7d05c45a26f3e Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Tue, 18 Jul 2006 16:37:13 -0300 Subject: V4L/DVB (4322): Fix dvb-pll autoprobing Trent Piepho pointed out that the pll test i2c transmission is slightly wrong; it was transmitting a zero length message, and then reading from the PLL. This was wrong; it should only be transmitting a single read i2c message. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 4c8a506..2be33f2 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -614,8 +614,7 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) { u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = pll_addr, .flags = 0, .buf = NULL, .len = 0 }, - { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; struct dvb_pll_priv *priv = NULL; int ret; @@ -623,8 +622,8 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - ret = i2c_transfer (i2c, msg, 2); - if (ret != 2) + ret = i2c_transfer (i2c, &msg, 1); + if (ret != 1) return -1; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); -- cgit v1.1 From eb4eeccc18246c852fffc771efc3c07a547aeb97 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Jul 2006 18:53:23 -0300 Subject: V4L/DVB (4341): VIDIOCSMICROCODE were missing on compat_ioctl32 video_code size is 24 on i386 and 32 on x86_64, so a proper handling is needed on compat_ioctl32 to fix it. This code should be tested, since just *a few* boards use this ioctl. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/compat_ioctl32.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index 353d02b..9dddff4 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c @@ -490,6 +490,23 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user return 0; } +struct video_code32 +{ + char loadwhat[16]; /* name or tag of file being passed */ + compat_int_t datasize; + unsigned char *data; +}; + +static inline int microcode32(struct video_code *kp, struct video_code32 __user *up) +{ + if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || + copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) || + get_user(kp->datasize, &up->datasize) || + copy_from_user(kp->data, up->data, up->datasize)) + return -EFAULT; + return 0; +} + #define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) #define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) #define VIDIOCGWIN32 _IOR('v',9, struct video_window32) @@ -498,6 +515,7 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user #define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) #define VIDIOCGFREQ32 _IOR('v',14, u32) #define VIDIOCSFREQ32 _IOW('v',15, u32) +#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32) /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ #define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4) @@ -590,6 +608,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg struct video_tuner vt; struct video_buffer vb; struct video_window vw; + struct video_code vc; struct v4l2_format v2f; struct v4l2_buffer v2b; struct v4l2_framebuffer v2fb; @@ -628,6 +647,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; + case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break; }; switch(cmd) { @@ -703,6 +723,10 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOC_G_FBUF: case VIDIOC_G_INPUT: compatible_arg = 0; + case VIDIOCSMICROCODE: + err = microcode32(&karg.vc, up); + compatible_arg = 0; + break; }; if(err) -- cgit v1.1 From 985bc96e27c729b8b686126ed26bba9fbaaf562d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Jul 2006 06:31:19 -0300 Subject: V4L/DVB (4343): Fix for compilation without V4L1 or V4L1_COMPAT Removed usage of HAVE_V4L1 Including videodev.h will just include videodev2.h if V4L1 is not supported V4L1 code at core drivers will honor CONFIG_V4L1_COMPAT stuff Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/msp3400-driver.c | 10 +++++++++- drivers/media/video/saa7134/saa7134-video.c | 2 +- drivers/media/video/tuner-core.c | 23 ++++++++++++----------- drivers/media/video/v4l2-common.c | 24 ++++++++++++++---------- drivers/media/video/videodev.c | 8 ++++++-- drivers/media/video/vivi.c | 4 ++-- 7 files changed, 46 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 2225d4b..ff4e7ed 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1226,7 +1226,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return cx8800_try_fmt(dev,fh,f); } -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1585,7 +1585,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, *id = 0; return 0; } -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT case VIDIOCSTUNER: { struct video_tuner *v = arg; diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index dbb75a7..56246b8 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -362,7 +362,7 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ - +#ifdef CONFIG_VIDEO_V4L1 static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) { if (rxsubchans == V4L2_TUNER_SUB_MONO) @@ -384,6 +384,7 @@ static int msp_mode_v4l1_to_v4l2(int mode) return V4L2_TUNER_MODE_LANG1; return V4L2_TUNER_MODE_MONO; } +#endif static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) { @@ -509,6 +510,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ +#ifdef CONFIG_VIDEO_V4L1 case VIDIOCGAUDIO: { struct video_audio *va = arg; @@ -577,6 +579,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOCSFREQ: + { + /* new channel -- kick audio carrier scan */ + msp_wake_thread(client); + break; + } +#endif case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 8277958..8656f24 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -2087,7 +2087,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 277d351..40590ba 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -590,6 +590,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (t->standby) t->standby (client); break; +#ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) return 0; @@ -599,17 +600,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) /* Should be implemented, since bttv calls it */ tuner_dbg("VIDIOCSAUDIO not implemented.\n"); break; - case TDA9887_SET_CONFIG: - if (t->type == TUNER_TDA9887) { - int *i = arg; - - t->tda9887_config = *i; - set_freq(client, t->tv_freq); - } - break; - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ case VIDIOCSCHAN: { static const v4l2_std_id map[] = { @@ -693,7 +683,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; return 0; } +#endif + case TDA9887_SET_CONFIG: + if (t->type == TUNER_TDA9887) { + int *i = arg; + t->tda9887_config = *i; + set_freq(client, t->tv_freq); + } + break; + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ case VIDIOC_S_STD: { v4l2_std_id *id = arg; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index f06dc19..2ecbeff 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -202,7 +202,7 @@ static char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT static const char *v4l1_ioctls[] = { [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", @@ -301,7 +301,7 @@ static const char *v4l2_ioctls[] = { #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) static const char *v4l2_int_ioctls[] = { -#ifdef HAVE_VIDEO_DECODER +#ifdef CONFIG_V4L1_COMPAT [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", @@ -367,7 +367,7 @@ void v4l_printk_ioctl(unsigned int cmd) (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ? v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); break; -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT case 'v': printk("v4l1 ioctl %s, dir=%s (0x%08x)\n", (_IOC_NR(cmd) < V4L1_IOCTLS) ? @@ -414,6 +414,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) printk ("%s: tuner type=%d\n", s, *p); break; } +#ifdef CONFIG_VIDEO_V4L1_COMPAT case DECODER_SET_VBI_BYPASS: case DECODER_ENABLE_OUTPUT: case DECODER_GET_STATUS: @@ -424,6 +425,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOCCAPTURE: case VIDIOCSYNC: case VIDIOCSWRITEMODE: +#endif case TUNER_SET_TYPE_ADDR: case TUNER_SET_STANDBY: case TDA9887_SET_CONFIG: @@ -755,6 +757,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) p->afc); break; } +#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGVBIFMT: case VIDIOCSVBIFMT: { @@ -924,6 +927,14 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) p->clipcount); break; } + case VIDIOCGFREQ: + case VIDIOCSFREQ: + { + unsigned long *p=arg; + printk ("%s: value=%lu\n", s, *p); + break; + } +#endif case VIDIOC_INT_AUDIO_CLOCK_FREQ: case VIDIOC_INT_I2S_CLOCK_FREQ: case VIDIOC_INT_S_STANDBY: @@ -933,13 +944,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) printk ("%s: value=%d\n", s, *p); break; } - case VIDIOCGFREQ: - case VIDIOCSFREQ: - { - unsigned long *p=arg; - printk ("%s: value=%lu\n", s, *p); - break; - } case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_QUERYSTD: diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 4c3f926..5c52819 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -760,7 +760,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_overlay(file, fh, *i); break; } -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1578,7 +1578,11 @@ int video_register_device(struct video_device *vfd, int type, int nr) __FUNCTION__); return ret; } - video_device_create_file(vfd, &class_device_attr_name); + ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name); + if (ret < 0) { + printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); + return ret; + } #if 1 /* needed until all drivers are fixed */ diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 41d23c8..38bd0c1 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -986,7 +986,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK)); } -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) { struct vivi_fh *fh=priv; @@ -1328,7 +1328,7 @@ static struct video_device vivi = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef HAVE_V4L1 +#ifdef CONFIG_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif .tvnorms = tvnorms, -- cgit v1.1 From fb0b664c22b80df62c9e555afcde6a8dab08f4f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Jul 2006 06:32:05 -0300 Subject: V4L/DVB (4344): Fix broken dependencies on media Kconfig Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 4 ++-- drivers/media/video/bt8xx/Kconfig | 2 +- drivers/media/video/cpia2/Kconfig | 2 +- drivers/media/video/usbvideo/Kconfig | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6d532f1..fe56862 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -145,7 +145,7 @@ config VIDEO_SAA5246A config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" - depends on VIDEO_DEV && I2C + depends on VIDEO_DEV && I2C && VIDEO_V4L1 help Support for I2C bus based teletext using the SAA5249 chip. At the moment this is only useful on some European WinTV cards. @@ -155,7 +155,7 @@ config VIDEO_SAA5249 config TUNER_3036 tristate "SAB3036 tuner" - depends on VIDEO_DEV && I2C + depends on VIDEO_DEV && I2C && VIDEO_V4L1 help Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 153f6a4..cdcf556 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig index 513cc09..e39a961 100644 --- a/drivers/media/video/cpia2/Kconfig +++ b/drivers/media/video/cpia2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CPIA2 tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV && USB + depends on VIDEO_DEV && USB && VIDEO_V4L1 ---help--- This is the video4linux driver for cameras based on Vision's CPiA2 (Colour Processor Interface ASIC), such as the Digital Blue QX5 diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index 59fb899..a0fd82b 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_V4L1 && EXPERIMENTAL + depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_V4L1 + depends on USB && VIDEO_DEV && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_V4L1 + depends on USB && VIDEO_DEV && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica @@ -39,7 +39,7 @@ config USB_KONICAWC config USB_QUICKCAM_MESSENGER tristate "USB Logitech Quickcam Messenger" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_DEV && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y or M here to enable support for the USB Logitech Quickcam -- cgit v1.1 From df2732706c745c827762aaf51892f281fb937680 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 24 Jul 2006 15:19:37 -0300 Subject: V4L/DVB (4365): OVERLAY flag were enabled by mistake A patch from Aug, 17 activated by mistake OVERLAY flag on cx88-video, together with several cx88-blackbird cleanups. This makes the cx88 driver to report: /dev/video0 [v4l2]: ioctl VIDIOC_G_FBUF: Invalid argument instead of: /dev/video0 [v4l2]: no overlay support Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ff4e7ed..547cdbd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1180,7 +1180,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | 0; if (UNSET != core->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; -- cgit v1.1 From 53dd8def52100ed8be4dae0cf1c2dc1f7e0fcd2c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 25 Jul 2006 09:31:42 -0300 Subject: V4L/DVB (4367): Videodev: Handle class_device related errors Add proper error checking and roll-back for failure of class_device_create_file() in videodev.c. Print error messages and unroll partially created sysfs entries. Also, failure of class_device_register() in video_register_device() is handled correctly. It was failing to de-allocate the minor number. This must be done in video_register_device(), since the caller has no way of knowing if failure occurred before or after the class device was registered. Also added an error message if video_register_device() is called with an unknown type, which should never happen. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5c52819..caa4f73 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1538,6 +1538,8 @@ int video_register_device(struct video_device *vfd, int type, int nr) name_base = "radio"; break; default: + printk(KERN_ERR "%s called with unknown type: %d\n", + __FUNCTION__, type); return -1; } @@ -1592,6 +1594,15 @@ int video_register_device(struct video_device *vfd, int type, int nr) "http://lwn.net/Articles/36850/\n", vfd->name); #endif return 0; + +fail_classdev: + class_device_unregister(&vfd->class_dev); +fail_minor: + mutex_lock(&videodev_lock); + video_device[vfd->minor] = NULL; + vfd->minor = -1; + mutex_unlock(&videodev_lock); + return ret; } /** -- cgit v1.1 From d94fc9a08e51432d0d5fc0f74a4f705d7b49c251 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 29 Jul 2006 17:18:06 -0300 Subject: V4L/DVB (4368): Bttv: use class_device_create_file and handle errors Revert bttv-driver.c from video_device_create_file() to use class_device_create_file() again. video_device_create_file() is only available when V4L1 is on. Proper error checking is added for failure of class_device_create_file(). Will print error message and unroll partially created sysfs entries. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 8 ++++++-- drivers/media/video/videodev.c | 7 ++++--- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 6db5e4e..20dff7c 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3923,8 +3923,12 @@ static int __devinit bttv_register_video(struct bttv *btv) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", btv->c.nr,btv->video_dev->minor & 0x1f); - - video_device_create_file(btv->video_dev, &class_device_attr_card); + if (class_device_create_file(&btv->video_dev->class_dev, + &class_device_attr_card)<0) { + printk(KERN_ERR "bttv%d: class_device_create_file 'card' " + "failed\n", btv->c.nr); + goto err; + } /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index caa4f73..46848e2 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1578,12 +1578,13 @@ int video_register_device(struct video_device *vfd, int type, int nr) if (ret) { printk(KERN_ERR "%s: class_device_register failed\n", __FUNCTION__); - return ret; + goto fail_minor; } ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name); if (ret < 0) { - printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); - return ret; + printk(KERN_ERR "%s: class_device_create_file 'name' failed\n", + __FUNCTION__); + goto fail_classdev; } #if 1 -- cgit v1.1 From 08d41808362a3663c0856c9720ad940a61156fb5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 22 Jul 2006 21:26:30 -0300 Subject: V4L/DVB (4373): Correctly handle sysfs error leg file removal in pvrusb2 Take note of which sysfs files / groups that the pvrusb2 successfully creates and only delete those specific items when tearing things down. (Previously we just blindly tore everything down every time.) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index ef46d4f..d1dda5c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -44,12 +44,16 @@ struct pvr2_sysfs { struct kobj_type ktype; struct class_device_attribute attr_v4l_minor_number; struct class_device_attribute attr_unit_number; + int v4l_minor_number_created_ok; + int unit_number_created_ok; }; #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC struct pvr2_sysfs_debugifc { struct class_device_attribute attr_debugcmd; struct class_device_attribute attr_debuginfo; + int debugcmd_created_ok; + int debuginfo_created_ok; }; #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ @@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item { struct pvr2_sysfs_ctl_item *item_next; struct attribute *attr_gen[7]; struct attribute_group grp; + int created_ok; char name[80]; }; @@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) struct pvr2_sysfs_func_set *fp; struct pvr2_ctrl *cptr; unsigned int cnt,acnt; + int ret; if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { return; @@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->grp.name = cip->name; cip->grp.attrs = cip->attr_gen; - sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); + ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); + if (ret) { + printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", + __FUNCTION__, ret); + return; + } + cip->created_ok = !0; } #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC @@ -616,22 +628,33 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip->attr_debuginfo.show = debuginfo_show; sfp->debugifc = dip; ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); - if (ret < 0) + if (ret < 0) { printk(KERN_WARNING "%s: class_device_create_file error: %d\n", __FUNCTION__, ret); + } else { + dip->debugcmd_created_ok = !0; + } ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); - if (ret < 0) + if (ret < 0) { printk(KERN_WARNING "%s: class_device_create_file error: %d\n", __FUNCTION__, ret); + } else { + dip->debuginfo_created_ok = !0; + } } static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) { if (!sfp->debugifc) return; - class_device_remove_file(sfp->class_dev, - &sfp->debugifc->attr_debuginfo); - class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd); + if (sfp->debugifc->debuginfo_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->debugifc->attr_debuginfo); + } + if (sfp->debugifc->debugcmd_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->debugifc->attr_debugcmd); + } kfree(sfp->debugifc); sfp->debugifc = NULL; } @@ -653,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) struct pvr2_sysfs_ctl_item *cip1,*cip2; for (cip1 = sfp->item_first; cip1; cip1 = cip2) { cip2 = cip1->item_next; - sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); + if (cip1->created_ok) { + sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); + } pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); kfree(cip1); } @@ -683,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) pvr2_sysfs_tear_down_debugifc(sfp); #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ pvr2_sysfs_tear_down_controls(sfp); - class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); - class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); + if (sfp->v4l_minor_number_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->attr_v4l_minor_number); + } + if (sfp->unit_number_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->attr_unit_number); + } pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); sfp->class_dev->class_data = NULL; class_device_unregister(sfp->class_dev); @@ -756,10 +787,14 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; sfp->attr_v4l_minor_number.store = NULL; - ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); - if (ret < 0) + ret = class_device_create_file(sfp->class_dev, + &sfp->attr_v4l_minor_number); + if (ret < 0) { printk(KERN_WARNING "%s: class_device_create_file error: %d\n", __FUNCTION__, ret); + } else { + sfp->v4l_minor_number_created_ok = !0; + } sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; @@ -767,9 +802,12 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->attr_unit_number.show = unit_number_show; sfp->attr_unit_number.store = NULL; ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); - if (ret < 0) + if (ret < 0) { printk(KERN_WARNING "%s: class_device_create_file error: %d\n", __FUNCTION__, ret); + } else { + sfp->unit_number_created_ok = !0; + } pvr2_sysfs_add_controls(sfp); #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC -- cgit v1.1 From 8c313111a2c843610f58d57b4e02159fecef4bbf Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 25 Jul 2006 20:37:03 -0300 Subject: V4L/DVB (4379): Videodev: Check return value of class_device_register() correctly Errors are return values < 0, not != 0. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 46848e2..0fc90cd 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1575,7 +1575,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base); ret = class_device_register(&vfd->class_dev); - if (ret) { + if (ret < 0) { printk(KERN_ERR "%s: class_device_register failed\n", __FUNCTION__); goto fail_minor; -- cgit v1.1 From ddecbe112b057c333a8e055fb417451a02b9df78 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 26 Jul 2006 17:08:29 -0300 Subject: V4L/DVB (4380): Bttv: Revert VBI_OFFSET to previous value, it works better A previous patch changed VBI_OFFSET to match what the datasheets say it should be. However, the bt8x8 datasheets are wrong. The old value of 244 is closer to what is actually observed. The real value appears to not be constant and is different for different chip revisions. Acked-by: Alan Cox Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-vbi.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 8c9f0f7..63676e7 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -31,11 +31,16 @@ #include #include "bttvp.h" -/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate: - bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC - HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge - of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */ -#define VBI_OFFSET ((64 + 0) * 2) +/* Offset from line sync pulse leading edge (0H) to start of VBI capture, + in fCLKx2 pixels. According to the datasheet, VBI capture starts + VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET + is 64 fCLKx1 pixels wide. VBI_HDELAY is set to 0, so this should be + (64 + 0) * 2 = 128 fCLKx2 pixels. But it's not! The datasheet is + Just Plain Wrong. The real value appears to be different for + different revisions of the bt8x8 chips, and to be affected by the + horizontal scaling factor. Experimentally, the value is measured + to be about 244. */ +#define VBI_OFFSET 244 #define VBI_DEFLINES 16 #define VBI_MAXLINES 32 -- cgit v1.1 From 9c9a43ed2734081124407c779b36a4761c41139b Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Wed, 5 Jul 2006 23:12:20 +0200 Subject: [CPUFREQ] return error when failing to set minfreq I just stumbled on this bug/feature, this is how to reproduce it: # echo 450000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq # echo 450000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq # echo powersave > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # cpufreq-info -p 450000 450000 powersave # echo 1800000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq ; echo $? 0 # cpufreq-info -p 450000 450000 powersave Here it is. The kernel refuses to set a min_freq higher than the max_freq but it allows a max_freq lower than min_freq (lowering min_freq also). This behaviour is pretty straightforward (but undocumented) and it doesn't return an error altough failing to accomplish the requested action (set min_freq). The problem (IMO) is basically that userspace is not allowed to set a full policy atomically while the kernel always does that thus it must enforce an ordering on operations. The attached patch returns -EINVAL if trying to increase frequencies starting from scaling_min_freq and documents the correct ordering of writes. Signed-off-by: Mattia Dongili Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones -- --- drivers/cpufreq/cpufreq.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index bc1088d..ad996c7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1343,6 +1343,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); + if (policy->min > data->min && policy->min > policy->max) { + ret = -EINVAL; + goto error_out; + } + /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(policy); if (ret) -- cgit v1.1 From 3bcb09a35641f2840bd59d8f82154f830dca282c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 6 Jul 2006 12:30:26 -0700 Subject: [CPUFREQ] [1/2] add __find_governor helper and clean up some error handling. Adds a __find_governor() helper function to look up a governor by name. Also restructures some error handling to conform to the "single-exit" model which is generally preferred for kernel code. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 57 ++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ad996c7..9b41637 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -284,39 +284,52 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition); * SYSFS INTERFACE * *********************************************************************/ +static struct cpufreq_governor *__find_governor(const char *str_governor) +{ + struct cpufreq_governor *t; + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) + return t; + + return NULL; +} + /** * cpufreq_parse_governor - parse a governor string */ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { + int err = -EINVAL; + if (!cpufreq_driver) - return -EINVAL; + goto out; + if (cpufreq_driver->setpolicy) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; - return 0; + err = 0; } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_POWERSAVE; - return 0; + err = 0; } - return -EINVAL; - } else { + } else if (cpufreq_driver->target) { struct cpufreq_governor *t; + mutex_lock(&cpufreq_governor_mutex); - if (!cpufreq_driver || !cpufreq_driver->target) - goto out; - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { - *governor = t; - mutex_unlock(&cpufreq_governor_mutex); - return 0; - } + + t = __find_governor(str_governor); + + if (t != NULL) { + *governor = t; + err = 0; } -out: + mutex_unlock(&cpufreq_governor_mutex); } - return -EINVAL; + out: + return err; } @@ -1265,23 +1278,21 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) int cpufreq_register_governor(struct cpufreq_governor *governor) { - struct cpufreq_governor *t; + int err; if (!governor) return -EINVAL; mutex_lock(&cpufreq_governor_mutex); - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { - mutex_unlock(&cpufreq_governor_mutex); - return -EBUSY; - } + err = -EBUSY; + if (__find_governor(governor->name) == NULL) { + err = 0; + list_add(&governor->governor_list, &cpufreq_governor_list); } - list_add(&governor->governor_list, &cpufreq_governor_list); mutex_unlock(&cpufreq_governor_mutex); - return 0; + return err; } EXPORT_SYMBOL_GPL(cpufreq_register_governor); -- cgit v1.1 From ea71497020c55cd39221e0abad5c1752ac6e3f47 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 6 Jul 2006 12:32:01 -0700 Subject: [CPUFREQ] [2/2] demand load governor modules. Demand-load cpufreq governor modules if needed. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9b41637..b3df613 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -321,6 +321,23 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, t = __find_governor(str_governor); + if (t == NULL) { + char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor); + + if (name) { + int ret; + + mutex_unlock(&cpufreq_governor_mutex); + ret = request_module(name); + mutex_lock(&cpufreq_governor_mutex); + + if (ret == 0) + t = __find_governor(str_governor); + } + + kfree(name); + } + if (t != NULL) { *governor = t; err = 0; -- cgit v1.1 From dba654d1508e7060c7d79ab2f63a00325fd84270 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 8 Jul 2006 00:27:49 +0200 Subject: kbuild: hardcode value of YACC&LEX for aic7-triple-x When we introduced -rR then aic7xxx no loger could pick up definition of YACC&LEX from make - so do it explicit now. Signed-off-by: Sam Ravnborg --- drivers/scsi/aic7xxx/aicasm/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile index 8c91fda..b98c5c1 100644 --- a/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/drivers/scsi/aic7xxx/aicasm/Makefile @@ -14,6 +14,8 @@ LIBS= -ldb clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG) # Override default kernel CFLAGS. This is a userland app. AICASM_CFLAGS:= -I/usr/include -I. +LEX= flex +YACC= bison YFLAGS= -d NOMAN= noman -- cgit v1.1 From 99f65f25c19a7a8a5789c300c2a575cff3453382 Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Tue, 1 Aug 2006 23:43:30 +0200 Subject: [PATCH] zd1211rw: Fixes radiotap header There has been a problem in the radiotap header. Monitor mode works now with tcpdump 3.94 + libpcap 0.9.4. ethereal 0.99.0 + libpcap 0.9.4 is broken, because it doesn't find the right offset for the IEEE 802.11 header. Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 3bdc54d..b394303 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -713,10 +713,10 @@ static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) struct zd_rt_hdr { struct ieee80211_radiotap_header rt_hdr; u8 rt_flags; + u8 rt_rate; u16 rt_channel; u16 rt_chbitmask; - u16 rt_rate; -}; +} __attribute__((packed)); static void fill_rt_header(void *buffer, struct zd_mac *mac, const struct ieee80211_rx_stats *stats, @@ -735,14 +735,14 @@ static void fill_rt_header(void *buffer, struct zd_mac *mac, if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; + hdr->rt_rate = stats->rate / 5; + /* FIXME: 802.11a */ hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( _zd_chip_get_channel(&mac->chip))); hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); - - hdr->rt_rate = stats->rate / 5; } /* Returns 1 if the data packet is for us and 0 otherwise. */ -- cgit v1.1 From 71eae25ece9ee6bc2fe9500c9c06bfbb46c55fb2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 1 Aug 2006 23:43:31 +0200 Subject: [PATCH] zd1211rw: Pass more management frame types up to host We'll be needing these at some point... Signed-off-by: Daniel Drake Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.h | 4 +++- drivers/net/wireless/zd1211rw/zd_mac.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 8051210..0eb9c8f 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -461,10 +461,12 @@ #define CR_RX_FILTER CTL_REG(0x068c) #define RX_FILTER_ASSOC_RESPONSE 0x0002 +#define RX_FILTER_REASSOC_RESPONSE 0x0008 #define RX_FILTER_PROBE_RESPONSE 0x0020 #define RX_FILTER_BEACON 0x0100 +#define RX_FILTER_DISASSOC 0x0400 #define RX_FILTER_AUTH 0x0800 -/* Sniff modus sets filter to 0xfffff */ +/* Monitor mode sets filter to 0xfffff */ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index b394303..1cf1fda 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -136,8 +136,10 @@ static int reset_mode(struct zd_mac *mac) { struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); struct zd_ioreq32 ioreqs[3] = { - { CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE| - RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE }, + { CR_RX_FILTER, RX_FILTER_BEACON | RX_FILTER_PROBE_RESPONSE | + RX_FILTER_AUTH | RX_FILTER_ASSOC_RESPONSE | + RX_FILTER_REASSOC_RESPONSE | + RX_FILTER_DISASSOC }, { CR_SNIFFER_ON, 0U }, { CR_ENCRYPTION_TYPE, NO_WEP }, }; -- cgit v1.1 From 40da08bca6f4e7dec4a75c3c47800e5f4ca4e567 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 1 Aug 2006 23:43:32 +0200 Subject: [PATCH] zd1211rw: Fix software encryption/decryption Apparently the ZD1211 doesn't mind, but the ZD1211B absolutely must be told that encryption is happening in software. Signed-off-by: Daniel Drake Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 1cf1fda..a66625c 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -108,7 +108,9 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) if (r) goto disable_int; - r = zd_set_encryption_type(chip, NO_WEP); + /* We must inform the device that we are doing encryption/decryption in + * software at the moment. */ + r = zd_set_encryption_type(chip, ENC_SNIFFER); if (r) goto disable_int; @@ -141,7 +143,6 @@ static int reset_mode(struct zd_mac *mac) RX_FILTER_REASSOC_RESPONSE | RX_FILTER_DISASSOC }, { CR_SNIFFER_ON, 0U }, - { CR_ENCRYPTION_TYPE, NO_WEP }, }; if (ieee->iw_mode == IW_MODE_MONITOR) { -- cgit v1.1 From b1162b639cc13d5a1ab9bcbd0a502599ddf49f86 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 1 Aug 2006 23:43:33 +0200 Subject: [PATCH] zd1211rw: Remove bogus assert This function is never called in interrupt context, and it doesn't matter if it is called in IRQ context or not. Signed-off-by: Daniel Drake Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 72f9052..f9a93f6 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -323,7 +323,6 @@ static void disable_read_regs_int(struct zd_usb *usb) { struct zd_usb_interrupt *intr = &usb->intr; - ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); intr->read_regs_enabled = 0; spin_unlock(&intr->lock); -- cgit v1.1 From b269825b9bb2c925bbaf4365ec9fa4c6a16e46b4 Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Tue, 1 Aug 2006 23:43:34 +0200 Subject: [PATCH] zd1211rw: Fixed endianess issue with length info tag detection Discovered a problem while accessing www.python.org on my PPC32. The problem was pretty consistent for all sticks. The reason was that while testing for the length info tag, I ignored the endianess of the host system. Please recognize that converting the constant to little endian, we create faster code. Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index f9a93f6..6320984 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -544,11 +544,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, * be padded. Unaligned access might also happen if the length_info * structure is not present. */ - if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) { + if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG)) + { unsigned int l, k, n; for (i = 0, l = 0;; i++) { - k = le16_to_cpu(get_unaligned( - &length_info->length[i])); + k = le16_to_cpu(get_unaligned(&length_info->length[i])); n = l+k; if (n > length) return; -- cgit v1.1 From fde627b54ce7bef094157074f3adb9b6e1a96d4c Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Tue, 1 Aug 2006 23:43:35 +0200 Subject: [PATCH] zd1211rw: Packet filter fix for managed (STA) mode I had problems with my AVM Fritz!Box access point. It appeared that the AP deauthorized me and the softmac didn't reconnect me. This patch handles the problem. Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 4 ++-- drivers/net/wireless/zd1211rw/zd_chip.h | 6 +++--- drivers/net/wireless/zd1211rw/zd_mac.c | 5 +---- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index efc9c4b..da9d06b 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -797,7 +797,7 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_ZD1211_RETRY_MAX, 0x2 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, AP_RX_FILTER }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, @@ -844,7 +844,7 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, { CR_ZD1211B_TXOP, 0x01800824 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, AP_RX_FILTER }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 0eb9c8f..069d2b4 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -466,6 +466,9 @@ #define RX_FILTER_BEACON 0x0100 #define RX_FILTER_DISASSOC 0x0400 #define RX_FILTER_AUTH 0x0800 +#define AP_RX_FILTER 0x0400feff +#define STA_RX_FILTER 0x0000ffff + /* Monitor mode sets filter to 0xfffff */ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) @@ -548,9 +551,6 @@ #define CR_ZD1211B_TXOP CTL_REG(0x0b20) #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) -#define AP_RX_FILTER 0x0400feff -#define STA_RX_FILTER 0x0000ffff - #define CWIN_SIZE 0x007f043f diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a66625c..d6f3e02 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -138,10 +138,7 @@ static int reset_mode(struct zd_mac *mac) { struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); struct zd_ioreq32 ioreqs[3] = { - { CR_RX_FILTER, RX_FILTER_BEACON | RX_FILTER_PROBE_RESPONSE | - RX_FILTER_AUTH | RX_FILTER_ASSOC_RESPONSE | - RX_FILTER_REASSOC_RESPONSE | - RX_FILTER_DISASSOC }, + { CR_RX_FILTER, STA_RX_FILTER }, { CR_SNIFFER_ON, 0U }, }; -- cgit v1.1 From 9cac2c35e26cc44978df654306bb92d7cfe7e2de Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 30 Jul 2006 20:20:54 -0700 Subject: [ATALK]: Make CONFIG_DEV_APPLETALK a tristate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we allow building appletalk drivers in-kernel when CONFIG_ATALK is modular. That doesn't work because these drivers use symbols such as "alloc_talkdev" which is exported from code built by CONFIG_ATALK. Noticed by Toralf Förster. Signed-off-by: David S. Miller --- drivers/net/appletalk/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig index b14e890..0a0e0cd 100644 --- a/drivers/net/appletalk/Kconfig +++ b/drivers/net/appletalk/Kconfig @@ -29,7 +29,7 @@ config ATALK even politically correct people are allowed to say Y here. config DEV_APPLETALK - bool "Appletalk interfaces support" + tristate "Appletalk interfaces support" depends on ATALK help AppleTalk is the protocol that Apple computers can use to communicate -- cgit v1.1 From e795d092507d571d66f2ec98d3efdc7dd284bf80 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 30 Jul 2006 20:44:19 -0700 Subject: [NET] infiniband: Cleanup ib_addr module to use the netevents Signed-off-by: Tom Tucker Signed-off-by: Steve Wise Signed-off-by: David S. Miller --- drivers/infiniband/core/addr.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index d294bbc..1205e80 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -35,6 +35,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Sean Hefty"); @@ -326,25 +327,22 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) } EXPORT_SYMBOL(rdma_addr_cancel); -static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pkt, struct net_device *orig_dev) +static int netevent_callback(struct notifier_block *self, unsigned long event, + void *ctx) { - struct arphdr *arp_hdr; + if (event == NETEVENT_NEIGH_UPDATE) { + struct neighbour *neigh = ctx; - arp_hdr = (struct arphdr *) skb->nh.raw; - - if (arp_hdr->ar_op == htons(ARPOP_REQUEST) || - arp_hdr->ar_op == htons(ARPOP_REPLY)) - set_timeout(jiffies); - - kfree_skb(skb); + if (neigh->dev->type == ARPHRD_INFINIBAND && + (neigh->nud_state & NUD_VALID)) { + set_timeout(jiffies); + } + } return 0; } -static struct packet_type addr_arp = { - .type = __constant_htons(ETH_P_ARP), - .func = addr_arp_recv, - .af_packet_priv = (void*) 1, +static struct notifier_block nb = { + .notifier_call = netevent_callback }; static int addr_init(void) @@ -353,13 +351,13 @@ static int addr_init(void) if (!addr_wq) return -ENOMEM; - dev_add_pack(&addr_arp); + register_netevent_notifier(&nb); return 0; } static void addr_cleanup(void) { - dev_remove_pack(&addr_arp); + unregister_netevent_notifier(&nb); destroy_workqueue(addr_wq); } -- cgit v1.1 From a20e9c6291f27cac4a9ab450d124794c012f87d4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 31 Jul 2006 22:38:16 -0700 Subject: [TG3]: Convert to netdev_alloc_skb Signed-off-by: David S. Miller --- drivers/net/tg3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1b8138f..6f97962 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.63" -#define DRV_MODULE_RELDATE "July 25, 2006" +#define DRV_MODULE_VERSION "3.64" +#define DRV_MODULE_RELDATE "July 31, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3097,7 +3097,7 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. */ - skb = dev_alloc_skb(skb_size); + skb = netdev_alloc_skb(tp->dev, skb_size); if (skb == NULL) return -ENOMEM; @@ -3270,7 +3270,7 @@ static int tg3_rx(struct tg3 *tp, int budget) tg3_recycle_rx(tp, opaque_key, desc_idx, *post_ptr); - copy_skb = dev_alloc_skb(len + 2); + copy_skb = netdev_alloc_skb(tp->dev, len + 2); if (copy_skb == NULL) goto drop_it_no_recycle; @@ -8618,7 +8618,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) err = -EIO; tx_len = 1514; - skb = dev_alloc_skb(tx_len); + skb = netdev_alloc_skb(tp->dev, tx_len); if (!skb) return -ENOMEM; -- cgit v1.1 From 87f5032e0ca149bd03f0e2b46071b0c4a2312e82 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 31 Jul 2006 22:39:40 -0700 Subject: [E1000]: Convert to netdev_alloc_skb Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index da62db8..627f224 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3127,7 +3127,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) break; } - /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN * means we reserve 2 more, this pushes us to allocate from the next * larger slab size * i.e. RXBUFFER_2048 --> size-4096 slab */ @@ -3708,7 +3708,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, #define E1000_CB_LENGTH 256 if (length < E1000_CB_LENGTH) { struct sk_buff *new_skb = - dev_alloc_skb(length + NET_IP_ALIGN); + netdev_alloc_skb(netdev, length + NET_IP_ALIGN); if (new_skb) { skb_reserve(new_skb, NET_IP_ALIGN); new_skb->dev = netdev; @@ -3979,7 +3979,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, while (cleaned_count--) { if (!(skb = buffer_info->skb)) - skb = dev_alloc_skb(bufsz); + skb = netdev_alloc_skb(netdev, bufsz); else { skb_trim(skb, 0); goto map_skb; @@ -3997,7 +3997,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " "at %p\n", bufsz, skb->data); /* Try again, without freeing the previous */ - skb = dev_alloc_skb(bufsz); + skb = netdev_alloc_skb(netdev, bufsz); /* Failed allocation, critical failure */ if (!skb) { dev_kfree_skb(oldskb); @@ -4121,7 +4121,8 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc->read.buffer_addr[j+1] = ~0; } - skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); + skb = netdev_alloc_skb(netdev, + adapter->rx_ps_bsize0 + NET_IP_ALIGN); if (unlikely(!skb)) { adapter->alloc_rx_buff_failed++; -- cgit v1.1 From c7c17423b9ea3c5559cfb480a00844f1df9eed06 Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Fri, 28 Jul 2006 10:03:55 -0500 Subject: [IA64] add platform check to snsc driver init Add a platform check to the snsc driver init function, to prevent loading on non-sn2 systems. Signed-off-by: Greg Edwards Signed-off-by: Tony Luck --- drivers/char/snsc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index afc6eda..07e0b75 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -374,7 +374,12 @@ scdrv_init(void) struct sysctl_data_s *scd; void *salbuf; dev_t first_dev, dev; - nasid_t event_nasid = ia64_sn_get_console_nasid(); + nasid_t event_nasid; + + if (!ia64_platform_is("sn2")) + return -ENODEV; + + event_nasid = ia64_sn_get_console_nasid(); if (alloc_chrdev_region(&first_dev, 0, num_cnodes, SYSCTL_BASENAME) < 0) { -- cgit v1.1 From 8b2e76687b39213725207b4a4264e11e8c7b86e6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 5 Jul 2006 02:38:56 -0700 Subject: USB: AT91 UDC updates, mostly power management UDC updates for AT91 series processors: - Get ready for at91sam926x processors (ARMv5tej not ARMv4t) - Suspend/resume support now behaves properly - In "standby" mode, UDC can be a source of system wakeup events (host resume, device connect/disconnect, etc) - Fix IRQ storming issues, seemingly related to clock disabling changes that went in a while back And minor cleanups, especially whitespace. Signed-off-by: David Brownell Signed-off-by: Andrew Victor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/at91_udc.c | 176 +++++++++++++++++++++++++++--------------- drivers/usb/gadget/at91_udc.h | 1 + 2 files changed, 113 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 1c459ff..cfebca0 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -57,19 +57,23 @@ /* * This controller is simple and PIO-only. It's used in many AT91-series - * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU), - * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions. + * full speed USB controllers, including the at91rm9200 (arm920T, with MMU), + * at91sam926x (arm926ejs, with MMU), and several no-mmu versions. * * This driver expects the board has been wired with two GPIOs suppporting * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the - * testing hasn't covered such cases.) The pullup is most important; it + * testing hasn't covered such cases.) + * + * The pullup is most important (so it's integrated on sam926x parts). It * provides software control over whether the host enumerates the device. + * * The VBUS sensing helps during enumeration, and allows both USB clocks * (and the transceiver) to stay gated off until they're necessary, saving - * power. During USB suspend, the 48 MHz clock is gated off. + * power. During USB suspend, the 48 MHz clock is gated off in hardware; + * it may also be gated off by software during some Linux sleep states. */ -#define DRIVER_VERSION "8 March 2005" +#define DRIVER_VERSION "3 May 2006" static const char driver_name [] = "at91_udc"; static const char ep0name[] = "ep0"; @@ -316,9 +320,15 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status) * * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE * that shouldn't normally be changed. + * + * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains, + * implying a need to wait for one write to complete (test relevant bits) + * before starting the next write. This shouldn't be an issue given how + * infrequently we write, except maybe for write-then-read idioms. */ #define SET_FX (AT91_UDP_TXPKTRDY) -#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) +#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \ + | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) /* pull OUT packet data from the endpoint's fifo */ static int read_fifo (struct at91_ep *ep, struct at91_request *req) @@ -472,7 +482,8 @@ static void nuke(struct at91_ep *ep, int status) /*-------------------------------------------------------------------------*/ -static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +static int at91_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); struct at91_udc *dev = ep->udc; @@ -582,11 +593,12 @@ static int at91_ep_disable (struct usb_ep * _ep) * interesting for request or buffer allocation. */ -static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) +static struct usb_request * +at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) { struct at91_request *req; - req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); + req = kcalloc(1, sizeof (struct at91_request), gfp_flags); if (!req) return NULL; @@ -862,6 +874,7 @@ static void stop_activity(struct at91_udc *udc) if (udc->gadget.speed == USB_SPEED_UNKNOWN) driver = NULL; udc->gadget.speed = USB_SPEED_UNKNOWN; + udc->suspended = 0; for (i = 0; i < NUM_ENDPOINTS; i++) { struct at91_ep *ep = &udc->ep[i]; @@ -889,8 +902,8 @@ static void clk_off(struct at91_udc *udc) return; udc->clocked = 0; udc->gadget.speed = USB_SPEED_UNKNOWN; - clk_disable(udc->iclk); clk_disable(udc->fclk); + clk_disable(udc->iclk); } /* @@ -911,9 +924,6 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); at91_set_gpio_value(udc->board.pullup_pin, 0); clk_off(udc); - - // REVISIT: with transceiver disabled, will D- float - // so that a host would falsely detect a device? } } @@ -1290,7 +1300,8 @@ static void handle_ep0(struct at91_udc *udc) if (udc->wait_for_addr_ack) { u32 tmp; - at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); + at91_udp_write(AT91_UDP_FADDR, + AT91_UDP_FEN | udc->addr); tmp = at91_udp_read(AT91_UDP_GLB_STAT); tmp &= ~AT91_UDP_FADDEN; if (udc->addr) @@ -1361,9 +1372,10 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) u32 rescans = 5; while (rescans--) { - u32 status = at91_udp_read(AT91_UDP_ISR); + u32 status; - status &= at91_udp_read(AT91_UDP_IMR); + status = at91_udp_read(AT91_UDP_ISR) + & at91_udp_read(AT91_UDP_IMR); if (!status) break; @@ -1379,18 +1391,17 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) stop_activity(udc); /* enable ep0 */ - at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); + at91_udp_write(AT91_UDP_CSR(0), + AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); udc->gadget.speed = USB_SPEED_FULL; udc->suspended = 0; at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); /* * NOTE: this driver keeps clocks off unless the - * USB host is present. That saves power, and also - * eliminates IRQs (reset, resume, suspend) that can - * otherwise flood from the controller. If your - * board doesn't support VBUS detection, suspend and - * resume irq logic may need more attention... + * USB host is present. That saves power, but for + * boards that don't support VBUS detection, both + * clocks need to be active most of the time. */ /* host initiated suspend (3+ms bus idle) */ @@ -1452,13 +1463,19 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) /*-------------------------------------------------------------------------*/ +static void nop_release(struct device *dev) +{ + /* nothing to free */ +} + static struct at91_udc controller = { .gadget = { - .ops = &at91_udc_ops, - .ep0 = &controller.ep[0].ep, - .name = driver_name, - .dev = { - .bus_id = "gadget" + .ops = &at91_udc_ops, + .ep0 = &controller.ep[0].ep, + .name = driver_name, + .dev = { + .bus_id = "gadget", + .release = nop_release, } }, .ep[0] = { @@ -1468,7 +1485,8 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(0)), .int_mask = 1 << 0, }, .ep[1] = { @@ -1479,7 +1497,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(1)), .int_mask = 1 << 1, }, .ep[2] = { @@ -1490,7 +1509,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(2)), .int_mask = 1 << 2, }, .ep[3] = { @@ -1501,7 +1521,8 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(3)), .int_mask = 1 << 3, }, .ep[4] = { @@ -1512,7 +1533,8 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(4)), .int_mask = 1 << 4, }, .ep[5] = { @@ -1523,10 +1545,11 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + + AT91_UDP_CSR(5)), .int_mask = 1 << 5, }, - /* ep6 and ep7 are also reserved */ + /* ep6 and ep7 are also reserved (custom silicon might use them) */ }; static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) @@ -1593,6 +1616,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) local_irq_disable(); udc->enabled = 0; + at91_udp_write(AT91_UDP_IDR, ~0); pullup(udc, 0); local_irq_enable(); @@ -1624,6 +1648,16 @@ static int __devinit at91udc_probe(struct platform_device *pdev) return -ENODEV; } + if (pdev->num_resources != 2) { + DBG("invalid num_resources"); + return -ENODEV; + } + if ((pdev->resource[0].flags != IORESOURCE_MEM) + || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + DBG("invalid resource type"); + return -ENODEV; + } + if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { DBG("someone's using UDC memory\n"); return -EBUSY; @@ -1649,19 +1683,26 @@ static int __devinit at91udc_probe(struct platform_device *pdev) if (retval < 0) goto fail0; - /* disable everything until there's a gadget driver and vbus */ - pullup(udc, 0); + /* don't do anything until we have both gadget driver and VBUS */ + clk_enable(udc->iclk); + at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + at91_udp_write(AT91_UDP_IDR, 0xffffffff); + clk_disable(udc->iclk); /* request UDC and maybe VBUS irqs */ - if (request_irq(AT91_ID_UDP, at91_udc_irq, IRQF_DISABLED, driver_name, udc)) { - DBG("request irq %d failed\n", AT91_ID_UDP); + udc->udp_irq = platform_get_irq(pdev, 0); + if (request_irq(udc->udp_irq, at91_udc_irq, + IRQF_DISABLED, driver_name, udc)) { + DBG("request irq %d failed\n", udc->udp_irq); retval = -EBUSY; goto fail1; } if (udc->board.vbus_pin > 0) { - if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) { - DBG("request vbus irq %d failed\n", udc->board.vbus_pin); - free_irq(AT91_ID_UDP, udc); + if (request_irq(udc->board.vbus_pin, at91_vbus_irq, + IRQF_DISABLED, driver_name, udc)) { + DBG("request vbus irq %d failed\n", + udc->board.vbus_pin); + free_irq(udc->udp_irq, udc); retval = -EBUSY; goto fail1; } @@ -1670,6 +1711,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) udc->vbus = 1; } dev_set_drvdata(dev, udc); + device_init_wakeup(dev, 1); create_debug_file(udc); INFO("%s version %s\n", driver_name, DRIVER_VERSION); @@ -1678,14 +1720,14 @@ static int __devinit at91udc_probe(struct platform_device *pdev) fail1: device_unregister(&udc->gadget.dev); fail0: - release_mem_region(AT91_VA_BASE_UDP, SZ_16K); + release_mem_region(AT91_BASE_UDP, SZ_16K); DBG("%s probe failed, %d\n", driver_name, retval); return retval; } -static int __devexit at91udc_remove(struct platform_device *dev) +static int __devexit at91udc_remove(struct platform_device *pdev) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); DBG("remove\n"); @@ -1694,10 +1736,11 @@ static int __devexit at91udc_remove(struct platform_device *dev) if (udc->driver != 0) usb_gadget_unregister_driver(udc->driver); + device_init_wakeup(&pdev->dev, 0); remove_debug_file(udc); if (udc->board.vbus_pin > 0) free_irq(udc->board.vbus_pin, udc); - free_irq(AT91_ID_UDP, udc); + free_irq(udc->udp_irq, udc); device_unregister(&udc->gadget.dev); release_mem_region(AT91_BASE_UDP, SZ_16K); @@ -1708,31 +1751,36 @@ static int __devexit at91udc_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg) +static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); + int wake = udc->driver && device_may_wakeup(&pdev->dev); - /* - * The "safe" suspend transitions are opportunistic ... e.g. when - * the USB link is suspended (48MHz clock autogated off), or when - * it's disconnected (programmatically gated off, elsewhere). - * Then we can suspend, and the chip can enter slow clock mode. - * - * The problem case is some component (user mode?) suspending this - * device while it's active, with the 48 MHz clock in use. There - * are two basic approaches: (a) veto suspend levels involving slow - * clock mode, (b) disconnect, so 48 MHz will no longer be in use - * and we can enter slow clock mode. This uses (b) for now, since - * it's simplest until AT91 PM exists and supports the other option. + /* Unless we can act normally to the host (letting it wake us up + * whenever it has work for us) force disconnect. Wakeup requires + * PLLB for USB events (signaling for reset, wakeup, or incoming + * tokens) and VBUS irqs (on systems which support them). */ - if (udc->vbus && !udc->suspended) + if ((!udc->suspended && udc->addr) + || !wake + || at91_suspend_entering_slow_clock()) { pullup(udc, 0); + disable_irq_wake(udc->udp_irq); + } else + enable_irq_wake(udc->udp_irq); + + if (udc->board.vbus_pin > 0) { + if (wake) + enable_irq_wake(udc->board.vbus_pin); + else + disable_irq_wake(udc->board.vbus_pin); + } return 0; } -static int at91udc_resume(struct platform_device *dev) +static int at91udc_resume(struct platform_device *pdev) { - struct at91_udc *udc = platform_get_drvdata(dev); + struct at91_udc *udc = platform_get_drvdata(pdev); /* maybe reconnect to host; if so, clocks on */ pullup(udc, 1); @@ -1748,7 +1796,7 @@ static struct platform_driver at91_udc = { .remove = __devexit_p(at91udc_remove), .shutdown = at91udc_shutdown, .suspend = at91udc_suspend, - .resume = at91udc_resume, + .resume = at91udc_resume, .driver = { .name = (char *) driver_name, .owner = THIS_MODULE, @@ -1767,6 +1815,6 @@ static void __devexit udc_exit_module(void) } module_exit(udc_exit_module); -MODULE_DESCRIPTION("AT91RM9200 udc driver"); +MODULE_DESCRIPTION("AT91 udc driver"); MODULE_AUTHOR("Thomas Rathbone, David Brownell"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index 5a4799c..882af42 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -141,6 +141,7 @@ struct at91_udc { struct clk *iclk, *fclk; struct platform_device *pdev; struct proc_dir_entry *pde; + int udp_irq; }; static inline struct at91_udc *to_udc(struct usb_gadget *g) -- cgit v1.1 From 0365ee0a8f7450c5e79302930d461e58161a96a1 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 19 Jun 2006 14:27:20 -0700 Subject: USB: AT91 OHCI updates, mostly power management OHCI updates for AT91 series processors: - Get ready for at91sam926x processors (ARMv5tej not ARMv4t) - Suspend/resume support now behaves properly - In "standby" mode, OHCI can be a source of system wakeup events (remote wakeup, device connect/disconnect, etc) And minor cleanups. Signed-off-by: David Brownell Signed-off-by: Andrew Victor Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 2 +- drivers/usb/host/ohci-at91.c | 88 +++++++++++++++++++++++++++++--------------- drivers/usb/host/ohci-hcd.c | 3 +- 3 files changed, 62 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 2ee742d..0050431 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_S3C2410 default y if PXA27x default y if ARCH_EP93XX - default y if ARCH_AT91RM9200 + default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index cdbafb7..85cc059 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -4,7 +4,7 @@ * Copyright (C) 2004 SAN People (Pty) Ltd. * Copyright (C) 2005 Thibaut VARENE * - * AT91RM9200 Bus Glue + * AT91 Bus Glue * * Based on fragments of 2.4 driver by Rick Bronson. * Based on ohci-omap.c @@ -19,12 +19,13 @@ #include #include -#ifndef CONFIG_ARCH_AT91RM9200 -#error "CONFIG_ARCH_AT91RM9200 must be defined." +#ifndef CONFIG_ARCH_AT91 +#error "CONFIG_ARCH_AT91 must be defined." #endif /* interface and function clocks */ static struct clk *iclk, *fclk; +static int clocked; extern int usb_disabled(void); @@ -35,13 +36,14 @@ static void at91_start_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); + dev_dbg(&pdev->dev, "start\n"); /* * Start the USB clocks. */ clk_enable(iclk); clk_enable(fclk); + clocked = 1; /* * The USB host controller must remain in reset. @@ -54,7 +56,7 @@ static void at91_stop_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); + dev_dbg(&pdev->dev, "stop\n"); /* * Put the USB host controller into reset. @@ -66,6 +68,7 @@ static void at91_stop_hc(struct platform_device *pdev) */ clk_disable(fclk); clk_disable(iclk); + clocked = 0; } @@ -78,14 +81,15 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /** - * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs + * usb_hcd_at91_probe - initialize AT91-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) +static int usb_hcd_at91_probe(const struct hc_driver *driver, + struct platform_device *pdev) { int retval; struct usb_hcd *hcd = NULL; @@ -95,12 +99,13 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device * return -ENODEV; } - if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + if ((pdev->resource[0].flags != IORESOURCE_MEM) + || (pdev->resource[1].flags != IORESOURCE_IRQ)) { pr_debug("hcd probe: invalid resource type\n"); return -ENODEV; } - hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); + hcd = usb_create_hcd(driver, &pdev->dev, "at91"); if (!hcd) return -ENOMEM; hcd->rsrc_start = pdev->resource[0].start; @@ -149,21 +154,23 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device * /* may be called with controller, bus, and devices active */ /** - * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs + * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_at91_probe(), first invoking * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. + * context, "rmmod" or something similar. * */ -static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) +static int usb_hcd_at91_remove(struct usb_hcd *hcd, + struct platform_device *pdev) { usb_remove_hcd(hcd); at91_stop_hc(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + disable_irq_wake(hcd->irq); clk_put(fclk); clk_put(iclk); @@ -178,19 +185,21 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde static int __devinit ohci_at91_start (struct usb_hcd *hcd) { -// struct at91_ohci_data *board = hcd->self.controller->platform_data; + struct at91_usbh_data *board = hcd->self.controller->platform_data; struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct usb_device *root = hcd->self.root_hub; int ret; if ((ret = ohci_init(ohci)) < 0) return ret; + root->maxchild = board->ports; + if ((ret = ohci_run(ohci)) < 0) { err("can't start %s", hcd->self.bus_name); ohci_stop(hcd); return ret; } -// hcd->self.root_hub->maxchild = board->ports; return 0; } @@ -198,7 +207,7 @@ ohci_at91_start (struct usb_hcd *hcd) static const struct hc_driver ohci_at91_hc_driver = { .description = hcd_name, - .product_desc = "AT91RM9200 OHCI", + .product_desc = "AT91 OHCI", .hcd_priv_size = sizeof(struct ohci_hcd), /* @@ -240,33 +249,54 @@ static const struct hc_driver ohci_at91_hc_driver = { /*-------------------------------------------------------------------------*/ -static int ohci_hcd_at91_drv_probe(struct platform_device *dev) +static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) { - return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); + device_init_wakeup(&pdev->dev, 1); + return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } -static int ohci_hcd_at91_drv_remove(struct platform_device *dev) +static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) { - return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); + device_init_wakeup(&pdev->dev, 0); + return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); } #ifdef CONFIG_PM -/* REVISIT suspend/resume look "too" simple here */ - static int -ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg) +ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) { - clk_disable(fclk); - clk_disable(iclk); + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(hcd->irq); + else + disable_irq_wake(hcd->irq); + + /* + * The integrated transceivers seem unable to notice disconnect, + * reconnect, or wakeup without the 48 MHz clock active. so for + * correctness, always discard connection state (using reset). + * + * REVISIT: some boards will be able to turn VBUS off... + */ + if (at91_suspend_entering_slow_clock()) { + ohci_usb_reset (ohci); + clk_disable(fclk); + clk_disable(iclk); + clocked = 0; + } return 0; } -static int ohci_hcd_at91_drv_resume(struct platform_device *dev) +static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) { - clk_enable(iclk); - clk_enable(fclk); + if (!clocked) { + clk_enable(iclk); + clk_enable(fclk); + } return 0; } @@ -275,7 +305,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev) #define ohci_hcd_at91_drv_resume NULL #endif -MODULE_ALIAS("at91rm9200-ohci"); +MODULE_ALIAS("at91_ohci"); static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, @@ -283,7 +313,7 @@ static struct platform_driver ohci_hcd_at91_driver = { .suspend = ohci_hcd_at91_drv_suspend, .resume = ohci_hcd_at91_drv_resume, .driver = { - .name = "at91rm9200-ohci", + .name = "at91_ohci", .owner = THIS_MODULE, }, }; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index afef5ac..94d8cf4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -913,7 +913,7 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif -#ifdef CONFIG_ARCH_AT91RM9200 +#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) #include "ohci-at91.c" #endif @@ -927,6 +927,7 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ || defined (CONFIG_ARCH_AT91RM9200) \ + || defined (CONFIG_ARCH_AT91SAM9261) \ ) #error "missing bus glue for ohci-hcd" #endif -- cgit v1.1 From b3fdab59b8f5d8e42fa339be74cd015dc1a3192f Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Wed, 2 Aug 2006 16:41:41 -0700 Subject: USB: Option driver: removed change history and linux/version.h include Signed-off-by: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f0530c1..2a07945 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -9,33 +9,7 @@ Portions copied from the Keyspan driver by Hugh Blemings - History: - - 2005-05-19 v0.1 Initial version, based on incomplete docs - and analysis of misbehavior with the standard driver - 2005-05-20 v0.2 Extended the input buffer to avoid losing - random 64-byte chunks of data - 2005-05-21 v0.3 implemented chars_in_buffer() - turned on low_latency - simplified the code somewhat - 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load - removed some dead code - added sponsor notice - coding style clean-up - 2005-06-20 v0.4.1 add missing braces :-/ - killed end-of-line whitespace - 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 - 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard - 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes - wants to send >2000 bytes. - 2006-04-10 v0.5 fixed two array overrun errors :-/ - 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 - 2006-05-15 v0.6 re-enable multi-port support - 2006-06-01 v0.6.1 add COBRA - 2006-06-01 v0.6.2 add backwards-compatibility stuff - 2006-06-01 v0.6.3 add Novatel Wireless - 2006-06-01 v0.7 Option => GSM - 2006-06-01 v0.7.1 add COBRA2 + History: see the git log. Work sponsored by: Sigos GmbH, Germany -- cgit v1.1 From 02b2ac5b0370b1157a5a99f2fdf006644b9b86d5 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Wed, 2 Aug 2006 16:41:41 -0700 Subject: USB: Option driver: Short driver names were identical The short driver names were not unique, which prevented the driver from actually loading. Also, one of the ioctl pointers was missing. Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 2a07945..283383d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -128,7 +128,7 @@ static struct usb_driver option_driver = { static struct usb_serial_driver option_3port_device = { .driver = { .owner = THIS_MODULE, - .name = "option", + .name = "option3", }, .description = "GSM modem (3-port)", .id_table = option_ids3, @@ -143,6 +143,7 @@ static struct usb_serial_driver option_3port_device = { .chars_in_buffer = option_chars_in_buffer, .throttle = option_rx_throttle, .unthrottle = option_rx_unthrottle, + .ioctl = option_ioctl, .set_termios = option_set_termios, .break_ctl = option_break_ctl, .tiocmget = option_tiocmget, @@ -155,7 +156,7 @@ static struct usb_serial_driver option_3port_device = { static struct usb_serial_driver option_1port_device = { .driver = { .owner = THIS_MODULE, - .name = "option", + .name = "option1", }, .description = "GSM modem (1-port)", .id_table = option_ids1, @@ -630,7 +631,6 @@ static void option_setup_urbs(struct usb_serial *serial) dbg("%s", __FUNCTION__); - for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); -- cgit v1.1 From 31fcbb733812bca52e8bee96d62ba56df0fc408b Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Wed, 12 Jul 2006 08:35:29 +0200 Subject: USB: Let option driver handle Anydata CDMA modems. Remove anydata driver. Signed-off-by: Jon K Hellan Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 24 ++++----- drivers/usb/serial/Makefile | 1 - drivers/usb/serial/anydata.c | 123 ------------------------------------------- drivers/usb/serial/option.c | 4 ++ 4 files changed, 13 insertions(+), 139 deletions(-) delete mode 100644 drivers/usb/serial/anydata.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index ac33bd4..f5b9438 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -62,15 +62,6 @@ config USB_SERIAL_AIRPRIME To compile this driver as a module, choose M here: the module will be called airprime. -config USB_SERIAL_ANYDATA - tristate "USB AnyData CDMA Wireless Driver" - depends on USB_SERIAL - help - Say Y here if you want to use a AnyData CDMA device. - - To compile this driver as a module, choose M here: the - module will be called anydata. - config USB_SERIAL_ARK3116 tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL @@ -502,15 +493,18 @@ config USB_SERIAL_XIRCOM module will be called keyspan_pda. config USB_SERIAL_OPTION - tristate "USB driver for GSM modems" + tristate "USB driver for GSM and CDMA modems" depends on USB_SERIAL help - Say Y here if you have an "Option" GSM PCMCIA card - (or an OEM version: branded Huawei, Audiovox, or Novatel). + Say Y here if you have a GSM or CDMA modem that's connected to USB. + + This driver also supports several PCMCIA cards which have a + built-in OHCI-USB adapter and an internally-connected GSM modem. + The USB bus on these cards is not accessible externally. - These cards feature a built-in OHCI-USB adapter and an - internally-connected GSM modem. The USB bus is not - accessible externally. + Supported devices include (some of?) those made by: + Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or + Anydata. To compile this driver as a module, choose M here: the module will be called option. diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 35d4acc..8efed2c 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -12,7 +12,6 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o -obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c deleted file mode 100644 index 01843ef..0000000 --- a/drivers/usb/serial/anydata.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * AnyData CDMA Serial USB driver - * - * Copyright (C) 2005 Greg Kroah-Hartman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -static struct usb_device_id id_table [] = { - { USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */ - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* if overridden by the user, then use their value for the size of the - * read and write urbs */ -static int buffer_size; -static int debug; - -static struct usb_driver anydata_driver = { - .name = "anydata", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - -static int anydata_open(struct usb_serial_port *port, struct file *filp) -{ - char *buffer; - int result = 0; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (buffer_size) { - /* override the default buffer sizes */ - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&port->dev, "%s - out of memory.\n", - __FUNCTION__); - return -ENOMEM; - } - kfree (port->read_urb->transfer_buffer); - port->read_urb->transfer_buffer = buffer; - port->read_urb->transfer_buffer_length = buffer_size; - - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) { - dev_err(&port->dev, "%s - out of memory.\n", - __FUNCTION__); - return -ENOMEM; - } - kfree (port->write_urb->transfer_buffer); - port->write_urb->transfer_buffer = buffer; - port->write_urb->transfer_buffer_length = buffer_size; - port->bulk_out_size = buffer_size; - } - - /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - usb_serial_generic_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __FUNCTION__, result); - - return result; -} - -static struct usb_serial_driver anydata_device = { - .driver = { - .owner = THIS_MODULE, - .name = "anydata", - }, - .id_table = id_table, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, - .open = anydata_open, -}; - -static int __init anydata_init(void) -{ - int retval; - - retval = usb_serial_register(&anydata_device); - if (retval) - return retval; - retval = usb_register(&anydata_driver); - if (retval) - usb_serial_deregister(&anydata_device); - return retval; -} - -static void __exit anydata_exit(void) -{ - usb_deregister(&anydata_driver); - usb_serial_deregister(&anydata_device); -} - -module_init(anydata_init); -module_exit(anydata_exit); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -module_param(buffer_size, int, 0); -MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 283383d..b020f13 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -72,6 +72,7 @@ static int option_send_setup(struct usb_serial_port *port); #define AUDIOVOX_VENDOR_ID 0x0F3D #define SIERRAWIRELESS_VENDOR_ID 0x1199 #define NOVATELWIRELESS_VENDOR_ID 0x1410 +#define ANYDATA_VENDOR_ID 0x16d5 #define OPTION_PRODUCT_OLD 0x5000 #define OPTION_PRODUCT_FUSION 0x6000 @@ -82,6 +83,7 @@ static int option_send_setup(struct usb_serial_port *port); #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 #define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 #define NOVATELWIRELESS_PRODUCT_U740 0x1400 +#define ANYDATA_PRODUCT_ID 0x6501 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, @@ -93,6 +95,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -105,6 +108,7 @@ static struct usb_device_id option_ids1[] = { { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; static struct usb_device_id option_ids3[] = { -- cgit v1.1 From 7c1c2f73e00b5d0413399a14b7ab9e80db94926f Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Thu, 20 Jul 2006 04:56:00 +0200 Subject: USB: Drop Sierra Wireless MC8755 from the Option driver This device is now supported by sierra.c. From: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b020f13..1df36cb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -16,7 +16,7 @@ This driver exists because the "normal" serial driver doesn't work too well with GSM modems. Issues: - data loss -- one single Receive URB is not nearly enough - - nonstandard flow (Option devices) and multiplex (Sierra) control + - nonstandard flow (Option devices) control - controlling the baud rate doesn't make sense This driver is named "option" because the most common device it's @@ -70,7 +70,6 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_VENDOR_ID 0x0AF0 #define HUAWEI_VENDOR_ID 0x12D1 #define AUDIOVOX_VENDOR_ID 0x0F3D -#define SIERRAWIRELESS_VENDOR_ID 0x1199 #define NOVATELWIRELESS_VENDOR_ID 0x1410 #define ANYDATA_VENDOR_ID 0x16d5 @@ -81,7 +80,6 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_PRODUCT_COBRA2 0x6600 #define HUAWEI_PRODUCT_E600 0x1001 #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 -#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 #define NOVATELWIRELESS_PRODUCT_U740 0x1400 #define ANYDATA_PRODUCT_ID 0x6501 @@ -93,7 +91,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, - { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ @@ -112,7 +109,6 @@ static struct usb_device_id option_ids1[] = { { } /* Terminating entry */ }; static struct usb_device_id option_ids3[] = { - { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { } /* Terminating entry */ }; -- cgit v1.1 From a01c452ee3a185a35140939c6dca08d77240b863 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Thu, 20 Jul 2006 05:01:21 +0200 Subject: USB: Removed 3-port device handler from Option driver Dead code. From: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1df36cb..c856e6f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -108,9 +108,6 @@ static struct usb_device_id option_ids1[] = { { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; -static struct usb_device_id option_ids3[] = { - { } /* Terminating entry */ -}; MODULE_DEVICE_TABLE(usb, option_ids); @@ -125,33 +122,6 @@ static struct usb_driver option_driver = { /* The card has three separate interfaces, which the serial driver * recognizes separately, thus num_port=1. */ -static struct usb_serial_driver option_3port_device = { - .driver = { - .owner = THIS_MODULE, - .name = "option3", - }, - .description = "GSM modem (3-port)", - .id_table = option_ids3, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 3, - .open = option_open, - .close = option_close, - .write = option_write, - .write_room = option_write_room, - .chars_in_buffer = option_chars_in_buffer, - .throttle = option_rx_throttle, - .unthrottle = option_rx_unthrottle, - .ioctl = option_ioctl, - .set_termios = option_set_termios, - .break_ctl = option_break_ctl, - .tiocmget = option_tiocmget, - .tiocmset = option_tiocmset, - .attach = option_startup, - .shutdown = option_shutdown, - .read_int_callback = option_instat_callback, -}; static struct usb_serial_driver option_1port_device = { .driver = { @@ -220,9 +190,6 @@ static int __init option_init(void) retval = usb_serial_register(&option_1port_device); if (retval) goto failed_1port_device_register; - retval = usb_serial_register(&option_3port_device); - if (retval) - goto failed_3port_device_register; retval = usb_register(&option_driver); if (retval) goto failed_driver_register; @@ -232,8 +199,6 @@ static int __init option_init(void) return 0; failed_driver_register: - usb_serial_deregister (&option_3port_device); -failed_3port_device_register: usb_serial_deregister (&option_1port_device); failed_1port_device_register: return retval; @@ -242,7 +207,6 @@ failed_1port_device_register: static void __exit option_exit(void) { usb_deregister (&option_driver); - usb_serial_deregister (&option_3port_device); usb_serial_deregister (&option_1port_device); } -- cgit v1.1 From a11570f2a48cbb6e10c520b46193e7b1b4b9245c Mon Sep 17 00:00:00 2001 From: Li Yang Date: Fri, 14 Jul 2006 19:58:14 +0800 Subject: USB: Fix Freescale high-speed USB host dependency The high-speed USB SOC only exists on MPC834x family not MPC83xx family. Signed-off-by: Li Yang Acked-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 85b0b4a..d63177a 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -892,7 +892,7 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ehci_pci_driver #endif -#ifdef CONFIG_PPC_83xx +#ifdef CONFIG_MPC834x #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver #endif -- cgit v1.1 From aec0d50b8a86bf04ea8e5885fef4f498d5d3168c Mon Sep 17 00:00:00 2001 From: Norihiko Tomiyama Date: Thu, 13 Jul 2006 09:43:02 +0900 Subject: USB: adding support for SHARP WS003SH to ipaq.c This small patch enables a support of "SHARP WS003SH". "SHARP WS003SH" (usullary called "W-ZERO3") is most polular All-in-one handheld CellPhone-plus-WindowsMobile5.0 in Japan. "SHARP WS003SH" has two modes, "Modem" and "ActiveSync". But, "ActiveSync" mode uses NDIS connection. Therefore, ipaq.c can only support "Modem" mode. http://www.sharp.co.jp/ws/ (Japanese Site) http://greggman.com/edit/editheadlines/2005-12-24.htm From: Norihiko Tomiyama Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipaq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 59c5d99..7e1bd5d 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -250,6 +250,7 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ + { USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */ { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ -- cgit v1.1 From 274a4bbc9df34d83485e67ad5200a43bd3c69600 Mon Sep 17 00:00:00 2001 From: Dave Platt Date: Tue, 18 Jul 2006 21:26:54 -0700 Subject: USB: Additional PID for the ftdi_sio driver Here's a short patch which adds one PID to the set of devices supported by the ftdi_sio driver. The device in question is a DLP module used as part of a ham radio USB-to-packet adapter. From: Dave Platt Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b458aed..a20da85 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -337,6 +337,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 04ef90f..9f7343a 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -182,6 +182,10 @@ /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ #define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ +/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ + +#define FTDI_TNC_X_PID 0xEBE0 + /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). * All of these devices use FTDI's vendor ID (0x0403). -- cgit v1.1 From b7aa94b682dc6b6dcdc01d36f8e65cef5aae81e2 Mon Sep 17 00:00:00 2001 From: Kim Oldfield Date: Tue, 25 Jul 2006 15:54:59 +1000 Subject: USB: New USB ID for Belkin Serial Adapter Can you add the USB IDs for the Belkin USB Serial adapter (P/N F5U257) to the pl2303 driver in the Linux Kernel? Are you the appropriate person to approach for this? I recently purchased a Belkin USB Serial adapter (P/N F5U257) and found that it didn't work. After a bit of experimentation I found that it works with the pl2303 driver once the ID has been added. See attached patch to fix this. Also attached is the output from lsusb -v just in case you require any information from there. From: Kim Oldfield Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 259db31..efbbc0a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -81,6 +81,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, { USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) }, { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, + { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index d9c1e6e..a692ac6 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -89,3 +89,7 @@ /* DATAPILOT Universal-2 Phone Cable */ #define DATAPILOT_U2_VENDOR_ID 0x0731 #define DATAPILOT_U2_PRODUCT_ID 0x2003 + +/* Belkin "F5U257" Serial Adapter */ +#define BELKIN_VENDOR_ID 0x050d +#define BELKIN_PRODUCT_ID 0x0257 -- cgit v1.1 From 3c332422f78159a0f5e4bc5f0ed8bbcbf51d9462 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 26 Jul 2006 13:59:23 +0100 Subject: usb-storage: Add US_FL_IGNORE_DEVICE flag; ignore ZyXEL G220F This patch adds a new unusual_devs flag for when usb-storage needs to ignore a device that it would otherwise claim. We need to ignore the ZyXEL G220F as it is a virtual CDROM drive which includes the windows driver for this USB-WLAN adapter. After the windows driver is installed on a windows system, it converts it into a WLAN adapter (by ejecting the virtual disc). The virtual CDROM is of no interest to Linux users. The zd1211rw driver will automatically perform the eject operation, we just need to ensure that usb-storage does not claim the device. Signed-off-by: Daniel Drake Signed-off-by: Matthew Dharm Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 +++++++++- drivers/usb/storage/usb.c | 13 +++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a5ca449..ca6c56f 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1106,7 +1106,15 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, "Optio S/S4", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + +/* This is a virtual windows driver CD, which the zd1211rw driver automatically + * converts into a WLAN device. */ +UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, + "ZyXEL", + "G-220F USB-WLAN Install", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5ee19be..8d7bdcb 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -483,7 +483,7 @@ static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) } /* Get the unusual_devs entries and the string descriptors */ -static void get_device_info(struct us_data *us, const struct usb_device_id *id) +static int get_device_info(struct us_data *us, const struct usb_device_id *id) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = @@ -500,6 +500,11 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) unusual_dev->useTransport; us->flags = USB_US_ORIG_FLAGS(id->driver_info); + if (us->flags & US_FL_IGNORE_DEVICE) { + printk(KERN_INFO USB_STORAGE "device ignored\n"); + return -ENODEV; + } + /* * This flag is only needed when we're in high-speed, so let's * disable it if we're in full-speed @@ -541,6 +546,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id) msgs[msg], UTS_RELEASE); } + + return 0; } /* Get the transport settings */ @@ -969,7 +976,9 @@ static int storage_probe(struct usb_interface *intf, * of the match from the usb_device_id table, so we can find the * corresponding entry in the private table. */ - get_device_info(us, id); + result = get_device_info(us, id); + if (result) + goto BadDevice; /* Get the transport, protocol, and pipe settings */ result = get_transport(us); -- cgit v1.1 From eda30fdeec30aec05bc8d644eb6f2509fb5ad43c Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Wed, 26 Jul 2006 22:36:29 -0700 Subject: USB: unusual_devs device removal This entry has been a mystery for some time. I had sent this patch as an RFC a while ago, and now we've had two reports of this not being needed, so I'm removing it. In the event there are reports of breakage, we should revert this patch, but add a US_FL_NEED_OVERRIDE flag. Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index ca6c56f..0f0874f 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -627,18 +627,6 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Digital Camera EX-20 DSC", US_SC_8070, US_PR_DEVICE, NULL, 0 ), -/* The entry was here before I took over, and had US_SC_RBC. It turns - * out that isn't needed. Additionally, Torsten Eriksson - * is able to use his device fine - * without this entry at all - but I don't suspect that will be true - * for all users (the protocol is likely needed), so is staying at - * this time. - Phil Dibowitz - */ -UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, - "LaCie", - "USB Hard Disk", - US_SC_DEVICE, US_PR_CB, NULL, 0 ), - /* Submitted by Joel Bourquard * Some versions of this device need the SubClass and Protocol overrides * while others don't. -- cgit v1.1 From 6ad576bb6715c1da1bb5c2ce59c3747368bba41f Mon Sep 17 00:00:00 2001 From: Oliver Bock Date: Thu, 27 Jul 2006 21:34:58 +0200 Subject: USB: cypress driver comment updates Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/cypress_cy7c63.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index e091d32..a4062a6 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -12,8 +12,13 @@ * the single I/O ports of the device. * * Supported vendors: AK Modul-Bus Computer GmbH -* Supported devices: CY7C63001A-PC (to be continued...) -* Supported functions: Read/Write Ports (to be continued...) +* (Firmware "Port-Chip") +* +* Supported devices: CY7C63001A-PC +* CY7C63001C-PXC +* CY7C63001C-SXC +* +* Supported functions: Read/Write Ports * * * This program is free software; you can redistribute it and/or -- cgit v1.1 From 23219c134865d524357e9bb90e5badb422ac8fff Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 25 Jul 2006 20:39:14 +1000 Subject: USB: Patch for rtl8150 to fix unplug problems The RTL8150 driver currently crashes the kernel if the USB lead is unplugged while the device is active. The attached patch adds error handling to tell the network layer that the device has gone away when the device is unplugged. With this patch, the device can be plugged and unplugged to one's hearts' content, without crashing anything. Oh, I've also added rudimentary suspend and resume methods. Signed-off-by: Peter Chubb Acked-by: Petko Manolov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/rtl8150.c | 83 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index e5e6e4f..bd09232 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -175,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); static void rtl8150_disconnect(struct usb_interface *intf); static int rtl8150_probe(struct usb_interface *intf, const struct usb_device_id *id); +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); +static int rtl8150_resume(struct usb_interface *intf); static const char driver_name [] = "rtl8150"; @@ -183,6 +185,8 @@ static struct usb_driver rtl8150_driver = { .probe = rtl8150_probe, .disconnect = rtl8150_disconnect, .id_table = rtl8150_table, + .suspend = rtl8150_suspend, + .resume = rtl8150_resume }; /* @@ -238,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) usb_fill_control_urb(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, &dev->rx_creg, size, ctrl_callback, dev); - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) + if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(dev->netdev); err("control request submission failed: %d", ret); - else + } else set_bit(RX_REG_SET, &dev->flags); return ret; @@ -416,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) struct sk_buff *skb; struct net_device *netdev; u16 rx_stat; + int status; dev = urb->context; if (!dev) @@ -465,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goon: usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto resched; } else { @@ -481,6 +491,7 @@ static void rx_fixup(unsigned long data) { rtl8150_t *dev; struct sk_buff *skb; + int status; dev = (rtl8150_t *)data; @@ -499,10 +510,13 @@ static void rx_fixup(unsigned long data) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); try_again: - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) { + netif_device_detach(dev->netdev); + } else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto tlsched; - } else { + } else { clear_bit(RX_URB_FAIL, &dev->flags); } @@ -574,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) resubmit: status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) err ("can't resubmit intr, %s-%s/input0, status %d", dev->udev->bus->bus_name, dev->udev->devpath, status); } +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_detach(dev->netdev); + + if (netif_running(dev->netdev)) { + usb_kill_urb(dev->rx_urb); + usb_kill_urb(dev->intr_urb); + } + return 0; +} + +static int rtl8150_resume(struct usb_interface *intf) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_attach(dev->netdev); + if (netif_running(dev->netdev)) { + dev->rx_urb->status = 0; + dev->rx_urb->actual_length = 0; + read_bulk_callback(dev->rx_urb, NULL); + + dev->intr_urb->status = 0; + dev->intr_urb->actual_length = 0; + intr_callback(dev->intr_urb, NULL); + } + return 0; +} /* ** @@ -690,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), skb->data, count, write_bulk_callback, dev); if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { - warn("failed tx_urb %d\n", res); - dev->stats.tx_errors++; - netif_start_queue(netdev); + /* Can we get/handle EPIPE here? */ + if (res == -ENODEV) + netif_device_detach(dev->netdev); + else { + warn("failed tx_urb %d\n", res); + dev->stats.tx_errors++; + netif_start_queue(netdev); + } } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -729,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); + return res; + } usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), dev->intr_buff, INTBUFSIZE, intr_callback, dev, dev->intr_interval); - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); - netif_start_queue(netdev); + usb_kill_urb(dev->rx_urb); + return res; + } enable_net_traffic(dev); set_carrier(netdev); + netif_start_queue(netdev); return res; } -- cgit v1.1 From 168ffc444663e34a20e6d04b6c31e5d495b283fb Mon Sep 17 00:00:00 2001 From: Marko Macek Date: Sun, 30 Jul 2006 01:55:12 -0700 Subject: USB: ati_remote.c: autorepeat fix When HZ is set to 250 (new default) or 100, the time span during which repeated events from the device are ignored could be too small due to ms->jiffies rounding. This causes the auto repeat to kick in early making it impossible for the user to generate individual press/release events. Increate the timeout to compensate. Signed-off-by: Marko Macek Cc: Dmitry Torokhov Cc: Vojtech Pavlik Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/ati_remote.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 05d2d60..df198cf 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -152,9 +152,8 @@ static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; * events. The hardware generates 5 events for the first keypress * and we have to take this into account for an accurate repeat * behaviour. - * (HZ / 20) == 50 ms and works well for me. */ -#define FILTER_TIME (HZ / 20) +#define FILTER_TIME 60 /* msec */ struct ati_remote { struct input_dev *idev; @@ -467,7 +466,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) /* Filter duplicate events which happen "too close" together. */ if ((ati_remote->old_data[0] == data[1]) && (ati_remote->old_data[1] == data[2]) && - time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) { + time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(FILTER_TIME))) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; -- cgit v1.1 From be0c8015a2e981b9079cb5f0e2bf868fa10249ae Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Jul 2006 01:43:53 +0200 Subject: USB: fix the USB_GADGET_DUMMY_HCD dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If USB=m, USB_GADGET=y, the option USB_GADGET_DUMMY_HCD mustn't be offered since selecting it results in a compile error. This patch fixes kernel Bugzilla #6534 reported by Toralf Förster. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 363b2ad..1a32d96 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -207,7 +207,7 @@ config USB_AT91 config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" - depends on USB && EXPERIMENTAL + depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL select USB_GADGET_DUALSPEED help This host controller driver emulates USB, looping all data transfer -- cgit v1.1 From b4dbda1a22d236842b75be4e2679a96a4fd72632 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 28 Jul 2006 17:07:34 -0400 Subject: USB: dummy-hcd: disable interrupts during req->complete This patch (as756) fixes a bug in dummy-hcd found by the lockdep checker. In one of the code paths, the driver did not disable interrupts before calling a request completion routine. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 4be4719..7d1c22c 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -609,7 +609,8 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) if (!dum->driver) return -ESHUTDOWN; - spin_lock_irqsave (&dum->lock, flags); + local_irq_save (flags); + spin_lock (&dum->lock); list_for_each_entry (req, &ep->queue, queue) { if (&req->req == _req) { list_del_init (&req->queue); @@ -618,7 +619,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) break; } } - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock (&dum->lock); if (retval == 0) { dev_dbg (udc_dev(dum), @@ -626,6 +627,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) req, _ep->name, _req->length, _req->buf); _req->complete (_ep, _req); } + local_irq_restore (flags); return retval; } -- cgit v1.1 From de1caa475120c716ff33d344b5ffefc288ed77c7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 31 Jul 2006 10:10:28 -0400 Subject: USB: unusual_devs entry for Nokia 3250 Here is another unusual_devs entry (as760) for another Nokia device, this time the 3250. From: Mario Rettig Signed-off-by: Alan Stern Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0f0874f..2793f9a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -145,6 +145,13 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Mario Rettig */ +UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, + "Nokia", + "Nokia 3250", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), + /* Reported by Sumedha Swamy and * Einar Th. Einarsson */ UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, -- cgit v1.1 From f443ddf1057776ed99d5006bbbefb018fcf7ce3a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 31 Jul 2006 10:16:24 -0400 Subject: USB: UHCI: Don't test the Short Packet Detect bit Apparently some UHCI controllers change the value of the Short Packet Detect (SPD) bit in the TD status word -- presumably when they receive a short packet. This patch (as759) changes uhci-hcd to avoid assuming that the bit is unchanged; in fact, the driver no longer looks at SPD at all. This fixes the second problem reported in Bugzilla #6752. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index c9d72ac..66c3f61 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -943,7 +943,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) /* We received a short packet */ if (urb->transfer_flags & URB_SHORT_NOT_OK) ret = -EREMOTEIO; - else if (ctrlstat & TD_CTRL_SPD) + + /* Fixup needed only if this isn't the URB's last TD */ + else if (&td->list != urbp->td_list.prev) ret = 1; } -- cgit v1.1 From 27fb4f0a7f00fda4044de44dcbe4d65b8359cc38 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Aug 2006 16:49:37 -0700 Subject: Revert "[PATCH] USB: convert usb class devices to real devices" This reverts bd00949647ddcea47ce4ea8bb2cfcfc98ebf9f2a commit because it required a newer version of udev to work properly than what is currently documented in Documentation/Changes. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index abee0f5..8de4f8c 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -194,13 +194,14 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), "%s", temp); - if (IS_ERR(intf->usb_dev)) { + intf->class_dev = class_device_create(usb_class->class, NULL, + MKDEV(USB_MAJOR, minor), + &intf->dev, "%s", temp); + if (IS_ERR(intf->class_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->usb_dev); + retval = PTR_ERR(intf->class_dev); } exit: return retval; @@ -241,8 +242,8 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); - intf->usb_dev = NULL; + class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->class_dev = NULL; intf->minor = -1; destroy_usb_class(); } -- cgit v1.1 From cae74b30dd98c10baa5b47b4698bf67e5eb15687 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Aug 2006 16:52:10 -0700 Subject: Revert "[PATCH] USB: move usb_device_class class devices to be real devices" This reverts c182274ffe1277f4e7c564719a696a37cacf74ea commit because it required a newer version of udev to work properly than what is currently documented in Documentation/Changes. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index f7bdd94..218621b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -517,19 +517,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig static struct usb_device *usbdev_lookup_minor(int minor) { - struct device *device; - struct usb_device *udev = NULL; + struct class_device *class_dev; + struct usb_device *dev = NULL; down(&usb_device_class->sem); - list_for_each_entry(device, &usb_device_class->devices, node) { - if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - udev = device->platform_data; + list_for_each_entry(class_dev, &usb_device_class->children, node) { + if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + dev = class_dev->class_data; break; } } up(&usb_device_class->sem); - return udev; + return dev; }; /* @@ -1580,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->usbfs_dev = device_create(usb_device_class, &dev->dev, - MKDEV(USB_DEVICE_MAJOR, minor), + dev->class_dev = class_device_create(usb_device_class, NULL, + MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, "usbdev%d.%d", dev->bus->busnum, dev->devnum); - dev->usbfs_dev->platform_data = dev; + dev->class_dev->class_data = dev; } static void usbdev_remove(struct usb_device *dev) { - device_unregister(dev->usbfs_dev); + class_device_unregister(dev->class_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, -- cgit v1.1 From bf74c7479ef47652005a2418eeb0d867451690da Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 26 Jul 2006 16:02:53 +0300 Subject: IB/mthca: Fix mthca_array_clear() thinko mthca_array_clear() does not clear the slot if the used count is positive. This leads to crashes in mthca_qp_event() since that uses mthca_array_get() to check that the qp is valid. Discovered by Ali Ayoub. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_allocator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c index 9ba3211..848e583 100644 --- a/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/drivers/infiniband/hw/mthca/mthca_allocator.c @@ -144,7 +144,9 @@ void mthca_array_clear(struct mthca_array *array, int index) if (--array->page_list[p].used == 0) { free_page((unsigned long) array->page_list[p].page); array->page_list[p].page = NULL; - } + } else + array->page_list[p].page[index & (PAGE_SIZE / + sizeof (void *) - 1)] = NULL; if (array->page_list[p].used < 0) pr_debug("Array %p index %d page %d with ref count %d < 0\n", -- cgit v1.1 From 69e9fbb460fa8766428960439841ffcf565032c1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 3 Aug 2006 09:44:22 -0700 Subject: IB/mthca: Clean up mthca array index mask Define a constant MTHCA_ARRAY_MASK to replace repeated uses of (PAGE_SIZE / sizeof (void *) - 1) in mthca array code. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_allocator.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c index 848e583..25157f5 100644 --- a/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/drivers/infiniband/hw/mthca/mthca_allocator.c @@ -108,14 +108,15 @@ void mthca_alloc_cleanup(struct mthca_alloc *alloc) * serialize access to the array. */ +#define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1) + void *mthca_array_get(struct mthca_array *array, int index) { int p = (index * sizeof (void *)) >> PAGE_SHIFT; - if (array->page_list[p].page) { - int i = index & (PAGE_SIZE / sizeof (void *) - 1); - return array->page_list[p].page[i]; - } else + if (array->page_list[p].page) + return array->page_list[p].page[index & MTHCA_ARRAY_MASK]; + else return NULL; } @@ -130,8 +131,7 @@ int mthca_array_set(struct mthca_array *array, int index, void *value) if (!array->page_list[p].page) return -ENOMEM; - array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] = - value; + array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value; ++array->page_list[p].used; return 0; @@ -145,8 +145,7 @@ void mthca_array_clear(struct mthca_array *array, int index) free_page((unsigned long) array->page_list[p].page); array->page_list[p].page = NULL; } else - array->page_list[p].page[index & (PAGE_SIZE / - sizeof (void *) - 1)] = NULL; + array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL; if (array->page_list[p].used < 0) pr_debug("Array %p index %d page %d with ref count %d < 0\n", -- cgit v1.1 From 75df23e229acab85b704f4603bdf5efdc7960e6a Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 25 Jul 2006 19:52:01 +0300 Subject: IB/cm: Fix error handling in ib_send_cm_req Report error code rather than success (0) on failure allocating timewait_info in ib_send_cm_req(). Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index f85c97f..0de335b 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -975,8 +975,10 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv-> id.local_id); - if (IS_ERR(cm_id_priv->timewait_info)) + if (IS_ERR(cm_id_priv->timewait_info)) { + ret = PTR_ERR(cm_id_priv->timewait_info); goto out; + } ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av); if (ret) -- cgit v1.1 From d916a8f1b43b358685b1672390ead11f2d3b74c6 Mon Sep 17 00:00:00 2001 From: Ishai Rabinovitz Date: Tue, 25 Jul 2006 19:54:09 +0300 Subject: IB/srp: Fix crash in srp_reconnect_target Protect against srp_reset_device() clearing the req_queue while srp_reconnect_target() is in progress (note that state change at the top of srp_reconnect_target() is not sufficient for this since srp_reset_device() ignores the state). Signed-off-by: Ishai Rabinovitz Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 8f472e7..ff94e4e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -526,8 +526,10 @@ static int srp_reconnect_target(struct srp_target_port *target) while (ib_poll_cq(target->cq, 1, &wc) > 0) ; /* nothing */ + spin_lock_irq(target->scsi_host->host_lock); list_for_each_entry_safe(req, tmp, &target->req_queue, list) srp_reset_req(target, req); + spin_unlock_irq(target->scsi_host->host_lock); target->rx_head = 0; target->tx_head = 0; -- cgit v1.1 From 559ce8f150d7d031c79c4d79173860f1bdfe3ce4 Mon Sep 17 00:00:00 2001 From: Ishai Rabinovitz Date: Thu, 3 Aug 2006 10:35:43 -0700 Subject: IB/srp: Work around data corruption bug on Mellanox targets Data corruption has been seen with Mellanox SRP targets when FMRs create a memory region with I/O virtual address != 0. Add a workaround that disables FMR merging for Mellanox targets (OUI 0002c9). Signed-off-by: Ishai Rabinovitz Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ff94e4e..8257d5a 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -77,6 +77,14 @@ MODULE_PARM_DESC(topspin_workarounds, static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; +static int mellanox_workarounds = 1; + +module_param(mellanox_workarounds, int, 0444); +MODULE_PARM_DESC(mellanox_workarounds, + "Enable workarounds for Mellanox SRP target bugs if != 0"); + +static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 }; + static void srp_add_one(struct ib_device *device); static void srp_remove_one(struct ib_device *device); static void srp_completion(struct ib_cq *cq, void *target_ptr); @@ -569,7 +577,7 @@ err: return ret; } -static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, +static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, int sg_cnt, struct srp_request *req, struct srp_direct_buf *buf) { @@ -579,10 +587,15 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, int page_cnt; int i, j; int ret; + struct srp_device *dev = target->srp_host->dev; if (!dev->fmr_pool) return -ENODEV; + if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) && + mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3)) + return -EINVAL; + len = page_cnt = 0; for (i = 0; i < sg_cnt; ++i) { if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { @@ -685,7 +698,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, buf->va = cpu_to_be64(sg_dma_address(scat)); buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); buf->len = cpu_to_be32(sg_dma_len(scat)); - } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, + } else if (srp_map_fmr(target, scat, count, req, (void *) cmd->add_data)) { /* * FMR mapping failed, and the scatterlist has more -- cgit v1.1 From 8ddc7c5326064434048ec1ecfe57659e08345cc1 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Thu, 13 Jul 2006 11:00:39 +0300 Subject: IB/ipoib: Remove broken link from Kconfig and documentation Remove references to the IPoIB IETF working group as it has been closed. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig index 13d6d01..d74653d 100644 --- a/drivers/infiniband/ulp/ipoib/Kconfig +++ b/drivers/infiniband/ulp/ipoib/Kconfig @@ -6,8 +6,7 @@ config INFINIBAND_IPOIB transports IP packets over InfiniBand so you can use your IB device as a fancy NIC. - The IPoIB protocol is defined by the IETF ipoib working - group: . + See Documentation/infiniband/ipoib.txt for more information config INFINIBAND_IPOIB_DEBUG bool "IP-over-InfiniBand debugging" if EMBEDDED -- cgit v1.1 From fd60ae404f104f12369e654af9cf03b1f1047661 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 3 Aug 2006 10:56:42 -0700 Subject: IB/uverbs: Avoid a crash on device hot remove Wait until all users have closed their device context before allowing device unregistration to complete. This prevents a crash caused by referring to stale data structures. A better solution would be to have a way to revoke contexts rather than waiting for userspace to close the context, but that's a much bigger change that will have to wait. For now let's at least avoid the crash. Signed-off-by: Jack Morgenstein Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 2 ++ drivers/infiniband/core/uverbs_main.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index bb9bee5..102a59c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,7 @@ struct ib_uverbs_device { struct kref ref; + struct completion comp; int devnum; struct cdev *dev; struct class_device *class_dev; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index e725ccc..4e16314 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref) struct ib_uverbs_device *dev = container_of(ref, struct ib_uverbs_device, ref); - kfree(dev); + complete(&dev->comp); } void ib_uverbs_release_ucq(struct ib_uverbs_file *file, @@ -740,6 +740,7 @@ static void ib_uverbs_add_one(struct ib_device *device) return; kref_init(&uverbs_dev->ref); + init_completion(&uverbs_dev->comp); spin_lock(&map_lock); uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); @@ -793,6 +794,8 @@ err_cdev: err: kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); + wait_for_completion(&uverbs_dev->comp); + kfree(uverbs_dev); return; } @@ -812,7 +815,10 @@ static void ib_uverbs_remove_one(struct ib_device *device) spin_unlock(&map_lock); clear_bit(uverbs_dev->devnum, dev_map); + kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); + wait_for_completion(&uverbs_dev->comp); + kfree(uverbs_dev); } static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, -- cgit v1.1 From 60854838596906ebae7f32e4de921e150e669b60 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Thu, 6 Jul 2006 18:05:51 +0400 Subject: pcie: fix warnings when CONFIG_PM=n Signed-off-by: Henrik Kretzschmar Signed-off-by: Alexey Dobriyan Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv_pci.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 50bfc1b..d0a3797 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -30,23 +30,6 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; -static int pcie_portdrv_save_config(struct pci_dev *dev) -{ - return pci_save_state(dev); -} - -static int pcie_portdrv_restore_config(struct pci_dev *dev) -{ - int retval; - - pci_restore_state(dev); - retval = pci_enable_device(dev); - if (retval) - return retval; - pci_set_master(dev); - return 0; -} - /* * pcie_portdrv_probe - Probe PCI-Express port devices * @dev: PCI-Express port device being probed @@ -86,6 +69,23 @@ static void pcie_portdrv_remove (struct pci_dev *dev) } #ifdef CONFIG_PM +static int pcie_portdrv_save_config(struct pci_dev *dev) +{ + return pci_save_state(dev); +} + +static int pcie_portdrv_restore_config(struct pci_dev *dev) +{ + int retval; + + pci_restore_state(dev); + retval = pci_enable_device(dev); + if (retval) + return retval; + pci_set_master(dev); + return 0; +} + static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); -- cgit v1.1 From e4fd1f4a6e05335d464fe003c164fea850a3b3f3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 6 Jul 2006 21:36:01 -0700 Subject: PCIE: cleanup on probe error If pcie_portdrv_probe() fails but it had already called pci_enable_device(), then call pci_disable_device() when returning error. Is there some reason that this isn't being done? or was it just missed? Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index d0a3797..478d0d2 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -56,8 +56,10 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", __FUNCTION__, dev->device, dev->vendor); } - if (pcie_port_device_register(dev)) + if (pcie_port_device_register(dev)) { + pci_disable_device(dev); return -ENOMEM; + } return 0; } -- cgit v1.1 From c8439cfccc4143b79f70d18015336d9fec0563e2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 18 Jul 2006 14:33:16 -0700 Subject: PCI: pci/search: EXPORTs cannot be __devinit EXPORTed symbols cannot be __init/__devinit. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index f8ae2b7..d529462 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -41,7 +41,7 @@ pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) * in the global list of PCI buses. If the bus is found, a pointer to its * data structure is returned. If no bus is found, %NULL is returned. */ -struct pci_bus * __devinit pci_find_bus(int domain, int busnr) +struct pci_bus * pci_find_bus(int domain, int busnr) { struct pci_bus *bus = NULL; struct pci_bus *tmp_bus; -- cgit v1.1 From 998be20fdff12274cd0e6a9f71ce1a93abf40718 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Wed, 26 Jul 2006 10:52:33 -0700 Subject: PCI Hotplug: add acpiphp to MAINTAINERS Add acpiphp to the MAINTAINERS file. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_core.c | 3 +-- drivers/pci/hotplug/acpiphp_glue.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 34de569..e2fef60 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -27,8 +27,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to , - * + * Send feedback to * */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ef95d12..ae67a8f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -26,7 +26,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ -- cgit v1.1 From 321311af25cbb65d3cc177e3777fedd526814ecc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 31 Jul 2006 08:53:15 +0200 Subject: PCI: Unhide the SMBus on Asus PU-DLS Unhide the SMBus controller on the Asus PU-DLS board. This fixes bug #6763. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e3c78c3..fb08bc9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -990,6 +990,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x8070: /* P4G8X Deluxe */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) + switch (dev->subsystem_device) { + case 0x80c9: /* PU-DLS */ + asus_hides_smbus = 1; + } if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch (dev->subsystem_device) { case 0x1751: /* M2N notebook */ @@ -1058,6 +1063,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge ); @@ -1081,6 +1087,7 @@ static void __init asus_hides_smbus_lpc(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); -- cgit v1.1 From 5669021e40964303994a20633548732c6bb26636 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Tue, 1 Aug 2006 14:59:19 -0700 Subject: PCI: docking station: remove dock uevents Remove uevent dock notifications. There are no consumers of these events at present, and uevents are likely not the correct way to send this type of event anyway. Until I get some kind of idea if anyone in userspace cares about dock events, I will just not send any. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/dock.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1c0a39d..578b99b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -58,8 +58,8 @@ struct dock_dependent_device { }; #define DOCK_DOCKING 0x00000001 -#define DOCK_EVENT KOBJ_DOCK -#define UNDOCK_EVENT KOBJ_UNDOCK +#define DOCK_EVENT 3 +#define UNDOCK_EVENT 2 static struct dock_station *dock_station; @@ -322,11 +322,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) static void dock_event(struct dock_station *ds, u32 event, int num) { - struct acpi_device *device; - - device = dock_create_acpi_device(ds->handle); - if (device) - kobject_uevent(&device->kobj, num); + /* + * we don't do events until someone tells me that + * they would like to have them. + */ } /** -- cgit v1.1 From 2131ca8915ae545c596f94e75b692be2811d9c03 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 13 Jul 2006 11:35:41 +0200 Subject: PNP: Add missing casts in printk() arguments Some resource_size_t values are fed to printk() without handling the fact that they can have different size depending on your .config. Signed-off-by: Pierre Ossman Signed-off-by: Greg Kroah-Hartman --- drivers/pnp/interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 3163e3d..9d8b415 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -265,8 +265,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - pnp_port_start(dev, i), - pnp_port_end(dev, i)); + (unsigned long long)pnp_port_start(dev, i), + (unsigned long long)pnp_port_end(dev, i)); } } for (i = 0; i < PNP_MAX_MEM; i++) { @@ -276,8 +276,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - pnp_mem_start(dev, i), - pnp_mem_end(dev, i)); + (unsigned long long)pnp_mem_start(dev, i), + (unsigned long long)pnp_mem_end(dev, i)); } } for (i = 0; i < PNP_MAX_IRQ; i++) { @@ -287,7 +287,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - pnp_irq(dev, i)); + (unsigned long long)pnp_irq(dev, i)); } } for (i = 0; i < PNP_MAX_DMA; i++) { @@ -297,7 +297,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - pnp_dma(dev, i)); + (unsigned long long)pnp_dma(dev, i)); } } ret = (buffer->curr - buf); -- cgit v1.1 From b41477f32a5aaf39a77741c0138b16f16a636c70 Mon Sep 17 00:00:00 2001 From: Ananda Raju Date: Mon, 24 Jul 2006 19:52:49 -0400 Subject: [PATCH] s2io driver bug fixes #1 This patch contains some of the bug fixes and enhancements done to s2io driver. Following are the brief description of changes 1. Introduced macro "S2IO_PARM_INT" for declaring integer load parameter 2. UDP_RR test failure, memset txdl after Tx completion 3. PXE boot may leave adapter in unknown state so do reset in probe. 4. Add Tx completion code in netpoll 5. In s2io_vpd_read() move array vpd_data[] to pointer, saves stack memory 6. Fix bug in ethtool online test Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 158 +++++++++++++++++++++++++++-------------------------- drivers/net/s2io.h | 5 ++ 2 files changed, 85 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e1fe3a0..4a4e38b 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -370,38 +370,50 @@ static const u64 fix_mac[] = { END_SIGN }; +MODULE_AUTHOR("Raghavendra Koushik "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + + /* Module Loadable parameters. */ -static unsigned int tx_fifo_num = 1; -static unsigned int tx_fifo_len[MAX_TX_FIFOS] = - {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; -static unsigned int rx_ring_num = 1; -static unsigned int rx_ring_sz[MAX_RX_RINGS] = - {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; -static unsigned int rts_frm_len[MAX_RX_RINGS] = - {[0 ...(MAX_RX_RINGS - 1)] = 0 }; -static unsigned int rx_ring_mode = 1; -static unsigned int use_continuous_tx_intrs = 1; -static unsigned int rmac_pause_time = 0x100; -static unsigned int mc_pause_threshold_q0q3 = 187; -static unsigned int mc_pause_threshold_q4q7 = 187; -static unsigned int shared_splits; -static unsigned int tmac_util_period = 5; -static unsigned int rmac_util_period = 5; -static unsigned int bimodal = 0; -static unsigned int l3l4hdr_size = 128; -#ifndef CONFIG_S2IO_NAPI -static unsigned int indicate_max_pkts; -#endif +S2IO_PARM_INT(tx_fifo_num, 1); +S2IO_PARM_INT(rx_ring_num, 1); + + +S2IO_PARM_INT(rx_ring_mode, 1); +S2IO_PARM_INT(use_continuous_tx_intrs, 1); +S2IO_PARM_INT(rmac_pause_time, 0x100); +S2IO_PARM_INT(mc_pause_threshold_q0q3, 187); +S2IO_PARM_INT(mc_pause_threshold_q4q7, 187); +S2IO_PARM_INT(shared_splits, 0); +S2IO_PARM_INT(tmac_util_period, 5); +S2IO_PARM_INT(rmac_util_period, 5); +S2IO_PARM_INT(bimodal, 0); +S2IO_PARM_INT(l3l4hdr_size, 128); /* Frequency of Rx desc syncs expressed as power of 2 */ -static unsigned int rxsync_frequency = 3; +S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ -static unsigned int intr_type = 0; +S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ -static unsigned int lro = 0; +S2IO_PARM_INT(lro, 0); /* Max pkts to be aggregated by LRO at one time. If not specified, * aggregation happens until we hit max IP pkt size(64K) */ -static unsigned int lro_max_pkts = 0xFFFF; +S2IO_PARM_INT(lro_max_pkts, 0xFFFF); +#ifndef CONFIG_S2IO_NAPI +S2IO_PARM_INT(indicate_max_pkts, 0); +#endif + +static unsigned int tx_fifo_len[MAX_TX_FIFOS] = + {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; +static unsigned int rx_ring_sz[MAX_RX_RINGS] = + {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; +static unsigned int rts_frm_len[MAX_RX_RINGS] = + {[0 ...(MAX_RX_RINGS - 1)] = 0 }; + +module_param_array(tx_fifo_len, uint, NULL, 0); +module_param_array(rx_ring_sz, uint, NULL, 0); +module_param_array(rts_frm_len, uint, NULL, 0); /* * S2IO device table. @@ -464,10 +476,9 @@ static int init_shared_mem(struct s2io_nic *nic) size += config->tx_cfg[i].fifo_len; } if (size > MAX_AVAILABLE_TXDS) { - DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ", - __FUNCTION__); + DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); - return FAILURE; + return -EINVAL; } lst_size = (sizeof(TxD_t) * config->max_txds); @@ -547,6 +558,7 @@ static int init_shared_mem(struct s2io_nic *nic) nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); if (!nic->ufo_in_band_v) return -ENOMEM; + memset(nic->ufo_in_band_v, 0, size); /* Allocation and initialization of RXDs in Rings */ size = 0; @@ -1213,7 +1225,7 @@ static int init_nic(struct s2io_nic *nic) break; } - /* Enable Tx FIFO partition 0. */ + /* Enable all configured Tx FIFO partitions */ val64 = readq(&bar0->tx_fifo_partition_0); val64 |= (TX_FIFO_PARTITION_EN); writeq(val64, &bar0->tx_fifo_partition_0); @@ -1650,7 +1662,7 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) writeq(temp64, &bar0->general_int_mask); /* * If Hercules adapter enable GPIO otherwise - * disabled all PCIX, Flash, MDIO, IIC and GPIO + * disable all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ @@ -2119,7 +2131,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } - txdlp->Host_Control = 0; + memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); return(skb); } @@ -2614,23 +2626,23 @@ no_rx: } #endif +#ifdef CONFIG_NET_POLL_CONTROLLER /** - * s2io_netpoll - Rx interrupt service handler for netpoll support + * s2io_netpoll - netpoll event handler entry point * @dev : pointer to the device structure. * Description: - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. + * This function will be called by upper layer to check for events on the + * interface in situations where interrupts are disabled. It is used for + * specific in-kernel networking tasks, such as remote consoles and kernel + * debugging over the network (example netdump in RedHat). */ - -#ifdef CONFIG_NET_POLL_CONTROLLER static void s2io_netpoll(struct net_device *dev) { nic_t *nic = dev->priv; mac_info_t *mac_control; struct config_param *config; XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64; + u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; disable_irq(dev->irq); @@ -2639,9 +2651,17 @@ static void s2io_netpoll(struct net_device *dev) mac_control = &nic->mac_control; config = &nic->config; - val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); + writeq(val64, &bar0->tx_traffic_int); + + /* we need to free up the transmitted skbufs or else netpoll will + * run out of skbs and will fail and eventually netpoll application such + * as netdump will fail. + */ + for (i = 0; i < config->tx_fifo_num; i++) + tx_intr_handler(&mac_control->fifos[i]); + /* check for received packet and indicate up to network */ for (i = 0; i < config->rx_ring_num; i++) rx_intr_handler(&mac_control->rings[i]); @@ -3327,7 +3347,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { - /* Clear parity err detect bit */ + /* Clear "detected parity error" bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ @@ -4942,7 +4962,8 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } static void s2io_vpd_read(nic_t *nic) { - u8 vpd_data[256],data; + u8 *vpd_data; + u8 data; int i=0, cnt, fail = 0; int vpd_addr = 0x80; @@ -4955,6 +4976,10 @@ static void s2io_vpd_read(nic_t *nic) vpd_addr = 0x50; } + vpd_data = kmalloc(256, GFP_KERNEL); + if (!vpd_data) + return; + for (i = 0; i < 256; i +=4 ) { pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); pci_read_config_byte(nic->pdev, (vpd_addr + 2), &data); @@ -4977,6 +5002,7 @@ static void s2io_vpd_read(nic_t *nic) memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } + kfree(vpd_data); } /** @@ -5295,7 +5321,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) else *data = 0; - return 0; + return *data; } /** @@ -6337,7 +6363,7 @@ static int s2io_card_up(nic_t * sp) s2io_set_multicast(dev); if (sp->lro) { - /* Initialize max aggregatable pkts based on MTU */ + /* Initialize max aggregatable pkts per session based on MTU */ sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; /* Check if we can use(if specified) user provided value */ if (lro_max_pkts < sp->lro_max_aggr_per_sess) @@ -6438,7 +6464,7 @@ static void s2io_tx_watchdog(struct net_device *dev) * @cksum : FCS checksum of the frame. * @ring_no : the ring from which this RxD was extracted. * Description: - * This function is called by the Tx interrupt serivce routine to perform + * This function is called by the Rx interrupt serivce routine to perform * some OS related operations on the SKB before passing it to the upper * layers. It mainly checks if the checksum is OK, if so adds it to the * SKBs cksum variable, increments the Rx packet count and passes the SKB @@ -6698,33 +6724,6 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); } -MODULE_AUTHOR("Raghavendra Koushik "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_param(tx_fifo_num, int, 0); -module_param(rx_ring_num, int, 0); -module_param(rx_ring_mode, int, 0); -module_param_array(tx_fifo_len, uint, NULL, 0); -module_param_array(rx_ring_sz, uint, NULL, 0); -module_param_array(rts_frm_len, uint, NULL, 0); -module_param(use_continuous_tx_intrs, int, 1); -module_param(rmac_pause_time, int, 0); -module_param(mc_pause_threshold_q0q3, int, 0); -module_param(mc_pause_threshold_q4q7, int, 0); -module_param(shared_splits, int, 0); -module_param(tmac_util_period, int, 0); -module_param(rmac_util_period, int, 0); -module_param(bimodal, bool, 0); -module_param(l3l4hdr_size, int , 0); -#ifndef CONFIG_S2IO_NAPI -module_param(indicate_max_pkts, int, 0); -#endif -module_param(rxsync_frequency, int, 0); -module_param(intr_type, int, 0); -module_param(lro, int, 0); -module_param(lro_max_pkts, int, 0); - static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) { if ( tx_fifo_num > 8) { @@ -6832,8 +6831,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"), - pci_disable_device(pdev); + DBG_PRINT(ERR_DBG, "Request Regions failed\n"); + pci_disable_device(pdev); return -ENODEV; } } @@ -6957,7 +6956,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* initialize the shared memory used by the NIC and the host */ if (init_shared_mem(sp)) { DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", - __FUNCTION__); + dev->name); ret = -ENOMEM; goto mem_alloc_failed; } @@ -7094,6 +7093,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->addr_len = ETH_ALEN; memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); + /* reset Nic and bring it to known state */ + s2io_reset(sp); + /* * Initialize the tasklet status and link state flags * and the card state parameter @@ -7131,11 +7133,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } s2io_vpd_read(sp); - DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); - DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", - get_xena_rev_id(sp->pdev), - s2io_driver_version); DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n"); + DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, + sp->product_name, get_xena_rev_id(sp->pdev)); + DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, + s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, sp->def_mac_addr[0].mac_addr[0], diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 217097b..1654f71 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -1011,4 +1011,9 @@ static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); + +#define S2IO_PARM_INT(X, def_val) \ + static unsigned int X = def_val;\ + module_param(X , uint, 0); + #endif /* _S2IO_H */ -- cgit v1.1 From 75c30b1368faaa9c740536b91a15a33aab62f30b Mon Sep 17 00:00:00 2001 From: Ananda Raju Date: Mon, 24 Jul 2006 19:55:09 -0400 Subject: [PATCH] s2io driver bug fixes #2 This patch contains some of the bug fixes and enhancements done to s2io driver. Following are the brief description of changes 1. code cleanup to handle gso modification better 2. Move repeated code in rx path, to a common function s2io_chk_rx_buffers() 3. Bug fix in MSI interrupt 4. clear statistics when card is down 5. Avoid linked list traversing in lro aggregation. 6. Use pci_dma_sync_single_for_cpu for buffer0 in case of 2/3 buffer mode. 7. ethtool tso get/set functions to set clear NETIF_F_TSO6 8. Stop LRO aggregation when we receive ECN notification Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 228 ++++++++++++++++++++++------------------------------- drivers/net/s2io.h | 5 ++ 2 files changed, 98 insertions(+), 135 deletions(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 4a4e38b..132ed32 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -76,7 +76,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.14.2" +#define DRV_VERSION "2.0.15.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -2383,9 +2383,14 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb->tail = (void *) (unsigned long)tmp; - ((RxD3_t*)rxdp)->Buffer0_ptr = - pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, + if (!(((RxD3_t*)rxdp)->Buffer0_ptr)) + ((RxD3_t*)rxdp)->Buffer0_ptr = + pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); + else + pci_dma_sync_single_for_device(nic->pdev, + (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2398,10 +2403,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer not used */ - ((RxD3_t*)rxdp)->Buffer1_ptr = - pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); + /* Buffer-1 will be dummy buffer. Not used */ + if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) { + ((RxD3_t*)rxdp)->Buffer1_ptr = + pci_map_single(nic->pdev, + ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); + } rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); @@ -2728,7 +2736,7 @@ static void rx_intr_handler(ring_info_t *ring_data) /* If your are next to put index then it's FIFO full condition */ if ((get_block == put_block) && (get_info.offset + 1) == put_info.offset) { - DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name); + DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); @@ -2748,18 +2756,15 @@ static void rx_intr_handler(ring_info_t *ring_data) HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { - pci_unmap_single(nic->pdev, (dma_addr_t) + pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((RxD3_t*)rxdp)->Buffer1_ptr, - BUF1_LEN, PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); } else { - pci_unmap_single(nic->pdev, (dma_addr_t) + pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) @@ -3548,7 +3553,7 @@ static void restore_xmsi_data(nic_t *nic) u64 val64; int i; - for (i=0; i< nic->avail_msix_vectors; i++) { + for (i=0; i < MAX_REQUESTED_MSI_X; i++) { writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6)); @@ -3567,7 +3572,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ - for (i=0; i< nic->avail_msix_vectors; i++) { + for (i=0; i < MAX_REQUESTED_MSI_X; i++) { val64 = (BIT(15) | vBIT(i, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, i)) { @@ -3828,13 +3833,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) TxD_t *txdp; TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; -#ifdef NETIF_F_TSO - int mss; -#endif u16 vlan_tag = 0; int vlan_priority = 0; mac_info_t *mac_control; struct config_param *config; + int offload_type; mac_control = &sp->mac_control; config = &sp->config; @@ -3882,13 +3885,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - txdp->Control_1 = 0; - txdp->Control_2 = 0; + offload_type = s2io_offload_type(skb); #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->gso_size; - if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; - txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); + txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); } #endif if (skb->ip_summed == CHECKSUM_HW) { @@ -3906,10 +3907,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { + if (offload_type == SKB_GSO_UDP) { int ufo_size; - ufo_size = skb_shinfo(skb)->gso_size; + ufo_size = s2io_udp_mss(skb); ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3926,16 +3927,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); txdp++; - txdp->Control_1 = 0; - txdp->Control_2 = 0; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3950,12 +3948,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type == SKB_GSO_UDP) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3964,13 +3962,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | TX_FIFO_LAST_LIST); - -#ifdef NETIF_F_TSO - if (mss) - val64 |= TX_FIFO_SPECIAL_FUNC; -#endif - if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + if (offload_type) val64 |= TX_FIFO_SPECIAL_FUNC; + writeq(val64, &tx_fifo->List_Control); mmiowb(); @@ -4004,13 +3998,41 @@ s2io_alarm_handle(unsigned long data) mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } +static int s2io_chk_rx_buffers(nic_t *sp, int rng_n) +{ + int rxb_size, level; + + if (!sp->lro) { + rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); + level = rx_buffer_level(sp, rxb_size, rng_n); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + int ret; + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "Out of memory in %s", + __FUNCTION__); + clear_bit(0, (&sp->tasklet_status)); + return -1; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) + tasklet_schedule(&sp->task); + + } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + } + return 0; +} + static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; int i; - int ret; mac_info_t *mac_control; struct config_param *config; @@ -4032,35 +4054,8 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) * reallocate the buffers from the interrupt handler itself, * else schedule a tasklet to reallocate the buffers. */ - for (i = 0; i < config->rx_ring_num; i++) { - if (!sp->lro) { - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", - dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); - clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, i) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - break; - } - } + for (i = 0; i < config->rx_ring_num; i++) + s2io_chk_rx_buffers(sp, i); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; @@ -4071,39 +4066,13 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs) { ring_info_t *ring = (ring_info_t *)dev_id; nic_t *sp = ring->nic; - struct net_device *dev = (struct net_device *) dev_id; - int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); - rx_intr_handler(ring); - rng_n = ring->ring_no; - if (!sp->lro) { - rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); - level = rx_buffer_level(sp, rxb_size, rng_n); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "Out of memory in %s", - __FUNCTION__); - clear_bit(0, (&sp->tasklet_status)); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - } + rx_intr_handler(ring); + s2io_chk_rx_buffers(sp, ring->ring_no); atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; } @@ -4268,37 +4237,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) * else schedule a tasklet to reallocate the buffers. */ #ifndef CONFIG_S2IO_NAPI - for (i = 0; i < config->rx_ring_num; i++) { - if (!sp->lro) { - int ret; - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", - dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); - clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - writeq(org_mask, &bar0->general_int_mask); - return IRQ_HANDLED; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); - } - } - else if (fill_rx_buffers(sp, i) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); - break; - } - } + for (i = 0; i < config->rx_ring_num; i++) + s2io_chk_rx_buffers(sp, i); #endif writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); @@ -4328,6 +4268,8 @@ static void s2io_updt_stats(nic_t *sp) if (cnt == 5) break; /* Updt failed */ } while(1); + } else { + memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t)); } } @@ -5779,6 +5721,19 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) return 0; } +static u32 s2io_ethtool_op_get_tso(struct net_device *dev) +{ + return (dev->features & NETIF_F_TSO) != 0; +} +static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); + else + dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + + return 0; +} static struct ethtool_ops netdev_ethtool_ops = { .get_settings = s2io_ethtool_gset, @@ -5799,8 +5754,8 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, + .get_tso = s2io_ethtool_op_get_tso, + .set_tso = s2io_ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, @@ -7438,8 +7393,13 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, if (ip->ihl != 5) /* IP has options */ return -1; + /* If we see CE codepoint in IP header, packet is not mergeable */ + if (INET_ECN_is_ce(ipv4_get_dsfield(ip))) + return -1; + + /* If we see ECE or CWR flags in TCP header, packet is not mergeable */ if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin || - !tcp->ack) { + tcp->ece || tcp->cwr || !tcp->ack) { /* * Currently recognize only the ack control word and * any other control field being set would result in @@ -7593,18 +7553,16 @@ static void queue_rx_frame(struct sk_buff *skb) static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { - struct sk_buff *tmp, *first = lro->parent; + struct sk_buff *first = lro->parent; first->len += tcp_len; first->data_len = lro->frags_len; skb_pull(skb, (skb->len - tcp_len)); - if ((tmp = skb_shinfo(first)->frag_list)) { - while (tmp->next) - tmp = tmp->next; - tmp->next = skb; - } + if (skb_shinfo(first)->frag_list) + lro->last_frag->next = skb; else skb_shinfo(first)->frag_list = skb; + lro->last_frag = skb; sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; } diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 1654f71..5ed49c3 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -719,6 +719,7 @@ struct msix_info_st { /* Data structure to represent a LRO session */ typedef struct lro { struct sk_buff *parent; + struct sk_buff *last_frag; u8 *l2h; struct iphdr *iph; struct tcphdr *tcph; @@ -1012,6 +1013,10 @@ static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); +#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size +#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size +#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type + #define S2IO_PARM_INT(X, def_val) \ static unsigned int X = def_val;\ module_param(X , uint, 0); -- cgit v1.1 From 817acf5ebd9ea21f134fc90064b0f6686c5b169d Mon Sep 17 00:00:00 2001 From: Sergei Shtylylov Date: Wed, 26 Jul 2006 00:53:53 +0400 Subject: [PATCH] Stop calling phy_stop_interrupts() twice Prevent phylib from freeing PHY IRQ twice on closing an eth device: phy_disconnect() first calls phy_stop_interrupts(), then it calls phy_stop_machine() which in turn calls phy_stop_interrupts() making the kernel complain on each bootup... Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik --- drivers/net/phy/phy.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 7d5c223..f5aad77 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -419,9 +419,8 @@ void phy_start_machine(struct phy_device *phydev, /* phy_stop_machine * - * description: Stops the state machine timer, sets the state to - * UP (unless it wasn't up yet), and then frees the interrupt, - * if it is in use. This function must be called BEFORE + * description: Stops the state machine timer, sets the state to UP + * (unless it wasn't up yet). This function must be called BEFORE * phy_detach. */ void phy_stop_machine(struct phy_device *phydev) @@ -433,9 +432,6 @@ void phy_stop_machine(struct phy_device *phydev) phydev->state = PHY_UP; spin_unlock(&phydev->lock); - if (phydev->irq != PHY_POLL) - phy_stop_interrupts(phydev); - phydev->adjust_state = NULL; } -- cgit v1.1 From e454358ace657af953b5b289f49cf733973f41e4 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Sun, 30 Jul 2006 00:14:09 -0400 Subject: [PATCH] myri10ge - Write the firmware in 256-bytes chunks When writing the firmware to the NIC, the FIFO is 256-bytes long, so we use 256-bytes chunks and a read to wait until the previous write is done. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c3e52c8..198c6f0 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -448,6 +448,7 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) struct mcp_gen_header *hdr; size_t hdr_offset; int status; + unsigned i; if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { dev_err(dev, "Unable to load %s firmware image via hotplug\n", @@ -479,18 +480,12 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) goto abort_with_fw; crc = crc32(~0, fw->data, fw->size); - if (mgp->tx.boundary == 2048) { - /* Avoid PCI burst on chipset with unaligned completions. */ - int i; - __iomem u32 *ptr = (__iomem u32 *) (mgp->sram + - MYRI10GE_FW_OFFSET); - for (i = 0; i < fw->size / 4; i++) { - __raw_writel(((u32 *) fw->data)[i], ptr + i); - wmb(); - } - } else { - myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data, - fw->size); + for (i = 0; i < fw->size; i += 256) { + myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i, + fw->data + i, + min(256U, (unsigned)(fw->size - i))); + mb(); + readb(mgp->sram); } /* corruption checking is good for parity recovery and buggy chipset */ memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size); -- cgit v1.1 From c54772e751c0262073e85a7aa87f093fc0dd44f1 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Sun, 30 Jul 2006 00:14:15 -0400 Subject: [PATCH] myri10ge - Fix spurious invokations of the watchdog reset handler Fix spurious invocations of the watchdog reset handler. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 198c6f0..06440a8 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -177,6 +177,7 @@ struct myri10ge_priv { struct work_struct watchdog_work; struct timer_list watchdog_timer; int watchdog_tx_done; + int watchdog_tx_req; int watchdog_resets; int tx_linearized; int pause; @@ -2542,7 +2543,8 @@ static void myri10ge_watchdog_timer(unsigned long arg) mgp = (struct myri10ge_priv *)arg; if (mgp->tx.req != mgp->tx.done && - mgp->tx.done == mgp->watchdog_tx_done) + mgp->tx.done == mgp->watchdog_tx_done && + mgp->watchdog_tx_req != mgp->watchdog_tx_done) /* nic seems like it might be stuck.. */ schedule_work(&mgp->watchdog_work); else @@ -2551,6 +2553,7 @@ static void myri10ge_watchdog_timer(unsigned long arg) jiffies + myri10ge_watchdog_timeout * HZ); mgp->watchdog_tx_done = mgp->tx.done; + mgp->watchdog_tx_req = mgp->tx.req; } static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -- cgit v1.1 From f1d39b291e2263f5e2f2ec5d4061802f76d8ae67 Mon Sep 17 00:00:00 2001 From: Unicorn Chang Date: Tue, 1 Aug 2006 12:18:07 +0800 Subject: [PATCH] ahci: skip protocol test altogether in spurious interrupt code Skip protocol test altogether in spurious interrupt code. If PIOS is received when it shouldn't, ahci will raise protocol violation. Signed-off-by: Unicorn Chang Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 77e7202a..904c25f 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -940,14 +940,8 @@ static void ahci_host_intr(struct ata_port *ap) return; /* ignore interim PIO setup fis interrupts */ - if (ata_tag_valid(ap->active_tag)) { - struct ata_queued_cmd *qc = - ata_qc_from_tag(ap, ap->active_tag); - - if (qc && qc->tf.protocol == ATA_PROT_PIO && - (status & PORT_IRQ_PIOS_FIS)) - return; - } + if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) + return; if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " -- cgit v1.1 From 22479e1c0d111c60d29a4759408394cbdc7548a5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:51:51 -0400 Subject: Input: keyboard - change to use kzalloc Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 30a7454..3e90aac 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1297,9 +1297,9 @@ static struct input_handle *kbd_connect(struct input_handler *handler, if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) return NULL; - if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) return NULL; - memset(handle, 0, sizeof(struct input_handle)); handle->dev = dev; handle->handler = handler; -- cgit v1.1 From 0c19fcd83793be248f8108a52f895c8d0034b182 Mon Sep 17 00:00:00 2001 From: Roberto Castagnola Date: Fri, 4 Aug 2006 22:52:13 -0400 Subject: Input: logips2pp - fix button mapping for MX300 MX300 does not have an EXTRA_BTN - it is a simple wheel mouse with an additional task-switcher button, which is reported as side button (and not task button). Signed-off-by: Daniel Drake Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/logips2pp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 2f0d288..54b696c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -238,8 +238,7 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 100, PS2PP_KIND_MX, /* MX510 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 111, PS2PP_KIND_MX, /* MX300 */ - PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN }, + { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */ { 112, PS2PP_KIND_MX, /* MX500 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, -- cgit v1.1 From 184dd2751c653a572c79c1fff969000b8880da40 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:52:26 -0400 Subject: Input: trackpoint - activate protocol when resuming Trackpoint driver was not sending the magic knock sequence upon resume causing incorrect device behavior after resuming from disk. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/trackpoint.c | 52 ++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 6d9ec9a..ae5871a 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -183,21 +183,26 @@ static struct attribute_group trackpoint_attr_group = { .attrs = trackpoint_attrs, }; -static void trackpoint_disconnect(struct psmouse *psmouse) +static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id) { - sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); + unsigned char param[2] = { 0 }; - kfree(psmouse->private); - psmouse->private = NULL; + if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) + return -1; + + if (param[0] != TP_MAGIC_IDENT) + return -1; + + if (firmware_id) + *firmware_id = param[1]; + + return 0; } static int trackpoint_sync(struct psmouse *psmouse) { - unsigned char toggle; struct trackpoint_data *tp = psmouse->private; - - if (!tp) - return -1; + unsigned char toggle; /* Disable features that may make device unusable with this driver */ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle); @@ -263,27 +268,38 @@ static void trackpoint_defaults(struct trackpoint_data *tp) tp->ext_dev = TP_DEF_EXT_DEV; } +static void trackpoint_disconnect(struct psmouse *psmouse) +{ + sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); + + kfree(psmouse->private); + psmouse->private = NULL; +} + +static int trackpoint_reconnect(struct psmouse *psmouse) +{ + if (trackpoint_start_protocol(psmouse, NULL)) + return -1; + + if (trackpoint_sync(psmouse)) + return -1; + + return 0; +} + int trackpoint_detect(struct psmouse *psmouse, int set_properties) { struct trackpoint_data *priv; struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char firmware_id; unsigned char button_info; - unsigned char param[2]; - - param[0] = param[1] = 0; - if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) - return -1; - - if (param[0] != TP_MAGIC_IDENT) + if (trackpoint_start_protocol(psmouse, &firmware_id)) return -1; if (!set_properties) return 0; - firmware_id = param[1]; - if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n"); button_info = 0; @@ -296,7 +312,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) psmouse->vendor = "IBM"; psmouse->name = "TrackPoint"; - psmouse->reconnect = trackpoint_sync; + psmouse->reconnect = trackpoint_reconnect; psmouse->disconnect = trackpoint_disconnect; trackpoint_defaults(priv); -- cgit v1.1 From 3d0f0fa0cb554541e10cb8cb84104e4b10828468 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:52:46 -0400 Subject: Input: atkbd - restore repeat rate when resuming Make the AT keyboard driver restore previously set repeat rate when resuming. Noticed by Linus Torvalds. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 103 ++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index ce1f10e..6bfa0cf 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -482,13 +482,7 @@ out: return IRQ_HANDLED; } -/* - * atkbd_event_work() is used to complete processing of events that - * can not be processed by input_event() which is often called from - * interrupt context. - */ - -static void atkbd_event_work(void *data) +static int atkbd_set_repeat_rate(struct atkbd *atkbd) { const short period[32] = { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125, @@ -496,41 +490,64 @@ static void atkbd_event_work(void *data) const short delay[4] = { 250, 500, 750, 1000 }; - struct atkbd *atkbd = data; + struct input_dev *dev = atkbd->dev; + unsigned char param; + int i = 0, j = 0; + + while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD]) + i++; + dev->rep[REP_PERIOD] = period[i]; + + while (j < ARRAY_SIZE(period) - 1 && delay[j] < dev->rep[REP_DELAY]) + j++; + dev->rep[REP_DELAY] = delay[j]; + + param = i | (j << 5); + return ps2_command(&atkbd->ps2dev, ¶m, ATKBD_CMD_SETREP); +} + +static int atkbd_set_leds(struct atkbd *atkbd) +{ struct input_dev *dev = atkbd->dev; unsigned char param[2]; - int i, j; - mutex_lock(&atkbd->event_mutex); + param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) + | (test_bit(LED_NUML, dev->led) ? 2 : 0) + | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); + if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS)) + return -1; - if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) { - param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) - | (test_bit(LED_NUML, dev->led) ? 2 : 0) - | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); - ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS); - - if (atkbd->extra) { - param[0] = 0; - param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) - | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) - | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) - | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) - | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); - ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS); - } + if (atkbd->extra) { + param[0] = 0; + param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) + | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) + | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) + | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) + | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); + if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS)) + return -1; } - if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) { - i = j = 0; - while (i < 31 && period[i] < dev->rep[REP_PERIOD]) - i++; - while (j < 3 && delay[j] < dev->rep[REP_DELAY]) - j++; - dev->rep[REP_PERIOD] = period[i]; - dev->rep[REP_DELAY] = delay[j]; - param[0] = i | (j << 5); - ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); - } + return 0; +} + +/* + * atkbd_event_work() is used to complete processing of events that + * can not be processed by input_event() which is often called from + * interrupt context. + */ + +static void atkbd_event_work(void *data) +{ + struct atkbd *atkbd = data; + + mutex_lock(&atkbd->event_mutex); + + if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) + atkbd_set_leds(atkbd); + + if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) + atkbd_set_repeat_rate(atkbd); mutex_unlock(&atkbd->event_mutex); } @@ -975,7 +992,6 @@ static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); struct serio_driver *drv = serio->drv; - unsigned char param[1]; if (!atkbd || !drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); @@ -985,10 +1001,6 @@ static int atkbd_reconnect(struct serio *serio) atkbd_disable(atkbd); if (atkbd->write) { - param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0) - | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0) - | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0); - if (atkbd_probe(atkbd)) return -1; if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) @@ -996,8 +1008,13 @@ static int atkbd_reconnect(struct serio *serio) atkbd_activate(atkbd); - if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS)) - return -1; +/* + * Restore repeat rate and LEDs (that were reset by atkbd_activate) + * to pre-resume state + */ + if (!atkbd->softrepeat) + atkbd_set_repeat_rate(atkbd); + atkbd_set_leds(atkbd); } atkbd_enable(atkbd); -- cgit v1.1 From c669869710abd1ba47f25569ccc478c42f62a888 Mon Sep 17 00:00:00 2001 From: Edwin Huffstutler Date: Fri, 4 Aug 2006 22:53:02 -0400 Subject: Input: ati_remote - make filter time a module parameter Signed-off-by: Dmitry Torokhov --- drivers/usb/input/ati_remote.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index df198cf..b00232c 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -111,6 +111,16 @@ #define NAME_BUFSIZE 80 /* size of product name, path buffers */ #define DATA_BUFSIZE 63 /* size of URB data buffers */ +/* + * Duplicate event filtering time. + * Sequential, identical KIND_FILTERED inputs with less than + * FILTER_TIME milliseconds between them are considered as repeat + * events. The hardware generates 5 events for the first keypress + * and we have to take this into account for an accurate repeat + * behaviour. + */ +#define FILTER_TIME 60 /* msec */ + static unsigned long channel_mask; module_param(channel_mask, ulong, 0444); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); @@ -119,6 +129,10 @@ static int debug; module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); +static int repeat_filter = FILTER_TIME; +module_param(repeat_filter, int, 0644); +MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); + #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) @@ -146,15 +160,6 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; /* Acceleration curve for directional control pad */ static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; -/* Duplicate event filtering time. - * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME jiffies between them are considered as repeat - * events. The hardware generates 5 events for the first keypress - * and we have to take this into account for an accurate repeat - * behaviour. - */ -#define FILTER_TIME 60 /* msec */ - struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -464,9 +469,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* Filter duplicate events which happen "too close" together. */ - if ((ati_remote->old_data[0] == data[1]) && - (ati_remote->old_data[1] == data[2]) && - time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(FILTER_TIME))) { + if (ati_remote->old_data[0] == data[1] && + ati_remote->old_data[1] == data[2] && + time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; @@ -476,8 +481,8 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; - if ((ati_remote->repeat_count > 0) - && (ati_remote->repeat_count < 5)) + if (ati_remote->repeat_count > 0 && + ati_remote->repeat_count < 5) return; -- cgit v1.1 From c605b679144a39f291debd7031a4ada0337f02ef Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:53:15 -0400 Subject: Input: ati_remote - relax permissions sysfs module parameters Allow changing debug and channel_mask parameters on the fly. Signed-off-by: Dmitry Torokhov --- drivers/usb/input/ati_remote.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index b00232c..bdf144b 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -122,11 +122,11 @@ #define FILTER_TIME 60 /* msec */ static unsigned long channel_mask; -module_param(channel_mask, ulong, 0444); +module_param(channel_mask, ulong, 0644); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug; -module_param(debug, int, 0444); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); static int repeat_filter = FILTER_TIME; -- cgit v1.1 From c3c38fbd0cc8cc200a65b2ca7700e4dddedc13a0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:53:24 -0400 Subject: Input: ati_remote - add missing input_sync() When emulating button toggle drivers need to send input_sync() between 'down' and 'up' events, otherwise some users might miss keypress because device's state is only considered finalized after EV_SYN/SYN_REPORT is received. Signed-off-by: Dmitry Torokhov --- drivers/usb/input/ati_remote.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index bdf144b..5a56f6c 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -489,6 +489,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 1); + input_sync(dev); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 0); input_sync(dev); -- cgit v1.1 From 2ffc1ccad85e8c2e81a6a4beb390fb4ce143256b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Aug 2006 22:53:37 -0400 Subject: Input: ati_remote - use msec instead of jiffies By using milliseconds instead of jiffies to calculate acceleration factor we make the code immune to changes in HZ. Signed-off-by: Dmitry Torokhov --- drivers/usb/input/ati_remote.c | 135 +++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 5a56f6c..3719fcb 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -157,9 +157,6 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; -/* Acceleration curve for directional control pad */ -static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -417,6 +414,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) } /* + * ati_remote_compute_accel + * + * Implements acceleration curve for directional control pad + * If elapsed time since last event is > 1/4 second, user "stopped", + * so reset acceleration. Otherwise, user is probably holding the control + * pad down, so we increase acceleration, ramping up over two seconds to + * a maximum speed. + */ +static int ati_remote_compute_accel(struct ati_remote *ati_remote) +{ + static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; + unsigned long now = jiffies; + int acc; + + if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { + acc = 1; + ati_remote->acc_jiffies = now; + } + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) + acc = accel[0]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) + acc = accel[1]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) + acc = accel[2]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) + acc = accel[3]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) + acc = accel[4]; + else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) + acc = accel[5]; + else + acc = accel[6]; + + return acc; +} + +/* * ati_remote_report_input */ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) @@ -494,63 +528,48 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) ati_remote_tbl[index].code, 0); input_sync(dev); - return; - } + } else { - /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. - * - * If elapsed time since last event is > 1/4 second, user "stopped", - * so reset acceleration. Otherwise, user is probably holding the control - * pad down, so we increase acceleration, ramping up over two seconds to - * a maximum speed. The acceleration curve is #defined above. - */ - if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { - acc = 1; - ati_remote->acc_jiffies = jiffies; - } - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; - else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; - else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; - else acc = accel[6]; - - input_regs(dev, regs); - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); + /* + * Other event kinds are from the directional control pad, and have an + * acceleration factor applied to them. Without this acceleration, the + * control pad is mostly unusable. + */ + acc = ati_remote_compute_accel(ati_remote); - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + input_regs(dev, regs); + switch (ati_remote_tbl[index].kind) { + case KIND_ACCEL: + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value * acc); + break; + case KIND_LU: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_RU: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_LD: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, acc); + break; + case KIND_RD: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, acc); + break; + default: + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); + } + input_sync(dev); + + ati_remote->old_jiffies = jiffies; + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; + } } /* -- cgit v1.1 From 927cbe8a3e9ebc466f76af5a5278a520dc2d5699 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Aug 2006 12:13:45 -0700 Subject: [PATCH] drivers/edac/edac_mc.h must #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With CONFIG_PCI=n: CC drivers/edac/edac_mc.o drivers/edac/edac_mc.c: In function ‘add_mc_to_global_list’: drivers/edac/edac_mc.c:1362: error: implicit declaration of function ‘to_platform_device’ drivers/edac/edac_mc.c:1362: error: invalid type argument of ‘->’ drivers/edac/edac_mc.c: In function ‘edac_mc_add_mc’: drivers/edac/edac_mc.c:1467: error: invalid type argument of ‘->’ drivers/edac/edac_mc.c: In function ‘edac_mc_del_mc’: drivers/edac/edac_mc.c:1504: error: invalid type argument of ‘->’ Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index bf6ab8a..a1cfd4e 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -29,6 +29,7 @@ #include #include #include +#include #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 -- cgit v1.1 From c3760ae1f914cf4479301a92c58ae65824ac5894 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 5 Aug 2006 12:13:59 -0700 Subject: [PATCH] crash in aty128_set_lcd_enable() on PowerBook Current Linus tree crashes in aty128_set_lcd_enable() because par->pdev is NULL. This happens since at least a week. Call trace is: aty128_set_lcd_enable aty128fb_set_par fbcon_init visual_init take_over_console fbcon_takeover notifier_call_chain blocking_notifier_call_chain register_framebuffer aty128fb_probe pci_device_probe bus_for_each_dev driver_attach bus_add_driver driver_register __pci_register_driver aty128fb_init init kernel_thread - info->fix was assigned twice. - par->vram_size is assigned in aty128_probe(), no need to redo it again in aty128_init() - register_framebuffer() uses uninitialized struct members, move it past par->pdev assignment and past aty128_bl_init(). Signed-off-by: Olaf Hering Acked-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/aty128fb.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 8b08121..3e827e0 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1913,9 +1913,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u8 chip_rev; u32 dac; - if (!par->vram_size) /* may have already been probed */ - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; - /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; @@ -2028,9 +2025,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_init_engine(par); - if (register_framebuffer(info) < 0) - return 0; - par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; @@ -2040,6 +2034,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_bl_init(par); #endif + if (register_framebuffer(info) < 0) + return 0; + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -2089,7 +2086,6 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ par = info->par; info->pseudo_palette = par->pseudo_palette; - info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; -- cgit v1.1 From af2bc7d222c2700ccda060184d7bced7d7cb9fc2 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 5 Aug 2006 12:14:04 -0700 Subject: [PATCH] omap-rng build fix Seems like the omap-rng driver in the main tree predates the switch from to ... now it builds OK. Signed-off-by: David Brownell Signed-off-by: Michael Buesch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hw_random/omap-rng.c | 51 ++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 819516b..a01d796 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -25,12 +25,12 @@ #include #include #include +#include #include -#include +#include #include #include -#include #define RNG_OUT_REG 0x00 /* Output register */ #define RNG_STAT_REG 0x04 /* Status register @@ -52,7 +52,7 @@ static void __iomem *rng_base; static struct clk *rng_ick; -static struct device *rng_dev; +static struct platform_device *rng_dev; static u32 omap_rng_read_reg(int reg) { @@ -83,9 +83,8 @@ static struct hwrng omap_rng_ops = { .data_read = omap_rng_data_read, }; -static int __init omap_rng_probe(struct device *dev) +static int __init omap_rng_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct resource *res, *mem; int ret; @@ -95,16 +94,14 @@ static int __init omap_rng_probe(struct device *dev) */ BUG_ON(rng_dev); - if (cpu_is_omap24xx()) { + if (cpu_is_omap24xx()) { rng_ick = clk_get(NULL, "rng_ick"); if (IS_ERR(rng_ick)) { - dev_err(dev, "Could not get rng_ick\n"); + dev_err(&pdev->dev, "Could not get rng_ick\n"); ret = PTR_ERR(rng_ick); return ret; - } - else { - clk_use(rng_ick); - } + } else + clk_enable(rng_ick); } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -117,7 +114,7 @@ static int __init omap_rng_probe(struct device *dev) if (mem == NULL) return -EBUSY; - dev_set_drvdata(dev, mem); + dev_set_drvdata(&pdev->dev, mem); rng_base = (u32 __iomem *)io_p2v(res->start); ret = hwrng_register(&omap_rng_ops); @@ -127,25 +124,25 @@ static int __init omap_rng_probe(struct device *dev) return ret; } - dev_info(dev, "OMAP Random Number Generator ver. %02x\n", + dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", omap_rng_read_reg(RNG_REV_REG)); omap_rng_write_reg(RNG_MASK_REG, 0x1); - rng_dev = dev; + rng_dev = pdev; return 0; } -static int __exit omap_rng_remove(struct device *dev) +static int __exit omap_rng_remove(struct platform_device *pdev) { - struct resource *mem = dev_get_drvdata(dev); + struct resource *mem = dev_get_drvdata(&pdev->dev); hwrng_unregister(&omap_rng_ops); omap_rng_write_reg(RNG_MASK_REG, 0x0); if (cpu_is_omap24xx()) { - clk_unuse(rng_ick); + clk_disable(rng_ick); clk_put(rng_ick); } @@ -157,18 +154,16 @@ static int __exit omap_rng_remove(struct device *dev) #ifdef CONFIG_PM -static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level) +static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message) { omap_rng_write_reg(RNG_MASK_REG, 0x0); - return 0; } -static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level) +static int omap_rng_resume(struct platform_device *pdev) { omap_rng_write_reg(RNG_MASK_REG, 0x1); - - return 1; + return 0; } #else @@ -179,9 +174,11 @@ static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level) #endif -static struct device_driver omap_rng_driver = { - .name = "omap_rng", - .bus = &platform_bus_type, +static struct platform_driver omap_rng_driver = { + .driver = { + .name = "omap_rng", + .owner = THIS_MODULE, + }, .probe = omap_rng_probe, .remove = __exit_p(omap_rng_remove), .suspend = omap_rng_suspend, @@ -193,12 +190,12 @@ static int __init omap_rng_init(void) if (!cpu_is_omap16xx() && !cpu_is_omap24xx()) return -ENODEV; - return driver_register(&omap_rng_driver); + return platform_driver_register(&omap_rng_driver); } static void __exit omap_rng_exit(void) { - driver_unregister(&omap_rng_driver); + platform_driver_unregister(&omap_rng_driver); } module_init(omap_rng_init); -- cgit v1.1 From f9abd1ace43d6186268856dbec2ebf411218d6ca Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 5 Aug 2006 12:14:07 -0700 Subject: [PATCH] md: Fix a bug that recently crept into md/linear A recent patch that allowed linear arrays to be reconfigured on-line allowed in a bug which results in divide by zero - not all mddev->array_size were converted to conf->array_size. This patch finished the conversion and fixed the bug. The offending patch was commit 7c7546ccf6463edbeee8d9aac6de7be1cd80d08a. Thanks to Simon Kirby for the bug report. Cc: Simon Kirby Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/linear.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/linear.c b/drivers/md/linear.c index ff83c9b..b99c19c 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -162,7 +162,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) goto out; } - min_spacing = mddev->array_size; + min_spacing = conf->array_size; sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); /* min_spacing is the minimum spacing that will fit the hash @@ -171,7 +171,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) * that is larger than min_spacing as use the size of that as * the actual spacing */ - conf->hash_spacing = mddev->array_size; + conf->hash_spacing = conf->array_size; for (i=0; i < cnt-1 ; i++) { sector_t sz = 0; int j; @@ -228,7 +228,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) curr_offset = 0; i = 0; for (curr_offset = 0; - curr_offset < mddev->array_size; + curr_offset < conf->array_size; curr_offset += conf->hash_spacing) { while (i < mddev->raid_disks-1 && -- cgit v1.1 From fd2d54300369690500fc9b1bac9440d2ee81913a Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Sat, 5 Aug 2006 12:14:19 -0700 Subject: [PATCH] au1100fb: info->var.rotate fix Fix "info->var.rotate" data settings. This info should be deduced directly from "fbdev->panel->control_base" defined into au1100fb.h. Signed-off-by: Rodolfo Giometti Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/au1100fb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index a92a91f..26086bf 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -164,10 +164,11 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) } info->screen_size = info->fix.line_length * info->var.yres_virtual; + info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \ + >> LCD_CONTROL_SM_BIT) * 90; /* Determine BPP mode and format */ - fbdev->regs->lcd_control = fbdev->panel->control_base | - ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); + fbdev->regs->lcd_control = fbdev->panel->control_base; fbdev->regs->lcd_intenable = 0; fbdev->regs->lcd_intstatus = 0; -- cgit v1.1 From bb39e419740435b7fbb0314e376ba468be7db67a Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Sat, 5 Aug 2006 12:14:22 -0700 Subject: [PATCH] au1100fb: Fix startup sequence - fix up the start up sequence. This new sequence allow you to correctly enable the LCD controller even if the bootloader has already did it. - fix up a wrong indentation issue. Signed-off-by: Rodolfo Giometti Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/au1100fb.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 26086bf..f25d5d6 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -156,7 +156,7 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ - } + } } else { /* mono */ info->fix.visual = FB_VISUAL_MONO10; @@ -169,16 +169,11 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) /* Determine BPP mode and format */ fbdev->regs->lcd_control = fbdev->panel->control_base; - - fbdev->regs->lcd_intenable = 0; - fbdev->regs->lcd_intstatus = 0; - fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; - fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; - fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; - + fbdev->regs->lcd_intenable = 0; + fbdev->regs->lcd_intstatus = 0; fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); if (panel_is_dual(fbdev->panel)) { @@ -207,6 +202,8 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) /* Resume controller */ fbdev->regs->lcd_control |= LCD_CONTROL_GO; + mdelay(10); + au1100fb_fb_blank(VESA_NO_BLANKING, info); return 0; } -- cgit v1.1 From 229395c90aadbadef76bacf52b9cb3326f509e93 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sat, 5 Aug 2006 12:14:36 -0700 Subject: [PATCH] pSeries hvsi char driver null pointer deref Under certain rare circumstances, it appears that there can be be a NULL-pointer deref when a user fiddles with terminal emeulation programs while outpu is being sent to the console. This patch checks for and avoids a NULL-pointer deref. Signed-off-by: Hollis Blanchard Signed-off-by: Linas Vepstas Cc: Paul Fulghum Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hvsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 41db806..54cbb58 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -311,7 +311,8 @@ static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, /* CD went away; no more connection */ pr_debug("hvsi%i: CD dropped\n", hp->index); hp->mctrl &= TIOCM_CD; - if (!(hp->tty->flags & CLOCAL)) + /* If userland hasn't done an open(2) yet, hp->tty is NULL. */ + if (hp->tty && !(hp->tty->flags & CLOCAL)) *to_hangup = hp->tty; } break; -- cgit v1.1 From 64e0cc38b69b8d43ab9793f50e4bb09cea0e6bb9 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sat, 5 Aug 2006 12:14:39 -0700 Subject: [PATCH] pSeries: hvsi char driver janitorial cleanup A set of tty line discipline cleanup patches were introduced before the dawn of time, in kernel version 2.4.21. This patch performs that cleanup for the hvsi driver. The hvsi driver is used only on IBM pSeries PowerPC boxes. The driver was originally written by Hollis Blanchard, who has delegated maintainership to me. So this my first and maybe only patch in this official new role, because this driver is otherwise bug-free :-) Alan: "Actually its also a bug fix, tty->ldisc should be locked by refcounting and the helpers do this for you." Signed-off-by: Linas Vepstas Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hvsi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 54cbb58..017f755 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -987,10 +987,7 @@ static void hvsi_write_worker(void *arg) start_j = 0; #endif /* DEBUG */ wake_up_all(&hp->emptyq); - if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags) - && hp->tty->ldisc.write_wakeup) - hp->tty->ldisc.write_wakeup(hp->tty); - wake_up_interruptible(&hp->tty->write_wait); + tty_wakeup(hp->tty); } out: -- cgit v1.1 From 453c3e478e94004606b394b9ea57de71094e7c6a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 5 Aug 2006 12:14:43 -0700 Subject: [PATCH] eicon: fix define conflict with ptrace * MODE_MASK is unused in eicon driver. * Conflicts with a ptrace stuff on arm. drivers/isdn/hardware/eicon/divasync.h:259:1: warning: "MODE_MASK" redefined include2/asm/ptrace.h:48:1: warning: this is the location of the previous definition Signed-off-by: Alexey Dobriyan Acked-by: Karsten Keil Acked-by: Armin Schindler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hardware/eicon/divasync.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h index 0a5be7f..af3eb9e 100644 --- a/drivers/isdn/hardware/eicon/divasync.h +++ b/drivers/isdn/hardware/eicon/divasync.h @@ -256,7 +256,6 @@ typedef struct #define NO_ORDER_CHECK_MASK 0x00000010 #define LOW_CHANNEL_MASK 0x00000020 #define NO_HSCX30_MASK 0x00000040 -#define MODE_MASK 0x00000080 #define SET_BOARD 0x00001000 #define SET_CRC4 0x00030000 #define SET_L1_TRISTATE 0x00040000 -- cgit v1.1 From e31f59ce593b073ee14241781edfb0637697eeb6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 5 Aug 2006 12:14:53 -0700 Subject: [PATCH] ieee1394: sbp2: enable auto spin-up for Maxtor disks At least Maxtor OneTouch III require a "start stop unit" command after auto spin-down before the next access can proceed. This patch activates the responsible code in scsi_mod for all Maxtor SBP-2 disks. https://bugzilla.novell.com/show_bug.cgi?id=183011 Maybe that should be done for all SBP-2 disks, but better be cautious. Signed-off-by: Stefan Richter Cc: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ieee1394/sbp2.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index aaa74f2..b08755e 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2515,6 +2515,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; + if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ + (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) + sdev->allow_restart = 1; return 0; } -- cgit v1.1 From fa25d8d6d3fa0fecd00cd4b909011291eae9257d Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sat, 5 Aug 2006 12:15:02 -0700 Subject: [PATCH] memory hotadd fixes: avoid check in acpi add_memory() does all necessary check to avoid collision. then, acpi layer doesn't have to check region by itself. (*) pfn_valid() just returns page struct is valid or not. It returns 0 if a section has been already added even is ioresource is not added. ioresource collision check in mm/memory_hotplug.c can do more precise collistion check. added enabled bit check just for sanity check.. Signed-off-by: KAMEZAWA Hiroyuki Cc: Keith Mannthey Cc: Yasunori Goto Cc: Dave Hansen Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 81e970a..e9175ea 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -230,17 +230,10 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) * (i.e. memory-hot-remove function) */ list_for_each_entry(info, &mem_device->res_list, list) { - u64 start_pfn, end_pfn; - - start_pfn = info->start_addr >> PAGE_SHIFT; - end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT; - - if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) { - /* already enabled. try next area */ + if (info->enabled) { /* just sanity check...*/ num_enabled++; continue; } - result = add_memory(node, info->start_addr, info->length); if (result) continue; -- cgit v1.1 From 5d2870faaa1fdcec795a6bf4dbbfc3e5d57fd7ab Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sat, 5 Aug 2006 12:15:04 -0700 Subject: [PATCH] memory hotadd fixes: avoid registering res twice both of acpi_memory_enable_device() and acpi_memory_add_device() may evaluate _CRS method. We should avoid evaluate device's resource twice if we could get it successfully in past. Signed-off-by: KAMEZWA Hiroyuki Cc: Keith Mannthey Cc: Yasunori Goto Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index e9175ea..b0d4b14 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -129,11 +129,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) struct acpi_memory_info *info, *n; + if (!list_empty(&mem_device->res_list)) + return 0; + status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, acpi_memory_get_resource, mem_device); if (ACPI_FAILURE(status)) { list_for_each_entry_safe(info, n, &mem_device->res_list, list) kfree(info); + INIT_LIST_HEAD(&mem_device->res_list); return -EINVAL; } -- cgit v1.1 From 2b8de5f50e4a302b83ebcd5b0120621336d50bd6 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Sat, 5 Aug 2006 12:15:12 -0700 Subject: [PATCH] pnpacpi: reject ACPI_PRODUCER resources A patch in -mm kernel correct the parsing of "address resources" of pnpacpi. Before we assumed it was memory only, but it could be also IO. But this change show an hidden bug : some resources could be producer type that are not handled by pnp layer. So we should ignore the producer resources. This patch fixes bug 6292 (http://bugzilla.kernel.org/show_bug.cgi?id=6292). Some devices like PNP0A03 have 0xd00-0xffff and 0x0-0xcf7 as IO producer resources. Before correcting "address resources" parsing, it was seen as memory and was harmless, because nobody tried to reserve this memory range as it should be IO. With the correction it become IO resources, and make failed all others device that want to register IO in this range and use pnp layer (like a ISA sound card). The solution is to ignore producer resources Signed-off-by: Matthieu CASTET Signed-off-by: Uwe Bugla Cc: Bjorn Helgaas Cc: Adam Belay Cc: "Brown, Len" Acked-by: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/pnpacpi/rsparser.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 2122688..dc79b0a 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -173,6 +173,9 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, return; } + if (p->producer_consumer == ACPI_PRODUCER) + return; + if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(res_table, p->minimum, p->address_length); @@ -252,9 +255,14 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) + return AE_OK; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) + return AE_OK; + for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, res->data.extended_irq.interrupts[i], -- cgit v1.1 From 3e3183bab0257a6d02038658c53b491e1378612f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 5 Aug 2006 12:15:19 -0700 Subject: [PATCH] SCX200_ACB: eliminate spurious timeout errors While busy-waiting for completion, check the hardware after scheduling; don't schedule and then immediately check the _timeout_. If the yield() took a long time (as it does on my OLPC prototype board when it's busy), we'd report a timeout even though the hardware was now ready. This fixes it, and also switches the yield() for a cond_resched() because we don't actually want to be _that_ nice about it. I see nice tightly-packed SMBus transactions now, rather than waiting for milliseconds between successive phases. Actually, we shouldn't be busy-waiting here at all. We should be using interrupts. That's an exercise for another day though. Signed-off-by: David Woodhouse Cc: Christer Weinigel Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/scx200_acb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index ced309f..eae9e81 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) unsigned long timeout; timeout = jiffies + POLL_TIMEOUT; - while (time_before(jiffies, timeout)) { + while (1) { status = inb(ACBST); /* Reset the status register to avoid the hang */ @@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - yield(); + if (time_after(jiffies, timeout)) + break; + cpu_relax(); + cond_resched(); } dev_err(&iface->adapter.dev, "timeout in state %s\n", -- cgit v1.1