Ver código fonte

[phantom] Add CLP settings interface

This interface provides access to firmware settings (e.g. MAC address)
that will apply to all drivers loaded for the duration of the current
system boot.
tags/v0.9.6
Michael Brown 16 anos atrás
pai
commit
1bc2adea9a
2 arquivos alterados com 368 adições e 0 exclusões
  1. 359
    0
      src/drivers/net/phantom/phantom.c
  2. 9
    0
      src/drivers/net/phantom/phantom.h

+ 359
- 0
src/drivers/net/phantom/phantom.c Ver arquivo

@@ -32,6 +32,7 @@
32 32
 #include <gpxe/if_ether.h>
33 33
 #include <gpxe/ethernet.h>
34 34
 #include <gpxe/spi.h>
35
+#include <gpxe/settings.h>
35 36
 #include "phantom.h"
36 37
 
37 38
 /**
@@ -72,6 +73,9 @@
72 73
 /** Maximum time to wait for test memory */
73 74
 #define PHN_TEST_MEM_TIMEOUT_MS 100
74 75
 
76
+/** Maximum time to wait for CLP command to be issued */
77
+#define PHN_CLP_CMD_TIMEOUT_MS 500
78
+
75 79
 /** Link state poll frequency
76 80
  *
77 81
  * The link state will be checked once in every N calls to poll().
@@ -150,6 +154,9 @@ struct phantom_nic_port {
150 154
 
151 155
 	/** Descriptor rings */
152 156
 	struct phantom_descriptor_rings *desc;
157
+
158
+	/** Non-volatile settings */
159
+	struct settings settings;
153 160
 };
154 161
 
155 162
 /** RX context creation request and response buffers */
@@ -1576,6 +1583,330 @@ static struct net_device_operations phantom_operations = {
1576 1583
 	.irq		= phantom_irq,
1577 1584
 };
1578 1585
 
