|
@@ -43,6 +43,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
43
|
43
|
/** List of USB buses */
|
44
|
44
|
struct list_head usb_buses = LIST_HEAD_INIT ( usb_buses );
|
45
|
45
|
|
|
46
|
+/** List of changed ports */
|
|
47
|
+static struct list_head usb_changed = LIST_HEAD_INIT ( usb_changed );
|
|
48
|
+
|
|
49
|
+/** List of halted endpoints */
|
|
50
|
+static struct list_head usb_halted = LIST_HEAD_INIT ( usb_halted );
|
|
51
|
+
|
46
|
52
|
/******************************************************************************
|
47
|
53
|
*
|
48
|
54
|
* Utility functions
|
|
@@ -560,7 +566,6 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
560
|
566
|
void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
561
|
567
|
int rc ) {
|
562
|
568
|
struct usb_device *usb = ep->usb;
|
563
|
|
- struct usb_bus *bus = usb->port->hub->bus;
|
564
|
569
|
|
565
|
570
|
/* Decrement fill level */
|
566
|
571
|
assert ( ep->fill > 0 );
|
|
@@ -572,7 +577,7 @@ void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
572
|
577
|
usb->name, usb_endpoint_name ( ep->address ),
|
573
|
578
|
strerror ( rc ) );
|
574
|
579
|
list_del ( &ep->halted );
|
575
|
|
- list_add_tail ( &ep->halted, &bus->halted );
|
|
580
|
+ list_add_tail ( &ep->halted, &usb_halted );
|
576
|
581
|
}
|
577
|
582
|
|
578
|
583
|
/* Report completion */
|
|
@@ -1576,12 +1581,12 @@ static void usb_detached ( struct usb_port *port ) {
|
1576
|
1581
|
}
|
1577
|
1582
|
|
1578
|
1583
|
/**
|
1579
|
|
- * Handle newly attached or detached USB devices
|
|
1584
|
+ * Handle newly attached or detached USB device
|
1580
|
1585
|
*
|
1581
|
1586
|
* @v port USB port
|
1582
|
1587
|
* @ret rc Return status code
|
1583
|
1588
|
*/
|
1584
|
|
-static int usb_hotplug ( struct usb_port *port ) {
|
|
1589
|
+static int usb_hotplugged ( struct usb_port *port ) {
|
1585
|
1590
|
struct usb_hub *hub = port->hub;
|
1586
|
1591
|
int rc;
|
1587
|
1592
|
|
|
@@ -1621,43 +1626,26 @@ static int usb_hotplug ( struct usb_port *port ) {
|
1621
|
1626
|
* @v port USB port
|
1622
|
1627
|
*/
|
1623
|
1628
|
void usb_port_changed ( struct usb_port *port ) {
|
1624
|
|
- struct usb_hub *hub = port->hub;
|
1625
|
|
- struct usb_bus *bus = hub->bus;
|
1626
|
1629
|
|
1627
|
1630
|
/* Record hub port status change */
|
1628
|
1631
|
list_del ( &port->changed );
|
1629
|
|
- list_add_tail ( &port->changed, &bus->changed );
|
|
1632
|
+ list_add_tail ( &port->changed, &usb_changed );
|
1630
|
1633
|
}
|
1631
|
1634
|
|
1632
|
1635
|
/**
|
1633
|
|
- * USB process
|
|
1636
|
+ * Handle newly attached or detached USB device
|
1634
|
1637
|
*
|
1635
|
|
- * @v bus USB bus
|
1636
|
1638
|
*/
|
1637
|
|
-static void usb_step ( struct usb_bus *bus ) {
|
1638
|
|
- struct usb_endpoint *ep;
|
|
1639
|
+static void usb_hotplug ( void ) {
|
1639
|
1640
|
struct usb_port *port;
|
1640
|
1641
|
|
1641
|
|
- /* Poll bus */
|
1642
|
|
- usb_poll ( bus );
|
1643
|
|
-
|
1644
|
|
- /* Attempt to reset first halted endpoint in list, if any. We
|
1645
|
|
- * do not attempt to process the complete list, since this
|
1646
|
|
- * would require extra code to allow for the facts that the
|
1647
|
|
- * halted endpoint list may change as we do so, and that
|
1648
|
|
- * resetting an endpoint may fail.
|
1649
|
|
- */
|
1650
|
|
- if ( ( ep = list_first_entry ( &bus->halted, struct usb_endpoint,
|
1651
|
|
- halted ) ) != NULL )
|
1652
|
|
- usb_endpoint_reset ( ep );
|
1653
|
|
-
|
1654
|
1642
|
/* Handle any changed ports, allowing for the fact that the
|
1655
|
1643
|
* port list may change as we perform hotplug actions.
|
1656
|
1644
|
*/
|
1657
|
|
- while ( ! list_empty ( &bus->changed ) ) {
|
|
1645
|
+ while ( ! list_empty ( &usb_changed ) ) {
|
1658
|
1646
|
|
1659
|
1647
|
/* Get first changed port */
|
1660
|
|
- port = list_first_entry ( &bus->changed, struct usb_port,
|
|
1648
|
+ port = list_first_entry ( &usb_changed, struct usb_port,
|
1661
|
1649
|
changed );
|
1662
|
1650
|
assert ( port != NULL );
|
1663
|
1651
|
|
|
@@ -1666,13 +1654,39 @@ static void usb_step ( struct usb_bus *bus ) {
|
1666
|
1654
|
INIT_LIST_HEAD ( &port->changed );
|
1667
|
1655
|
|
1668
|
1656
|
/* Perform appropriate hotplug action */
|
1669
|
|
- usb_hotplug ( port );
|
|
1657
|
+ usb_hotplugged ( port );
|
1670
|
1658
|
}
|
1671
|
1659
|
}
|
1672
|
1660
|
|
|
1661
|
+/**
|
|
1662
|
+ * USB process
|
|
1663
|
+ *
|
|
1664
|
+ * @v process USB process
|
|
1665
|
+ */
|
|
1666
|
+static void usb_step ( struct process *process __unused ) {
|
|
1667
|
+ struct usb_bus *bus;
|
|
1668
|
+ struct usb_endpoint *ep;
|
|
1669
|
+
|
|
1670
|
+ /* Poll all buses */
|
|
1671
|
+ for_each_usb_bus ( bus )
|
|
1672
|
+ usb_poll ( bus );
|
|
1673
|
+
|
|
1674
|
+ /* Attempt to reset first halted endpoint in list, if any. We
|
|
1675
|
+ * do not attempt to process the complete list, since this
|
|
1676
|
+ * would require extra code to allow for the facts that the
|
|
1677
|
+ * halted endpoint list may change as we do so, and that
|
|
1678
|
+ * resetting an endpoint may fail.
|
|
1679
|
+ */
|
|
1680
|
+ if ( ( ep = list_first_entry ( &usb_halted, struct usb_endpoint,
|
|
1681
|
+ halted ) ) != NULL )
|
|
1682
|
+ usb_endpoint_reset ( ep );
|
|
1683
|
+
|
|
1684
|
+ /* Handle any changed ports */
|
|
1685
|
+ usb_hotplug();
|
|
1686
|
+}
|
|
1687
|
+
|
1673
|
1688
|
/** USB process */
|
1674
|
|
-static struct process_descriptor usb_process_desc =
|
1675
|
|
- PROC_DESC ( struct usb_bus, process, usb_step );
|
|
1689
|
+PERMANENT_PROCESS ( usb_process, usb_step );
|
1676
|
1690
|
|
1677
|
1691
|
/******************************************************************************
|
1678
|
1692
|
*
|
|
@@ -1755,10 +1769,10 @@ int register_usb_hub ( struct usb_hub *hub ) {
|
1755
|
1769
|
/* Delay to allow ports to stabilise */
|
1756
|
1770
|
mdelay ( USB_PORT_DELAY_MS );
|
1757
|
1771
|
|
1758
|
|
- /* Attach any devices already present */
|
|
1772
|
+ /* Mark all ports as changed */
|
1759
|
1773
|
for ( i = 1 ; i <= hub->ports ; i++ ) {
|
1760
|
1774
|
port = usb_port ( hub, i );
|
1761
|
|
- usb_hotplug ( port );
|
|
1775
|
+ usb_port_changed ( port );
|
1762
|
1776
|
}
|
1763
|
1777
|
|
1764
|
1778
|
/* Some hubs seem to defer reporting device connections until
|
|
@@ -1766,7 +1780,10 @@ int register_usb_hub ( struct usb_hub *hub ) {
|
1766
|
1780
|
* Poll the bus once now in order to pick up any such
|
1767
|
1781
|
* connections.
|
1768
|
1782
|
*/
|
1769
|
|
- usb_step ( bus );
|
|
1783
|
+ usb_poll ( bus );
|
|
1784
|
+
|
|
1785
|
+ /* Attach any devices already present */
|
|
1786
|
+ usb_hotplug();
|
1770
|
1787
|
|
1771
|
1788
|
return 0;
|
1772
|
1789
|
|
|
@@ -1862,9 +1879,6 @@ struct usb_bus * alloc_usb_bus ( struct device *dev, unsigned int ports,
|
1862
|
1879
|
bus->op = op;
|
1863
|
1880
|
INIT_LIST_HEAD ( &bus->devices );
|
1864
|
1881
|
INIT_LIST_HEAD ( &bus->hubs );
|
1865
|
|
- INIT_LIST_HEAD ( &bus->changed );
|
1866
|
|
- INIT_LIST_HEAD ( &bus->halted );
|
1867
|
|
- process_init_stopped ( &bus->process, &usb_process_desc, NULL );
|
1868
|
1882
|
bus->host = &bus->op->bus;
|
1869
|
1883
|
|
1870
|
1884
|
/* Allocate root hub */
|
|
@@ -1904,9 +1918,6 @@ int register_usb_bus ( struct usb_bus *bus ) {
|
1904
|
1918
|
if ( ( rc = register_usb_hub ( bus->hub ) ) != 0 )
|
1905
|
1919
|
goto err_register_hub;
|
1906
|
1920
|
|
1907
|
|
- /* Start bus process */
|
1908
|
|
- process_add ( &bus->process );
|
1909
|
|
-
|
1910
|
1921
|
return 0;
|
1911
|
1922
|
|
1912
|
1923
|
unregister_usb_hub ( bus->hub );
|
|
@@ -1926,10 +1937,6 @@ void unregister_usb_bus ( struct usb_bus *bus ) {
|
1926
|
1937
|
|
1927
|
1938
|
/* Sanity checks */
|
1928
|
1939
|
assert ( bus->hub != NULL );
|
1929
|
|
- assert ( process_running ( &bus->process ) );
|
1930
|
|
-
|
1931
|
|
- /* Stop bus process */
|
1932
|
|
- process_del ( &bus->process );
|
1933
|
1940
|
|
1934
|
1941
|
/* Unregister root hub */
|
1935
|
1942
|
unregister_usb_hub ( bus->hub );
|
|
@@ -1943,7 +1950,6 @@ void unregister_usb_bus ( struct usb_bus *bus ) {
|
1943
|
1950
|
/* Sanity checks */
|
1944
|
1951
|
assert ( list_empty ( &bus->devices ) );
|
1945
|
1952
|
assert ( list_empty ( &bus->hubs ) );
|
1946
|
|
- assert ( ! process_running ( &bus->process ) );
|
1947
|
1953
|
}
|
1948
|
1954
|
|
1949
|
1955
|
/**
|
|
@@ -1952,11 +1958,16 @@ void unregister_usb_bus ( struct usb_bus *bus ) {
|
1952
|
1958
|
* @v bus USB bus
|
1953
|
1959
|
*/
|
1954
|
1960
|
void free_usb_bus ( struct usb_bus *bus ) {
|
|
1961
|
+ struct usb_endpoint *ep;
|
|
1962
|
+ struct usb_port *port;
|
1955
|
1963
|
|
1956
|
1964
|
/* Sanity checks */
|
1957
|
1965
|
assert ( list_empty ( &bus->devices ) );
|
1958
|
1966
|
assert ( list_empty ( &bus->hubs ) );
|
1959
|
|
- assert ( ! process_running ( &bus->process ) );
|
|
1967
|
+ list_for_each_entry ( ep, &usb_halted, halted )
|
|
1968
|
+ assert ( ep->usb->port->hub->bus != bus );
|
|
1969
|
+ list_for_each_entry ( port, &usb_changed, changed )
|
|
1970
|
+ assert ( port->hub->bus != bus );
|
1960
|
1971
|
|
1961
|
1972
|
/* Free root hub */
|
1962
|
1973
|
free_usb_hub ( bus->hub );
|