[PATCH 1/3] usb: gadget: dummy_hcd: refactor dummy_start to be DRY

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

 



When dummy_hcd is created as a SuperSpeed controller (configurable via
a module parameter) dummy_start() is called twice, once to make the
SuperSpeed HCD and once to make the Highspeed HCD. When it is created
as a HighSpeed controller, then dummy_start() is only called once.

The way dummy_start() was written, the URB list and the timer are
initialized twice (in the superspeed case). Besides looking weird
it is also possible that this can be buggy, because the way it works
is that we initialize the timer and the list when starting the
SuperSpeed HCD, we return all the way back to the USB core (so
possibly the timer and list start to get used due to requests
by the hub) and then we initialize them again while starting
the HighSpeed HCD. It is not impossible for this to result at
least in lost/leaked URBs.

So, rework dummy_start() to only initialize dummy_hcd struct
fields once and delete dummy_start_ss() helper function
as it is no longer useful.

Signed-off-by: Pantelis Koukousoulas <pktoss@xxxxxxxxx>
---
 drivers/usb/gadget/dummy_hcd.c | 50 ++++++++++++++----------------------------
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8c06430..dbbee3e 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -2314,45 +2314,23 @@ static ssize_t urbs_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(urbs);
 
-static int dummy_start_ss(struct dummy_hcd *dum_hcd)
-{
-	init_timer(&dum_hcd->timer);
-	dum_hcd->timer.function = dummy_timer;
-	dum_hcd->timer.data = (unsigned long)dum_hcd;
-	dum_hcd->rh_state = DUMMY_RH_RUNNING;
-	dum_hcd->stream_en_ep = 0;
-	INIT_LIST_HEAD(&dum_hcd->urbp_list);
-	dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
-	dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
-	dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
-#ifdef CONFIG_USB_OTG
-	dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
-#endif
-	return 0;
-
-	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
-}
-
 static int dummy_start(struct usb_hcd *hcd)
 {
 	struct dummy_hcd	*dum_hcd = hcd_to_dummy_hcd(hcd);
 
 	/*
-	 * MASTER side init ... we emulate a root hub that'll only ever
-	 * talk to one device (the slave side).  Also appears in sysfs,
-	 * just like more familiar pci-based HCDs.
+	 * These are per-device, not per HCD, so they should only be
+	 * initialized once although in the superspeed case this
+	 * function will be called twice. Thus we use a conditional.
 	 */
-	if (!usb_hcd_is_primary_hcd(hcd))
-		return dummy_start_ss(dum_hcd);
-
-	spin_lock_init(&dum_hcd->dum->lock);
-	init_timer(&dum_hcd->timer);
-	dum_hcd->timer.function = dummy_timer;
-	dum_hcd->timer.data = (unsigned long)dum_hcd;
-	dum_hcd->rh_state = DUMMY_RH_RUNNING;
-
-	INIT_LIST_HEAD(&dum_hcd->urbp_list);
+	if (dum_hcd->rh_state != DUMMY_RH_RUNNING) {
+		spin_lock_init(&dum_hcd->dum->lock);
+		init_timer(&dum_hcd->timer);
+		dum_hcd->timer.function = dummy_timer;
+		dum_hcd->timer.data = (unsigned long)dum_hcd;
+		INIT_LIST_HEAD(&dum_hcd->urbp_list);
+		dum_hcd->rh_state = DUMMY_RH_RUNNING;
+	}
 
 	hcd->power_budget = POWER_BUDGET;
 	hcd->state = HC_STATE_RUNNING;
@@ -2362,6 +2340,12 @@ static int dummy_start(struct usb_hcd *hcd)
 	hcd->self.otg_port = 1;
 #endif
 
+	/* In dummy_hcd the SuperSpeed HCD is the secondary one */
+	if (!usb_hcd_is_primary_hcd(hcd)) {
+		dum_hcd->stream_en_ep = 0;
+		return 0;
+	}
+
 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
 	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
 }
-- 
1.9.1

--
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