1586
+/***************************************************************************
1587
+ *
1588
+ * CLP settings
1589
+ *
1590
+ */
1591
+
1592
+/** Phantom CLP data
1593
+ *
1594
+ */
1595
+union phantom_clp_data {
1596
+	/** Data bytes
1597
+	 *
1598
+	 * This field is right-aligned; if only N bytes are present
1599
+	 * then bytes[0]..bytes[7-N] should be zero, and the data
1600
+	 * should be in bytes[7-N+1] to bytes[7];
1601
+	 */
1602
+	uint8_t bytes[8];
1603
+	/** Dwords for the CLP interface */
1604
+	struct {
1605
+		/** High dword, in network byte order */
1606
+		uint32_t hi;
1607
+		/** Low dword, in network byte order */
1608
+		uint32_t lo;
1609
+	} dwords;
1610
+};
1611
+#define PHN_CLP_BLKSIZE ( sizeof ( union phantom_clp_data ) )
1612
+
1613
+/**
1614
+ * Wait for Phantom CLP command to complete
1615
+ *
1616
+ * @v phantom		Phantom NIC
1617
+ * @ret rc		Return status code
1618
+ */
1619
+static int phantom_clp_wait ( struct phantom_nic *phantom ) {
1620
+	unsigned int retries;
1621
+	uint32_t status;
1622
+
1623
+	for ( retries = 0 ; retries < PHN_CLP_CMD_TIMEOUT_MS ; retries++ ) {
1624
+		status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
1625
+		if ( status & UNM_CAM_RAM_CLP_STATUS_DONE )
1626
+			return 0;
1627
+		mdelay ( 1 );
1628
+	}
1629
+
1630
+	DBGC ( phantom, "Phantom %p timed out waiting for CLP command\n",
1631
+	       phantom );
1632
+	return -ETIMEDOUT;
1633
+}
1634
+
1635
+/**
1636
+ * Issue Phantom CLP command
1637
+ *
1638
+ * @v phantom		Phantom NIC
1639
+ * @v port		Virtual port number
1640
+ * @v opcode		Opcode
1641
+ * @v data_in		Data in, or NULL
1642
+ * @v data_out		Data out, or NULL
1643
+ * @v offset		Offset within data
1644
+ * @v len		Data buffer length
1645
+ * @ret len		Total transfer length (for reads), or negative error
1646
+ */
1647
+static int phantom_clp_cmd ( struct phantom_nic *phantom, unsigned int port,
1648
+			     unsigned int opcode, const void *data_in,
1649
+			     void *data_out, size_t offset, size_t len ) {
1650
+	union phantom_clp_data data;
1651
+	unsigned int index = ( offset / sizeof ( data ) );
1652
+	unsigned int last = 0;
1653
+	size_t in_frag_len;
1654
+	uint8_t *in_frag;
1655
+	uint32_t command;
1656
+	uint32_t status;
1657
+	size_t read_len;
1658
+	unsigned int error;
1659
+	size_t out_frag_len;
1660
+	uint8_t *out_frag;
1661
+	int rc;
1662
+
1663
+	/* Sanity checks */
1664
+	assert ( ( offset % sizeof ( data ) ) == 0 );
1665
+	if ( len > 255 ) {
1666
+		DBGC ( phantom, "Phantom %p invalid CLP length %zd\n",
1667
+		       phantom, len );
1668
+		return -EINVAL;
1669
+	}
1670
+
1671
+	/* Check that CLP interface is ready */
1672
+	if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
1673
+		return rc;
1674
+
1675
+	/* Copy data in */
1676
+	memset ( &data, 0, sizeof ( data ) );
1677
+	if ( data_in ) {
1678
+		assert ( offset < len );
1679
+		in_frag_len = ( len - offset );
1680
+		if ( in_frag_len > sizeof ( data ) ) {
1681
+			in_frag_len = sizeof ( data );
1682
+		} else {
1683
+			last = 1;
1684
+		}
1685
+		in_frag = &data.bytes[ sizeof ( data ) - in_frag_len ];
1686
+		memcpy ( in_frag, ( data_in + offset ), in_frag_len );
1687
+		phantom_writel ( phantom, be32_to_cpu ( data.dwords.lo ),
1688
+				 UNM_CAM_RAM_CLP_DATA_LO );
1689
+		phantom_writel ( phantom, be32_to_cpu ( data.dwords.hi ),
1690
+				 UNM_CAM_RAM_CLP_DATA_HI );
1691
+	}
1692
+
1693
+	/* Issue CLP command */
1694
+	command = ( ( index << 24 ) | ( ( data_in ? len : 0 ) << 16 ) |
1695
+		    ( port << 8 ) | ( last << 7 ) | ( opcode << 0 ) );
1696
+	phantom_writel ( phantom, command, UNM_CAM_RAM_CLP_COMMAND );
1697
+	mb();
1698
+	phantom_writel ( phantom, UNM_CAM_RAM_CLP_STATUS_START,
1699
+			 UNM_CAM_RAM_CLP_STATUS );
1700
+
1701
+	/* Wait for command to complete */
1702
+	if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
1703
+		return rc;
1704
+
1705
+	/* Get command status */
1706
+	status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
1707
+	read_len = ( ( status >> 16 ) & 0xff );
1708
+	error = ( ( status >> 8 ) & 0xff );
1709
+	if ( error ) {
1710
+		DBGC ( phantom, "Phantom %p CLP command error %02x\n",
1711
+		       phantom, error );
1712
+		return -EIO;
1713
+	}
1714
+
1715
+	/* Copy data out */
1716
+	if ( data_out ) {
1717
+		data.dwords.lo = cpu_to_be32 ( phantom_readl ( phantom,
1718
+						  UNM_CAM_RAM_CLP_DATA_LO ) );
1719
+		data.dwords.hi = cpu_to_be32 ( phantom_readl ( phantom,
1720
+						  UNM_CAM_RAM_CLP_DATA_HI ) );
1721
+		out_frag_len = ( read_len - offset );
1722
+		if ( out_frag_len > sizeof ( data ) )
1723
+			out_frag_len = sizeof ( data );
1724
+		out_frag = &data.bytes[ sizeof ( data ) - out_frag_len ];
1725
+		if ( out_frag_len > ( len - offset ) )
1726
+			out_frag_len = ( len - offset );
1727
+		memcpy ( ( data_out + offset ), out_frag, out_frag_len );
1728
+	}
1729
+
1730
+	return read_len;
1731
+}
1732
+
1733
+/**
1734
+ * Store Phantom CLP setting
1735
+ *
1736
+ * @v phantom		Phantom NIC
1737
+ * @v port		Virtual port number
1738
+ * @v setting		Setting number
1739
+ * @v data		Data buffer
1740
+ * @v len		Length of data buffer
1741
+ * @ret rc		Return status code
1742
+ */
1743
+static int phantom_clp_store ( struct phantom_nic *phantom, unsigned int port,
1744
+			       unsigned int setting, const void *data,
1745
+			       size_t len ) {
1746
+	unsigned int opcode = setting;
1747
+	size_t offset;
1748
+	int rc;
1749
+
1750
+	for ( offset = 0 ; offset < len ; offset += PHN_CLP_BLKSIZE ) {
1751
+		if ( ( rc = phantom_clp_cmd ( phantom, port, opcode, data,
1752
+					      NULL, offset, len ) ) < 0 )
1753
+			return rc;
1754
+	}
1755
+	return 0;
1756
+}
1757
+
1758
+/**
1759
+ * Fetch Phantom CLP setting
1760
+ *
1761
+ * @v phantom		Phantom NIC
1762
+ * @v port		Virtual port number
1763
+ * @v setting		Setting number
1764
+ * @v data		Data buffer
1765
+ * @v len		Length of data buffer
1766
+ * @ret len		Length of setting, or negative error
1767
+ */
1768
+static int phantom_clp_fetch ( struct phantom_nic *phantom, unsigned int port,
1769
+			       unsigned int setting, void *data, size_t len ) {
1770
+	unsigned int opcode = ( setting + 1 );
1771
+	size_t offset = 0;
1772
+	int read_len;
1773
+
1774
+	while ( 1 ) {
1775
+		read_len = phantom_clp_cmd ( phantom, port, opcode, NULL,
1776
+					     data, offset, len );
1777
+		if ( read_len < 0 )
1778
+			return read_len;
1779
+		offset += PHN_CLP_BLKSIZE;
1780
+		if ( offset >= ( unsigned ) read_len )
1781
+			break;
1782
+		if ( offset >= len )
1783
+			break;
1784
+	}
1785
+	return read_len;
1786
+}
1787
+
1788
+/** A Phantom CLP setting */
1789
+struct phantom_clp_setting {
1790
+	/** gPXE setting */
1791
+	struct setting *setting;
1792
+	/** Setting number */
1793
+	unsigned int number;
1794
+};
1795
+
1796
+/** Phantom CLP settings */
1797
+static struct phantom_clp_setting clp_settings[] = {
1798
+	{ &mac_setting, 0x01 },
1799
+};
1800
+
1801
+/**
1802
+ * Find Phantom CLP setting
1803
+ *
1804
+ * @v setting		gPXE setting
1805
+ * @v clp_setting	Equivalent Phantom CLP setting, or NULL
1806
+ */
1807
+static struct phantom_clp_setting *
1808
+phantom_find_clp_setting ( struct phantom_nic *phantom,
1809
+			   struct setting *setting ) {
1810
+	struct phantom_clp_setting *clp_setting;
1811
+	unsigned int i;
1812
+
1813
+	for ( i = 0 ; i < ( sizeof ( clp_settings ) /
1814
+			    sizeof ( clp_settings[0] ) ) ; i++ ) {
1815
+		clp_setting = &clp_settings[i];
1816
+		if ( setting_cmp ( setting, clp_setting->setting ) == 0 )
1817
+			return clp_setting;
1818
+	}
1819
+
1820
+	DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n",
1821
+		phantom, setting->name );
1822
+
1823
+	return NULL;
1824
+}
1825
+
1826
+/**
1827
+ * Store Phantom CLP setting
1828
+ *
1829
+ * @v settings		Settings block
1830
+ * @v setting		Setting to store
1831
+ * @v data		Setting data, or NULL to clear setting
1832
+ * @v len		Length of setting data
1833
+ * @ret rc		Return status code
1834
+ */
1835
+static int phantom_store_setting ( struct settings *settings,
1836
+				   struct setting *setting,
1837
+				   const void *data, size_t len ) {
1838
+	struct phantom_nic_port *phantom_port =
1839
+		container_of ( settings, struct phantom_nic_port, settings );
1840
+	struct phantom_nic *phantom = phantom_port->phantom;
1841
+	struct phantom_clp_setting *clp_setting;
1842
+	int rc;
1843
+
1844
+	/* Find Phantom setting equivalent to gPXE setting */
1845
+	clp_setting = phantom_find_clp_setting ( phantom, setting );
1846
+	if ( ! clp_setting )
1847
+		return -ENOTSUP;
1848
+
1849
+	/* Store setting */
1850
+	if ( ( rc = phantom_clp_store ( phantom, phantom_port->port,
1851
+					clp_setting->number,
1852
+					data, len ) ) != 0 ) {
1853
+		DBGC ( phantom, "Phantom %p could not store setting \"%s\": "
1854
+		       "%s\n", phantom, setting->name, strerror ( rc ) );
1855
+		return rc;
1856
+	}
1857
+
1858
+	return 0;
1859
+}
1860
+
1861
+/**
1862
+ * Fetch Phantom CLP setting
1863
+ *
1864
+ * @v settings		Settings block
1865
+ * @v setting		Setting to fetch
1866
+ * @v data		Buffer to fill with setting data
1867
+ * @v len		Length of buffer
1868
+ * @ret len		Length of setting data, or negative error
1869
+ */
1870
+static int phantom_fetch_setting ( struct settings *settings,
1871
+				   struct setting *setting,
1872
+				   void *data, size_t len ) {
1873
+	struct phantom_nic_port *phantom_port =
1874
+		container_of ( settings, struct phantom_nic_port, settings );
1875
+	struct phantom_nic *phantom = phantom_port->phantom;
1876
+	struct phantom_clp_setting *clp_setting;
1877
+	int read_len;
1878
+	int rc;
1879
+
1880
+	/* Find Phantom setting equivalent to gPXE setting */
1881
+	clp_setting = phantom_find_clp_setting ( phantom, setting );
1882
+	if ( ! clp_setting )
1883
+		return -ENOTSUP;
1884
+
1885
+	/* Fetch setting */
1886
+	if ( ( read_len = phantom_clp_fetch ( phantom, phantom_port->port,
1887
+					      clp_setting->number,
1888
+					      data, len ) ) < 0 ) {
1889
+		rc = read_len;
1890
+		DBGC ( phantom, "Phantom %p could not fetch setting \"%s\": "
1891
+		       "%s\n", phantom, setting->name, strerror ( rc ) );
1892
+		return rc;
1893
+	}
1894
+
1895
+	return read_len;
1896
+}
1897
+
1898
+/** Phantom CLP settings operations */
1899
+static struct settings_operations phantom_settings_operations = {
1900
+	.store		= phantom_store_setting,
1901
+	.fetch		= phantom_fetch_setting,
1902
+};
1903
+
1904
+/***************************************************************************
1905
+ *
1906
+ * Initialisation
1907
+ *
1908
+ */
1909
+
1579 1910
 /**
1580 1911
  * Map Phantom CRB window
1581 1912
  *
@@ -1894,6 +2225,7 @@ static int phantom_probe ( struct pci_device *pci,
1894 2225
 	struct phantom_nic *phantom;
1895 2226
 	struct net_device *netdev;
1896 2227
 	struct phantom_nic_port *phantom_port;
2228
+	struct settings *parent_settings;
1897 2229
 	int i;
1898 2230
 	int rc;
1899 2231
 
@@ -1935,6 +2267,9 @@ static int phantom_probe ( struct pci_device *pci,
1935 2267
 		netdev->dev = &pci->dev;
1936 2268
 		phantom_port->phantom = phantom;
1937 2269
 		phantom_port->port = i;
2270
+		settings_init ( &phantom_port->settings,
2271
+				&phantom_settings_operations,
2272
+				&netdev->refcnt, "clp" );
1938 2273
 	}
1939 2274
 
1940 2275
 	/* BUG5945 - need to hack PCI config space on P3 B1 silicon.
@@ -1978,8 +2313,27 @@ static int phantom_probe ( struct pci_device *pci,
1978 2313
 		}
1979 2314
 	}
1980 2315
 
2316
+	/* Register settings blocks */
2317
+	for ( i = 0 ; i < phantom->num_ports ; i++ ) {
2318
+		phantom_port = netdev_priv ( phantom->netdev[i] );
2319
+		parent_settings = netdev_settings ( phantom->netdev[i] );
2320
+		if ( ( rc = register_settings ( &phantom_port->settings,
2321
+						parent_settings ) ) != 0 ) {
2322
+			DBGC ( phantom, "Phantom %p could not register port "
2323
+			       "%d settings: %s\n",
2324
+			       phantom, i, strerror ( rc ) );
2325
+			goto err_register_settings;
2326
+		}
2327
+	}
2328
+
1981 2329
 	return 0;
