Commit d73cb0ca authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] USB: usb-skeleton: removed static array of devices.

This allowed a lock to be removed.
Also removed the MOD_* functions, and some remove logic was cleaned
up by Oliver Neukum.
parent 3dba28d8
/* /*
* USB Skeleton driver - 0.8 * USB Skeleton driver - 0.9
* *
* Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
* *
...@@ -17,10 +17,10 @@ ...@@ -17,10 +17,10 @@
* *
* TODO: * TODO:
* - fix urb->status race condition in write sequence * - fix urb->status race condition in write sequence
* - move minor_table to a dynamic list.
* *
* History: * History:
* *
* 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
* 2002_09_26 - 0.8 - changes due to USB core conversion to struct device * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
* driver. * driver.
* 2002_02_12 - 0.7 - zero out dev in probe function for devices that do * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
...@@ -83,18 +83,10 @@ MODULE_DEVICE_TABLE (usb, skel_table); ...@@ -83,18 +83,10 @@ MODULE_DEVICE_TABLE (usb, skel_table);
#ifdef CONFIG_USB_DYNAMIC_MINORS #ifdef CONFIG_USB_DYNAMIC_MINORS
/*
* if the user wants to use dynamic minor numbers, then we can have up to 256
* devices
*/
#define USB_SKEL_MINOR_BASE 0 #define USB_SKEL_MINOR_BASE 0
#define MAX_DEVICES 256
#else #else
/* Get a minor range for your devices from the usb maintainer */ /* Get a minor range for your devices from the usb maintainer */
#define USB_SKEL_MINOR_BASE 200 #define USB_SKEL_MINOR_BASE 200
/* we can have up to this number of device plugged in at once */
#define MAX_DEVICES 16
#endif #endif
/* Structure to hold all of our device specific stuff */ /* Structure to hold all of our device specific stuff */
...@@ -117,8 +109,8 @@ struct usb_skel { ...@@ -117,8 +109,8 @@ struct usb_skel {
struct urb * write_urb; /* the urb used to send data */ struct urb * write_urb; /* the urb used to send data */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
struct work_struct work; /* work queue entry for line discipline waking up */ struct work_struct work; /* work queue entry for line discipline waking up */
int open_count; /* number of times this port has been opened */ int open; /* if the port is open or not */
struct semaphore sem; /* locks this structure */ struct semaphore sem; /* locks this structure */
}; };
...@@ -139,13 +131,6 @@ static void skel_disconnect (struct usb_interface *intf); ...@@ -139,13 +131,6 @@ static void skel_disconnect (struct usb_interface *intf);
static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs); static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
/* array of pointers to our devices that are currently connected */
static struct usb_skel *minor_table[MAX_DEVICES];
/* lock to protect the minor_table structure */
static DECLARE_MUTEX (minor_table_mutex);
/* /*
* File operations needed when we register this driver. * File operations needed when we register this driver.
* This assumes that this driver NEEDS file operations, * This assumes that this driver NEEDS file operations,
...@@ -218,7 +203,6 @@ static inline void usb_skel_debug_data (const char *function, int size, const un ...@@ -218,7 +203,6 @@ static inline void usb_skel_debug_data (const char *function, int size, const un
*/ */
static inline void skel_delete (struct usb_skel *dev) static inline void skel_delete (struct usb_skel *dev)
{ {
minor_table[dev->minor] = NULL;
if (dev->bulk_in_buffer != NULL) if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer); kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL) if (dev->bulk_out_buffer != NULL)
...@@ -235,41 +219,31 @@ static inline void skel_delete (struct usb_skel *dev) ...@@ -235,41 +219,31 @@ static inline void skel_delete (struct usb_skel *dev)
static int skel_open (struct inode *inode, struct file *file) static int skel_open (struct inode *inode, struct file *file)
{ {
struct usb_skel *dev = NULL; struct usb_skel *dev = NULL;
struct usb_interface *interface;
int subminor; int subminor;
int retval = 0; int retval = 0;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
subminor = minor (inode->i_rdev) - USB_SKEL_MINOR_BASE; subminor = minor (inode->i_rdev);
if ((subminor < 0) ||
(subminor >= MAX_DEVICES)) {
return -ENODEV;
}
/* Increment our usage count for the module. interface = usb_find_interface (&skel_driver,
* This is redundant here, because "struct file_operations" mk_kdev(USB_MAJOR, subminor));
* has an "owner" field. This line is included here soley as if (!interface) {
* a reference for drivers using lesser structures... ;-) err ("%s - error, can't find device for minor %d",
*/ __FUNCTION__, subminor);
MOD_INC_USE_COUNT;
/* lock our minor table and get our local data for this minor */
down (&minor_table_mutex);
dev = minor_table[subminor];
if (dev == NULL) {
up (&minor_table_mutex);
MOD_DEC_USE_COUNT;
return -ENODEV; return -ENODEV;
} }
dev = dev_get_drvdata (&interface->dev);
if (!dev)
return -ENODEV;
/* lock this device */ /* lock this device */
down (&dev->sem); down (&dev->sem);
/* unlock the minor table */
up (&minor_table_mutex);
/* increment our usage count for the driver */ /* increment our usage count for the driver */
++dev->open_count; ++dev->open;
/* save our object in the file's private structure */ /* save our object in the file's private structure */
file->private_data = dev; file->private_data = dev;
...@@ -297,13 +271,10 @@ static int skel_release (struct inode *inode, struct file *file) ...@@ -297,13 +271,10 @@ static int skel_release (struct inode *inode, struct file *file)
dbg("%s - minor %d", __FUNCTION__, dev->minor); dbg("%s - minor %d", __FUNCTION__, dev->minor);
/* lock our minor table */
down (&minor_table_mutex);
/* lock our device */ /* lock our device */
down (&dev->sem); down (&dev->sem);
if (dev->open_count <= 0) { if (dev->open <= 0) {
dbg ("%s - device not opened", __FUNCTION__); dbg ("%s - device not opened", __FUNCTION__);
retval = -ENODEV; retval = -ENODEV;
goto exit_not_opened; goto exit_not_opened;
...@@ -313,25 +284,16 @@ static int skel_release (struct inode *inode, struct file *file) ...@@ -313,25 +284,16 @@ static int skel_release (struct inode *inode, struct file *file)
/* the device was unplugged before the file was released */ /* the device was unplugged before the file was released */
up (&dev->sem); up (&dev->sem);
skel_delete (dev); skel_delete (dev);
up (&minor_table_mutex);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
/* decrement our usage count for the device */ /* shutdown any bulk writes that might be going on */
--dev->open_count; usb_unlink_urb (dev->write_urb);
if (dev->open_count <= 0) {
/* shutdown any bulk writes that might be going on */
usb_unlink_urb (dev->write_urb);
dev->open_count = 0;
}
/* decrement our usage count for the module */ dev->open = 0;
MOD_DEC_USE_COUNT;
exit_not_opened: exit_not_opened:
up (&dev->sem); up (&dev->sem);
up (&minor_table_mutex);
return retval; return retval;
} }
...@@ -529,7 +491,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -529,7 +491,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
return -ENODEV; return -ENODEV;
} }
down (&minor_table_mutex);
retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor); retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor);
if (retval) { if (retval) {
/* something prevented us from registering this driver */ /* something prevented us from registering this driver */
...@@ -544,7 +505,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -544,7 +505,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
goto exit_minor; goto exit_minor;
} }
memset (dev, 0x00, sizeof (*dev)); memset (dev, 0x00, sizeof (*dev));
minor_table[minor] = dev;
init_MUTEX (&dev->sem); init_MUTEX (&dev->sem);
dev->udev = udev; dev->udev = udev;
...@@ -600,13 +560,17 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -600,13 +560,17 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
dev->devfs = devfs_register (usb_devfs_handle, name, dev->devfs = devfs_register (usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, DEVFS_FL_DEFAULT, USB_MAJOR,
USB_SKEL_MINOR_BASE + dev->minor, dev->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH, S_IRGRP | S_IWGRP | S_IROTH,
&skel_fops, NULL); &skel_fops, NULL);
/* let the user know what node this device is now attached to */ /* let the user know what node this device is now attached to */
info ("USB Skeleton device now attached to USBSkel%d", dev->minor); info ("USB Skeleton device now attached to USBSkel%d", dev->minor);
/* add device id so the device works when advertised */
interface->kdev = mk_kdev(USB_MAJOR, dev->minor);
goto exit; goto exit;
error: error:
...@@ -617,7 +581,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -617,7 +581,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
usb_deregister_dev (1, minor); usb_deregister_dev (1, minor);
exit: exit:
up (&minor_table_mutex);
if (dev) { if (dev) {
dev_set_drvdata (&interface->dev, dev); dev_set_drvdata (&interface->dev, dev);
return 0; return 0;
...@@ -642,9 +605,11 @@ static void skel_disconnect(struct usb_interface *interface) ...@@ -642,9 +605,11 @@ static void skel_disconnect(struct usb_interface *interface)
if (!dev) if (!dev)
return; return;
down (&minor_table_mutex);
down (&dev->sem); down (&dev->sem);
/* remove device id to disable open() */
interface->kdev = NODEV;
minor = dev->minor; minor = dev->minor;
/* remove our devfs node */ /* remove our devfs node */
...@@ -654,7 +619,7 @@ static void skel_disconnect(struct usb_interface *interface) ...@@ -654,7 +619,7 @@ static void skel_disconnect(struct usb_interface *interface)
usb_deregister_dev (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) {
up (&dev->sem); up (&dev->sem);
skel_delete (dev); skel_delete (dev);
} else { } else {
...@@ -663,7 +628,6 @@ static void skel_disconnect(struct usb_interface *interface) ...@@ -663,7 +628,6 @@ static void skel_disconnect(struct usb_interface *interface)
} }
info("USB Skeleton #%d now disconnected", minor); info("USB Skeleton #%d now disconnected", minor);
up (&minor_table_mutex);
} }
......
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