Commit 5bc21855 authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/usr/src/bklinux-2.5 into cantab.net:/usr/src/tng

parents ea51ad20 7970f12d
...@@ -120,6 +120,7 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \ ...@@ -120,6 +120,7 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/drivers/usb/core/urb.c \ $(TOPDIR)/drivers/usb/core/urb.c \
$(TOPDIR)/drivers/usb/core/message.c \ $(TOPDIR)/drivers/usb/core/message.c \
$(TOPDIR)/drivers/usb/core/config.c \ $(TOPDIR)/drivers/usb/core/config.c \
$(TOPDIR)/drivers/usb/core/file.c \
$(TOPDIR)/drivers/usb/core/usb.c \ $(TOPDIR)/drivers/usb/core/usb.c \
$(TOPDIR)/drivers/video/fbmem.c \ $(TOPDIR)/drivers/video/fbmem.c \
$(TOPDIR)/drivers/video/fbcmap.c \ $(TOPDIR)/drivers/video/fbcmap.c \
......
...@@ -285,6 +285,7 @@ ...@@ -285,6 +285,7 @@
!Edrivers/usb/core/urb.c !Edrivers/usb/core/urb.c
!Edrivers/usb/core/config.c !Edrivers/usb/core/config.c
!Edrivers/usb/core/message.c !Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/usb.c !Edrivers/usb/core/usb.c
</sect1> </sect1>
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 5 PATCHLEVEL = 5
SUBLEVEL = 24 SUBLEVEL = 25
EXTRAVERSION = EXTRAVERSION =
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -79,7 +79,7 @@ install: $(BOOTIMAGE) ...@@ -79,7 +79,7 @@ install: $(BOOTIMAGE)
clean: clean:
@echo 'Cleaning up (boot)' @echo 'Cleaning up (boot)'
@rm -f tools/build @rm -f tools/build vmlinux.bin bvmlinux.bin
@rm -f setup bootsect zImage compressed/vmlinux.out @rm -f setup bootsect zImage compressed/vmlinux.out
@rm -f bsetup bbootsect bzImage compressed/bvmlinux.out @rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
@$(MAKE) -C compressed clean @$(MAKE) -C compressed clean
......
...@@ -1173,18 +1173,6 @@ static void channel_init(struct ata_channel *ch) ...@@ -1173,18 +1173,6 @@ static void channel_init(struct ata_channel *ch)
gd->next = NULL; /* linked list of major devs */ gd->next = NULL; /* linked list of major devs */
gd->fops = ide_fops; /* file operations */ gd->fops = ide_fops; /* file operations */
gd->de_arr = kmalloc(sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
if (gd->de_arr)
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
else
goto err_kmalloc_gd_de_arr;
gd->flags = kmalloc(sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
if (gd->flags)
memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
else
goto err_kmalloc_gd_flags;
ch->gd = gd; ch->gd = gd;
add_gendisk(gd); add_gendisk(gd);
......
...@@ -1151,7 +1151,8 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1151,7 +1151,8 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
endpoint = bulk_out_endpoint[0]; endpoint = bulk_out_endpoint[0];
bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress; bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
/* create our write urb pool */ /* create our write urb pool */
for (i = 0; i < NUM_BULK_URBS; ++i) { for (i = 0; i < NUM_BULK_URBS; ++i) {
struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
...@@ -1166,8 +1167,6 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1166,8 +1167,6 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
} }
bluetooth->write_urb_pool[i] = urb; bluetooth->write_urb_pool[i] = urb;
} }
bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
endpoint = interrupt_in_endpoint[0]; endpoint = interrupt_in_endpoint[0];
bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
......
...@@ -372,7 +372,7 @@ static void usblp_cleanup (struct usblp *usblp) ...@@ -372,7 +372,7 @@ static void usblp_cleanup (struct usblp *usblp)
{ {
devfs_unregister (usblp->devfs); devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL; usblp_table [usblp->minor] = NULL;
usb_deregister_dev (&usblp_driver, 1, usblp->minor); usb_deregister_dev (1, usblp->minor);
info("usblp%d: removed", usblp->minor); info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer); kfree (usblp->writeurb->transfer_buffer);
...@@ -812,20 +812,10 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -812,20 +812,10 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
init_waitqueue_head(&usblp->wait); init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum; usblp->ifnum = ifnum;
retval = usb_register_dev(&usblp_driver, 1, &usblp->minor); retval = usb_register_dev(&usblp_fops, USBLP_MINOR_BASE, 1, &usblp->minor);
if (retval) { if (retval) {
if (retval != -ENODEV) { err("Not able to get a minor for this device.");
err("Not able to get a minor for this device."); goto abort;
goto abort;
}
/* Look for a free usblp_table entry on our own. */
while (usblp_table[usblp->minor]) {
usblp->minor++;
if (usblp->minor >= USBLP_MINORS) {
err("no more free usblp devices");
goto abort;
}
}
} }
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
...@@ -901,7 +891,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -901,7 +891,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
return usblp; return usblp;
abort_minor: abort_minor:
usb_deregister_dev (&usblp_driver, 1, usblp->minor); usb_deregister_dev (1, usblp->minor);
abort: abort:
if (usblp) { if (usblp) {
usb_free_urb(usblp->writeurb); usb_free_urb(usblp->writeurb);
...@@ -1111,9 +1101,6 @@ static struct usb_driver usblp_driver = { ...@@ -1111,9 +1101,6 @@ static struct usb_driver usblp_driver = {
name: "usblp", name: "usblp",
probe: usblp_probe, probe: usblp_probe,
disconnect: usblp_disconnect, disconnect: usblp_disconnect,
fops: &usblp_fops,
minor: USBLP_MINOR_BASE,
num_minors: USBLP_MINORS,
id_table: usblp_ids, id_table: usblp_ids,
}; };
......
...@@ -2,17 +2,17 @@ ...@@ -2,17 +2,17 @@
# Makefile for USB Core files and filesystem # Makefile for USB Core files and filesystem
# #
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o config.o export-objs := usb.o hcd.o hcd-pci.o urb.o message.o config.o file.o
usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \ usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
config.o config.o file.o
ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o usbcore-objs += hcd-pci.o
endif endif
ifeq ($(CONFIG_USB_DEVICEFS),y) ifeq ($(CONFIG_USB_DEVICEFS),y)
usbcore-objs += devio.o inode.o drivers.o devices.o usbcore-objs += devio.o inode.o devices.o
endif endif
obj-$(CONFIG_USB) += usbcore.o obj-$(CONFIG_USB) += usbcore.o
......
/*
* drivers/usb/file.c
*
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999 (new USB architecture)
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
more docs, etc)
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
EXPORT_SYMBOL(usb_devfs_handle);
#define MAX_USB_MINORS 256
static struct file_operations *usb_minors[MAX_USB_MINORS];
static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED;
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
struct file_operations *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
spin_unlock (&minor_lock);
if (!c || !(new_fops = fops_get(c)))
return err;
old_fops = file->f_op;
file->f_op = new_fops;
/* Curiouser and curiouser... NULL ->open() as "no device" ? */
if (file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
static struct file_operations usb_fops = {
owner: THIS_MODULE,
open: usb_open,
};
int usb_major_init(void)
{
if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
err("unable to get major %d for usb devices", USB_MAJOR);
return -EBUSY;
}
usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
return 0;
}
void usb_major_cleanup(void)
{
devfs_unregister(usb_devfs_handle);
devfs_unregister_chrdev(USB_MAJOR, "usb");
}
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @fops: the file operations for this USB device
* @minor: the requested starting minor for this device.
* @num_minors: number of minor numbers requested for this device
* @start_minor: place to put the new starting minor number
*
* This should be called by all USB drivers that use the USB major number.
* If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be
* dynamically allocated out of the list of available ones. If it is not
* enabled, the minor number will be based on the next available free minor,
* starting at the requested @minor.
*
* usb_deregister_dev() must be called when the driver is done with
* the minor numbers given out by this function.
*
* Returns -EINVAL if something bad happens with trying to register a
* device, and 0 on success, alone with a value that the driver should
* use in start_minor.
*/
int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor)
{
int i;
int j;
int good_spot;
int retval = -EINVAL;
#ifdef CONFIG_USB_DYNAMIC_MINORS
/*
* We don't care what the device tries to start at, we want to start
* at zero to pack the devices into the smallest available space with
* no holes in the minor range.
*/
minor = 0;
#endif
dbg ("asking for %d minors, starting at %d", num_minors, minor);
if (fops == NULL)
goto exit;
*start_minor = 0;
spin_lock (&minor_lock);
for (i = minor; i < MAX_USB_MINORS; ++i) {
if (usb_minors[i])
continue;
good_spot = 1;
for (j = 1; j <= num_minors-1; ++j)
if (usb_minors[i+j]) {
good_spot = 0;
break;
}
if (good_spot == 0)
continue;
*start_minor = i;
dbg("found a minor chunk free, starting at %d", i);
for (i = *start_minor; i < (*start_minor + num_minors); ++i)
usb_minors[i] = fops;
retval = 0;
goto exit;
}
exit:
spin_unlock (&minor_lock);
return retval;
}
EXPORT_SYMBOL(usb_register_dev);
/**
* usb_deregister_dev - deregister a USB device's dynamic minor.
* @num_minors: number of minor numbers to put back.
* @start_minor: the starting minor number
*
* Used in conjunction with usb_register_dev(). This function is called
* when the USB driver is finished with the minor numbers gotten from a
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev (int num_minors, int start_minor)
{
int i;
dbg ("removing %d minors starting at %d", num_minors, start_minor);
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = NULL;
spin_unlock (&minor_lock);
}
EXPORT_SYMBOL(usb_deregister_dev);
...@@ -48,7 +48,6 @@ static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED; ...@@ -48,7 +48,6 @@ static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
static int mount_count; /* = 0 */ static int mount_count; /* = 0 */
static struct dentry *devices_dentry; static struct dentry *devices_dentry;
static struct dentry *drivers_dentry;
static int num_buses; /* = 0 */ static int num_buses; /* = 0 */
static uid_t devuid; /* = 0 */ static uid_t devuid; /* = 0 */
...@@ -548,16 +547,6 @@ static int create_special_files (void) ...@@ -548,16 +547,6 @@ static int create_special_files (void)
return -ENODEV; return -ENODEV;
} }
drivers_dentry = fs_create_file ("drivers",
listmode | S_IFREG,
NULL, NULL,
&usbdevfs_drivers_fops,
listuid, listgid);
if (drivers_dentry == NULL) {
err ("Unable to create drivers usbfs file");
return -ENODEV;
}
return 0; return 0;
} }
...@@ -565,10 +554,7 @@ static void remove_special_files (void) ...@@ -565,10 +554,7 @@ static void remove_special_files (void)
{ {
if (devices_dentry) if (devices_dentry)
fs_remove_file (devices_dentry); fs_remove_file (devices_dentry);
if (drivers_dentry)
fs_remove_file (drivers_dentry);
devices_dentry = NULL; devices_dentry = NULL;
drivers_dentry = NULL;
remove_mount(); remove_mount();
} }
...@@ -581,11 +567,6 @@ void usbfs_update_special (void) ...@@ -581,11 +567,6 @@ void usbfs_update_special (void)
if (inode) if (inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
} }
if (drivers_dentry) {
inode = devices_dentry->d_inode;
if (inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
} }
void usbfs_add_bus(struct usb_bus *bus) void usbfs_add_bus(struct usb_bus *bus)
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/interrupt.h> /* for in_interrupt() */ #include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -45,6 +44,8 @@ ...@@ -45,6 +44,8 @@
extern int usb_hub_init(void); extern int usb_hub_init(void);
extern void usb_hub_cleanup(void); extern void usb_hub_cleanup(void);
extern int usb_major_init(void);
extern void usb_major_cleanup(void);
/* /*
* Prototypes for the device driver probing/loading functions * Prototypes for the device driver probing/loading functions
...@@ -58,75 +59,23 @@ static void usb_check_support(struct usb_device *); ...@@ -58,75 +59,23 @@ static void usb_check_support(struct usb_device *);
*/ */
LIST_HEAD(usb_driver_list); LIST_HEAD(usb_driver_list);
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
#define MAX_USB_MINORS 256
static struct usb_driver *usb_minors[MAX_USB_MINORS];
static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED;
static int usb_register_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg("registering %d minors, starting at %d", num_minors, start_minor);
if (start_minor + num_minors >= MAX_USB_MINORS)
return -EINVAL;
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
if (usb_minors[i]) {
spin_unlock (&minor_lock);
err("minor %d is already in use, error registering %s driver",
i, driver->name);
return -EINVAL;
}
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = driver;
spin_unlock (&minor_lock);
return 0;
}
static void usb_deregister_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg ("%s is removing %d minors starting at %d", driver->name,
num_minors, start_minor);
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = NULL;
spin_unlock (&minor_lock);
}
/** /**
* usb_register - register a USB driver * usb_register - register a USB driver
* @new_driver: USB operations for the driver * @new_driver: USB operations for the driver
* *
* Registers a USB driver with the USB core. The list of unattached * Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing * interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices. * the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success. * Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/ */
int usb_register(struct usb_driver *new_driver) int usb_register(struct usb_driver *new_driver)
{ {
int retval = 0; int retval = 0;
if ((new_driver->fops) && (new_driver->num_minors == 0)) {
err ("%s driver must specify num_minors", new_driver->name);
return -EINVAL;
}
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (new_driver->fops != NULL) {
retval = usb_register_minors (new_driver, new_driver->num_minors, new_driver->minor);
if (retval)
return retval;
}
#endif
info("registered new driver %s", new_driver->name); info("registered new driver %s", new_driver->name);
...@@ -143,92 +92,6 @@ int usb_register(struct usb_driver *new_driver) ...@@ -143,92 +92,6 @@ int usb_register(struct usb_driver *new_driver)
} }
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @new_driver: USB operations for the driver
* @num_minors: number of minor numbers requested for this device
* @start_minor: place to put the new starting minor number
*
* Used to ask the USB core for a new minor number for a device that has
* just showed up. This is used to dynamically allocate minor numbers
* from the pool of USB reserved minor numbers.
*
* This should be called by all drivers that use the USB major number.
* This only returns a good value of CONFIG_USB_DYNAMIC_MINORS is
* selected by the user.
*
* usb_deregister_dev() should be called when the driver is done with
* the minor numbers given out by this function.
*
* Returns -ENODEV if CONFIG_USB_DYNAMIC_MINORS is not enabled in this
* kernel, -EINVAL if something bad happens with trying to register a
* device, and 0 on success, alone with a value that the driver should
* use in start_minor.
*/
#ifdef CONFIG_USB_DYNAMIC_MINORS
int usb_register_dev (struct usb_driver *new_driver, int num_minors, int *start_minor)
{
int i;
int j;
int good_spot;
int retval = -EINVAL;
dbg ("%s is asking for %d minors", new_driver->name, num_minors);
if (new_driver->fops == NULL)
goto exit;
*start_minor = 0;
spin_lock (&minor_lock);
for (i = 0; i < MAX_USB_MINORS; ++i) {
if (usb_minors[i])
continue;
good_spot = 1;
for (j = 1; j <= num_minors-1; ++j)
if (usb_minors[i+j]) {
good_spot = 0;
break;
}
if (good_spot == 0)
continue;
*start_minor = i;
spin_unlock (&minor_lock);
retval = usb_register_minors (new_driver, num_minors, *start_minor);
if (retval) {
/* someone snuck in here, so let's start looking all over again */
spin_lock (&minor_lock);
i = 0;
continue;
}
goto exit;
}
spin_unlock (&minor_lock);
exit:
return retval;
}
/**
* usb_deregister_dev - deregister a USB device's dynamic minor.
* @driver: USB operations for the driver
* @num_minors: number of minor numbers to put back.
* @start_minor: the starting minor number
*
* Used in conjunction with usb_register_dev(). This function is called
* when the USB driver is finished with the minor numbers gotten from a
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev (struct usb_driver *driver, int num_minors, int start_minor)
{
usb_deregister_minors (driver, num_minors, start_minor);
}
#endif /* CONFIG_USB_DYNAMIC_MINORS */
/** /**
* usb_scan_devices - scans all unclaimed USB interfaces * usb_scan_devices - scans all unclaimed USB interfaces
* Context: !in_interrupt () * Context: !in_interrupt ()
...@@ -298,11 +161,15 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev) ...@@ -298,11 +161,15 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
} }
/** /**
* usb_deregister - unregister a USB driver * usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister * @driver: USB operations of the driver to unregister
* Context: !in_interrupt () * Context: !in_interrupt ()
* *
* Unlinks the specified driver from the internal USB driver list. * Unlinks the specified driver from the internal USB driver list.
*
* NOTE: If you called usb_register_dev(), you still need to call
* usb_deregister_dev() to clean up your driver's allocated minor numbers,
* this * call will no longer do it for you.
*/ */
void usb_deregister(struct usb_driver *driver) void usb_deregister(struct usb_driver *driver)
{ {
...@@ -310,11 +177,6 @@ void usb_deregister(struct usb_driver *driver) ...@@ -310,11 +177,6 @@ void usb_deregister(struct usb_driver *driver)
info("deregistering driver %s", driver->name); info("deregistering driver %s", driver->name);
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (driver->fops != NULL)
usb_deregister_minors (driver, driver->num_minors, driver->minor);
#endif
/* /*
* first we remove the driver, to be sure it doesn't get used by * first we remove the driver, to be sure it doesn't get used by
* another thread while we are stepping through removing entries * another thread while we are stepping through removing entries
...@@ -1357,55 +1219,6 @@ int usb_new_device(struct usb_device *dev) ...@@ -1357,55 +1219,6 @@ int usb_new_device(struct usb_device *dev)
return 0; return 0;
} }
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
struct usb_driver *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
spin_unlock (&minor_lock);
if (!c || !(new_fops = fops_get(c->fops)))
return err;
old_fops = file->f_op;
file->f_op = new_fops;
/* Curiouser and curiouser... NULL ->open() as "no device" ? */
if (file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
static struct file_operations usb_fops = {
owner: THIS_MODULE,
open: usb_open,
};
int usb_major_init(void)
{
if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
err("unable to get major %d for usb devices", USB_MAJOR);
return -EBUSY;
}
usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
return 0;
}
void usb_major_cleanup(void)
{
devfs_unregister(usb_devfs_handle);
devfs_unregister_chrdev(USB_MAJOR, "usb");
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct list_head *usb_driver_get_list(void) struct list_head *usb_driver_get_list(void)
...@@ -1463,11 +1276,6 @@ EXPORT_SYMBOL(usb_register); ...@@ -1463,11 +1276,6 @@ EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister); EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_scan_devices); EXPORT_SYMBOL(usb_scan_devices);
#ifdef CONFIG_USB_DYNAMIC_MINORS
EXPORT_SYMBOL(usb_register_dev);
EXPORT_SYMBOL(usb_deregister_dev);
#endif
EXPORT_SYMBOL(usb_alloc_dev); EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev); EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_get_dev); EXPORT_SYMBOL(usb_get_dev);
...@@ -1489,5 +1297,4 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor); ...@@ -1489,5 +1297,4 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number); EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -36,26 +36,7 @@ CONFIG_USB_OHCI_HCD ...@@ -36,26 +36,7 @@ CONFIG_USB_OHCI_HCD
The module will be called ohci-hcd.o. If you want to compile it The module will be called ohci-hcd.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>. as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_UHCI CONFIG_USB_UHCI_HCD_ALT
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
host controller). If your USB host controller conforms to this
standard, you may want to say Y, but see below. All recent boards
with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
i810, i820) conform to this standard. Also all VIA PCI chipsets
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
133).
Currently there exist two drivers for UHCI host controllers: this
one and the so-called JE driver, which you can get from
"UHCI alternate (JE) support", below. You need only one.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usb-uhci.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_UHCI_ALT
The Universal Host Controller Interface is a standard by Intel for The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB accessing the USB hardware in the PC (which is also called the USB
host controller). If your USB host controller conforms to this host controller). If your USB host controller conforms to this
...@@ -65,31 +46,11 @@ CONFIG_USB_UHCI_ALT ...@@ -65,31 +46,11 @@ CONFIG_USB_UHCI_ALT
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
133). If unsure, say Y. 133). If unsure, say Y.
Currently there exist two drivers for UHCI host controllers: this
so-called JE driver, and the one you get from "UHCI support", above.
You need only one.
This code is also available as a module ( = code which can be This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
The module will be called uhci.o. If you want to compile it as a The module will be called uhci-hcd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_OHCI
The Open Host Controller Interface is a standard by
Compaq/Microsoft/National for accessing the USB PC hardware (also
called USB host controller). If your USB host controller conforms to
this standard, say Y. The USB host controllers on most non-Intel
architectures and on several x86 compatibles with non-Intel chipsets
-- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
Aladdin Pro..) -- conform to this standard.
You may want to read <file:Documentation/usb/ohci.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usb-ohci.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SL811HS CONFIG_USB_SL811HS
Say Y here if you have a SL811HS USB host controller in your system. Say Y here if you have a SL811HS USB host controller in your system.
......
...@@ -2,23 +2,9 @@ ...@@ -2,23 +2,9 @@
# USB Host Controller Drivers # USB Host Controller Drivers
# #
comment 'USB Host Controller Drivers' comment 'USB Host Controller Drivers'
dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' EHCI HCD (USB 2.0) support' CONFIG_USB_EHCI_HCD $CONFIG_USB
dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' OHCI HCD support' CONFIG_USB_OHCI_HCD $CONFIG_USB
if [ "$CONFIG_USB_UHCI_HCD_ALT" != "y" ]; then dep_tristate ' UHCI HCD (most Intel and VIA) support' CONFIG_USB_UHCI_HCD_ALT $CONFIG_USB
dep_tristate ' UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
fi
if [ "$CONFIG_USB_UHCI_HCD" != "y" ]; then
dep_tristate ' UHCI HCD Alternate (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
fi
#if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
# dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
#fi
#if [ "$CONFIG_USB_UHCI" != "y" ]; then
# dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
#else
# define_bool CONFIG_USB_UHCI_ALT n
#fi
#dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
if [ "$CONFIG_ARM" = "y" ]; then if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB
......
...@@ -190,6 +190,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -190,6 +190,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
__u32 temp, ndp, i; __u32 temp, ndp, i;
temp = roothub_a (controller); temp = roothub_a (controller);
if (temp == ~(u32)0)
return;
ndp = (temp & RH_A_NDP); ndp = (temp & RH_A_NDP);
if (verbose) { if (verbose) {
......
...@@ -502,11 +502,19 @@ static void ohci_irq (struct usb_hcd *hcd) ...@@ -502,11 +502,19 @@ static void ohci_irq (struct usb_hcd *hcd)
if ((ohci->hcca->done_head != 0) if ((ohci->hcca->done_head != 0)
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
} else if ((ints = (readl (&regs->intrstatus)
& readl (&regs->intrenable))) == 0) { /* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
ohci->disabled++;
err ("%s device removed!", hcd->self.bus_name);
return;
/* interrupt for some other device? */
} else if ((ints &= readl (&regs->intrenable)) == 0) {
return; return;
} }
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); // dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
if (ints & OHCI_INTR_UE) { if (ints & OHCI_INTR_UE) {
......
...@@ -1665,37 +1665,15 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ...@@ -1665,37 +1665,15 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
uhci_unlink_generic(uhci, urb); uhci_unlink_generic(uhci, urb);
if (urb->transfer_flags & USB_ASYNC_UNLINK) { spin_lock(&uhci->urb_remove_list_lock);
urbp->status = urb->status = -ECONNABORTED;
spin_lock(&uhci->urb_remove_list_lock); /* If we're the first, set the next interrupt bit */
if (list_empty(&uhci->urb_remove_list))
/* If we're the first, set the next interrupt bit */ uhci_set_next_interrupt(uhci);
if (list_empty(&uhci->urb_remove_list)) list_add(&urbp->urb_list, &uhci->urb_remove_list);
uhci_set_next_interrupt(uhci);
list_add(&urbp->urb_list, &uhci->urb_remove_list);
spin_unlock(&uhci->urb_remove_list_lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
} else {
urb->status = -ENOENT;
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
if (in_interrupt()) { /* wait at least 1 frame */
static int errorcount = 10;
if (errorcount--)
dbg("uhci_urb_dequeue called from interrupt for urb %p", urb);
udelay(1000);
} else
schedule_timeout(1+1*HZ/1000);
uhci_finish_urb(hcd, urb);
}
spin_unlock(&uhci->urb_remove_list_lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
return 0; return 0;
} }
...@@ -1788,7 +1766,7 @@ static void stall_callback(unsigned long ptr) ...@@ -1788,7 +1766,7 @@ static void stall_callback(unsigned long ptr)
tmp = tmp->next; tmp = tmp->next;
u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; u->transfer_flags |= USB_TIMEOUT_KILLED;
uhci_urb_dequeue(hcd, u); uhci_urb_dequeue(hcd, u);
} }
......
...@@ -271,21 +271,15 @@ static int uhci_urb_enqueue (struct usb_hcd *hcd, struct urb *urb, int mem_flags ...@@ -271,21 +271,15 @@ static int uhci_urb_enqueue (struct usb_hcd *hcd, struct urb *urb, int mem_flags
static int uhci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) static int uhci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{ {
unsigned long flags=0; unsigned long flags=0;
struct uhci_hcd *uhci; struct uhci_hcd *uhci = hcd_to_uhci (hcd);
int ret;
dbg("uhci_urb_dequeue called for %p",urb); dbg("uhci_urb_dequeue called for %p",urb);
uhci = hcd_to_uhci (hcd); spin_lock_irqsave (&uhci->urb_list_lock, flags);
ret = uhci_unlink_urb_async(uhci, urb, UNLINK_ASYNC_STORE_URB);
if (urb->transfer_flags & USB_ASYNC_UNLINK) { spin_unlock_irqrestore (&uhci->urb_list_lock, flags);
int ret; return ret;
spin_lock_irqsave (&uhci->urb_list_lock, flags);
ret = uhci_unlink_urb_async(uhci, urb, UNLINK_ASYNC_STORE_URB);
spin_unlock_irqrestore (&uhci->urb_list_lock, flags);
return ret;
}
else
return uhci_unlink_urb_sync(uhci, urb);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int uhci_get_frame (struct usb_hcd *hcd) static int uhci_get_frame (struct usb_hcd *hcd)
......
...@@ -541,22 +541,6 @@ static void uhci_clean_iso_step1(struct uhci_hcd *uhci, urb_priv_t *urb_priv) ...@@ -541,22 +541,6 @@ static void uhci_clean_iso_step1(struct uhci_hcd *uhci, urb_priv_t *urb_priv)
} }
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static void uhci_clean_iso_step2(struct uhci_hcd *uhci, urb_priv_t *urb_priv)
{
struct list_head *p;
uhci_desc_t *td;
int now=UHCI_GET_CURRENT_FRAME(uhci);
dbg("uhci_clean_iso_step2");
while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
td = list_entry (p, uhci_desc_t, desc_list);
list_del (p);
INIT_LIST_HEAD(&td->horizontal);
list_add_tail (&td->horizontal, &uhci->free_desc_td);
td->last_used=now;
}
}
/*-------------------------------------------------------------------*/
/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink) /* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink)
CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark) CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark)
CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink) CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink)
...@@ -759,44 +743,6 @@ static int uhci_unlink_urb_async (struct uhci_hcd *uhci, struct urb *urb, int mo ...@@ -759,44 +743,6 @@ static int uhci_unlink_urb_async (struct uhci_hcd *uhci, struct urb *urb, int mo
return 0; // completion will follow return 0; // completion will follow
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
// kills an urb by unlinking descriptors and waiting for at least one frame
static int uhci_unlink_urb_sync (struct uhci_hcd *uhci, struct urb *urb)
{
uhci_desc_t *qh;
urb_priv_t *urb_priv;
unsigned long flags=0;
spin_lock_irqsave (&uhci->urb_list_lock, flags);
// err("uhci_unlink_urb_sync %p, %i",urb,urb->status);
// move descriptors out the the running chains, dequeue urb
uhci_unlink_urb_async(uhci, urb, UNLINK_ASYNC_DONT_STORE);
urb_priv = urb->hcpriv;
spin_unlock_irqrestore (&uhci->urb_list_lock, flags);
// cleanup the rest
switch (usb_pipetype (urb->pipe)) {
case PIPE_INTERRUPT:
case PIPE_ISOCHRONOUS:
uhci_wait_ms(1);
uhci_clean_iso_step2(uhci, urb_priv);
break;
case PIPE_BULK:
case PIPE_CONTROL:
qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
uhci_clean_transfer(uhci, urb, qh, CLEAN_TRANSFER_DELETION_MARK);
uhci_wait_ms(1);
}
urb->status = -ENOENT; // mark urb as killed
finish_urb(uhci,urb);
return 0;
}
/*-------------------------------------------------------------------*/
// unlink urbs for specific device or all devices // unlink urbs for specific device or all devices
static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev, int remove_all) static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev, int remove_all)
{ {
...@@ -816,8 +762,6 @@ static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev, ...@@ -816,8 +762,6 @@ static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev,
// err("unlink urb: %p, dev %p, ud %p", urb, usb_dev,urb->dev); // err("unlink urb: %p, dev %p, ud %p", urb, usb_dev,urb->dev);
//urb->transfer_flags |=USB_ASYNC_UNLINK;
if (remove_all || (usb_dev == urb->dev)) { if (remove_all || (usb_dev == urb->dev)) {
spin_unlock_irqrestore (&uhci->urb_list_lock, flags); spin_unlock_irqrestore (&uhci->urb_list_lock, flags);
err("forced removing of queued URB %p due to disconnect",urb); err("forced removing of queued URB %p due to disconnect",urb);
...@@ -850,7 +794,7 @@ static void uhci_check_timeouts(struct uhci_hcd *uhci) ...@@ -850,7 +794,7 @@ static void uhci_check_timeouts(struct uhci_hcd *uhci)
type = usb_pipetype (urb->pipe); type = usb_pipetype (urb->pipe);
if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) { if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) {
urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; urb->transfer_flags |= USB_TIMEOUT_KILLED;
async_dbg("uhci_check_timeout: timeout for %p",urb); async_dbg("uhci_check_timeout: timeout for %p",urb);
uhci_unlink_urb_async(uhci, urb, UNLINK_ASYNC_STORE_URB); uhci_unlink_urb_async(uhci, urb, UNLINK_ASYNC_STORE_URB);
} }
......
...@@ -401,6 +401,7 @@ static void mdc800_usb_download_notify (struct urb *urb) ...@@ -401,6 +401,7 @@ static void mdc800_usb_download_notify (struct urb *urb)
***************************************************************************/ ***************************************************************************/
static struct usb_driver mdc800_usb_driver; static struct usb_driver mdc800_usb_driver;
static struct file_operations mdc800_device_ops;
/* /*
* Callback to search the Mustek MDC800 on the USB Bus * Callback to search the Mustek MDC800 on the USB Bus
...@@ -476,7 +477,7 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum, ...@@ -476,7 +477,7 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum,
down (&mdc800->io_lock); down (&mdc800->io_lock);
retval = usb_register_dev (&mdc800_usb_driver, 1, &mdc800->minor); retval = usb_register_dev (&mdc800_device_ops, MDC800_DEVICE_MINOR_BASE, 1, &mdc800->minor);
if (retval && (retval != -ENODEV)) { if (retval && (retval != -ENODEV)) {
err ("Not able to get a minor for this device."); err ("Not able to get a minor for this device.");
return 0; return 0;
...@@ -537,7 +538,7 @@ static void mdc800_usb_disconnect (struct usb_device *dev,void* ptr) ...@@ -537,7 +538,7 @@ static void mdc800_usb_disconnect (struct usb_device *dev,void* ptr)
if (mdc800->state == NOT_CONNECTED) if (mdc800->state == NOT_CONNECTED)
return; return;
usb_deregister_dev (&mdc800_usb_driver, 1, mdc800->minor); usb_deregister_dev (1, mdc800->minor);
mdc800->state=NOT_CONNECTED; mdc800->state=NOT_CONNECTED;
...@@ -942,12 +943,10 @@ MODULE_DEVICE_TABLE (usb, mdc800_table); ...@@ -942,12 +943,10 @@ MODULE_DEVICE_TABLE (usb, mdc800_table);
*/ */
static struct usb_driver mdc800_usb_driver = static struct usb_driver mdc800_usb_driver =
{ {
owner: THIS_MODULE,
name: "mdc800", name: "mdc800",
probe: mdc800_usb_probe, probe: mdc800_usb_probe,
disconnect: mdc800_usb_disconnect, disconnect: mdc800_usb_disconnect,
fops: &mdc800_device_ops,
minor: MDC800_DEVICE_MINOR_BASE,
num_minors: 1,
id_table: mdc800_table id_table: mdc800_table
}; };
......
...@@ -971,17 +971,11 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum, ...@@ -971,17 +971,11 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
down(&scn_mutex); down(&scn_mutex);
retval = usb_register_dev(&scanner_driver, 1, &scn_minor); retval = usb_register_dev(&usb_scanner_fops, SCN_BASE_MNR, 1, &scn_minor);
if (retval) { if (retval) {
if (retval != -ENODEV) { err ("Not able to get a minor for this device.");
err ("Not able to get a minor for this device."); up(&scn_mutex);
up(&scn_mutex); return NULL;
return NULL;
}
for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
if (!p_scn_table[scn_minor])
break;
}
} }
/* Check to make sure that the last slot isn't already taken */ /* Check to make sure that the last slot isn't already taken */
...@@ -1112,7 +1106,7 @@ disconnect_scanner(struct usb_device *dev, void *ptr) ...@@ -1112,7 +1106,7 @@ disconnect_scanner(struct usb_device *dev, void *ptr)
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor); dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs); devfs_unregister(scn->devfs);
usb_deregister_dev(&scanner_driver, 1, scn->scn_minor); usb_deregister_dev(1, scn->scn_minor);
p_scn_table[scn->scn_minor] = NULL; p_scn_table[scn->scn_minor] = NULL;
usb_free_urb(scn->scn_irq); usb_free_urb(scn->scn_irq);
up (&(scn->sem)); up (&(scn->sem));
...@@ -1125,9 +1119,6 @@ usb_driver scanner_driver = { ...@@ -1125,9 +1119,6 @@ usb_driver scanner_driver = {
name: "usbscanner", name: "usbscanner",
probe: probe_scanner, probe: probe_scanner,
disconnect: disconnect_scanner, disconnect: disconnect_scanner,
fops: &usb_scanner_fops,
minor: SCN_BASE_MNR,
num_minors: SCN_MAX_MNR,
id_table: NULL, /* This would be scanner_device_ids, but we id_table: NULL, /* This would be scanner_device_ids, but we
need to check every USB device, in case need to check every USB device, in case
we match a user defined vendor/product ID. */ we match a user defined vendor/product ID. */
......
...@@ -193,7 +193,7 @@ static int hiddev_fasync(int fd, struct file *file, int on) ...@@ -193,7 +193,7 @@ static int hiddev_fasync(int fd, struct file *file, int on)
static void hiddev_cleanup(struct hiddev *hiddev) static void hiddev_cleanup(struct hiddev *hiddev)
{ {
devfs_unregister(hiddev->devfs); devfs_unregister(hiddev->devfs);
usb_deregister_dev(&hiddev_driver, 1, hiddev->minor); usb_deregister_dev(1, hiddev->minor);
hiddev_table[hiddev->minor] = NULL; hiddev_table[hiddev->minor] = NULL;
kfree(hiddev); kfree(hiddev);
} }
...@@ -626,21 +626,16 @@ int hiddev_connect(struct hid_device *hid) ...@@ -626,21 +626,16 @@ int hiddev_connect(struct hid_device *hid)
if (i == hid->maxapplication) if (i == hid->maxapplication)
return -1; return -1;
retval = usb_register_dev (&hiddev_driver, 1, &minor); retval = usb_register_dev (&hiddev_fops, HIDDEV_MINOR_BASE, 1, &minor);
if (retval) { if (retval) {
if (retval != -ENODEV) { err ("Not able to get a minor for this device.");
err ("Not able to get a minor for this device."); return -1;
return -1;
}
for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
if (minor == HIDDEV_MINORS) {
printk(KERN_ERR "hiddev: no more free hiddev devices\n");
return -1;
}
} }
if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) {
usb_deregister_dev (1, minor);
return -1; return -1;
}
memset(hiddev, 0, sizeof(struct hiddev)); memset(hiddev, 0, sizeof(struct hiddev));
init_waitqueue_head(&hiddev->wait); init_waitqueue_head(&hiddev->wait);
...@@ -708,9 +703,6 @@ static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -708,9 +703,6 @@ static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
static /* const */ struct usb_driver hiddev_driver = { static /* const */ struct usb_driver hiddev_driver = {
name: "hiddev", name: "hiddev",
probe: hiddev_usbd_probe, probe: hiddev_usbd_probe,
fops: &hiddev_fops,
minor: HIDDEV_MINOR_BASE,
num_minors: HIDDEV_MINORS,
}; };
int __init hiddev_init(void) int __init hiddev_init(void)
......
...@@ -742,14 +742,9 @@ static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum, ...@@ -742,14 +742,9 @@ static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum,
if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999) if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
return NULL; return NULL;
retval = usb_register_dev (&dabusb_driver, 1, &devnum); retval = usb_register_dev (&dabusb_fops, DABUSB_MINOR, 1, &devnum);
if (retval) { if (retval)
if (retval != -ENODEV) return NULL;
return NULL;
devnum = dabusb_find_struct ();
if (devnum == -1)
return NULL;
}
s = &dabusb[devnum]; s = &dabusb[devnum];
...@@ -791,7 +786,7 @@ static void dabusb_disconnect (struct usb_device *usbdev, void *ptr) ...@@ -791,7 +786,7 @@ static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
dbg("dabusb_disconnect"); dbg("dabusb_disconnect");
usb_deregister_dev (&dabusb_driver, 1, s->devnum); usb_deregister_dev (1, s->devnum);
s->remove_pending = 1; s->remove_pending = 1;
wake_up (&s->wait); wake_up (&s->wait);
if (s->state == _started) if (s->state == _started)
...@@ -814,9 +809,6 @@ static struct usb_driver dabusb_driver = ...@@ -814,9 +809,6 @@ static struct usb_driver dabusb_driver =
name: "dabusb", name: "dabusb",
probe: dabusb_probe, probe: dabusb_probe,
disconnect: dabusb_disconnect, disconnect: dabusb_disconnect,
fops: &dabusb_fops,
minor: DABUSB_MINOR,
num_minors: NRDABUSB,
id_table: dabusb_ids, id_table: dabusb_ids,
}; };
......
...@@ -1948,23 +1948,11 @@ static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum, ...@@ -1948,23 +1948,11 @@ static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum,
init_waitqueue_head (&cp->bufferwait); init_waitqueue_head (&cp->bufferwait);
down (&dev_table_mutex); down (&dev_table_mutex);
ret = usb_register_dev (&auerswald_driver, 1, &dtindex); ret = usb_register_dev (&auerswald_fops, AUER_MINOR_BASE, 1, &dtindex);
if (ret) { if (ret) {
if (ret != -ENODEV) { err ("Not able to get a minor for this device.");
err ("Not able to get a minor for this device."); up (&dev_table_mutex);
up (&dev_table_mutex); goto pfail;
goto pfail;
}
/* find a free slot in the device table */
for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
if (dev_table[dtindex] == NULL)
break;
}
if ( dtindex >= AUER_MAX_DEVICES) {
err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
up (&dev_table_mutex);
goto pfail;
}
} }
/* Give the device a name */ /* Give the device a name */
...@@ -2096,7 +2084,7 @@ static void auerswald_disconnect (struct usb_device *usbdev, void *driver_contex ...@@ -2096,7 +2084,7 @@ static void auerswald_disconnect (struct usb_device *usbdev, void *driver_contex
devfs_unregister (cp->devfs); devfs_unregister (cp->devfs);
/* give back our USB minor number */ /* give back our USB minor number */
usb_deregister_dev (&auerswald_driver, 1, cp->dtindex); usb_deregister_dev (1, cp->dtindex);
/* Stop the interrupt endpoint */ /* Stop the interrupt endpoint */
auerswald_int_release (cp); auerswald_int_release (cp);
...@@ -2153,9 +2141,6 @@ static struct usb_driver auerswald_driver = { ...@@ -2153,9 +2141,6 @@ static struct usb_driver auerswald_driver = {
name: "auerswald", name: "auerswald",
probe: auerswald_probe, probe: auerswald_probe,
disconnect: auerswald_disconnect, disconnect: auerswald_disconnect,
fops: &auerswald_fops,
minor: AUER_MINOR_BASE,
num_minors: AUER_MAX_DEVICES,
id_table: auerswald_ids, id_table: auerswald_ids,
}; };
......
...@@ -246,9 +246,6 @@ static struct usb_driver brlvger_driver = ...@@ -246,9 +246,6 @@ static struct usb_driver brlvger_driver =
name: "brlvger", name: "brlvger",
probe: brlvger_probe, probe: brlvger_probe,
disconnect: brlvger_disconnect, disconnect: brlvger_disconnect,
fops: &brlvger_fops,
minor: BRLVGER_MINOR,
num_minors: MAX_NR_BRLVGER_DEVS,
id_table: brlvger_ids, id_table: brlvger_ids,
}; };
...@@ -316,21 +313,10 @@ brlvger_probe (struct usb_device *dev, unsigned ifnum, ...@@ -316,21 +313,10 @@ brlvger_probe (struct usb_device *dev, unsigned ifnum,
down(&reserve_sem); down(&reserve_sem);
retval = usb_register_dev(&brlvger_driver, 1, &i); retval = usb_register_dev(&brlvger_fops, BRLVGER_MINOR, 1, &i);
if (retval) { if (retval) {
if (retval != -ENODEV) { err("Not able to get a minor for this device.");
err("Not able to get a minor for this device."); goto error;
goto error;
}
for( i = 0; i < MAX_NR_BRLVGER_DEVS; i++ )
if( display_table[i] == NULL )
break;
if( i == MAX_NR_BRLVGER_DEVS ) {
err( "This driver cannot handle more than %d "
"braille displays", MAX_NR_BRLVGER_DEVS);
goto error;
}
} }
if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){ if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){
...@@ -431,7 +417,7 @@ brlvger_disconnect(struct usb_device *dev, void *ptr) ...@@ -431,7 +417,7 @@ brlvger_disconnect(struct usb_device *dev, void *ptr)
info("Display %d disconnecting", priv->subminor); info("Display %d disconnecting", priv->subminor);
devfs_unregister(priv->devfs); devfs_unregister(priv->devfs);
usb_deregister_dev(&brlvger_driver, 1, priv->subminor); usb_deregister_dev(1, priv->subminor);
down(&disconnect_sem); down(&disconnect_sem);
display_table[priv->subminor] = NULL; display_table[priv->subminor] = NULL;
......
...@@ -49,7 +49,11 @@ ...@@ -49,7 +49,11 @@
#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>" #define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
#define DRIVER_DESC "USB Rio 500 driver" #define DRIVER_DESC "USB Rio 500 driver"
#define RIO_MINOR 64 #ifdef CONFIG_USB_DYNAMIC_MINORS
#define RIO_MINOR 0
#else
#define RIO_MINOR 64
#endif
/* stall/wait timeout for rio */ /* stall/wait timeout for rio */
#define NAK_TIMEOUT (HZ) #define NAK_TIMEOUT (HZ)
...@@ -65,6 +69,7 @@ struct rio_usb_data { ...@@ -65,6 +69,7 @@ struct rio_usb_data {
unsigned int ifnum; /* Interface number of the USB device */ unsigned int ifnum; /* Interface number of the USB device */
int isopen; /* nz if open */ int isopen; /* nz if open */
int present; /* Device is present on the bus */ int present; /* Device is present on the bus */
int minor; /* minor number assigned to us */
char *obuf, *ibuf; /* transfer buffers */ char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */ wait_queue_head_t wait_q; /* for timeouts */
...@@ -449,9 +454,16 @@ static void *probe_rio(struct usb_device *dev, unsigned int ifnum, ...@@ -449,9 +454,16 @@ static void *probe_rio(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct rio_usb_data *rio = &rio_instance; struct rio_usb_data *rio = &rio_instance;
int retval;
info("USB Rio found at address %d", dev->devnum); info("USB Rio found at address %d", dev->devnum);
retval = usb_register_dev(&usb_rio_fops, RIO_MINOR, 1, &rio->minor);
if (retval) {
err("Not able to get a minor for this device.");
return NULL;
}
rio->present = 1; rio->present = 1;
rio->rio_dev = dev; rio->rio_dev = dev;
...@@ -486,6 +498,7 @@ static void disconnect_rio(struct usb_device *dev, void *ptr) ...@@ -486,6 +498,7 @@ static void disconnect_rio(struct usb_device *dev, void *ptr)
struct rio_usb_data *rio = (struct rio_usb_data *) ptr; struct rio_usb_data *rio = (struct rio_usb_data *) ptr;
devfs_unregister(rio->devfs); devfs_unregister(rio->devfs);
usb_deregister_dev(1, rio->minor);
down(&(rio->lock)); down(&(rio->lock));
if (rio->isopen) { if (rio->isopen) {
...@@ -515,9 +528,6 @@ static struct usb_driver rio_driver = { ...@@ -515,9 +528,6 @@ static struct usb_driver rio_driver = {
name: "rio500", name: "rio500",
probe: probe_rio, probe: probe_rio,
disconnect: disconnect_rio, disconnect: disconnect_rio,
fops: &usb_rio_fops,
minor: RIO_MINOR,
num_minors: 1,
id_table: rio_table, id_table: rio_table,
}; };
......
/* /*
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller * Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
**
** Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
**
**
** ChangeLog:
** .... Most of the time spend reading sources & docs.
** v0.2.x First official release for the Linux kernel.
** v0.3.0 Beutified and structured, some bugs fixed.
** v0.3.x URBifying bulk requests and bugfixing. First relatively
** stable release. Still can touch device's registers only
** from top-halves.
** v0.4.0 Control messages remained unurbified are now URBs.
** Now we can touch the HW at any time.
** v0.4.9 Control urbs again use process context to wait. Argh...
** Some long standing bugs (enable_net_traffic) fixed.
** Also nasty trick about resubmiting control urb from
** interrupt context used. Please let me know how it
** behaves. Pegasus II support added since this version.
** TODO: suppressing HCD warnings spewage on disconnect.
** v0.4.13 Ethernet address is now set at probe(), not at open()
** time as this seems to break dhcpd.
** v0.5.0 branch to 2.5.x kernels
** v0.5.1 ethtool support added
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is free software; you can redistribute it and/or modify
* but WITHOUT ANY WARRANTY; without even the implied warranty of * it under the terms of the GNU General Public License version 2 as
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * published by the Free Software Foundation.
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * ChangeLog:
* along with this program; if not, write to the Free Software * .... Most of the time spent on reading sources & docs.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * v0.2.x First official release for the Linux kernel.
* v0.3.0 Beutified and structured, some bugs fixed.
* v0.3.x URBifying bulk requests and bugfixing. First relatively
* stable release. Still can touch device's registers only
* from top-halves.
* v0.4.0 Control messages remained unurbified are now URBs.
* Now we can touch the HW at any time.
* v0.4.9 Control urbs again use process context to wait. Argh...
* Some long standing bugs (enable_net_traffic) fixed.
* Also nasty trick about resubmiting control urb from
* interrupt context used. Please let me know how it
* behaves. Pegasus II support added since this version.
* TODO: suppressing HCD warnings spewage on disconnect.
* v0.4.13 Ethernet address is now set at probe(), not at open()
* time as this seems to break dhcpd.
* v0.5.0 branch to 2.5.x kernels
* v0.5.1 ethtool support added
* v0.5.5 rx socket buffers are in a pool and the their allocation
* is out of the interrupt routine.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -58,14 +46,13 @@ ...@@ -58,14 +46,13 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v0.5.4 (2002/04/11)" #define DRIVER_VERSION "v0.5.6 (2002/06/23)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
static const char driver_name[] = "pegasus"; static const char driver_name[] = "pegasus";
#define PEGASUS_USE_INTR #undef PEGASUS_WRITE_EEPROM
#define PEGASUS_WRITE_EEPROM
#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \ #define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
BMSR_100FULL | BMSR_ANEGCAPABLE) BMSR_100FULL | BMSR_ANEGCAPABLE)
...@@ -499,13 +486,57 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) ...@@ -499,13 +486,57 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
return 0; return 0;
} }
static void fill_skb_pool(pegasus_t *pegasus)
{
int i;
for (i=0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i])
continue;
pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2);
/*
** we give up if the allocation fail. the tasklet will be
** rescheduled again anyway...
*/
if (pegasus->rx_pool[i] == NULL)
return;
pegasus->rx_pool[i]->dev = pegasus->net;
skb_reserve(pegasus->rx_pool[i], 2);
}
}
static void free_skb_pool(pegasus_t *pegasus)
{
int i;
for (i=0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i]) {
dev_kfree_skb(pegasus->rx_pool[i]);
pegasus->rx_pool[i] = NULL;
}
}
}
static inline struct sk_buff *pull_skb(pegasus_t *pegasus)
{
int i;
struct sk_buff *skb;
for (i=0; i < RX_SKBS; i++) {
if (likely(pegasus->rx_pool[i] != NULL)) {
skb = pegasus->rx_pool[i];
pegasus->rx_pool[i] = NULL;
return skb;
}
}
return NULL;
}
static void read_bulk_callback(struct urb *urb) static void read_bulk_callback(struct urb *urb)
{ {
pegasus_t *pegasus = urb->context; pegasus_t *pegasus = urb->context;
struct net_device *net; struct net_device *net;
int count = urb->actual_length; int rx_status, count = urb->actual_length;
int rx_status;
struct sk_buff *skb;
__u16 pkt_len; __u16 pkt_len;
if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING)) if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
...@@ -519,7 +550,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -519,7 +550,7 @@ static void read_bulk_callback(struct urb *urb)
case 0: case 0:
break; break;
case -ETIMEDOUT: case -ETIMEDOUT:
dbg("reset MAC"); dbg("%s: reset MAC", net->name);
pegasus->flags &= ~PEGASUS_RX_BUSY; pegasus->flags &= ~PEGASUS_RX_BUSY;
break; break;
case -ENOENT: case -ENOENT:
...@@ -546,23 +577,24 @@ static void read_bulk_callback(struct urb *urb) ...@@ -546,23 +577,24 @@ static void read_bulk_callback(struct urb *urb)
} }
pkt_len = (rx_status & 0xfff) - 8; pkt_len = (rx_status & 0xfff) - 8;
if (!pegasus->rx_skb) if (pegasus->rx_skb == NULL)
goto tl_sched; printk("%s: rx_skb == NULL\n", __FUNCTION__);
/*
** we are sure at this point pegasus->rx_skb != NULL
** so we go ahead and pass up the packet.
*/
skb_put(pegasus->rx_skb, pkt_len); skb_put(pegasus->rx_skb, pkt_len);
pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net); pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
netif_rx(pegasus->rx_skb); netif_rx(pegasus->rx_skb);
if (!(skb = dev_alloc_skb(PEGASUS_MTU + 2))) {
pegasus->rx_skb = NULL;
goto tl_sched;
}
skb->dev = net;
skb_reserve(skb, 2);
pegasus->rx_skb = skb;
pegasus->stats.rx_packets++; pegasus->stats.rx_packets++;
pegasus->stats.rx_bytes += pkt_len; pegasus->stats.rx_bytes += pkt_len;
spin_lock(&pegasus->rx_pool_lock);
pegasus->rx_skb = pull_skb(pegasus);
spin_unlock(&pegasus->rx_pool_lock);
if (pegasus->rx_skb == NULL)
goto tl_sched;
goon: goon:
FILL_BULK_URB(pegasus->rx_urb, pegasus->usb, FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1), usb_rcvbulkpipe(pegasus->usb, 1),
...@@ -587,11 +619,19 @@ static void rx_fixup(unsigned long data) ...@@ -587,11 +619,19 @@ static void rx_fixup(unsigned long data)
pegasus = (pegasus_t *)data; pegasus = (pegasus_t *)data;
spin_lock_irq(&pegasus->rx_pool_lock);
fill_skb_pool(pegasus);
spin_unlock_irq(&pegasus->rx_pool_lock);
if (pegasus->flags & PEGASUS_RX_URB_FAIL) if (pegasus->flags & PEGASUS_RX_URB_FAIL)
if (pegasus->rx_skb) if (pegasus->rx_skb)
goto try_again; goto try_again;
if (pegasus->rx_skb == NULL) {
if (!(pegasus->rx_skb = dev_alloc_skb(PEGASUS_MTU + 2))) { spin_lock_irq(&pegasus->rx_pool_lock);
pegasus->rx_skb = pull_skb(pegasus);
spin_unlock_irq(&pegasus->rx_pool_lock);
}
if (pegasus->rx_skb == NULL) {
warn("wow, low on memory");
tasklet_schedule(&pegasus->rx_tl); tasklet_schedule(&pegasus->rx_tl);
return; return;
} }
...@@ -625,7 +665,6 @@ static void write_bulk_callback(struct urb *urb) ...@@ -625,7 +665,6 @@ static void write_bulk_callback(struct urb *urb)
netif_wake_queue(pegasus->net); netif_wake_queue(pegasus->net);
} }
#ifdef PEGASUS_USE_INTR
static void intr_callback(struct urb *urb) static void intr_callback(struct urb *urb)
{ {
pegasus_t *pegasus = urb->context; pegasus_t *pegasus = urb->context;
...@@ -662,7 +701,6 @@ static void intr_callback(struct urb *urb) ...@@ -662,7 +701,6 @@ static void intr_callback(struct urb *urb)
} }
} }
} }
#endif
static void pegasus_tx_timeout(struct net_device *net) static void pegasus_tx_timeout(struct net_device *net)
{ {
...@@ -748,15 +786,62 @@ static void set_carrier(struct net_device *net) ...@@ -748,15 +786,62 @@ static void set_carrier(struct net_device *net)
} }
static void free_all_urbs(pegasus_t *pegasus)
{
usb_free_urb(pegasus->intr_urb);
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
}
static void unlink_all_urbs(pegasus_t *pegasus)
{
usb_unlink_urb(pegasus->intr_urb);
usb_unlink_urb(pegasus->tx_urb);
usb_unlink_urb(pegasus->rx_urb);
usb_unlink_urb(pegasus->ctrl_urb);
}
static int alloc_urbs(pegasus_t *pegasus)
{
pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->ctrl_urb) {
return 0;
}
pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->rx_urb) {
usb_free_urb(pegasus->ctrl_urb);
return 0;
}
pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->tx_urb) {
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
return 0;
}
pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->intr_urb) {
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
return 0;
}
return 1;
}
static int pegasus_open(struct net_device *net) static int pegasus_open(struct net_device *net)
{ {
pegasus_t *pegasus = (pegasus_t *) net->priv; pegasus_t *pegasus = (pegasus_t *) net->priv;
int res; int res;
if (!(pegasus->rx_skb = dev_alloc_skb(PEGASUS_MTU + 2))) if (pegasus->rx_skb == NULL)
pegasus->rx_skb = pull_skb(pegasus);
/*
** Note: no point to free the pool. it is empty :-)
*/
if (!pegasus->rx_skb)
return -ENOMEM; return -ENOMEM;
pegasus->rx_skb->dev = net;
skb_reserve(pegasus->rx_skb, 2);
down(&pegasus->sem); down(&pegasus->sem);
FILL_BULK_URB(pegasus->rx_urb, pegasus->usb, FILL_BULK_URB(pegasus->rx_urb, pegasus->usb,
...@@ -765,19 +850,20 @@ static int pegasus_open(struct net_device *net) ...@@ -765,19 +850,20 @@ static int pegasus_open(struct net_device *net)
read_bulk_callback, pegasus); read_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
warn("%s: failed rx_urb %d", __FUNCTION__, res); warn("%s: failed rx_urb %d", __FUNCTION__, res);
#ifdef PEGASUS_USE_INTR
FILL_INT_URB(pegasus->intr_urb, pegasus->usb, FILL_INT_URB(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3), usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff), pegasus->intr_buff, sizeof(pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval); intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
warn("%s: failed intr_urb %d", __FUNCTION__, res); warn("%s: failed intr_urb %d", __FUNCTION__, res);
#endif
netif_start_queue(net); netif_start_queue(net);
pegasus->flags |= PEGASUS_RUNNING; pegasus->flags |= PEGASUS_RUNNING;
if ((res = enable_net_traffic(net, pegasus->usb))) { if ((res = enable_net_traffic(net, pegasus->usb))) {
err("can't enable_net_traffic() - %d", res); err("can't enable_net_traffic() - %d", res);
res = -EIO; res = -EIO;
usb_unlink_urb(pegasus->rx_urb);
usb_unlink_urb(pegasus->intr_urb);
free_skb_pool(pegasus);
goto exit; goto exit;
} }
set_carrier(net); set_carrier(net);
...@@ -797,13 +883,7 @@ static int pegasus_close(struct net_device *net) ...@@ -797,13 +883,7 @@ static int pegasus_close(struct net_device *net)
netif_stop_queue(net); netif_stop_queue(net);
if (!(pegasus->flags & PEGASUS_UNPLUG)) if (!(pegasus->flags & PEGASUS_UNPLUG))
disable_net_traffic(pegasus); disable_net_traffic(pegasus);
unlink_all_urbs(pegasus);
usb_unlink_urb(pegasus->rx_urb);
usb_unlink_urb(pegasus->tx_urb);
usb_unlink_urb(pegasus->ctrl_urb);
#ifdef PEGASUS_USE_INTR
usb_unlink_urb(pegasus->intr_urb);
#endif
up(&pegasus->sem); up(&pegasus->sem);
return 0; return 0;
...@@ -986,38 +1066,14 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -986,38 +1066,14 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
pegasus->dev_index = dev_index; pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait); init_waitqueue_head(&pegasus->ctrl_wait);
pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); if (!alloc_urbs(pegasus)) {
if (!pegasus->ctrl_urb) {
kfree(pegasus);
return NULL;
}
pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->rx_urb) {
usb_free_urb(pegasus->ctrl_urb);
kfree(pegasus);
return NULL;
}
pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->tx_urb) {
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
kfree(pegasus);
return NULL;
}
pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->intr_urb) {
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
kfree(pegasus); kfree(pegasus);
return NULL; return NULL;
} }
net = init_etherdev(NULL, 0); net = init_etherdev(NULL, 0);
if (!net) { if (!net) {
usb_free_urb(pegasus->tx_urb); free_all_urbs(pegasus);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
kfree(pegasus); kfree(pegasus);
return NULL; return NULL;
} }
...@@ -1039,32 +1095,26 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1039,32 +1095,26 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
net->set_multicast_list = pegasus_set_multicast; net->set_multicast_list = pegasus_set_multicast;
net->get_stats = pegasus_netdev_stats; net->get_stats = pegasus_netdev_stats;
net->mtu = PEGASUS_MTU; net->mtu = PEGASUS_MTU;
spin_lock_init(&pegasus->rx_pool_lock);
pegasus->features = usb_dev_id[dev_index].private; pegasus->features = usb_dev_id[dev_index].private;
#ifdef PEGASUS_USE_INTR
get_interrupt_interval(pegasus); get_interrupt_interval(pegasus);
#endif
if (reset_mac(pegasus)) { if (reset_mac(pegasus)) {
err("can't reset MAC"); err("can't reset MAC");
unregister_netdev(pegasus->net); unregister_netdev(pegasus->net);
usb_free_urb(pegasus->tx_urb); free_all_urbs(pegasus);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
kfree(pegasus->net); kfree(pegasus->net);
kfree(pegasus); kfree(pegasus);
pegasus = NULL; pegasus = NULL;
goto exit; goto exit;
} }
info("%s: %s", net->name, usb_dev_id[dev_index].name);
set_ethernet_addr(pegasus); set_ethernet_addr(pegasus);
fill_skb_pool(pegasus);
printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
if (pegasus->features & PEGASUS_II) { if (pegasus->features & PEGASUS_II) {
info("setup Pegasus II specific registers"); info("setup Pegasus II specific registers");
setup_pegasus_II(pegasus); setup_pegasus_II(pegasus);
} }
pegasus->phy = mii_phy_probe(pegasus); pegasus->phy = mii_phy_probe(pegasus);
if (pegasus->phy == 0xff) { if (pegasus->phy == 0xff) {
warn("can't locate MII phy, using default"); warn("can't locate MII phy, using default");
...@@ -1087,14 +1137,9 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr) ...@@ -1087,14 +1137,9 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
pegasus->flags |= PEGASUS_UNPLUG; pegasus->flags |= PEGASUS_UNPLUG;
unregister_netdev(pegasus->net); unregister_netdev(pegasus->net);
usb_put_dev(dev); usb_put_dev(dev);
usb_unlink_urb(pegasus->intr_urb); unlink_all_urbs(pegasus);
usb_unlink_urb(pegasus->tx_urb); free_all_urbs(pegasus);
usb_unlink_urb(pegasus->rx_urb); free_skb_pool(pegasus);
usb_unlink_urb(pegasus->ctrl_urb);
usb_free_urb(pegasus->intr_urb);
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
usb_free_urb(pegasus->ctrl_urb);
if (pegasus->rx_skb) if (pegasus->rx_skb)
dev_kfree_skb(pegasus->rx_skb); dev_kfree_skb(pegasus->rx_skb);
kfree(pegasus->net); kfree(pegasus->net);
......
...@@ -2,18 +2,8 @@ ...@@ -2,18 +2,8 @@
* Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net) * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License version 2 as published
* the Free Software Foundation; either version 2 of the License, or * by the Free Software Foundation.
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -23,6 +13,7 @@ ...@@ -23,6 +13,7 @@
#define HAS_HOME_PNA 0x40000000 #define HAS_HOME_PNA 0x40000000
#define PEGASUS_MTU 1536 #define PEGASUS_MTU 1536
#define RX_SKBS 4
#define EPROM_WRITE 0x01 #define EPROM_WRITE 0x01
#define EPROM_READ 0x02 #define EPROM_READ 0x02
...@@ -100,10 +91,12 @@ typedef struct pegasus { ...@@ -100,10 +91,12 @@ typedef struct pegasus {
int intr_interval; int intr_interval;
struct tasklet_struct rx_tl; struct tasklet_struct rx_tl;
struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
struct sk_buff *rx_pool[RX_SKBS];
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
struct usb_ctrlrequest dr; struct usb_ctrlrequest dr;
wait_queue_head_t ctrl_wait; wait_queue_head_t ctrl_wait;
struct semaphore sem; struct semaphore sem;
spinlock_t rx_pool_lock;
unsigned char intr_buff[8]; unsigned char intr_buff[8];
__u8 tx_buff[PEGASUS_MTU]; __u8 tx_buff[PEGASUS_MTU];
__u8 eth_regs[4]; __u8 eth_regs[4];
......
/* /*
* Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net) * Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* *
* This program is 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 <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -19,7 +18,6 @@ ...@@ -19,7 +18,6 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
/* Version Information */ /* Version Information */
...@@ -106,7 +104,7 @@ unsigned long multicast_filter_limit = 32; ...@@ -106,7 +104,7 @@ unsigned long multicast_filter_limit = 32;
static void fill_skb_pool(rtl8150_t *); static void fill_skb_pool(rtl8150_t *);
static void free_skb_pool(rtl8150_t *); static void free_skb_pool(rtl8150_t *);
static struct sk_buff *pull_skb(rtl8150_t *); static inline struct sk_buff *pull_skb(rtl8150_t *);
static void rtl8150_disconnect(struct usb_device *dev, void *ptr); static void rtl8150_disconnect(struct usb_device *dev, void *ptr);
static void *rtl8150_probe(struct usb_device *dev, unsigned int ifnum, static void *rtl8150_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id); const struct usb_device_id *id);
...@@ -312,7 +310,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -312,7 +310,7 @@ static void read_bulk_callback(struct urb *urb)
case -ENOENT: case -ENOENT:
return; /* the urb is in unlink state */ return; /* the urb is in unlink state */
case -ETIMEDOUT: case -ETIMEDOUT:
warn("reset needed may be?.."); warn("may be reset is needed?..");
goto goon; goto goon;
default: default:
warn("Rx status %d", urb->status); warn("Rx status %d", urb->status);
...@@ -331,13 +329,13 @@ static void read_bulk_callback(struct urb *urb) ...@@ -331,13 +329,13 @@ static void read_bulk_callback(struct urb *urb)
netif_rx(dev->rx_skb); netif_rx(dev->rx_skb);
dev->stats.rx_packets++; dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len; dev->stats.rx_bytes += pkt_len;
spin_lock(&dev->rx_pool_lock);
skb = pull_skb(dev); skb = pull_skb(dev);
spin_unlock(&dev->rx_pool_lock);
if (!skb) if (!skb)
goto resched; goto resched;
skb->dev = netdev;
skb_reserve(skb, 2);
dev->rx_skb = skb; dev->rx_skb = skb;
goon: goon:
FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
...@@ -361,11 +359,16 @@ static void rx_fixup(unsigned long data) ...@@ -361,11 +359,16 @@ static void rx_fixup(unsigned long data)
dev = (rtl8150_t *)data; dev = (rtl8150_t *)data;
spin_lock_irq(&dev->rx_pool_lock);
fill_skb_pool(dev); fill_skb_pool(dev);
spin_unlock_irq(&dev->rx_pool_lock);
if (test_bit(RX_URB_FAIL, &dev->flags)) if (test_bit(RX_URB_FAIL, &dev->flags))
if (dev->rx_skb) if (dev->rx_skb)
goto try_again; goto try_again;
if (!(skb = pull_skb(dev))) spin_lock_irq(&dev->rx_pool_lock);
skb = pull_skb(dev);
spin_unlock_irq(&dev->rx_pool_lock);
if (skb == NULL)
goto tlsched; goto tlsched;
dev->rx_skb = skb; dev->rx_skb = skb;
FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
...@@ -426,51 +429,41 @@ static void fill_skb_pool(rtl8150_t *dev) ...@@ -426,51 +429,41 @@ static void fill_skb_pool(rtl8150_t *dev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int i; int i;
unsigned long flags;
spin_lock_irqsave(&dev->rx_pool_lock, flags);
for (i = 0; i < RX_SKB_POOL_SIZE; i++) { for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
if (dev->rx_skb_pool[i]) if (dev->rx_skb_pool[i])
continue; continue;
skb = dev_alloc_skb(RTL8150_MTU + 2); skb = dev_alloc_skb(RTL8150_MTU + 2);
if (!skb) { if (!skb) {
spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return; return;
} }
skb->dev = dev->netdev; skb->dev = dev->netdev;
skb_reserve(skb, 2); skb_reserve(skb, 2);
dev->rx_skb_pool[i] = skb; dev->rx_skb_pool[i] = skb;
} }
spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
} }
static void free_skb_pool(rtl8150_t *dev) static void free_skb_pool(rtl8150_t *dev)
{ {
int i; int i;
spin_lock_irq(&dev->rx_pool_lock);
for (i = 0; i < RX_SKB_POOL_SIZE; i++) for (i = 0; i < RX_SKB_POOL_SIZE; i++)
if (dev->rx_skb_pool[i]) if (dev->rx_skb_pool[i])
dev_kfree_skb(dev->rx_skb_pool[i]); dev_kfree_skb(dev->rx_skb_pool[i]);
spin_unlock_irq(&dev->rx_pool_lock);
} }
static struct sk_buff *pull_skb(rtl8150_t *dev) static inline struct sk_buff *pull_skb(rtl8150_t *dev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int i; int i;
unsigned long flags;
spin_lock_irqsave(&dev->rx_pool_lock, flags);
for (i = 0; i < RX_SKB_POOL_SIZE; i++) { for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
if (dev->rx_skb_pool[i]) { if (dev->rx_skb_pool[i]) {
skb = dev->rx_skb_pool[i]; skb = dev->rx_skb_pool[i];
dev->rx_skb_pool[i] = NULL; dev->rx_skb_pool[i] = NULL;
spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return skb; return skb;
} }
} }
spin_unlock_irqrestore(&dev->rx_pool_lock, flags);
return NULL; return NULL;
} }
...@@ -578,8 +571,8 @@ static int rtl8150_open(struct net_device *netdev) ...@@ -578,8 +571,8 @@ static int rtl8150_open(struct net_device *netdev)
if (dev == NULL) { if (dev == NULL) {
return -ENODEV; return -ENODEV;
} }
if (dev->rx_skb == NULL)
dev->rx_skb = pull_skb(dev); dev->rx_skb = pull_skb(dev);
if (!dev->rx_skb) if (!dev->rx_skb)
return -ENOMEM; return -ENOMEM;
...@@ -816,13 +809,13 @@ static void rtl8150_disconnect(struct usb_device *udev, void *ptr) ...@@ -816,13 +809,13 @@ static void rtl8150_disconnect(struct usb_device *udev, void *ptr)
dev = NULL; dev = NULL;
} }
static int __init usb_rtl8150_init(void) int __init usb_rtl8150_init(void)
{ {
info(DRIVER_DESC " " DRIVER_VERSION); info(DRIVER_DESC " " DRIVER_VERSION);
return usb_register(&rtl8150_driver); return usb_register(&rtl8150_driver);
} }
static void __exit usb_rtl8150_exit(void) void __exit usb_rtl8150_exit(void)
{ {
usb_deregister(&rtl8150_driver); usb_deregister(&rtl8150_driver);
} }
......
...@@ -428,18 +428,13 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -428,18 +428,13 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
void *data, u16 size) void *data, u16 size)
{ {
int status; int status;
struct usb_ctrlrequest *dr;
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
if (!dr)
return -ENOMEM;
/* fill in the devrequest structure */ /* fill in the devrequest structure */
dr->bRequestType = requesttype; us->dr->bRequestType = requesttype;
dr->bRequest = request; us->dr->bRequest = request;
dr->wValue = cpu_to_le16(value); us->dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index); us->dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size); us->dr->wLength = cpu_to_le16(size);
/* lock the URB */ /* lock the URB */
down(&(us->current_urb_sem)); down(&(us->current_urb_sem));
...@@ -452,7 +447,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -452,7 +447,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
/* fill the URB */ /* fill the URB */
FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) dr, data, size, (unsigned char*) us->dr, data, size,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
/* submit the URB */ /* submit the URB */
...@@ -1162,7 +1157,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -1162,7 +1157,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int pipe; int pipe;
/* issue the command -- use usb_control_msg() because /* issue the command -- use usb_control_msg() because
* the state machine is not yet alive */ * this is not a scsi queued-command */
pipe = usb_rcvctrlpipe(us->pusb_dev, 0); pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
result = usb_control_msg(us->pusb_dev, pipe, result = usb_control_msg(us->pusb_dev, pipe,
US_BULK_GET_MAX_LUN, US_BULK_GET_MAX_LUN,
...@@ -1181,8 +1176,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -1181,8 +1176,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
/* Use usb_clear_halt() because the state machine /* Use usb_clear_halt() because this is not a
* is not yet alive */ * scsi queued-command */
usb_clear_halt(us->pusb_dev, pipe); usb_clear_halt(us->pusb_dev, pipe);
} }
...@@ -1356,27 +1351,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1356,27 +1351,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
* Reset routines * Reset routines
***********************************************************************/ ***********************************************************************/
struct us_timeout {
struct us_data *us;
spinlock_t timer_lock;
};
/* The timeout event handler
*/
static void usb_stor_timeout_handler(unsigned long to__)
{
struct us_timeout *to = (struct us_timeout *) to__;
struct us_data *us = to->us;
US_DEBUGP("Timeout occurred\n");
/* abort the current request */
usb_stor_abort_transport(us);
/* let the reset routine know we have finished */
spin_unlock(&to->timer_lock);
}
/* This is the common part of the device reset code. /* This is the common part of the device reset code.
* *
* It's handy that every transport mechanism uses the control endpoint for * It's handy that every transport mechanism uses the control endpoint for
...@@ -1385,28 +1359,20 @@ static void usb_stor_timeout_handler(unsigned long to__) ...@@ -1385,28 +1359,20 @@ static void usb_stor_timeout_handler(unsigned long to__)
* Basically, we send a reset with a 20-second timeout, so we don't get * Basically, we send a reset with a 20-second timeout, so we don't get
* jammed attempting to do the reset. * jammed attempting to do the reset.
*/ */
void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, static int usb_stor_reset_common(struct us_data *us,
u8 request, u8 requesttype,
u16 value, u16 index, void *data, u16 size) u16 value, u16 index, void *data, u16 size)
{ {
int result; int result;
struct us_timeout timeout_data = {us, SPIN_LOCK_UNLOCKED};
struct timer_list timeout_list;
/* prepare the timeout handler */
spin_lock(&timeout_data.timer_lock);
init_timer(&timeout_list);
/* A 20-second timeout may seem rather long, but a LaCie /* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going * StudioDrive USB2 device takes 16+ seconds to get going
* following a powerup or USB attach event. */ * following a powerup or USB attach event. */
timeout_list.expires = jiffies + 20 * HZ; /* Use usb_control_msg() because this is not a queued-command */
timeout_list.data = (unsigned long) &timeout_data; result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
timeout_list.function = usb_stor_timeout_handler; request, requesttype, value, index, data, size,
add_timer(&timeout_list); 20*HZ);
result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
request, requesttype, value, index, data, size);
if (result < 0) if (result < 0)
goto Done; goto Done;
...@@ -1415,41 +1381,30 @@ void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, ...@@ -1415,41 +1381,30 @@ void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype,
schedule_timeout(HZ*6); schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
/* Use usb_clear_halt() because this is not a queued-command */
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, result = usb_clear_halt(us->pusb_dev,
usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
if (result < 0) if (result < 0)
goto Done; goto Done;
US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
result = usb_stor_clear_halt(us, result = usb_clear_halt(us->pusb_dev,
usb_sndbulkpipe(us->pusb_dev, us->ep_out)); usb_sndbulkpipe(us->pusb_dev, us->ep_out));
Done: Done:
/* prevent the timer from coming back to haunt us */
if (!del_timer(&timeout_list)) {
/* the handler has already started; wait for it to finish */
spin_lock(&timeout_data.timer_lock);
/* change the abort into a timeout */
if (result == -ENOENT)
result = -ETIMEDOUT;
}
/* return a result code based on the result of the control message */ /* return a result code based on the result of the control message */
if (result >= 0) if (result < 0) {
US_DEBUGP("Soft reset done\n");
else
US_DEBUGP("Soft reset failed: %d\n", result); US_DEBUGP("Soft reset failed: %d\n", result);
if (result == -ETIMEDOUT)
us->srb->result = DID_TIME_OUT << 16;
else if (result == -ENOENT)
us->srb->result = DID_ABORT << 16;
else if (result < 0)
us->srb->result = DID_ERROR << 16; us->srb->result = DID_ERROR << 16;
else result = FAILED;
} else {
US_DEBUGP("Soft reset done\n");
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
result = SUCCESS;
}
return result;
} }
/* This issues a CB[I] Reset to the device in question /* This issues a CB[I] Reset to the device in question
...@@ -1463,10 +1418,9 @@ int usb_stor_CB_reset(struct us_data *us) ...@@ -1463,10 +1418,9 @@ int usb_stor_CB_reset(struct us_data *us)
memset(cmd, 0xFF, sizeof(cmd)); memset(cmd, 0xFF, sizeof(cmd));
cmd[0] = SEND_DIAGNOSTIC; cmd[0] = SEND_DIAGNOSTIC;
cmd[1] = 4; cmd[1] = 4;
usb_stor_reset_common(us, US_CBI_ADSC, return usb_stor_reset_common(us, US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, cmd, sizeof(cmd)); 0, us->ifnum, cmd, sizeof(cmd));
return (us->srb->result == GOOD << 1 ? SUCCESS : FAILED);
} }
/* This issues a Bulk-only Reset to the device in question, including /* This issues a Bulk-only Reset to the device in question, including
...@@ -1476,8 +1430,7 @@ int usb_stor_Bulk_reset(struct us_data *us) ...@@ -1476,8 +1430,7 @@ int usb_stor_Bulk_reset(struct us_data *us)
{ {
US_DEBUGP("Bulk reset requested\n"); US_DEBUGP("Bulk reset requested\n");
usb_stor_reset_common(us, US_BULK_RESET_REQUEST, return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, NULL, 0); 0, us->ifnum, NULL, 0);
return (us->srb->result == GOOD << 1 ? SUCCESS : FAILED);
} }
...@@ -361,65 +361,42 @@ static int usb_stor_control_thread(void * __us) ...@@ -361,65 +361,42 @@ static int usb_stor_control_thread(void * __us)
BUG_ON(action != US_ACT_COMMAND); BUG_ON(action != US_ACT_COMMAND);
/* lock the device pointers */
down(&(us->dev_semaphore));
/* reject the command if the direction indicator /* reject the command if the direction indicator
* is UNKNOWN * is UNKNOWN
*/ */
if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
US_DEBUGP("UNKNOWN data direction\n"); US_DEBUGP("UNKNOWN data direction\n");
us->srb->result = DID_ERROR << 16; us->srb->result = DID_ERROR << 16;
scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
scsi_unlock(host);
continue;
} }
/* reject if target != 0 or if LUN is higher than /* reject if target != 0 or if LUN is higher than
* the maximum known LUN * the maximum known LUN
*/ */
if (us->srb->target && else if (us->srb->target &&
!(us->flags & US_FL_SCM_MULT_TARG)) { !(us->flags & US_FL_SCM_MULT_TARG)) {
US_DEBUGP("Bad target number (%d/%d)\n", US_DEBUGP("Bad target number (%d/%d)\n",
us->srb->target, us->srb->lun); us->srb->target, us->srb->lun);
us->srb->result = DID_BAD_TARGET << 16; us->srb->result = DID_BAD_TARGET << 16;
scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
scsi_unlock(host);
continue;
} }
if (us->srb->lun > us->max_lun) { else if (us->srb->lun > us->max_lun) {
US_DEBUGP("Bad LUN (%d/%d)\n", US_DEBUGP("Bad LUN (%d/%d)\n",
us->srb->target, us->srb->lun); us->srb->target, us->srb->lun);
us->srb->result = DID_BAD_TARGET << 16; us->srb->result = DID_BAD_TARGET << 16;
scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
scsi_unlock(host);
continue;
} }
/* handle those devices which can't do a START_STOP */ /* handle those devices which can't do a START_STOP */
if ((us->srb->cmnd[0] == START_STOP) && else if ((us->srb->cmnd[0] == START_STOP) &&
(us->flags & US_FL_START_STOP)) { (us->flags & US_FL_START_STOP)) {
US_DEBUGP("Skipping START_STOP command\n"); US_DEBUGP("Skipping START_STOP command\n");
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
scsi_lock(host);
us->srb->scsi_done(us->srb);
us->srb = NULL;
scsi_unlock(host);
continue;
} }
/* lock the device pointers */
down(&(us->dev_semaphore));
/* our device has gone - pretend not ready */ /* our device has gone - pretend not ready */
if (!test_bit(DEV_ATTACHED, &us->bitflags)) { else if (!test_bit(DEV_ATTACHED, &us->bitflags)) {
US_DEBUGP("Request is for removed device\n"); US_DEBUGP("Request is for removed device\n");
/* For REQUEST_SENSE, it's the data. But /* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like * for anything else, it should look like
...@@ -443,24 +420,25 @@ static int usb_stor_control_thread(void * __us) ...@@ -443,24 +420,25 @@ static int usb_stor_control_thread(void * __us)
sizeof(usb_stor_sense_notready)); sizeof(usb_stor_sense_notready));
us->srb->result = CHECK_CONDITION << 1; us->srb->result = CHECK_CONDITION << 1;
} }
} else { /* test_bit(DEV_ATTACHED, &us->bitflags) */ } /* test_bit(DEV_ATTACHED, &us->bitflags) */
/* Handle those devices which need us to fake /* Handle those devices which need us to fake
* their inquiry data */ * their inquiry data */
if ((us->srb->cmnd[0] == INQUIRY) && else if ((us->srb->cmnd[0] == INQUIRY) &&
(us->flags & US_FL_FIX_INQUIRY)) { (us->flags & US_FL_FIX_INQUIRY)) {
unsigned char data_ptr[36] = { unsigned char data_ptr[36] = {
0x00, 0x80, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00}; 0x1F, 0x00, 0x00, 0x00};
US_DEBUGP("Faking INQUIRY command\n"); US_DEBUGP("Faking INQUIRY command\n");
fill_inquiry_response(us, data_ptr, 36); fill_inquiry_response(us, data_ptr, 36);
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
} else { }
/* we've got a command, let's do it! */
US_DEBUG(usb_stor_show_command(us->srb)); /* we've got a command, let's do it! */
us->proto_handler(us->srb, us); else {
} US_DEBUG(usb_stor_show_command(us->srb));
us->proto_handler(us->srb, us);
} }
/* unlock the device pointers */ /* unlock the device pointers */
...@@ -487,54 +465,114 @@ static int usb_stor_control_thread(void * __us) ...@@ -487,54 +465,114 @@ static int usb_stor_control_thread(void * __us)
return 0; return 0;
} }
/* Set up the IRQ pipe and handler /* Set up the URB, the usb_ctrlrequest, and the IRQ pipe and handler.
* ss->dev_semaphore should already be locked.
* Note that this function assumes that all the data in the us_data * Note that this function assumes that all the data in the us_data
* strucuture is current. This includes the ep_int field, which gives us * strucuture is current. This includes the ep_int field, which gives us
* the endpoint for the interrupt. * the endpoint for the interrupt.
* Returns non-zero on failure, zero on success * Returns non-zero on failure, zero on success
*/ */
static int usb_stor_allocate_irq(struct us_data *ss) static int usb_stor_allocate_urbs(struct us_data *ss)
{ {
unsigned int pipe; unsigned int pipe;
int maxp; int maxp;
int result; int result;
US_DEBUGP("Allocating IRQ for CBI transport\n"); /* allocate the URB we're going to use */
US_DEBUGP("Allocating URB\n");
/* lock access to the data structure */ ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
down(&(ss->irq_urb_sem)); if (!ss->current_urb) {
US_DEBUGP("allocation failed\n");
/* allocate the URB */
ss->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->irq_urb) {
up(&(ss->irq_urb_sem));
US_DEBUGP("couldn't allocate interrupt URB");
return 1; return 1;
} }
/* calculate the pipe and max packet size */ /* allocate the usb_ctrlrequest for control packets */
pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & US_DEBUGP("Allocating usb_ctrlrequest\n");
USB_ENDPOINT_NUMBER_MASK); ss->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); if (!ss->dr) {
if (maxp > sizeof(ss->irqbuf)) US_DEBUGP("allocation failed\n");
maxp = sizeof(ss->irqbuf);
/* fill in the URB with our data */
FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp,
usb_stor_CBI_irq, ss, ss->ep_int->bInterval);
/* submit the URB for processing */
result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
if (result) {
usb_free_urb(ss->irq_urb);
up(&(ss->irq_urb_sem));
return 2; return 2;
} }
/* unlock the data structure and return success */ /* allocate the IRQ URB, if it is needed */
if (ss->protocol == US_PR_CBI) {
US_DEBUGP("Allocating IRQ for CBI transport\n");
/* lock access to the data structure */
down(&(ss->irq_urb_sem));
/* allocate the URB */
ss->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->irq_urb) {
up(&(ss->irq_urb_sem));
US_DEBUGP("couldn't allocate interrupt URB");
return 3;
}
/* calculate the pipe and max packet size */
pipe = usb_rcvintpipe(ss->pusb_dev,
ss->ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
if (maxp > sizeof(ss->irqbuf))
maxp = sizeof(ss->irqbuf);
/* fill in the URB with our data */
FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf,
maxp, usb_stor_CBI_irq, ss, ss->ep_int->bInterval);
/* submit the URB for processing */
result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
if (result) {
up(&(ss->irq_urb_sem));
return 4;
}
/* unlock the data structure */
up(&(ss->irq_urb_sem));
} /* ss->protocol == US_PR_CBI */
return 0; /* success */
}
/* Deallocate the URB, the usb_ctrlrequest, and the IRQ pipe.
* ss->dev_semaphore must already be locked.
*/
static void usb_stor_deallocate_urbs(struct us_data *ss)
{
int result;
/* release the IRQ, if we have one */
down(&(ss->irq_urb_sem));
if (ss->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(ss->irq_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
usb_free_urb(ss->irq_urb);
ss->irq_urb = NULL;
}
up(&(ss->irq_urb_sem)); up(&(ss->irq_urb_sem));
return 0;
/* free the usb_ctrlrequest buffer */
if (ss->dr) {
kfree(ss->dr);
ss->dr = NULL;
}
/* free up the main URB for this device */
if (ss->current_urb) {
US_DEBUGP("-- releasing main URB\n");
result = usb_unlink_urb(ss->current_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
usb_free_urb(ss->current_urb);
ss->current_urb = NULL;
}
/* mark the device as gone */
clear_bit(DEV_ATTACHED, &ss->bitflags);
usb_put_dev(ss->pusb_dev);
ss->pusb_dev = NULL;
} }
/* Probe to see if a new device is actually a SCSI device */ /* Probe to see if a new device is actually a SCSI device */
...@@ -712,13 +750,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -712,13 +750,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
USB_ENDPOINT_NUMBER_MASK; USB_ENDPOINT_NUMBER_MASK;
ss->ep_int = ep_int; ss->ep_int = ep_int;
/* allocate an IRQ callback if one is needed */ /* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) if (usb_stor_allocate_urbs(ss))
goto BadDevice;
/* allocate the URB we're going to use */
ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->current_urb)
goto BadDevice; goto BadDevice;
/* Re-Initialize the device if it needs it */ /* Re-Initialize the device if it needs it */
...@@ -741,11 +774,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -741,11 +774,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
memset(ss, 0, sizeof(struct us_data)); memset(ss, 0, sizeof(struct us_data));
new_device = 1; new_device = 1;
/* allocate the URB we're going to use */
ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->current_urb)
goto BadDevice;
/* Initialize the mutexes only when the struct is new */ /* Initialize the mutexes only when the struct is new */
init_completion(&(ss->notify)); init_completion(&(ss->notify));
init_MUTEX_LOCKED(&(ss->ip_waitq)); init_MUTEX_LOCKED(&(ss->ip_waitq));
...@@ -943,8 +971,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -943,8 +971,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
} }
US_DEBUGP("Protocol: %s\n", ss->protocol_name); US_DEBUGP("Protocol: %s\n", ss->protocol_name);
/* allocate an IRQ callback if one is needed */ /* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) if (usb_stor_allocate_urbs(ss))
goto BadDevice; goto BadDevice;
/* /*
...@@ -1020,26 +1048,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1020,26 +1048,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* we come here if there are any problems */ /* we come here if there are any problems */
BadDevice: BadDevice:
US_DEBUGP("storage_probe() failed\n"); US_DEBUGP("storage_probe() failed\n");
down(&ss->irq_urb_sem); usb_stor_deallocate_urbs(ss);
if (ss->irq_urb) {
usb_unlink_urb(ss->irq_urb);
usb_free_urb(ss->irq_urb);
ss->irq_urb = NULL;
}
up(&ss->irq_urb_sem);
if (ss->current_urb) {
usb_unlink_urb(ss->current_urb);
usb_free_urb(ss->current_urb);
ss->current_urb = NULL;
}
clear_bit(DEV_ATTACHED, &ss->bitflags);
ss->pusb_dev = NULL;
if (new_device) if (new_device)
kfree(ss); kfree(ss);
else else
up(&ss->dev_semaphore); up(&ss->dev_semaphore);
usb_put_dev(dev);
return NULL; return NULL;
} }
...@@ -1047,7 +1060,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1047,7 +1060,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
static void storage_disconnect(struct usb_device *dev, void *ptr) static void storage_disconnect(struct usb_device *dev, void *ptr)
{ {
struct us_data *ss = ptr; struct us_data *ss = ptr;
int result;
US_DEBUGP("storage_disconnect() called\n"); US_DEBUGP("storage_disconnect() called\n");
...@@ -1057,33 +1069,8 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) ...@@ -1057,33 +1069,8 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
return; return;
} }
/* lock access to the device data structure */
down(&(ss->dev_semaphore)); down(&(ss->dev_semaphore));
usb_stor_deallocate_urbs(ss);
/* release the IRQ, if we have one */
down(&(ss->irq_urb_sem));
if (ss->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(ss->irq_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
usb_free_urb(ss->irq_urb);
ss->irq_urb = NULL;
}
up(&(ss->irq_urb_sem));
/* free up the main URB for this device */
US_DEBUGP("-- releasing main URB\n");
result = usb_unlink_urb(ss->current_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
usb_free_urb(ss->current_urb);
ss->current_urb = NULL;
/* mark the device as gone */
usb_put_dev(ss->pusb_dev);
ss->pusb_dev = NULL;
clear_bit(DEV_ATTACHED, &ss->bitflags);
/* unlock access to the device data structure */
up(&(ss->dev_semaphore)); up(&(ss->dev_semaphore));
} }
......
...@@ -185,6 +185,7 @@ struct us_data { ...@@ -185,6 +185,7 @@ struct us_data {
/* control and bulk communications data */ /* control and bulk communications data */
struct semaphore current_urb_sem; /* to protect irq_urb */ struct semaphore current_urb_sem; /* to protect irq_urb */
struct urb *current_urb; /* non-int USB requests */ struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */
/* the semaphore for sleeping the control thread */ /* the semaphore for sleeping the control thread */
struct semaphore sema; /* to sleep thread on */ struct semaphore sema; /* to sleep thread on */
......
...@@ -189,9 +189,6 @@ static struct usb_driver skel_driver = { ...@@ -189,9 +189,6 @@ static struct usb_driver skel_driver = {
name: "skeleton", name: "skeleton",
probe: skel_probe, probe: skel_probe,
disconnect: skel_disconnect, disconnect: skel_disconnect,
fops: &skel_fops,
minor: USB_SKEL_MINOR_BASE,
num_minors: MAX_DEVICES,
id_table: skel_table, id_table: skel_table,
}; };
...@@ -532,29 +529,18 @@ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const stru ...@@ -532,29 +529,18 @@ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const stru
} }
down (&minor_table_mutex); down (&minor_table_mutex);
retval = usb_register_dev (&skel_driver, 1, &minor); retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor);
if (retval) { if (retval) {
if (retval != -ENODEV) { /* something prevented us from registering this driver */
/* something prevented us from registering this driver */ err ("Not able to get a minor for this device.");
err ("Not able to get a minor for this device."); goto exit;
goto exit;
}
/* we could not get a dynamic minor, so lets find one of our own */
for (minor = 0; minor < MAX_DEVICES; ++minor) {
if (minor_table[minor] == NULL)
break;
}
if (minor >= MAX_DEVICES) {
err ("Too many devices plugged in, can not handle this device.");
goto exit;
}
} }
/* allocate memory for our device state and intialize it */ /* allocate memory for our device state and intialize it */
dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL); dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
if (dev == NULL) { if (dev == NULL) {
err ("Out of memory"); err ("Out of memory");
goto exit; goto exit_minor;
} }
memset (dev, 0x00, sizeof (*dev)); memset (dev, 0x00, sizeof (*dev));
minor_table[minor] = dev; minor_table[minor] = dev;
...@@ -628,6 +614,9 @@ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const stru ...@@ -628,6 +614,9 @@ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const stru
skel_delete (dev); skel_delete (dev);
dev = NULL; dev = NULL;
exit_minor:
usb_deregister_dev (1, minor);
exit: exit:
up (&minor_table_mutex); up (&minor_table_mutex);
return dev; return dev;
...@@ -655,7 +644,7 @@ static void skel_disconnect(struct usb_device *udev, void *ptr) ...@@ -655,7 +644,7 @@ static void skel_disconnect(struct usb_device *udev, void *ptr)
devfs_unregister (dev->devfs); devfs_unregister (dev->devfs);
/* give back our dynamic minor */ /* give back our dynamic minor */
usb_deregister_dev (&skel_driver, 1, minor); usb_deregister_dev (1, minor);
/* if the device is not opened, then we clean up right now */ /* if the device is not opened, then we clean up right now */
if (!dev->open_count) { if (!dev->open_count) {
......
...@@ -954,7 +954,7 @@ static int notesize(struct memelfnote *en) ...@@ -954,7 +954,7 @@ static int notesize(struct memelfnote *en)
int sz; int sz;
sz = sizeof(struct elf_note); sz = sizeof(struct elf_note);
sz += roundup(strlen(en->name), 4); sz += roundup(strlen(en->name) + 1, 4);
sz += roundup(en->datasz, 4); sz += roundup(en->datasz, 4);
return sz; return sz;
...@@ -989,7 +989,7 @@ static int writenote(struct memelfnote *men, struct file *file) ...@@ -989,7 +989,7 @@ static int writenote(struct memelfnote *men, struct file *file)
{ {
struct elf_note en; struct elf_note en;
en.n_namesz = strlen(men->name); en.n_namesz = strlen(men->name) + 1;
en.n_descsz = men->datasz; en.n_descsz = men->datasz;
en.n_type = men->type; en.n_type = men->type;
......
...@@ -25,6 +25,13 @@ void wait_buffer_until_released (const struct buffer_head * bh) ...@@ -25,6 +25,13 @@ void wait_buffer_until_released (const struct buffer_head * bh)
{ {
int repeat_counter = 0; int repeat_counter = 0;
/*
* FIXME! Temporary cludge until ReiserFS people tell what they
* actually are trying to protect against!
*/
if (1)
return;
while (atomic_read (&(bh->b_count)) > 1) { while (atomic_read (&(bh->b_count)) > 1) {
if ( !(++repeat_counter % 30000000) ) { if ( !(++repeat_counter % 30000000) ) {
......
...@@ -104,6 +104,7 @@ ...@@ -104,6 +104,7 @@
#include <linux/interrupt.h> /* for in_interrupt() */ #include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/list.h> /* for struct list_head */ #include <linux/list.h> /* for struct list_head */
#include <linux/device.h> /* for struct device */ #include <linux/device.h> /* for struct device */
#include <linux/fs.h> /* for struct file_operations */
static __inline__ void wait_ms(unsigned int ms) static __inline__ void wait_ms(unsigned int ms)
...@@ -648,14 +649,6 @@ struct usb_device_id { ...@@ -648,14 +649,6 @@ struct usb_device_id {
* because its device has been (or is being) disconnected. The * because its device has been (or is being) disconnected. The
* handle passed is what was returned by probe(), or was provided * handle passed is what was returned by probe(), or was provided
* to usb_driver_claim_interface(). * to usb_driver_claim_interface().
* @fops: USB drivers can reuse some character device framework in
* the USB subsystem by providing a file operations vector and
* a minor number.
* @minor: Used with fops to simplify creating USB character devices.
* Such drivers have sixteen character devices, using the USB
* major number and starting with this minor number.
* @num_minors: Used with minor to specify how many minors are used by
* this driver.
* @ioctl: Used for drivers that want to talk to userspace through * @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to * the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they * expose information to user space regardless of where they
...@@ -694,11 +687,6 @@ struct usb_driver { ...@@ -694,11 +687,6 @@ struct usb_driver {
); );
struct list_head driver_list; struct list_head driver_list;
struct file_operations *fops;
int minor;
int num_minors;
struct semaphore serialize; struct semaphore serialize;
/* ioctl -- userspace apps can talk to drivers through usbfs */ /* ioctl -- userspace apps can talk to drivers through usbfs */
...@@ -722,13 +710,8 @@ extern struct bus_type usb_bus_type; ...@@ -722,13 +710,8 @@ extern struct bus_type usb_bus_type;
extern int usb_register(struct usb_driver *); extern int usb_register(struct usb_driver *);
extern void usb_deregister(struct usb_driver *); extern void usb_deregister(struct usb_driver *);
#ifndef CONFIG_USB_DYNAMIC_MINORS extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor);
static inline int usb_register_dev(struct usb_driver *new_driver, int num_minors, int *start_minor) { return -ENODEV; } extern void usb_deregister_dev(int num_minors, int start_minor);
static inline void usb_deregister_dev(struct usb_driver *driver, int num_minors, int start_minor) {}
#else
extern int usb_register_dev(struct usb_driver *new_driver, int num_minors, int *start_minor);
extern void usb_deregister_dev(struct usb_driver *driver, int num_minors, int start_minor);
#endif
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment