Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: make usb port a real device

This patch turns each USB port on a hub into a new struct device. This
new device has the USB hub interface device as its parent. The port
devices are stored in a new structure (usb_port), and an array of
usb_ports are dynamically allocated once we know how many ports the USB
hub has.

Move the port_owner variable out of usb_hub and into this new structure.

A new file will be created in the hub interface sysfs directory, so
add documentation.

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Lan Tianyu and committed by
Greg Kroah-Hartman
fa2a9566 9c208904

+82 -16
+7
Documentation/ABI/testing/sysfs-bus-usb
··· 220 220 If the device doesn't support LTM, the file will read "no". 221 221 The file will be present for all speeds of USB devices, and will 222 222 always read "no" for USB 1.1 and USB 2.0 devices. 223 + 224 + What: /sys/bus/usb/devices/.../(hub interface)/portX 225 + Date: August 2012 226 + Contact: Lan Tianyu <tianyu.lan@intel.com> 227 + Description: 228 + The /sys/bus/usb/devices/.../(hub interface)/portX 229 + is usb port device's sysfs directory.
+75 -16
drivers/usb/core/hub.c
··· 39 39 #endif 40 40 #endif 41 41 42 + struct usb_port { 43 + struct device dev; 44 + struct dev_state *port_owner; 45 + }; 46 + 42 47 struct usb_hub { 43 48 struct device *intfdev; /* the "interface" device */ 44 49 struct usb_device *hdev; ··· 88 83 u8 indicator[USB_MAXCHILDREN]; 89 84 struct delayed_work leds; 90 85 struct delayed_work init_work; 91 - struct dev_state **port_owners; 86 + struct usb_port **ports; 92 87 }; 93 88 94 89 static inline int hub_is_superspeed(struct usb_device *hdev) ··· 161 156 #define HUB_DEBOUNCE_STEP 25 162 157 #define HUB_DEBOUNCE_STABLE 100 163 158 159 + #define to_usb_port(_dev) \ 160 + container_of(_dev, struct usb_port, dev) 164 161 165 162 static int usb_reset_and_verify_device(struct usb_device *udev); 166 163 ··· 1229 1222 return 0; 1230 1223 } 1231 1224 1225 + static void usb_port_device_release(struct device *dev) 1226 + { 1227 + struct usb_port *port_dev = to_usb_port(dev); 1228 + 1229 + kfree(port_dev); 1230 + } 1231 + 1232 + static void usb_hub_remove_port_device(struct usb_hub *hub, 1233 + int port1) 1234 + { 1235 + device_unregister(&hub->ports[port1 - 1]->dev); 1236 + } 1237 + 1238 + struct device_type usb_port_device_type = { 1239 + .name = "usb_port", 1240 + .release = usb_port_device_release, 1241 + }; 1242 + 1243 + static int usb_hub_create_port_device(struct usb_hub *hub, 1244 + int port1) 1245 + { 1246 + struct usb_port *port_dev = NULL; 1247 + int retval; 1248 + 1249 + port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); 1250 + if (!port_dev) { 1251 + retval = -ENOMEM; 1252 + goto exit; 1253 + } 1254 + 1255 + hub->ports[port1 - 1] = port_dev; 1256 + port_dev->dev.parent = hub->intfdev; 1257 + port_dev->dev.type = &usb_port_device_type; 1258 + dev_set_name(&port_dev->dev, "port%d", port1); 1259 + 1260 + retval = device_register(&port_dev->dev); 1261 + if (retval) 1262 + goto error_register; 1263 + return 0; 1264 + 1265 + error_register: 1266 + put_device(&port_dev->dev); 1267 + exit: 1268 + return retval; 1269 + } 1270 + 1232 1271 static int hub_configure(struct usb_hub *hub, 1233 1272 struct usb_endpoint_descriptor *endpoint) 1234 1273 { ··· 1284 1231 u16 hubstatus, hubchange; 1285 1232 u16 wHubCharacteristics; 1286 1233 unsigned int pipe; 1287 - int maxp, ret; 1234 + int maxp, ret, i; 1288 1235 char *message = "out of memory"; 1289 1236 1290 1237 hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); ··· 1326 1273 1327 1274 hdev->children = kzalloc(hdev->maxchild * 1328 1275 sizeof(struct usb_device *), GFP_KERNEL); 1329 - hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), 1330 - GFP_KERNEL); 1331 - if (!hdev->children || !hub->port_owners) { 1276 + hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), 1277 + GFP_KERNEL); 1278 + if (!hdev->children || !hub->ports) { 1332 1279 ret = -ENOMEM; 1333 1280 goto fail; 1334 1281 } ··· 1537 1484 if (hub->has_indicators && blinkenlights) 1538 1485 hub->indicator [0] = INDICATOR_CYCLE; 1539 1486 1487 + for (i = 0; i < hdev->maxchild; i++) 1488 + if (usb_hub_create_port_device(hub, i + 1) < 0) 1489 + dev_err(hub->intfdev, 1490 + "couldn't create port%d device.\n", i + 1); 1491 + 1540 1492 hub_activate(hub, HUB_INIT); 1541 1493 return 0; 1542 1494 ··· 1566 1508 { 1567 1509 struct usb_hub *hub = usb_get_intfdata(intf); 1568 1510 struct usb_device *hdev = interface_to_usbdev(intf); 1511 + int i; 1512 + 1513 + for (i = 0; i < hdev->maxchild; i++) 1514 + usb_hub_remove_port_device(hub, i + 1); 1569 1515 1570 1516 /* Take the hub off the event list and don't let it be added again */ 1571 1517 spin_lock_irq(&hub_event_lock); ··· 1592 1530 1593 1531 usb_free_urb(hub->urb); 1594 1532 kfree(hdev->children); 1595 - kfree(hub->port_owners); 1533 + kfree(hub->ports); 1596 1534 kfree(hub->descriptor); 1597 1535 kfree(hub->status); 1598 1536 kfree(hub->buffer); ··· 1724 1662 /* This assumes that devices not managed by the hub driver 1725 1663 * will always have maxchild equal to 0. 1726 1664 */ 1727 - *ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]); 1665 + *ppowner = &(hdev_to_hub(hdev)->ports[port1 - 1]->port_owner); 1728 1666 return 0; 1729 1667 } 1730 1668 ··· 1761 1699 1762 1700 void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) 1763 1701 { 1702 + struct usb_hub *hub = hdev_to_hub(hdev); 1764 1703 int n; 1765 - struct dev_state **powner; 1766 1704 1767 - n = find_port_owner(hdev, 1, &powner); 1768 - if (n == 0) { 1769 - for (; n < hdev->maxchild; (++n, ++powner)) { 1770 - if (*powner == owner) 1771 - *powner = NULL; 1772 - } 1705 + for (n = 0; n < hdev->maxchild; n++) { 1706 + if (hub->ports[n]->port_owner == owner) 1707 + hub->ports[n]->port_owner = NULL; 1773 1708 } 1709 + 1774 1710 } 1775 1711 1776 1712 /* The caller must hold udev's lock */ ··· 1779 1719 if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) 1780 1720 return false; 1781 1721 hub = hdev_to_hub(udev->parent); 1782 - return !!hub->port_owners[udev->portnum - 1]; 1722 + return !!hub->ports[udev->portnum - 1]->port_owner; 1783 1723 } 1784 - 1785 1724 1786 1725 static void recursively_mark_NOTATTACHED(struct usb_device *udev) 1787 1726 {