diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
commit | f1da2c3860e301527d56a1ef0b56c649ee7c4b1b (patch) | |
tree | 562b5d2e8b9cb62eb983d78ff6bcf9789e08fcf6 /drivers/usb | |
parent | 00f11569ac8ca73cbcdef8822de1583e79aee571 (diff) |
Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
The IP22 cache bugs which are plaguing some machines are still unfixed.
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Config.in | 4 | ||||
-rw-r--r-- | drivers/usb/audio.c | 31 | ||||
-rw-r--r-- | drivers/usb/bluetooth.c | 9 | ||||
-rw-r--r-- | drivers/usb/dabusb.c | 3 | ||||
-rw-r--r-- | drivers/usb/dc2xx.c | 3 | ||||
-rw-r--r-- | drivers/usb/devices.c | 116 | ||||
-rw-r--r-- | drivers/usb/evdev.c | 6 | ||||
-rw-r--r-- | drivers/usb/joydev.c | 6 | ||||
-rw-r--r-- | drivers/usb/mdc800.c | 3 | ||||
-rw-r--r-- | drivers/usb/mousedev.c | 6 | ||||
-rw-r--r-- | drivers/usb/printer.c | 18 | ||||
-rw-r--r-- | drivers/usb/usb.c | 27 |
12 files changed, 159 insertions, 73 deletions
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index 55b8b1df5..7e29c7807 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -28,6 +28,9 @@ comment 'USB Controllers' comment 'USB Devices' dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI + fi dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB @@ -68,7 +71,6 @@ comment 'USB Devices' dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV - dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB fi diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 67f1635a6..4560ad602 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -171,6 +171,7 @@ #include <linux/string.h> #include <linux/timer.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/module.h> #include <linux/sound.h> #include <linux/soundcard.h> @@ -1944,10 +1945,13 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file) static int usb_audio_release_mixdev(struct inode *inode, struct file *file) { struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; - struct usb_audio_state *s = ms->state; + struct usb_audio_state *s; + lock_kernel(); + s = ms->state; down(&open_sem); release(s); + unlock_kernel(); return 0; } @@ -2283,23 +2287,28 @@ static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma) { struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; struct dmabuf *db; - int ret; + int ret = -EINVAL; + lock_kernel(); if (vma->vm_flags & VM_WRITE) { if ((ret = prog_dmabuf_out(as)) != 0) - return ret; + goto out; db = &as->usbout.dma; } else if (vma->vm_flags & VM_READ) { if ((ret = prog_dmabuf_in(as)) != 0) - return ret; + goto out; db = &as->usbin.dma; } else - return -EINVAL; + goto out; + ret = -EINVAL; if (vma->vm_pgoff != 0) - return -EINVAL; + goto out; - return dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot); + ret = dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot); +out: + unlock_kernel(); + return ret; } static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -2615,10 +2624,13 @@ static int usb_audio_open(struct inode *inode, struct file *file) static int usb_audio_release(struct inode *inode, struct file *file) { struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - struct usb_audio_state *s = as->state; - struct usb_device *dev = s->usbdev; + struct usb_audio_state *s; + struct usb_device *dev; struct usb_interface *iface; + lock_kernel(); + s = as->state; + dev = s->usbdev; if (file->f_mode & FMODE_WRITE) drain_out(as, file->f_flags & O_NONBLOCK); down(&open_sem); @@ -2643,6 +2655,7 @@ static int usb_audio_release(struct inode *inode, struct file *file) as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); release(s); wake_up(&open_wait); + unlock_kernel(); return 0; } diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c index aaea67a4c..bd7be69e8 100644 --- a/drivers/usb/bluetooth.c +++ b/drivers/usb/bluetooth.c @@ -1,11 +1,15 @@ /* - * bluetooth.c Version 0.1 + * bluetooth.c Version 0.2 * * Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com> * * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B * * + * (07/11/2000) Version 0.2 gkh + * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe + * function. + * * (07/09/2000) Version 0.1 gkh * Initial release. Has support for sending ACL data (which is really just * a HCI frame.) Raw HCI commands and HCI events are not supported. @@ -619,6 +623,7 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum) memset(bluetooth, 0, sizeof(struct usb_bluetooth)); + bluetooth->magic = USB_BLUETOOTH_MAGIC; bluetooth->dev = dev; bluetooth->minor = minor; bluetooth->tqueue.routine = bluetooth_softint; @@ -676,6 +681,8 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum) tty_register_devfs (&bluetooth_tty_driver, 0, minor); info("Bluetooth converter now attached to ttyBLUE%d (or usb/ttblue/%d for devfs)", minor, minor); + bluetooth_table[minor] = bluetooth; + return bluetooth; /* success */ probe_error: diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index 8b1df4edf..9b3bc24fa 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -38,6 +38,7 @@ #include <asm/atomic.h> #include <linux/delay.h> #include <linux/usb.h> +#include <linux/smp_lock.h> #include "dabusb.h" #include "dabfirmware.h" @@ -613,6 +614,7 @@ static int dabusb_release (struct inode *inode, struct file *file) dbg("dabusb_release"); + lock_kernel(); down (&s->mutex); dabusb_stop (s); dabusb_free_buffers (s); @@ -626,6 +628,7 @@ static int dabusb_release (struct inode *inode, struct file *file) wake_up (&s->remove_ok); s->opened = 0; + unlock_kernel(); return 0; } diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c index 4fcfa640c..bb960a4af 100644 --- a/drivers/usb/dc2xx.c +++ b/drivers/usb/dc2xx.c @@ -60,6 +60,7 @@ #include <linux/module.h> #undef DEBUG #include <linux/usb.h> +#include <linux/smp_lock.h> @@ -298,10 +299,12 @@ static int camera_release (struct inode *inode, struct file *file) kfree (camera->buf); /* If camera was unplugged with open file ... */ + lock_kernel(); if (!camera->dev) { minor_data [camera->subminor] = NULL; kfree (camera); } + unlock_kernel(); dbg ("close"); diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c index c99f86973..df02bcf2a 100644 --- a/drivers/usb/devices.c +++ b/drivers/usb/devices.c @@ -45,6 +45,9 @@ * up an eventual usbd * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch> * Turned into its own filesystem + * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk> + * Converted file reading routine to dump to buffer once + * per device, not per bus * * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $ */ @@ -367,23 +370,40 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de /*****************************************************************/ -static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev, - struct usb_bus *bus, int level, int index, int count) +/* This is a recursive function. Parameters: + * buffer - the user-space buffer to write data into + * nbytes - the maximum number of bytes to write + * skip_bytes - the number of bytes to skip before writing anything + * file_offset - the offset into the devices file on completion + */ +static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, + struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) { int chix; - int cnt = 0; + int ret, cnt = 0; int parent_devnum = 0; - + char *pages_start, *data_end; + unsigned int length; + ssize_t total_written = 0; + + /* don't bother with anything else if we're not writing any data */ + if (*nbytes <= 0) + return 0; + if (level > MAX_TOPO_LEVEL) - return start; + return total_written; + /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */ + if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1))) + return -ENOMEM; + if (usbdev->parent && usbdev->parent->devnum != -1) parent_devnum = usbdev->parent->devnum; /* * So the root hub's parent is 0 and any device that is * plugged into the root hub has a parent of 0. */ - start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count, - usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); + data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count, + usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); /* * level = topology-tier level; * parent_devnum = parent device number; @@ -392,30 +412,58 @@ static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev, */ /* If this is the root hub, display the bandwidth information */ if (level == 0) - start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, + data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC, (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC, bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs); - start = usb_dump_desc(start, end, usbdev); - if (start > end) - return start + sprintf(start, "(truncated)\n"); + + data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev); + + if (data_end > (pages_start + (2 * PAGE_SIZE) - 256)) + data_end += sprintf(data_end, "(truncated)\n"); + + length = data_end - pages_start; + /* if we can start copying some data to the user */ + if (length > *skip_bytes) { + length -= *skip_bytes; + if (length > *nbytes) + length = *nbytes; + if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) { + free_pages((unsigned long)pages_start, 1); + + if (total_written == 0) + return -EFAULT; + return total_written; + } + *nbytes -= length; + *file_offset += length; + total_written += length; + *buffer += length; + *skip_bytes = 0; + } else + *skip_bytes -= length; + + free_pages((unsigned long)pages_start, 1); + /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { - if (start > end) - return start; - if (usbdev->children[chix]) - start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt); + if (usbdev->children[chix]) { + ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix], + bus, level + 1, chix, ++cnt); + if (ret == -EFAULT) + return total_written; + total_written += ret; + } } - return start; + return total_written; } static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { struct list_head *buslist; struct usb_bus *bus; - char *page, *end; - ssize_t ret = 0; - unsigned int pos, len; + ssize_t ret, total_written = 0; + loff_t skip_bytes = *ppos; if (*ppos < 0) return -EINVAL; @@ -423,34 +471,18 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff return 0; if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - if (!(page = (char*) __get_free_pages(GFP_KERNEL,1))) - return -ENOMEM; - pos = *ppos; + /* enumerate busses */ for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { /* print devices for this bus */ bus = list_entry(buslist, struct usb_bus, bus_list); - end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0); - len = end - page; - if (len > pos) { - len -= pos; - if (len > nbytes) - len = nbytes; - if (copy_to_user(buf, page + pos, len)) { - if (!ret) - ret = -EFAULT; - break; - } - nbytes -= len; - buf += len; - ret += len; - pos = 0; - *ppos += len; - } else - pos -= len; + /* recurse through all children of the root hub */ + ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); + if (ret < 0) + return ret; + total_written += ret; } - free_pages((unsigned long)page, 1); - return ret; + return total_written; } /* Kernel lock for "lastev" protection */ diff --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c index 7eca5e304..e11327cef 100644 --- a/drivers/usb/evdev.c +++ b/drivers/usb/evdev.c @@ -37,6 +37,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/smp_lock.h> struct evdev { int exist; @@ -91,8 +92,10 @@ static int evdev_fasync(int fd, struct file *file, int on) static int evdev_release(struct inode * inode, struct file * file) { struct evdev_list *list = file->private_data; - struct evdev_list **listptr = &list->evdev->list; + struct evdev_list **listptr; + lock_kernel(); + listptr = &list->evdev->list; evdev_fasync(-1, file, 0); while (*listptr && (*listptr != list)) @@ -110,6 +113,7 @@ static int evdev_release(struct inode * inode, struct file * file) } kfree(list); + unlock_kernel(); return 0; } diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c index 5349d515c..2210ad0d1 100644 --- a/drivers/usb/joydev.c +++ b/drivers/usb/joydev.c @@ -44,6 +44,7 @@ #include <linux/module.h> #include <linux/poll.h> #include <linux/init.h> +#include <linux/smp_lock.h> #define JOYDEV_MINOR_BASE 0 #define JOYDEV_MINORS 32 @@ -160,8 +161,10 @@ static int joydev_fasync(int fd, struct file *file, int on) static int joydev_release(struct inode * inode, struct file * file) { struct joydev_list *list = file->private_data; - struct joydev_list **listptr = &list->joydev->list; + struct joydev_list **listptr; + lock_kernel(); + listptr = &list->joydev->list; joydev_fasync(-1, file, 0); while (*listptr && (*listptr != list)) @@ -179,6 +182,7 @@ static int joydev_release(struct inode * inode, struct file * file) } kfree(list); + unlock_kernel(); return 0; } diff --git a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c index dc578df33..80a1ebbf4 100644 --- a/drivers/usb/mdc800.c +++ b/drivers/usb/mdc800.c @@ -76,6 +76,7 @@ #include <linux/init.h> #include <linux/malloc.h> #include <linux/module.h> +#include <linux/smp_lock.h> #include <linux/usb.h> @@ -582,6 +583,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file) int retval=0; dbg ("Mustek MDC800 device closed."); + lock_kernel(); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { mdc800->open=0; @@ -593,6 +595,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file) { retval=-EIO; } + unlock_kernel(); return retval; } diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c index 5c871a88d..ea5ad301b 100644 --- a/drivers/usb/mousedev.c +++ b/drivers/usb/mousedev.c @@ -38,6 +38,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/config.h> +#include <linux/smp_lock.h> #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X #define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 @@ -159,8 +160,10 @@ static int mousedev_fasync(int fd, struct file *file, int on) static int mousedev_release(struct inode * inode, struct file * file) { struct mousedev_list *list = file->private_data; - struct mousedev_list **listptr = &list->mousedev->list; + struct mousedev_list **listptr; + lock_kernel(); + listptr = &list->mousedev->list; mousedev_fasync(-1, file, 0); while (*listptr && (*listptr != list)) @@ -197,6 +200,7 @@ static int mousedev_release(struct inode * inode, struct file * file) } kfree(list); + unlock_kernel(); return 0; } diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c index 4dc11aee0..987f1a8b5 100644 --- a/drivers/usb/printer.c +++ b/drivers/usb/printer.c @@ -37,6 +37,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/signal.h> #include <linux/poll.h> #include <linux/init.h> @@ -167,17 +168,19 @@ static int usblp_open(struct inode *inode, struct file *file) if (minor < 0 || minor >= USBLP_MINORS) return -ENODEV; + lock_kernel(); usblp = usblp_table[minor]; + retval = -ENODEV; if (!usblp || !usblp->dev) - return -ENODEV; + goto out; + retval = -EBUSY; if (usblp->used) - return -EBUSY; + goto out; - if ((retval = usblp_check_status(usblp))) { - return retval; - } + if ((retval = usblp_check_status(usblp))) + goto out; usblp->used = 1; file->private_data = usblp; @@ -189,8 +192,9 @@ static int usblp_open(struct inode *inode, struct file *file) usblp->readcount = 0; usb_submit_urb(&usblp->readurb); } - - return 0; +out: + unlock_kernel(); + return retval; } static int usblp_release(struct inode *inode, struct file *file) diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 3fba783e0..9c650cfdc 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -58,8 +58,6 @@ static struct usb_driver *usb_minors[16]; int usb_register(struct usb_driver *new_driver) { - struct list_head *tmp; - if (new_driver->fops != NULL) { if (usb_minors[new_driver->minor/16]) { err("error registering %s driver", new_driver->name); @@ -75,13 +73,22 @@ int usb_register(struct usb_driver *new_driver) /* Add it to the list of known drivers */ list_add(&new_driver->driver_list, &usb_driver_list); - /* - * We go through all existing devices, and see if any of them would - * be acceptable to the new driver.. This is done using a depth-first - * search for devices without a registered driver already, then - * running 'probe' with each of the drivers registered on every one - * of these. - */ + usb_scan_devices(); + + return 0; +} + +/* + * We go through all existing devices, and see if any of them would + * be acceptable to the new driver.. This is done using a depth-first + * search for devices without a registered driver already, then + * running 'probe' with each of the drivers registered on every one + * of these. + */ +void usb_scan_devices(void) +{ + struct list_head *tmp; + tmp = usb_bus_list.next; while (tmp != &usb_bus_list) { struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list); @@ -89,7 +96,6 @@ int usb_register(struct usb_driver *new_driver) tmp = tmp->next; usb_check_support(bus->root_hub); } - return 0; } /* @@ -1772,6 +1778,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_register); EXPORT_SYMBOL(usb_deregister); +EXPORT_SYMBOL(usb_scan_devices); EXPORT_SYMBOL(usb_alloc_bus); EXPORT_SYMBOL(usb_free_bus); EXPORT_SYMBOL(usb_register_bus); |