Browse Source

[usb] Maintain single lists of halted endpoints and changed ports

When an EHCI hotplug action results in the controller disowning the
port, it will result in a hotplug action on the corresponding UHCI or
OHCI controller.  Allow such hotplug actions to be carried out as part
of the same call to usb_step() or usb_register_bus(), by maintaining a
single central list of changed ports.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
e4783add79
2 changed files with 55 additions and 50 deletions
  1. 55
    44
      src/drivers/bus/usb.c
  2. 0
    6
      src/include/ipxe/usb.h

+ 55
- 44
src/drivers/bus/usb.c View File

43
 /** List of USB buses */
43
 /** List of USB buses */
44
 struct list_head usb_buses = LIST_HEAD_INIT ( usb_buses );
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
  * Utility functions
54
  * Utility functions
560
 void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf,
566
 void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf,
561
 			int rc ) {
567
 			int rc ) {
562
 	struct usb_device *usb = ep->usb;
568
 	struct usb_device *usb = ep->usb;
563
-	struct usb_bus *bus = usb->port->hub->bus;
564
 
569
 
565
 	/* Decrement fill level */
570
 	/* Decrement fill level */
566
 	assert ( ep->fill > 0 );
571
 	assert ( ep->fill > 0 );
572
 		       usb->name, usb_endpoint_name ( ep->address ),
577
 		       usb->name, usb_endpoint_name ( ep->address ),
573
 		       strerror ( rc ) );
578
 		       strerror ( rc ) );
574
 		list_del ( &ep->halted );
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
 	/* Report completion */
583
 	/* Report completion */
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
  * @v port		USB port
1586
  * @v port		USB port
1582
  * @ret rc		Return status code
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
 	struct usb_hub *hub = port->hub;
1590
 	struct usb_hub *hub = port->hub;
1586
 	int rc;
1591
 	int rc;
1587
 
1592
 
1621
  * @v port		USB port
1626
  * @v port		USB port
1622
  */
1627
  */
1623
 void usb_port_changed ( struct usb_port *port ) {
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
 	/* Record hub port status change */
1630
 	/* Record hub port status change */
1628
 	list_del ( &port->changed );
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
 	struct usb_port *port;
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
 	/* Handle any changed ports, allowing for the fact that the
1642
 	/* Handle any changed ports, allowing for the fact that the
1655
 	 * port list may change as we perform hotplug actions.
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
 		/* Get first changed port */
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
 					  changed );
1649
 					  changed );
1662
 		assert ( port != NULL );
1650
 		assert ( port != NULL );
1663
 
1651
 
1666
 		INIT_LIST_HEAD ( &port->changed );
1654
 		INIT_LIST_HEAD ( &port->changed );
1667
 
1655
 
1668
 		/* Perform appropriate hotplug action */
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
 /** USB process */
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
 	/* Delay to allow ports to stabilise */
1769
 	/* Delay to allow ports to stabilise */
1756
 	mdelay ( USB_PORT_DELAY_MS );
1770
 	mdelay ( USB_PORT_DELAY_MS );
1757
 
1771
 
1758
-	/* Attach any devices already present */
1772
+	/* Mark all ports as changed */
1759
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1773
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1760
 		port = usb_port ( hub, i );
1774
 		port = usb_port ( hub, i );
1761
-		usb_hotplug ( port );
1775
+		usb_port_changed ( port );
1762
 	}
1776
 	}
1763
 
1777
 
1764
 	/* Some hubs seem to defer reporting device connections until
1778
 	/* Some hubs seem to defer reporting device connections until
1766
 	 * Poll the bus once now in order to pick up any such
1780
 	 * Poll the bus once now in order to pick up any such
1767
 	 * connections.
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
 	return 0;
1788
 	return 0;
1772
 
1789
 
1862
 	bus->op = op;
1879
 	bus->op = op;
1863
 	INIT_LIST_HEAD ( &bus->devices );
1880
 	INIT_LIST_HEAD ( &bus->devices );
1864
 	INIT_LIST_HEAD ( &bus->hubs );
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
 	bus->host = &bus->op->bus;
1882
 	bus->host = &bus->op->bus;
1869
 
1883
 
1870
 	/* Allocate root hub */
1884
 	/* Allocate root hub */
1904
 	if ( ( rc = register_usb_hub ( bus->hub ) ) != 0 )
1918
 	if ( ( rc = register_usb_hub ( bus->hub ) ) != 0 )
1905
 		goto err_register_hub;
1919
 		goto err_register_hub;
1906
 
1920
 
1907
-	/* Start bus process */
1908
-	process_add ( &bus->process );
1909
-
1910
 	return 0;
1921
 	return 0;
1911
 
1922
 
1912
 	unregister_usb_hub ( bus->hub );
1923
 	unregister_usb_hub ( bus->hub );
1926
 
1937
 
1927
 	/* Sanity checks */
1938
 	/* Sanity checks */
1928
 	assert ( bus->hub != NULL );
1939
 	assert ( bus->hub != NULL );
1929
-	assert ( process_running ( &bus->process ) );
1930
-
1931
-	/* Stop bus process */
1932
-	process_del ( &bus->process );
1933
 
1940
 
1934
 	/* Unregister root hub */
1941
 	/* Unregister root hub */
1935
 	unregister_usb_hub ( bus->hub );
1942
 	unregister_usb_hub ( bus->hub );
1943
 	/* Sanity checks */
1950
 	/* Sanity checks */
1944
 	assert ( list_empty ( &bus->devices ) );
1951
 	assert ( list_empty ( &bus->devices ) );
1945
 	assert ( list_empty ( &bus->hubs ) );
1952
 	assert ( list_empty ( &bus->hubs ) );
1946
-	assert ( ! process_running ( &bus->process ) );
1947
 }
1953
 }
1948
 
1954
 
1949
 /**
1955
 /**
1952
  * @v bus		USB bus
1958
  * @v bus		USB bus
1953
  */
1959
  */
1954
 void free_usb_bus ( struct usb_bus *bus ) {
1960
 void free_usb_bus ( struct usb_bus *bus ) {
1961
+	struct usb_endpoint *ep;
1962
+	struct usb_port *port;
1955
 
1963
 
1956
 	/* Sanity checks */
1964
 	/* Sanity checks */
1957
 	assert ( list_empty ( &bus->devices ) );
1965
 	assert ( list_empty ( &bus->devices ) );
1958
 	assert ( list_empty ( &bus->hubs ) );
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
 	/* Free root hub */
1972
 	/* Free root hub */
1962
 	free_usb_hub ( bus->hub );
1973
 	free_usb_hub ( bus->hub );

+ 0
- 6
src/include/ipxe/usb.h View File

922
 	struct list_head devices;
922
 	struct list_head devices;
923
 	/** List of hubs */
923
 	/** List of hubs */
924
 	struct list_head hubs;
924
 	struct list_head hubs;
925
-	/** List of changed ports */
926
-	struct list_head changed;
927
-	/** List of halted endpoints */
928
-	struct list_head halted;
929
-	/** Process */
930
-	struct process process;
931
 
925
 
932
 	/** Host controller operations */
926
 	/** Host controller operations */
933
 	struct usb_bus_host_operations *host;
927
 	struct usb_bus_host_operations *host;

Loading…
Cancel
Save