* [PATCH 1/5 v8] usb: Adding SuperSpeed support to dummy_hcd
@ 2011-03-23 8:02 Tatyana Brokhman
[not found] ` <1300867372-20811-1-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
0 siblings, 1 reply; 10+ messages in thread
From: Tatyana Brokhman @ 2011-03-23 8:02 UTC (permalink / raw)
To: gregkh
Cc: linux-arm-msm, balbi, ablay, Tatyana Brokhman,
open list:USB GADGET/PERIPH..., open list
This patch adds SS support to the dummy hcd module. It may be used to test
SS device when no (SS) HW is available.
USB 3.0 hub includes 2 hubs - HS and SS ones.
This patch adds support for a SS hub in the dummy_hcd module. Thus, when
dummy_hcd enabled it will register 2 root hubs (SS and HS).
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 3214ca3..4f4db96 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -62,9 +62,12 @@
#define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */
static const char driver_name [] = "dummy_hcd";
+static const char ss_driver_name[] = "ss_dummy_hcd";
static const char driver_desc [] = "USB Host+Gadget Emulator";
+static const char ss_driver_desc[] = "SS USB Host+Gadget Emulator";
static const char gadget_name [] = "dummy_udc";
+static const char ss_gadget_name[] = "ss_dummy_udc";
MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_AUTHOR ("David Brownell");
@@ -220,6 +223,7 @@ static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
}
static struct dummy *the_controller;
+static struct dummy *the_ss_controller;
/*-------------------------------------------------------------------------*/
@@ -259,10 +263,94 @@ stop_activity (struct dummy *dum)
/* driver now does any non-usb quiescing necessary */
}
-/* caller must hold lock */
+/**
+ * set_ss_link_state() - Sets the current state of the SuperSpeed link
+ * @dum: pointer to the dummy_hcd structure to update the link
+ * state for
+ *
+ * This function updates the port_status according to the link
+ * state. The old status is saved befor updating.
+ * Note: this function should be called only for SuperSpeed
+ * master and the caller must hold the lock.
+ */
+static void
+set_ss_link_state(struct dummy *dum)
+{
+ dum->active = 0;
+ if ((dum->port_status & USB_SS_PORT_STAT_POWER) == 0)
+ dum->port_status = 0;
+
+ /* UDC suspend must cause a disconnect */
+ else if (!dum->pullup || dum->udc_suspended) {
+ dum->port_status &= ~(USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_ENABLE);
+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0)
+ dum->port_status |=
+ (USB_PORT_STAT_C_CONNECTION << 16);
+ } else {
+ /* device is connected and not suspended */
+ dum->port_status |= (USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_SPEED_5GBPS) ;
+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0)
+ dum->port_status |=
+ (USB_PORT_STAT_C_CONNECTION << 16);
+ if ((dum->port_status & USB_PORT_STAT_ENABLE) == 1 &&
+ (dum->port_status & USB_SS_PORT_LS_U0) == 1 &&
+ dum->rh_state != DUMMY_RH_SUSPENDED)
+ dum->active = 1;
+ }
+
+
+ if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active)
+ dum->resuming = 0;
+
+ /* if !connected or reset */
+ if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
+ (dum->port_status & USB_PORT_STAT_RESET) != 0) {
+ /*
+ * We're connected and not reseted (reset occured now),
+ * and driver attached - disconnect!
+ */
+ if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
+ (dum->old_status & USB_PORT_STAT_RESET) == 0 &&
+ dum->driver) {
+ stop_activity(dum);
+ spin_unlock(&dum->lock);
+ dum->driver->disconnect(&dum->gadget);
+ spin_lock(&dum->lock);
+ }
+ } else if (dum->active != dum->old_active) {
+ if (dum->old_active && dum->driver->suspend) {
+ spin_unlock(&dum->lock);
+ dum->driver->suspend(&dum->gadget);
+ spin_lock(&dum->lock);
+ } else if (!dum->old_active && dum->driver->resume) {
+ spin_unlock(&dum->lock);
+ dum->driver->resume(&dum->gadget);
+ spin_lock(&dum->lock);
+ }
+ }
+
+ dum->old_status = dum->port_status;
+ dum->old_active = dum->active;
+}
+
+/**
+ * set_link_state() - Sets the current state of the link
+ * @dum: pointer to the dummy_hcd structure to update the link
+ * state for
+ *
+ * This function updates the port_status according to the link
+ * state. The old status is saved befor updating.
+ * Note: caller must hold the lock.
+ */
static void
set_link_state (struct dummy *dum)
{
+ if (dum == the_ss_controller) {
+ set_ss_link_state(dum);
+ return;
+ }
dum->active = 0;
if ((dum->port_status & USB_PORT_STAT_POWER) == 0)
dum->port_status = 0;
@@ -343,7 +431,13 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
dum = ep_to_dummy (ep);
if (!dum->driver || !is_enabled (dum))
return -ESHUTDOWN;
- max = le16_to_cpu(desc->wMaxPacketSize) & 0x3ff;
+
+ /*
+ * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
+ * maximum packet size.
+ * For SS devices the wMaxPacketSize is limited by 1024.
+ */
+ max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff;
/* drivers must not request bad settings, since lower levels
* (hardware or its drivers) may not check. some endpoints
@@ -361,6 +455,10 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto done;
}
switch (dum->gadget.speed) {
+ case USB_SPEED_SUPER:
+ if (max == 1024)
+ break;
+ goto done;
case USB_SPEED_HIGH:
if (max == 512)
break;
@@ -379,6 +477,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto done;
/* real hardware might not handle all packet sizes */
switch (dum->gadget.speed) {
+ case USB_SPEED_SUPER:
case USB_SPEED_HIGH:
if (max <= 1024)
break;
@@ -399,6 +498,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto done;
/* real hardware might not handle all packet sizes */
switch (dum->gadget.speed) {
+ case USB_SPEED_SUPER:
case USB_SPEED_HIGH:
if (max <= 1024)
break;
@@ -751,9 +851,14 @@ int
usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
- struct dummy *dum = the_controller;
+ struct dummy *dum;
int retval, i;
+ if (driver->speed == USB_SPEED_SUPER)
+ dum = the_ss_controller;
+ else
+ dum = the_controller;
+
if (!dum)
return -EINVAL;
if (dum->driver)
@@ -787,7 +892,11 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver,
}
dum->gadget.ep0 = &dum->ep [0].ep;
- dum->ep [0].ep.maxpacket = 64;
+ dum->gadget.speed = driver->speed;
+ if (driver->speed == USB_SPEED_SUPER)
+ dum->ep[0].ep.maxpacket = 9;
+ else
+ dum->ep[0].ep.maxpacket = 64;
list_del_init (&dum->ep [0].ep.ep_list);
INIT_LIST_HEAD(&dum->fifo_req.queue);
@@ -817,12 +926,20 @@ EXPORT_SYMBOL(usb_gadget_probe_driver);
int
usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
- struct dummy *dum = the_controller;
+ struct dummy *dum ;
unsigned long flags;
+ if (!driver || !driver->unbind)
+ return -EINVAL;
+
+ if (driver->speed == USB_SPEED_SUPER)
+ dum = the_ss_controller;
+ else
+ dum = the_controller;
+
if (!dum)
return -ENODEV;
- if (!driver || driver != dum->driver || !driver->unbind)
+ if (driver != dum->driver)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
@@ -899,6 +1016,34 @@ static int dummy_udc_probe (struct platform_device *pdev)
return rc;
}
+static int dummy_ss_udc_probe(struct platform_device *pdev)
+{
+ struct dummy *dum = the_ss_controller;
+ int rc;
+
+ dum->gadget.name = gadget_name;
+ dum->gadget.ops = &dummy_ops;
+ dum->gadget.is_dualspeed = 1;
+
+ /* maybe claim OTG support, though we won't complete HNP */
+ dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
+
+ dev_set_name(&dum->gadget.dev, "ss_gadget");
+ dum->gadget.dev.parent = &pdev->dev;
+ dum->gadget.dev.release = dummy_gadget_release;
+ rc = device_register(&dum->gadget.dev);
+ if (rc < 0)
+ return rc;
+
+ usb_get_hcd(dummy_to_hcd(dum));
+
+ platform_set_drvdata(pdev, dum);
+ rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
+ if (rc < 0)
+ device_unregister(&dum->gadget.dev);
+ return rc;
+}
+
static int dummy_udc_remove (struct platform_device *pdev)
{
struct dummy *dum = platform_get_drvdata (pdev);
@@ -948,6 +1093,17 @@ static struct platform_driver dummy_udc_driver = {
},
};
+static struct platform_driver dummy_ss_udc_driver = {
+ .probe = dummy_ss_udc_probe,
+ .remove = dummy_udc_remove,
+ .suspend = dummy_udc_suspend,
+ .resume = dummy_udc_resume,
+ .driver = {
+ .name = (char *) ss_gadget_name,
+ .owner = THIS_MODULE,
+ },
+};
+
/*-------------------------------------------------------------------------*/
/* MASTER/HOST SIDE DRIVER
@@ -1161,6 +1317,21 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
tmp *= 8 /* applies to entire frame */;
limit += limit * tmp;
}
+ if (dum->gadget.speed == USB_SPEED_SUPER) {
+ switch (ep->desc->bmAttributes & 0x03) {
+ case USB_ENDPOINT_XFER_ISOC:
+ /* Sec. 4.4.8.2 USB3.0 Spec */
+ limit = 3 * 16 * 1024 * 8;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ /* Sec. 4.4.7.2 USB3.0 Spec */
+ limit = 3 * 1024 * 8;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ default:
+ break;
+ }
+ }
return limit;
}
@@ -1246,6 +1417,24 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,
case USB_DEVICE_A_ALT_HNP_SUPPORT:
dum->gadget.a_alt_hnp_support = 1;
break;
+ case USB_DEVICE_U1_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_U1_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
+ case USB_DEVICE_U2_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_U2_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
+ case USB_DEVICE_LTM_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_LTM_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
default:
ret_val = -EOPNOTSUPP;
}
@@ -1272,6 +1461,24 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,
case USB_DEVICE_REMOTE_WAKEUP:
w_value = USB_DEVICE_REMOTE_WAKEUP;
break;
+ case USB_DEVICE_U1_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_U1_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
+ case USB_DEVICE_U2_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_U2_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
+ case USB_DEVICE_LTM_ENABLE:
+ if (dum->gadget.speed == USB_SPEED_SUPER)
+ w_value = USB_DEV_STAT_LTM_ENABLED;
+ else
+ ret_val = -EOPNOTSUPP;
+ break;
default:
ret_val = -EOPNOTSUPP;
break;
@@ -1352,6 +1559,10 @@ static void dummy_timer (unsigned long _dum)
case USB_SPEED_HIGH:
total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
break;
+ case USB_SPEED_SUPER:
+ /* Bus speed is 500000 bytes/ms, so use a little less */
+ total = 490000;
+ break;
default:
dev_err (dummy_dev(dum), "bogus device speed\n");
return;
@@ -1597,7 +1808,184 @@ hub_descriptor (struct usb_hub_descriptor *desc)
desc->u.hs.DeviceRemovable[1] = 0xff;
}
-static int dummy_hub_control (
+static inline void
+ss_hub_descriptor(struct usb_hub_descriptor *desc)
+{
+ memset(desc, 0, sizeof *desc);
+ desc->bDescriptorType = 0x2a;
+ desc->bDescLength = 12;
+ desc->wHubCharacteristics = cpu_to_le16(0x0001);
+ desc->bNbrPorts = 1;
+ desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
+ desc->u.ss.DeviceRemovable = 0xffff;
+}
+
+/**
+ * dummy_ss_hub_control() - handles the control requests of the dummy (ss hub)
+ * master.
+ * @hcd: pointer to the hcd to handle
+ * @typeReq: type of the request
+ * @wValue: wValue of the request
+ * @wIndex: wIndex of the request
+ * @buf: buffer for reply in case of an IN request
+ * @wLength: wLength of the request
+ *
+ * Return int - 0 on success, error code otherwise
+ *
+ * This function handles the control requests of the dummy (ss
+ * hub) master. All control requests that are part of the
+ * enumeration are handled by the dummy_timer
+ * Note: this function is used only for the SS root hub
+ */
+static int dummy_ss_hub_control(
+ struct usb_hcd *hcd,
+ u16 typeReq,
+ u16 wValue,
+ u16 wIndex,
+ char *buf,
+ u16 wLength)
+{
+ struct dummy *dum;
+ int retval = 0;
+ unsigned long flags;
+
+ if (!HCD_HW_ACCESSIBLE(hcd))
+ return -ETIMEDOUT;
+
+ dum = hcd_to_dummy(hcd);
+ spin_lock_irqsave(&dum->lock, flags);
+ switch (typeReq) {
+ case ClearHubFeature:
+ break;
+ case ClearPortFeature:
+ switch (wValue) {
+ case USB_PORT_FEAT_POWER:
+ if (dum->port_status & USB_SS_PORT_STAT_POWER)
+ dev_dbg(dummy_dev(dum), "power-off\n");
+ /* FALLS THROUGH */
+ default:
+ dum->port_status &= ~(1 << wValue);
+ set_link_state(dum);
+ }
+ break;
+ case GetHubDescriptor:
+ ss_hub_descriptor((struct usb_hub_descriptor *) buf);
+ break;
+ case GetHubStatus:
+ /*
+ * We report that no change occured in the hub status
+ * (power and overcurent conditions)
+ */
+ *(__le32 *) buf = cpu_to_le32 (0);
+ break;
+ case GetPortStatus:
+ /* We have only one port */
+ if (wIndex != 1)
+ retval = -EPIPE;
+
+ /*
+ * whoever resets or resumes must GetPortStatus to
+ * complete it!!
+ */
+ /* TODO: add support for suspend/resume */
+ if ((dum->port_status & USB_PORT_STAT_RESET) != 0 &&
+ time_after_eq(jiffies, dum->re_timeout)) {
+ dum->port_status |= (USB_PORT_STAT_C_RESET << 16);
+ dum->port_status &= ~USB_PORT_STAT_RESET;
+ }
+ if (dum->pullup)
+ dum->port_status |= USB_PORT_STAT_ENABLE;
+
+ set_link_state(dum);
+
+ ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status);
+ ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);
+ break;
+ case SetHubFeature:
+ retval = -EPIPE;
+ break;
+ case SetPortFeature:
+ switch (wValue) {
+ case USB_PORT_FEAT_LINK_STATE:
+ /*
+ * Since this is dummy we don't have an actual link so
+ * there is nothing to do for the SET_LINK_STATE cmd
+ */
+ break;
+ case USB_PORT_FEAT_U1_TIMEOUT:
+ case USB_PORT_FEAT_U2_TIMEOUT:
+ /* TODO: add suspend/resume support! */
+ break;
+ case USB_PORT_FEAT_POWER:
+ dum->port_status |= USB_SS_PORT_STAT_POWER;
+ set_link_state(dum);
+ break;
+ case USB_PORT_FEAT_BH_PORT_RESET:
+ case USB_PORT_FEAT_RESET:
+ /* if it's already enabled, disable */
+ dum->port_status = 0;
+ dum->port_status = (USB_SS_PORT_STAT_POWER |
+ USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_RESET);
+ /*
+ * We want to reset device status. All but the
+ * Self powered feature
+ */
+ dum->devstatus &= 0x0000 |
+ (1 << USB_DEVICE_SELF_POWERED);
+ /*
+ * FIXME: what is the correct reset signaling interval?
+ * Is it still 50msec as for HS?
+ */
+ dum->re_timeout = jiffies + msecs_to_jiffies(50);
+ /* FALLS THROUGH */
+ default:
+ if ((dum->port_status &
+ USB_SS_PORT_STAT_POWER) != 0) {
+ dum->port_status |= (1 << wValue);
+ set_link_state(dum);
+ }
+ }
+ break;
+ case GetPortErrorCount:
+ /* We'll always return 0 since this is a dummy hub */
+ *(__le32 *) buf = cpu_to_le32 (0);
+ break;
+ case SetHubDepth:
+ break;
+ default:
+ dev_dbg(dummy_dev(dum),
+ "hub control req%04x v%04x i%04x l%d\n",
+ typeReq, wValue, wIndex, wLength);
+ /* "protocol stall" on error */
+ retval = -EPIPE;
+ }
+ spin_unlock_irqrestore(&dum->lock, flags);
+
+ if ((dum->port_status & PORT_C_MASK) != 0)
+ usb_hcd_poll_rh_status(hcd);
+ return retval;
+}
+
+
+/**
+ * dummy_hub_control() - handles the control requests of the dummy (hs hub)
+ * master.
+ * @hcd: pointer to the hcd to handle
+ * @typeReq: type of the request
+ * @wValue: wValue of the request
+ * @wIndex: wIndex of the request
+ * @buf: buffer for reply in case of an IN request
+ * @wLength: wLength of the request
+ *
+ * Return int - 0 on success, error code otherwise
+ *
+ * This function handles the control requests of the dummy (hs
+ * hub) master. All control requests that are part of the
+ * enumeration are handled by the dummy_timer
+ * Note: this function is used only for the HS root hub
+ */
+static int dummy_hub_control(
struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
@@ -1711,7 +2099,11 @@ static int dummy_hub_control (
dum->port_status &= ~(USB_PORT_STAT_ENABLE
| USB_PORT_STAT_LOW_SPEED
| USB_PORT_STAT_HIGH_SPEED);
- dum->devstatus = 0;
+ /*
+ * We want to reset device status. All but the
+ * Self powered feature
+ */
+ dum->devstatus &= (1 << USB_DEVICE_SELF_POWERED);
/* 50msec reset signaling */
dum->re_timeout = jiffies + msecs_to_jiffies(50);
/* FALLS THROUGH */
@@ -1788,6 +2180,9 @@ show_urb (char *buf, size_t size, struct urb *urb)
case USB_SPEED_LOW: s = "ls"; break;
case USB_SPEED_FULL: s = "fs"; break;
case USB_SPEED_HIGH: s = "hs"; break;
+ case USB_SPEED_SUPER:
+ s = "ss";
+ break;
default: s = "?"; break;
}; s; }),
ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",
@@ -1894,6 +2289,27 @@ static const struct hc_driver dummy_hcd = {
.bus_resume = dummy_bus_resume,
};
+static const struct hc_driver dummy_ss_hcd = {
+ .description = (char *) ss_driver_name,
+ .product_desc = "Dummy SS host controller",
+ .hcd_priv_size = sizeof(struct dummy),
+
+ .flags = HCD_USB3,
+
+ .start = dummy_start,
+ .stop = dummy_stop,
+
+ .urb_enqueue = dummy_urb_enqueue,
+ .urb_dequeue = dummy_urb_dequeue,
+
+ .get_frame_number = dummy_h_get_frame,
+
+ .hub_status_data = dummy_hub_status,
+ .hub_control = dummy_ss_hub_control,
+ .bus_suspend = dummy_bus_suspend,
+ .bus_resume = dummy_bus_resume,
+};
+
static int dummy_hcd_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -1914,6 +2330,26 @@ static int dummy_hcd_probe(struct platform_device *pdev)
return retval;
}
+static int dummy_hcd_probe_ss(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+ int retval;
+
+ dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", ss_driver_desc);
+
+ hcd = usb_create_hcd(&dummy_ss_hcd, &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd)
+ return -ENOMEM;
+ the_ss_controller = hcd_to_dummy(hcd);
+
+ retval = usb_add_hcd(hcd, 0, 0);
+ if (retval != 0) {
+ usb_put_hcd(hcd);
+ the_ss_controller = NULL;
+ }
+ return retval;
+}
+
static int dummy_hcd_remove (struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -1925,6 +2361,17 @@ static int dummy_hcd_remove (struct platform_device *pdev)
return 0;
}
+static int dummy_ss_hcd_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+
+ hcd = platform_get_drvdata(pdev);
+ usb_remove_hcd(hcd);
+ usb_put_hcd(hcd);
+ the_ss_controller = NULL;
+ return 0;
+}
+
static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd;
@@ -1966,10 +2413,23 @@ static struct platform_driver dummy_hcd_driver = {
},
};
+static struct platform_driver dummy_ss_hcd_driver = {
+ .probe = dummy_hcd_probe_ss,
+ .remove = dummy_ss_hcd_remove,
+ .suspend = dummy_hcd_suspend,
+ .resume = dummy_hcd_resume,
+ .driver = {
+ .name = (char *) ss_driver_name,
+ .owner = THIS_MODULE,
+ },
+};
+
/*-------------------------------------------------------------------------*/
static struct platform_device *the_udc_pdev;
+static struct platform_device *the_ss_udc_pdev;
static struct platform_device *the_hcd_pdev;
+static struct platform_device *the_ss_hcd_pdev;
static int __init init (void)
{
@@ -1981,34 +2441,73 @@ static int __init init (void)
the_hcd_pdev = platform_device_alloc(driver_name, -1);
if (!the_hcd_pdev)
return retval;
+
+ the_ss_hcd_pdev = platform_device_alloc(ss_driver_name, -1);
+ if (!the_ss_hcd_pdev)
+ goto err_alloc_ss_hcd;
+
the_udc_pdev = platform_device_alloc(gadget_name, -1);
if (!the_udc_pdev)
goto err_alloc_udc;
+ the_ss_udc_pdev = platform_device_alloc(ss_gadget_name, -1);
+ if (!the_ss_udc_pdev)
+ goto err_alloc_ss_udc;
+
retval = platform_driver_register(&dummy_hcd_driver);
if (retval < 0)
goto err_register_hcd_driver;
+
+ retval = platform_driver_register(&dummy_ss_hcd_driver);
+ if (retval < 0)
+ goto err_register_ss_hcd_driver;
+
retval = platform_driver_register(&dummy_udc_driver);
if (retval < 0)
goto err_register_udc_driver;
+ retval = platform_driver_register(&dummy_ss_udc_driver);
+ if (retval < 0)
+ goto err_register_ss_udc_driver;
+
retval = platform_device_add(the_hcd_pdev);
if (retval < 0)
goto err_add_hcd;
+
+ retval = platform_device_add(the_ss_hcd_pdev);
+ if (retval < 0)
+ goto err_add_ss_hcd;
+
retval = platform_device_add(the_udc_pdev);
if (retval < 0)
goto err_add_udc;
+
+ retval = platform_device_add(the_ss_udc_pdev);
+ if (retval < 0)
+ goto err_add_ss_udc;
return retval;
+err_add_ss_udc:
+ platform_device_unregister(the_udc_pdev);
err_add_udc:
+ platform_device_del(the_ss_hcd_pdev);
+err_add_ss_hcd:
platform_device_del(the_hcd_pdev);
err_add_hcd:
+ platform_driver_unregister(&dummy_ss_udc_driver);
+err_register_ss_udc_driver:
platform_driver_unregister(&dummy_udc_driver);
err_register_udc_driver:
+ platform_driver_unregister(&dummy_ss_hcd_driver);
+err_register_ss_hcd_driver:
platform_driver_unregister(&dummy_hcd_driver);
err_register_hcd_driver:
+ platform_device_put(the_ss_udc_pdev);
+err_alloc_ss_udc:
platform_device_put(the_udc_pdev);
err_alloc_udc:
+ platform_device_put(the_ss_hcd_pdev);
+err_alloc_ss_hcd:
platform_device_put(the_hcd_pdev);
return retval;
}
@@ -2017,8 +2516,12 @@ module_init (init);
static void __exit cleanup (void)
{
platform_device_unregister(the_udc_pdev);
+ platform_device_unregister(the_ss_udc_pdev);
platform_device_unregister(the_hcd_pdev);
+ platform_device_unregister(the_ss_hcd_pdev);
platform_driver_unregister(&dummy_udc_driver);
+ platform_driver_unregister(&dummy_ss_udc_driver);
platform_driver_unregister(&dummy_hcd_driver);
+ platform_driver_unregister(&dummy_ss_hcd_driver);
}
module_exit (cleanup);
--
1.7.3.3
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 10+ messages in thread[parent not found: <1300867372-20811-1-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>]
* Re: [PATCH 1/5 v8] usb: Adding SuperSpeed support to dummy_hcd [not found] ` <1300867372-20811-1-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> @ 2011-03-25 13:47 ` Felipe Balbi 2011-03-27 12:19 ` Tanya Brokhman 0 siblings, 1 reply; 10+ messages in thread From: Felipe Balbi @ 2011-03-25 13:47 UTC (permalink / raw) To: Tatyana Brokhman Cc: gregkh-l3A5Bk7waGM, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0, ablay-sgV2jX0FEOL9JmXXK+q4OQ, open list:USB GADGET/PERIPH..., open list Hi, On Wed, Mar 23, 2011 at 10:02:51AM +0200, Tatyana Brokhman wrote: > This patch adds SS support to the dummy hcd module. It may be used to test > SS device when no (SS) HW is available. > USB 3.0 hub includes 2 hubs - HS and SS ones. > This patch adds support for a SS hub in the dummy_hcd module. Thus, when > dummy_hcd enabled it will register 2 root hubs (SS and HS). > > Signed-off-by: Tatyana Brokhman <tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> missing tear line. > diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c > index 3214ca3..4f4db96 100644 > --- a/drivers/usb/gadget/dummy_hcd.c > +++ b/drivers/usb/gadget/dummy_hcd.c > @@ -62,9 +62,12 @@ > #define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */ > > static const char driver_name [] = "dummy_hcd"; > +static const char ss_driver_name[] = "ss_dummy_hcd"; > static const char driver_desc [] = "USB Host+Gadget Emulator"; > +static const char ss_driver_desc[] = "SS USB Host+Gadget Emulator"; > > static const char gadget_name [] = "dummy_udc"; > +static const char ss_gadget_name[] = "ss_dummy_udc"; > > MODULE_DESCRIPTION (DRIVER_DESC); > MODULE_AUTHOR ("David Brownell"); > @@ -220,6 +223,7 @@ static inline struct dummy *gadget_dev_to_dummy (struct device *dev) > } > > static struct dummy *the_controller; > +static struct dummy *the_ss_controller; the only thing I don't like, is why you splitted the ss controller to a separate controller. Why don't you use the same ? From SW perspective, we can treat SS and HS/FS/LS controllers as one unit. -- balbi -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH 1/5 v8] usb: Adding SuperSpeed support to dummy_hcd 2011-03-25 13:47 ` Felipe Balbi @ 2011-03-27 12:19 ` Tanya Brokhman 2011-03-28 8:41 ` Felipe Balbi 0 siblings, 1 reply; 10+ messages in thread From: Tanya Brokhman @ 2011-03-27 12:19 UTC (permalink / raw) To: balbi Cc: gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' Hi > > > > MODULE_DESCRIPTION (DRIVER_DESC); > > MODULE_AUTHOR ("David Brownell"); > > @@ -220,6 +223,7 @@ static inline struct dummy *gadget_dev_to_dummy > (struct device *dev) > > } > > > > static struct dummy *the_controller; > > +static struct dummy *the_ss_controller; > > the only thing I don't like, is why you splitted the ss controller to a > separate controller. Why don't you use the same ? From SW perspective, > we can treat SS and HS/FS/LS controllers as one unit. > Actually I'm not sure about that... Because SS controller handles things a bit differently than HS/FS/LS. For example look at set_ss_link_state(), the port status is reported differently than for HS/FS/LS devices. It could be done, I mean spare the the_ss_controller variable and use the_controller, and we did that at first, but later on we decided to go back to this implementation since the code got too complex. Since dummy_hcd.c is used for debugging purposes we decided that simplicity is the better approach here. Best regards, Tanya Brokhman Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5 v8] usb: Adding SuperSpeed support to dummy_hcd 2011-03-27 12:19 ` Tanya Brokhman @ 2011-03-28 8:41 ` Felipe Balbi [not found] ` <20110328084157.GH2251-UiBtZHVXSwEVvW8u9ZQWYwjfymiNCTlR@public.gmane.org> 0 siblings, 1 reply; 10+ messages in thread From: Felipe Balbi @ 2011-03-28 8:41 UTC (permalink / raw) To: Tanya Brokhman Cc: balbi, gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' On Sun, Mar 27, 2011 at 02:19:25PM +0200, Tanya Brokhman wrote: > Hi > > > > > > > MODULE_DESCRIPTION (DRIVER_DESC); > > > MODULE_AUTHOR ("David Brownell"); > > > @@ -220,6 +223,7 @@ static inline struct dummy *gadget_dev_to_dummy > > (struct device *dev) > > > } > > > > > > static struct dummy *the_controller; > > > +static struct dummy *the_ss_controller; > > > > the only thing I don't like, is why you splitted the ss controller to a > > separate controller. Why don't you use the same ? From SW perspective, > > we can treat SS and HS/FS/LS controllers as one unit. > > > > Actually I'm not sure about that... Because SS controller handles things a > bit differently than HS/FS/LS. For example look at set_ss_link_state(), the > port status is reported differently than for HS/FS/LS devices. > It could be done, I mean spare the the_ss_controller variable and use > the_controller, and we did that at first, but later on we decided to go back > to this implementation since the code got too complex. Since dummy_hcd.c is > used for debugging purposes we decided that simplicity is the better > approach here. you can have two different functions and decide which one to call by checking gadget->speed. -- balbi ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <20110328084157.GH2251-UiBtZHVXSwEVvW8u9ZQWYwjfymiNCTlR@public.gmane.org>]
* [PATCH] usb: merge the two dummy_hcds into one [not found] ` <20110328084157.GH2251-UiBtZHVXSwEVvW8u9ZQWYwjfymiNCTlR@public.gmane.org> @ 2011-04-14 11:46 ` Sebastian Andrzej Siewior 2011-04-14 15:45 ` Alan Stern 0 siblings, 1 reply; 10+ messages in thread From: Sebastian Andrzej Siewior @ 2011-04-14 11:46 UTC (permalink / raw) To: Felipe Balbi Cc: Tanya Brokhman, gregkh-l3A5Bk7waGM, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, ablay-sgV2jX0FEOL9JmXXK+q4OQ, 'open list:USB GADGET/PERIPH...', 'open list' This patch merges the two HCDs so there is one for both. Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org> --- drivers/usb/gadget/dummy_hcd.c | 353 ++++++++++++---------------------------- 1 files changed, 102 insertions(+), 251 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 634c4ec..db44183 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -62,12 +62,9 @@ #define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */ static const char driver_name [] = "dummy_hcd"; -static const char ss_driver_name[] = "ss_dummy_hcd"; static const char driver_desc [] = "USB Host+Gadget Emulator"; -static const char ss_driver_desc[] = "SS USB Host+Gadget Emulator"; static const char gadget_name [] = "dummy_udc"; -static const char ss_gadget_name[] = "ss_dummy_udc"; MODULE_DESCRIPTION (DRIVER_DESC); MODULE_AUTHOR ("David Brownell"); @@ -223,7 +220,6 @@ static inline struct dummy *gadget_dev_to_dummy (struct device *dev) } static struct dummy *the_controller; -static struct dummy *the_ss_controller; /*-------------------------------------------------------------------------*/ @@ -263,8 +259,73 @@ stop_activity (struct dummy *dum) /* driver now does any non-usb quiescing necessary */ } + /** - * set_ss_link_state() - Sets the current state of the SuperSpeed link + * set_link_state_usb2() - Sets the current state of the link + * @dum: pointer to the dummy_hcd structure to update the link + * state for + * + * This function updates the port_status according to the link + * state. The old status is saved befor updating. + * Note: caller must hold the lock. + */ +static void set_link_state_usb2(struct dummy *dum) +{ + dum->active = 0; + if ((dum->port_status & USB_PORT_STAT_POWER) == 0) + dum->port_status = 0; + + /* UDC suspend must cause a disconnect */ + else if (!dum->pullup || dum->udc_suspended) { + dum->port_status &= ~(USB_PORT_STAT_CONNECTION | + USB_PORT_STAT_ENABLE | + USB_PORT_STAT_LOW_SPEED | + USB_PORT_STAT_HIGH_SPEED | + USB_PORT_STAT_SUSPEND); + if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0) + dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); + } else { + dum->port_status |= USB_PORT_STAT_CONNECTION; + if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0) + dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); + if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0) + dum->port_status &= ~USB_PORT_STAT_SUSPEND; + else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && + dum->rh_state != DUMMY_RH_SUSPENDED) + dum->active = 1; + } + + if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active) + dum->resuming = 0; + + if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 || + (dum->port_status & USB_PORT_STAT_RESET) != 0) { + if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 && + (dum->old_status & USB_PORT_STAT_RESET) == 0 && + dum->driver) { + stop_activity (dum); + spin_unlock (&dum->lock); + dum->driver->disconnect (&dum->gadget); + spin_lock (&dum->lock); + } + } else if (dum->active != dum->old_active) { + if (dum->old_active && dum->driver->suspend) { + spin_unlock (&dum->lock); + dum->driver->suspend (&dum->gadget); + spin_lock (&dum->lock); + } else if (!dum->old_active && dum->driver->resume) { + spin_unlock (&dum->lock); + dum->driver->resume (&dum->gadget); + spin_lock (&dum->lock); + } + } + + dum->old_status = dum->port_status; + dum->old_active = dum->active; +} + +/** + * set_link_state_usb3() - Sets the current state of the SuperSpeed link * @dum: pointer to the dummy_hcd structure to update the link * state for * @@ -273,8 +334,7 @@ stop_activity (struct dummy *dum) * Note: this function should be called only for SuperSpeed * master and the caller must hold the lock. */ -static void -set_ss_link_state(struct dummy *dum) +static void set_link_state_usb3(struct dummy *dum) { dum->active = 0; if ((dum->port_status & USB_SS_PORT_STAT_POWER) == 0) @@ -335,73 +395,14 @@ set_ss_link_state(struct dummy *dum) dum->old_active = dum->active; } -/** - * set_link_state() - Sets the current state of the link - * @dum: pointer to the dummy_hcd structure to update the link - * state for - * - * This function updates the port_status according to the link - * state. The old status is saved befor updating. - * Note: caller must hold the lock. - */ -static void -set_link_state (struct dummy *dum) +static void set_link_state(struct dummy *dum) { - if (dum == the_ss_controller) { - set_ss_link_state(dum); - return; - } - dum->active = 0; - if ((dum->port_status & USB_PORT_STAT_POWER) == 0) - dum->port_status = 0; - - /* UDC suspend must cause a disconnect */ - else if (!dum->pullup || dum->udc_suspended) { - dum->port_status &= ~(USB_PORT_STAT_CONNECTION | - USB_PORT_STAT_ENABLE | - USB_PORT_STAT_LOW_SPEED | - USB_PORT_STAT_HIGH_SPEED | - USB_PORT_STAT_SUSPEND); - if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0) - dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); - } else { - dum->port_status |= USB_PORT_STAT_CONNECTION; - if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0) - dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); - if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0) - dum->port_status &= ~USB_PORT_STAT_SUSPEND; - else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && - dum->rh_state != DUMMY_RH_SUSPENDED) - dum->active = 1; - } - - if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active) - dum->resuming = 0; - - if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 || - (dum->port_status & USB_PORT_STAT_RESET) != 0) { - if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 && - (dum->old_status & USB_PORT_STAT_RESET) == 0 && - dum->driver) { - stop_activity (dum); - spin_unlock (&dum->lock); - dum->driver->disconnect (&dum->gadget); - spin_lock (&dum->lock); - } - } else if (dum->active != dum->old_active) { - if (dum->old_active && dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); - } else if (!dum->old_active && dum->driver->resume) { - spin_unlock (&dum->lock); - dum->driver->resume (&dum->gadget); - spin_lock (&dum->lock); - } - } + struct usb_hcd *hcd = dummy_to_hcd(dum); - dum->old_status = dum->port_status; - dum->old_active = dum->active; + if (hcd->speed == HCD_USB3) + set_link_state_usb3(dum); + else + set_link_state_usb2(dum); } /*-------------------------------------------------------------------------*/ @@ -851,14 +852,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)) { - struct dummy *dum; + struct dummy *dum = the_controller; int retval, i; - if (driver->speed == USB_SPEED_SUPER) - dum = the_ss_controller; - else - dum = the_controller; - if (!dum) return -EINVAL; if (dum->driver) @@ -926,17 +922,12 @@ EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) { - struct dummy *dum ; + struct dummy *dum = the_controller; unsigned long flags; if (!driver || !driver->unbind) return -EINVAL; - if (driver->speed == USB_SPEED_SUPER) - dum = the_ss_controller; - else - dum = the_controller; - if (!dum) return -ENODEV; if (driver != dum->driver) @@ -1018,34 +1009,6 @@ static int dummy_udc_probe (struct platform_device *pdev) return rc; } -static int dummy_ss_udc_probe(struct platform_device *pdev) -{ - struct dummy *dum = the_ss_controller; - int rc; - - dum->gadget.name = gadget_name; - dum->gadget.ops = &dummy_ops; - dum->gadget.is_dualspeed = 1; - - /* maybe claim OTG support, though we won't complete HNP */ - dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); - - dev_set_name(&dum->gadget.dev, "ss_gadget"); - dum->gadget.dev.parent = &pdev->dev; - dum->gadget.dev.release = dummy_gadget_release; - rc = device_register(&dum->gadget.dev); - if (rc < 0) - return rc; - - usb_get_hcd(dummy_to_hcd(dum)); - - platform_set_drvdata(pdev, dum); - rc = device_create_file(&dum->gadget.dev, &dev_attr_function); - if (rc < 0) - device_unregister(&dum->gadget.dev); - return rc; -} - static int dummy_udc_remove (struct platform_device *pdev) { struct dummy *dum = platform_get_drvdata (pdev); @@ -1095,17 +1058,6 @@ static struct platform_driver dummy_udc_driver = { }, }; -static struct platform_driver dummy_ss_udc_driver = { - .probe = dummy_ss_udc_probe, - .remove = dummy_udc_remove, - .suspend = dummy_udc_suspend, - .resume = dummy_udc_resume, - .driver = { - .name = (char *) ss_gadget_name, - .owner = THIS_MODULE, - }, -}; - /*-------------------------------------------------------------------------*/ /* MASTER/HOST SIDE DRIVER @@ -1823,7 +1775,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) } /** - * dummy_ss_hub_control() - handles the control requests of the dummy (ss hub) + * dummy_hub_control_usb3() - handles the control requests of the dummy (ss hub) * master. * @hcd: pointer to the hcd to handle * @typeReq: type of the request @@ -1839,7 +1791,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) * enumeration are handled by the dummy_timer * Note: this function is used only for the SS root hub */ -static int dummy_ss_hub_control( +static int dummy_hub_control_usb3( struct usb_hcd *hcd, u16 typeReq, u16 wValue, @@ -1867,7 +1819,7 @@ static int dummy_ss_hub_control( /* FALLS THROUGH */ default: dum->port_status &= ~(1 << wValue); - set_link_state(dum); + set_link_state_usb3(dum); } break; case GetHubDescriptor: @@ -1898,7 +1850,7 @@ static int dummy_ss_hub_control( if (dum->pullup) dum->port_status |= USB_PORT_STAT_ENABLE; - set_link_state(dum); + set_link_state_usb3(dum); ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status); ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); @@ -1920,7 +1872,7 @@ static int dummy_ss_hub_control( break; case USB_PORT_FEAT_POWER: dum->port_status |= USB_SS_PORT_STAT_POWER; - set_link_state(dum); + set_link_state_usb3(dum); break; case USB_PORT_FEAT_BH_PORT_RESET: case USB_PORT_FEAT_RESET: @@ -1933,8 +1885,7 @@ static int dummy_ss_hub_control( * We want to reset device status. All but the * Self powered feature */ - dum->devstatus &= 0x0000 | - (1 << USB_DEVICE_SELF_POWERED); + dum->devstatus &= (1 << USB_DEVICE_SELF_POWERED); /* * FIXME: what is the correct reset signaling interval? * Is it still 50msec as for HS? @@ -1945,7 +1896,7 @@ static int dummy_ss_hub_control( if ((dum->port_status & USB_SS_PORT_STAT_POWER) != 0) { dum->port_status |= (1 << wValue); - set_link_state(dum); + set_link_state_usb3(dum); } } break; @@ -1969,9 +1920,8 @@ static int dummy_ss_hub_control( return retval; } - /** - * dummy_hub_control() - handles the control requests of the dummy (hs hub) + * dummy_hub_control_usb2() - handles the control requests of the dummy (hs hub) * master. * @hcd: pointer to the hcd to handle * @typeReq: type of the request @@ -1987,7 +1937,7 @@ static int dummy_ss_hub_control( * enumeration are handled by the dummy_timer * Note: this function is used only for the HS root hub */ -static int dummy_hub_control( +static int dummy_hub_control_usb2( struct usb_hcd *hcd, u16 typeReq, u16 wValue, @@ -2023,7 +1973,7 @@ static int dummy_hub_control( /* FALLS THROUGH */ default: dum->port_status &= ~(1 << wValue); - set_link_state (dum); + set_link_state_usb2(dum); } break; case GetHubDescriptor: @@ -2069,7 +2019,7 @@ static int dummy_hub_control( } } } - set_link_state (dum); + set_link_state_usb2(dum); ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status); ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); break; @@ -2085,7 +2035,7 @@ static int dummy_hub_control( /* HNP would happen here; for now we * assume b_bus_req is always true. */ - set_link_state (dum); + set_link_state_usb2(dum); if (((1 << USB_DEVICE_B_HNP_ENABLE) & dum->devstatus) != 0) dev_dbg (dummy_dev(dum), @@ -2094,7 +2044,7 @@ static int dummy_hub_control( break; case USB_PORT_FEAT_POWER: dum->port_status |= USB_PORT_STAT_POWER; - set_link_state (dum); + set_link_state_usb2(dum); break; case USB_PORT_FEAT_RESET: /* if it's already enabled, disable */ @@ -2112,7 +2062,7 @@ static int dummy_hub_control( default: if ((dum->port_status & USB_PORT_STAT_POWER) != 0) { dum->port_status |= (1 << wValue); - set_link_state (dum); + set_link_state_usb2(dum); } } break; @@ -2132,6 +2082,17 @@ static int dummy_hub_control( return retval; } +static int dummy_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength) +{ + if (hcd->speed == HCD_USB3) + return dummy_hub_control_usb3(hcd, typeReq, wValue, wIndex, buf, + wLength); + + return dummy_hub_control_usb2(hcd, typeReq, wValue, wIndex, buf, + wLength); +} + static int dummy_bus_suspend (struct usb_hcd *hcd) { struct dummy *dum = hcd_to_dummy (hcd); @@ -2182,9 +2143,7 @@ show_urb (char *buf, size_t size, struct urb *urb) case USB_SPEED_LOW: s = "ls"; break; case USB_SPEED_FULL: s = "fs"; break; case USB_SPEED_HIGH: s = "hs"; break; - case USB_SPEED_SUPER: - s = "ss"; - break; + case USB_SPEED_SUPER: s = "ss"; break; default: s = "?"; break; }; s; }), ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "", @@ -2275,7 +2234,7 @@ static const struct hc_driver dummy_hcd = { .product_desc = "Dummy host controller", .hcd_priv_size = sizeof(struct dummy), - .flags = HCD_USB2, + .flags = HCD_USB3, .start = dummy_start, .stop = dummy_stop, @@ -2291,27 +2250,6 @@ static const struct hc_driver dummy_hcd = { .bus_resume = dummy_bus_resume, }; -static const struct hc_driver dummy_ss_hcd = { - .description = (char *) ss_driver_name, - .product_desc = "Dummy SS host controller", - .hcd_priv_size = sizeof(struct dummy), - - .flags = HCD_USB3, - - .start = dummy_start, - .stop = dummy_stop, - - .urb_enqueue = dummy_urb_enqueue, - .urb_dequeue = dummy_urb_dequeue, - - .get_frame_number = dummy_h_get_frame, - - .hub_status_data = dummy_hub_status, - .hub_control = dummy_ss_hub_control, - .bus_suspend = dummy_bus_suspend, - .bus_resume = dummy_bus_resume, -}; - static int dummy_hcd_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -2332,26 +2270,6 @@ static int dummy_hcd_probe(struct platform_device *pdev) return retval; } -static int dummy_hcd_probe_ss(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - int retval; - - dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", ss_driver_desc); - - hcd = usb_create_hcd(&dummy_ss_hcd, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) - return -ENOMEM; - the_ss_controller = hcd_to_dummy(hcd); - - retval = usb_add_hcd(hcd, 0, 0); - if (retval != 0) { - usb_put_hcd(hcd); - the_ss_controller = NULL; - } - return retval; -} - static int dummy_hcd_remove (struct platform_device *pdev) { struct usb_hcd *hcd; @@ -2363,17 +2281,6 @@ static int dummy_hcd_remove (struct platform_device *pdev) return 0; } -static int dummy_ss_hcd_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - - hcd = platform_get_drvdata(pdev); - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - the_ss_controller = NULL; - return 0; -} - static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state) { struct usb_hcd *hcd; @@ -2415,23 +2322,10 @@ static struct platform_driver dummy_hcd_driver = { }, }; -static struct platform_driver dummy_ss_hcd_driver = { - .probe = dummy_hcd_probe_ss, - .remove = dummy_ss_hcd_remove, - .suspend = dummy_hcd_suspend, - .resume = dummy_hcd_resume, - .driver = { - .name = (char *) ss_driver_name, - .owner = THIS_MODULE, - }, -}; - /*-------------------------------------------------------------------------*/ static struct platform_device *the_udc_pdev; -static struct platform_device *the_ss_udc_pdev; static struct platform_device *the_hcd_pdev; -static struct platform_device *the_ss_hcd_pdev; static int __init init (void) { @@ -2443,73 +2337,34 @@ static int __init init (void) the_hcd_pdev = platform_device_alloc(driver_name, -1); if (!the_hcd_pdev) return retval; - - the_ss_hcd_pdev = platform_device_alloc(ss_driver_name, -1); - if (!the_ss_hcd_pdev) - goto err_alloc_ss_hcd; - the_udc_pdev = platform_device_alloc(gadget_name, -1); if (!the_udc_pdev) goto err_alloc_udc; - the_ss_udc_pdev = platform_device_alloc(ss_gadget_name, -1); - if (!the_ss_udc_pdev) - goto err_alloc_ss_udc; - retval = platform_driver_register(&dummy_hcd_driver); if (retval < 0) goto err_register_hcd_driver; - - retval = platform_driver_register(&dummy_ss_hcd_driver); - if (retval < 0) - goto err_register_ss_hcd_driver; - retval = platform_driver_register(&dummy_udc_driver); if (retval < 0) goto err_register_udc_driver; - retval = platform_driver_register(&dummy_ss_udc_driver); - if (retval < 0) - goto err_register_ss_udc_driver; - retval = platform_device_add(the_hcd_pdev); if (retval < 0) goto err_add_hcd; - - retval = platform_device_add(the_ss_hcd_pdev); - if (retval < 0) - goto err_add_ss_hcd; - retval = platform_device_add(the_udc_pdev); if (retval < 0) goto err_add_udc; - - retval = platform_device_add(the_ss_udc_pdev); - if (retval < 0) - goto err_add_ss_udc; return retval; -err_add_ss_udc: - platform_device_unregister(the_udc_pdev); err_add_udc: - platform_device_del(the_ss_hcd_pdev); -err_add_ss_hcd: platform_device_del(the_hcd_pdev); err_add_hcd: - platform_driver_unregister(&dummy_ss_udc_driver); -err_register_ss_udc_driver: platform_driver_unregister(&dummy_udc_driver); err_register_udc_driver: - platform_driver_unregister(&dummy_ss_hcd_driver); -err_register_ss_hcd_driver: platform_driver_unregister(&dummy_hcd_driver); err_register_hcd_driver: - platform_device_put(the_ss_udc_pdev); -err_alloc_ss_udc: platform_device_put(the_udc_pdev); err_alloc_udc: - platform_device_put(the_ss_hcd_pdev); -err_alloc_ss_hcd: platform_device_put(the_hcd_pdev); return retval; } @@ -2518,12 +2373,8 @@ module_init (init); static void __exit cleanup (void) { platform_device_unregister(the_udc_pdev); - platform_device_unregister(the_ss_udc_pdev); platform_device_unregister(the_hcd_pdev); - platform_device_unregister(the_ss_hcd_pdev); platform_driver_unregister(&dummy_udc_driver); - platform_driver_unregister(&dummy_ss_udc_driver); platform_driver_unregister(&dummy_hcd_driver); - platform_driver_unregister(&dummy_ss_hcd_driver); } module_exit (cleanup); -- 1.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] usb: merge the two dummy_hcds into one 2011-04-14 11:46 ` [PATCH] usb: merge the two dummy_hcds into one Sebastian Andrzej Siewior @ 2011-04-14 15:45 ` Alan Stern 2011-04-14 17:45 ` Sebastian Andrzej Siewior 2011-04-26 6:18 ` Tanya Brokhman 0 siblings, 2 replies; 10+ messages in thread From: Alan Stern @ 2011-04-14 15:45 UTC (permalink / raw) To: Sebastian Andrzej Siewior Cc: Felipe Balbi, Tanya Brokhman, gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' On Thu, 14 Apr 2011, Sebastian Andrzej Siewior wrote: > This patch merges the two HCDs so there is one for both. It is too premature for this. In fact, the support for USB-3 HCDs is currently in flux. Sarah Sharp has submitted a whole bunch of patches to allow for the creation of primary and secondary HCDs, representing the USB-2 and USB-3 root hubs of an xHCI controller. dummy-hcd should use the same mechanism. This will means creating only one host-side platform device, and then creating two usb_hcd structures below it. Tanya's design should be based on Sarah's work. Alan Stern ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] usb: merge the two dummy_hcds into one 2011-04-14 15:45 ` Alan Stern @ 2011-04-14 17:45 ` Sebastian Andrzej Siewior 2011-04-26 6:18 ` Tanya Brokhman 1 sibling, 0 replies; 10+ messages in thread From: Sebastian Andrzej Siewior @ 2011-04-14 17:45 UTC (permalink / raw) To: Alan Stern Cc: Felipe Balbi, Tanya Brokhman, gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' * Alan Stern | 2011-04-14 11:45:34 [-0400]: >In fact, the support for USB-3 HCDs is currently in flux. Sarah Sharp >has submitted a whole bunch of patches to allow for the creation of >primary and secondary HCDs, representing the USB-2 and USB-3 root hubs >of an xHCI controller. dummy-hcd should use the same mechanism. Yeah, after I merged those two I've seen that I can't assign USB2 and USB3 at the same time so I looked what xhci is doing in this case. >This will means creating only one host-side platform device, and then >creating two usb_hcd structures below it. Tanya's design should be >based on Sarah's work. Yes, it makes sense. >Alan Stern Sebastian ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH] usb: merge the two dummy_hcds into one 2011-04-14 15:45 ` Alan Stern 2011-04-14 17:45 ` Sebastian Andrzej Siewior @ 2011-04-26 6:18 ` Tanya Brokhman 2011-04-26 10:24 ` Sebastian Andrzej Siewior 1 sibling, 1 reply; 10+ messages in thread From: Tanya Brokhman @ 2011-04-26 6:18 UTC (permalink / raw) To: 'Alan Stern', 'Sebastian Andrzej Siewior' Cc: 'Felipe Balbi', gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' > On Thu, 14 Apr 2011, Sebastian Andrzej Siewior wrote: > > > This patch merges the two HCDs so there is one for both. > > It is too premature for this. > > In fact, the support for USB-3 HCDs is currently in flux. Sarah Sharp > has submitted a whole bunch of patches to allow for the creation of > primary and secondary HCDs, representing the USB-2 and USB-3 root hubs > of an xHCI controller. dummy-hcd should use the same mechanism. > > This will means creating only one host-side platform device, and then > creating two usb_hcd structures below it. Tanya's design should be > based on Sarah's work. > Hi Alan Thank you for your inputs. I'm not familiar with Sarah's work you mentioned. I'll have to look into that. Could you please point me to where I can find this code? Has it been merged into linux-next yet or just posted on the mailing list? Best regards, Tanya Brokhman Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] usb: merge the two dummy_hcds into one 2011-04-26 6:18 ` Tanya Brokhman @ 2011-04-26 10:24 ` Sebastian Andrzej Siewior 2011-04-28 5:18 ` Tanya Brokhman 0 siblings, 1 reply; 10+ messages in thread From: Sebastian Andrzej Siewior @ 2011-04-26 10:24 UTC (permalink / raw) To: Tanya Brokhman Cc: 'Alan Stern', 'Felipe Balbi', gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' Tanya Brokhman wrote: >> This will means creating only one host-side platform device, and then >> creating two usb_hcd structures below it. Tanya's design should be >> based on Sarah's work. >> > > Hi Alan Hi Tanya, > Thank you for your inputs. I'm not familiar with Sarah's work you mentioned. > I'll have to look into that. Could you please point me to where I can find > this code? Has it been merged into linux-next yet or just posted on the > mailing list? Please take a look at xhci_pci_probe() where usb_create_shared_hcd() is used. It was introduced by commit f6ff0ac878eb420011fa2448851dd48c3a7e7b31 Author: Sarah Sharp <sarah.a.sharp@linux.intel.com> Date: Thu Dec 16 11:21:10 2010 -0800 xhci: Register second xHCI roothub. in v2.6.39-rc1. Sebastian ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH] usb: merge the two dummy_hcds into one 2011-04-26 10:24 ` Sebastian Andrzej Siewior @ 2011-04-28 5:18 ` Tanya Brokhman 0 siblings, 0 replies; 10+ messages in thread From: Tanya Brokhman @ 2011-04-28 5:18 UTC (permalink / raw) To: 'Sebastian Andrzej Siewior' Cc: 'Alan Stern', 'Felipe Balbi', gregkh, linux-arm-msm, ablay, 'open list:USB GADGET/PERIPH...', 'open list' > > Please take a look at xhci_pci_probe() where usb_create_shared_hcd() is > used. It was introduced by > > commit f6ff0ac878eb420011fa2448851dd48c3a7e7b31 > Author: Sarah Sharp <sarah.a.sharp@linux.intel.com> > Date: Thu Dec 16 11:21:10 2010 -0800 > > xhci: Register second xHCI roothub. > > in v2.6.39-rc1. > > Sebastian Thanks Sebastian. I'm on it. Best regards, Tanya Brokhman Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-04-28 5:16 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-23 8:02 [PATCH 1/5 v8] usb: Adding SuperSpeed support to dummy_hcd Tatyana Brokhman
[not found] ` <1300867372-20811-1-git-send-email-tlinder-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-03-25 13:47 ` Felipe Balbi
2011-03-27 12:19 ` Tanya Brokhman
2011-03-28 8:41 ` Felipe Balbi
[not found] ` <20110328084157.GH2251-UiBtZHVXSwEVvW8u9ZQWYwjfymiNCTlR@public.gmane.org>
2011-04-14 11:46 ` [PATCH] usb: merge the two dummy_hcds into one Sebastian Andrzej Siewior
2011-04-14 15:45 ` Alan Stern
2011-04-14 17:45 ` Sebastian Andrzej Siewior
2011-04-26 6:18 ` Tanya Brokhman
2011-04-26 10:24 ` Sebastian Andrzej Siewior
2011-04-28 5:18 ` Tanya Brokhman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).