1982 2330
 
2331
+	i = ( phantom->num_ports - 1 );
2332
+ err_register_settings:
2333
+	for ( ; i >= 0 ; i-- ) {
2334
+		phantom_port = netdev_priv ( phantom->netdev[i] );
2335
+		unregister_settings ( &phantom_port->settings );
2336
+	}
1983 2337
 	i = ( phantom->num_ports - 1 );
1984 2338
  err_register_netdev:
1985 2339
 	for ( ; i >= 0 ; i-- )
@@ -2010,8 +2364,13 @@ static int phantom_probe ( struct pci_device *pci,
2010 2364
  */
2011 2365
 static void phantom_remove ( struct pci_device *pci ) {
2012 2366
 	struct phantom_nic *phantom = pci_get_drvdata ( pci );
2367
+	struct phantom_nic_port *phantom_port;
2013 2368
 	int i;
2014 2369
 
2370
+	for ( i = ( phantom->num_ports - 1 ) ; i >= 0 ; i-- ) {
2371
+		phantom_port = netdev_priv ( phantom->netdev[i] );
2372
+		unregister_settings ( &phantom_port->settings );
2373
+	}
2015 2374
 	for ( i = ( phantom->num_ports - 1 ) ; i >= 0 ; i-- )
2016 2375
 		unregister_netdev ( phantom->netdev[i] );
2017 2376
 	phantom_halt_pegs ( phantom );

+ 9
- 0
src/drivers/net/phantom/phantom.h Ver arquivo

@@ -106,6 +106,15 @@ enum unm_reg_blocks {
106 106
 #define UNM_CAM_RAM_DMESG_SIG(n)	( UNM_CAM_RAM + 0x0003c + (n) * 0x10 )
107 107
 #define UNM_CAM_RAM_DMESG_SIG_MAGIC		0xcafebabeUL
108 108
 #define UNM_CAM_RAM_NUM_DMESG_BUFFERS		5
109
+#define UNM_CAM_RAM_CLP_COMMAND		( UNM_CAM_RAM + 0x000c0 )
110
+#define UNM_CAM_RAM_CLP_COMMAND_LAST		0x00000080UL
111
+#define UNM_CAM_RAM_CLP_DATA_LO		( UNM_CAM_RAM + 0x000c4 )
112
+#define UNM_CAM_RAM_CLP_DATA_HI		( UNM_CAM_RAM + 0x000c8 )
113
+#define UNM_CAM_RAM_CLP_STATUS		( UNM_CAM_RAM + 0x000cc )
114
+#define UNM_CAM_RAM_CLP_STATUS_START		0x00000001UL
115
+#define UNM_CAM_RAM_CLP_STATUS_DONE		0x00000002UL
116
+#define UNM_CAM_RAM_CLP_STATUS_ERROR		0x0000ff00UL
117
+#define UNM_CAM_RAM_CLP_STATUS_UNINITIALISED	0xffffffffUL
109 118
 #define UNM_CAM_RAM_WOL_PORT_MODE	( UNM_CAM_RAM + 0x00198 )
110 119
 #define UNM_CAM_RAM_MAC_ADDRS		( UNM_CAM_RAM + 0x001c0 )
111 120
 #define UNM_CAM_RAM_COLD_BOOT		( UNM_CAM_RAM + 0x001fc )

Carregando…
Cancelar
Salvar