ChangeSet 1.872, 2002/12/12 12:39:31-08:00, [EMAIL PROTECTED]
[PATCH] USB: start to remove static minor based arrays in drivers
Here are minimal usb_find_interface() patches for the core, usblp and
scanner.
Basic design is:
- device major (USB_MAJOR for now) and minor are stored in probe()
function to struct usb_interface as kdev_t
- open() can use new core function usb_find_interface() to find matching
device in drivers device list
- disconnect() will set kdev_t struct usb_interface to NODEV, so open
wont open it anymore without new probe()
I tested these patches and they work for me. I will work on small patches
of other work in these drivers (like removal of lock_kernel/unlock_kernel
in usblp, fixing the disconnect problems in both drivers etc.). Those
patches would be very small too, but there will be quite many.
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/class/usblp.c Fri Dec 13 17:18:56 2002
@@ -188,8 +188,6 @@
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
-static struct usblp *usblp_table[USBLP_MINORS];
-
/* Quirks: various printer quirks are handled by this table & its flags. */
struct quirk_printer_struct {
@@ -325,17 +323,22 @@
static int usblp_open(struct inode *inode, struct file *file)
{
- int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
+ int minor = minor(inode->i_rdev);
struct usblp *usblp;
+ struct usb_interface *intf;
int retval;
if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV;
lock_kernel();
- usblp = usblp_table[minor];
retval = -ENODEV;
+ intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor));
+ if (!intf) {
+ goto out;
+ }
+ usblp = dev_get_drvdata (&intf->dev);
if (!usblp || !usblp->dev)
goto out;
@@ -382,7 +385,6 @@
static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
- usblp_table [usblp->minor] = NULL;
usb_deregister_dev (1, usblp->minor);
info("usblp%d: removed", usblp->minor);
@@ -905,14 +907,11 @@
usblp_check_status(usblp, 0);
#endif
- /* add a table entry so the device works when advertised */
- usblp_table[usblp->minor] = usblp;
-
/* If we have devfs, create with perms=660. */
sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
- USBLP_MINOR_BASE + usblp->minor,
+ usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
@@ -925,6 +924,10 @@
usblp->dev->descriptor.idProduct);
dev_set_drvdata (&intf->dev, usblp);
+
+ /* add device id so the device works when advertised */
+ intf->kdev = mk_kdev(USB_MAJOR,usblp->minor);
+
return 0;
abort_minor:
@@ -1108,6 +1111,9 @@
static void usblp_disconnect(struct usb_interface *intf)
{
struct usblp *usblp = dev_get_drvdata (&intf->dev);
+
+ /* remove device id to disable open() */
+ intf->kdev = NODEV;
if (!usblp || !usblp->dev) {
err("bogus disconnect");
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/core/usb.c Fri Dec 13 17:18:56 2002
@@ -470,6 +470,40 @@
return NULL;
}
+/**
+ * usb_find_interface - find usb_interface pointer for driver and device
+ * @drv: the driver whose current configuration is considered
+ * @kdev: the desired device
+ *
+ * This walks the driver device list and returns a pointer to the interface
+ * with the matching kdev_t.
+ */
+struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev)
+{
+ struct list_head *entry;
+ struct device *dev;
+ struct usb_interface *intf;
+
+ list_for_each(entry, &drv->driver.devices) {
+ dev = container_of(entry, struct device, driver_list);
+
+ /* can't look at usb devices, only interfaces */
+ if (dev->driver == &usb_generic_driver)
+ continue;
+
+ intf = to_usb_interface(dev);
+ if (!intf)
+ continue;
+
+ if (kdev_same(intf->kdev,kdev)) {
+ return intf;
+ }
+ }
+
+ /* no device found that matches */
+ return NULL;
+}
+
static int usb_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_interface *intf;
@@ -1445,6 +1479,7 @@
EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id);
+EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_new_device);
EXPORT_SYMBOL(usb_reset_device);
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/image/scanner.c Fri Dec 13 17:18:56 2002
@@ -398,6 +398,7 @@
{
struct scn_usb_data *scn;
struct usb_device *dev;
+ struct usb_interface *intf;
int scn_minor;
@@ -409,13 +410,13 @@
dbg("open_scanner: scn_minor:%d", scn_minor);
- if (!p_scn_table[scn_minor]) {
+ intf = usb_find_interface(&scanner_driver, mk_kdev(USB_MAJOR,scn_minor));
+ if (!intf) {
up(&scn_mutex);
err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
-
- scn = p_scn_table[scn_minor];
+ scn = dev_get_drvdata (&intf->dev);
dev = scn->scn_dev;
@@ -458,7 +459,7 @@
static int
close_scanner(struct inode * inode, struct file * file)
{
- struct scn_usb_data *scn;
+ struct scn_usb_data *scn = file->private_data;
int scn_minor;
@@ -466,15 +467,9 @@
dbg("close_scanner: scn_minor:%d", scn_minor);
- if (!p_scn_table[scn_minor]) {
- err("close_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
-
down(&scn_mutex);
-
- scn = p_scn_table[scn_minor];
down(&(scn->sem));
+
scn->isopen = 0;
file->private_data = NULL;
@@ -695,17 +690,12 @@
unsigned int cmd, unsigned long arg)
{
struct usb_device *dev;
-
+ struct scn_usb_data *scn = file->private_data;
int scn_minor;
scn_minor = USB_SCN_MINOR(inode);
- if (!p_scn_table[scn_minor]) {
- err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
-
- dev = p_scn_table[scn_minor]->scn_dev;
+ dev = scn->scn_dev;
switch (cmd)
{
@@ -987,13 +977,6 @@
return -ENOMEM;
}
-/* Check to make sure that the last slot isn't already taken */
- if (p_scn_table[scn_minor]) {
- err("probe_scanner: No more minor devices remaining.");
- up(&scn_mutex);
- return -ENOMEM;
- }
-
dbg("probe_scanner: Allocated minor:%d", scn_minor);
if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
@@ -1082,17 +1065,19 @@
scn->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
- SCN_BASE_MNR + scn->scn_minor,
+ scn->scn_minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops,
NULL);
if (scn->devfs == NULL)
dbg("scanner%d: device node registration failed", scn_minor);
- p_scn_table[scn_minor] = scn;
-
up(&scn_mutex);
dev_set_drvdata(&intf->dev, scn);
+
+ /* add device id so the device works when advertised */
+ intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor);
+
return 0;
}
@@ -1101,6 +1086,9 @@
{
struct scn_usb_data *scn = dev_get_drvdata(&intf->dev);
+ /* remove device id to disable open() */
+ intf->kdev = NODEV;
+
dev_set_drvdata(&intf->dev, NULL);
if (scn) {
down (&scn_mutex);
@@ -1119,7 +1107,6 @@
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
usb_deregister_dev(1, scn->scn_minor);
- p_scn_table[scn->scn_minor] = NULL;
usb_free_urb(scn->scn_irq);
up (&(scn->sem));
kfree (scn);
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- a/drivers/usb/image/scanner.h Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/image/scanner.h Fri Dec 13 17:18:56 2002
@@ -216,7 +216,7 @@
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress &
USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
-#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
+#define USB_SCN_MINOR(X) minor((X)->i_rdev)
#ifdef DEBUG
#define SCN_DEBUG(X) X
@@ -273,7 +273,5 @@
};
extern devfs_handle_t usb_devfs_handle;
-
-static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
static struct usb_driver scanner_driver;
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h Fri Dec 13 17:18:56 2002
+++ b/include/linux/usb.h Fri Dec 13 17:18:56 2002
@@ -117,6 +117,7 @@
unsigned max_altsetting; /* total memory allocated */
struct usb_driver *driver; /* driver */
+ kdev_t kdev; /* node this interface is bound to */
struct device dev; /* interface specific device info */
void *private_data;
};
@@ -270,6 +271,8 @@
struct usb_interface *iface);
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id);
+
+struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev);
/**
* usb_make_path - returns stable device path in the usb tree
-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel