[PATCH experimental 4/6] usb: cdc-wdm: adding interface => wdm_device list lookup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Bjørn Mork <bjorn@xxxxxxx>
---
 drivers/usb/class/cdc-wdm.c |   71 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 684e89b..af93df9 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -77,6 +77,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 #define WDM_DEFAULT_BUFSIZE	256
 
 static DEFINE_MUTEX(wdm_mutex);
+static LIST_HEAD(wdm_device_list);
 
 /* --- method tables --- */
 
@@ -111,13 +112,45 @@ struct wdm_device {
 	struct work_struct	rxwork;
 	int			werr;
 	int			rerr;
+
+	struct list_head	device_list;
 };
 
 static struct usb_driver wdm_driver;
 
+/* return intfdata if we own the interface, else look up intf in the list */
 static struct wdm_device *wdm_get_device(struct usb_interface *intf)
 {
-	struct wdm_device *desc = usb_get_intfdata(intf);
+	struct wdm_device *desc = NULL;
+
+	pr_debug("%s: intf->dev.driver=%p, &wdm_driver=%p\n", __func__, to_usb_driver(intf->dev.driver), &wdm_driver);
+
+	mutex_lock(&wdm_mutex);
+	if (to_usb_driver(intf->dev.driver) == &wdm_driver)
+		desc = usb_get_intfdata(intf);
+	else
+		list_for_each_entry(desc, &wdm_device_list, device_list)
+			if (desc->intf == intf)
+				break;
+	mutex_unlock(&wdm_mutex);
+
+	return desc;
+}
+
+/* caller holds wdm_mutex */
+static struct wdm_device *wdm_get_device_by_minor(int minor)
+{
+	struct wdm_device *desc = NULL;
+
+	list_for_each_entry(desc, &wdm_device_list, device_list) {
+		pr_debug("%s: looking at %s (%p)\n", __func__, dev_name(&desc->intf->dev), desc->intf);
+		if (desc->intf->minor == minor)
+			break;
+	}
+
+	if (desc)
+		pr_debug("%s: returning desc->intf=%p for minor=%u\n", __func__, desc->intf, minor);
+
 	return desc;
 }
 
@@ -524,11 +557,11 @@ static int wdm_open(struct inode *inode, struct file *file)
 	struct wdm_device *desc;
 
 	mutex_lock(&wdm_mutex);
-	intf = usb_find_interface(&wdm_driver, minor);
-	if (!intf)
+	desc = wdm_get_device_by_minor(minor);
+	if (!desc)
 		goto out;
 
-	desc = wdm_get_device(intf);
+	intf = desc->intf;
 	if (test_bit(WDM_DISCONNECTING, &desc->flags))
 		goto out;
 	file->private_data = desc;
@@ -715,6 +748,10 @@ static struct wdm_device *wdm_create(struct usb_interface *intf, u16 bufsize)
 		desc
 	);
 
+	mutex_lock(&wdm_mutex);
+	list_add(&desc->device_list, &wdm_device_list);
+	mutex_unlock(&wdm_mutex);
+
 	return desc;
 
 err:
@@ -807,8 +844,10 @@ static void wdm_destroy(struct wdm_device *desc)
 	cancel_work_sync(&desc->rxwork);
 	mutex_unlock(&desc->wlock);
 	mutex_unlock(&desc->rlock);
-	if (!desc->count)
+	if (!desc->count) {
+		list_del(&desc->device_list);
 		cleanup(desc);
+	}
 	mutex_unlock(&wdm_mutex);
 
 }
@@ -816,7 +855,9 @@ static void wdm_destroy(struct wdm_device *desc)
 static void wdm_disconnect(struct usb_interface *intf)
 {
 	struct wdm_device *desc = wdm_get_device(intf);
-	wdm_destroy(desc);
+
+	if (desc)
+		wdm_destroy(desc);
 }
 
 #ifdef CONFIG_PM
@@ -825,6 +866,9 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
 	struct wdm_device *desc = wdm_get_device(intf);
 	int rv = 0;
 
+	if (!desc)
+		goto out;
+
 	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
 
 	/* if this is an autosuspend the caller does the locking */
@@ -852,6 +896,7 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
 		mutex_unlock(&desc->rlock);
 	}
 
+out:
 	return rv;
 }
 #endif
@@ -873,13 +918,17 @@ static int recover_from_urb_loss(struct wdm_device *desc)
 static int wdm_resume(struct usb_interface *intf)
 {
 	struct wdm_device *desc = wdm_get_device(intf);
-	int rv;
+	int rv = 0;
+
+	if (!desc)
+		goto out;
 
 	dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
 
 	clear_bit(WDM_SUSPENDING, &desc->flags);
 	rv = recover_from_urb_loss(desc);
 
+out:
 	return rv;
 }
 #endif
@@ -888,6 +937,9 @@ static int wdm_pre_reset(struct usb_interface *intf)
 {
 	struct wdm_device *desc = wdm_get_device(intf);
 
+	if (!desc)
+		goto out;
+
 	mutex_lock(&desc->rlock);
 	mutex_lock(&desc->wlock);
 	kill_urbs(desc);
@@ -902,6 +954,7 @@ static int wdm_pre_reset(struct usb_interface *intf)
 	desc->rerr = -EINTR;
 	spin_unlock_irq(&desc->iuspin);
 	wake_up_all(&desc->wait);
+out:
 	return 0;
 }
 
@@ -910,9 +963,13 @@ static int wdm_post_reset(struct usb_interface *intf)
 	struct wdm_device *desc = wdm_get_device(intf);
 	int rv;
 
+	if (!desc)
+		goto out;
+
 	rv = recover_from_urb_loss(desc);
 	mutex_unlock(&desc->wlock);
 	mutex_unlock(&desc->rlock);
+out:
 	return 0;
 }
 
-- 
1.7.8.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux