Browse Source

[phantom] Unhalt/halt all PEGs during driver startup/shutdown

A hardware bug means that reads through the expansion ROM BAR can
return corrupted data if the PEGs are running.  This breaks platforms
that re-read the expansion ROM after invoking gPXE code, such as IBM
blade servers.

Halt PEGs during driver shutdown, and unhalt PEGs during driver
startup if we detect that this is not the first startup since
power-on.
tags/v0.9.6
Michael Brown 15 years ago
parent
commit
664f4cf365
2 changed files with 70 additions and 0 deletions
  1. 45
    0
      src/drivers/net/phantom/phantom.c
  2. 25
    0
      src/drivers/net/phantom/phantom.h

+ 45
- 0
src/drivers/net/phantom/phantom.c View File

@@ -294,6 +294,11 @@ static unsigned long phantom_crb_access_2m ( struct phantom_nic *phantom,
294 294
 		{ UNM_CRB_BLK_CAM,	0x416 },
295 295
 		{ UNM_CRB_BLK_ROMUSB,	0x421 },
296 296
 		{ UNM_CRB_BLK_TEST,	0x295 },
297
+		{ UNM_CRB_BLK_PEG_0,	0x340 },
298
+		{ UNM_CRB_BLK_PEG_1,	0x341 },
299
+		{ UNM_CRB_BLK_PEG_2,	0x342 },
300
+		{ UNM_CRB_BLK_PEG_3,	0x343 },
301
+		{ UNM_CRB_BLK_PEG_4,	0x34b },
297 302
 	};
298 303
 	unsigned int block = UNM_CRB_BLK ( reg );
299 304
 	unsigned long offset = UNM_CRB_OFFSET ( reg );
@@ -1687,6 +1692,39 @@ static int phantom_read_flash ( struct phantom_nic *phantom ) {
1687 1692
 	return 0;
1688 1693
 }
1689 1694
 
1695
+/**
1696
+ * Halt all PEGs
1697
+ *
1698
+ * @v phantom		Phantom NIC
1699
+ */
1700
+static void phantom_halt_pegs ( struct phantom_nic *phantom ) {
1701
+	phantom_writel ( phantom, 1, UNM_PEG_0_HALT );
1702
+	phantom_writel ( phantom, 1, UNM_PEG_1_HALT );
1703
+	phantom_writel ( phantom, 1, UNM_PEG_2_HALT );
1704
+	phantom_writel ( phantom, 1, UNM_PEG_3_HALT );
1705
+	phantom_writel ( phantom, 1, UNM_PEG_4_HALT );
1706
+}
1707
+
1708
+/**
1709
+ * Unhalt all PEGs
1710
+ *
1711
+ * @v phantom		Phantom NIC
1712
+ */
1713
+static void phantom_unhalt_pegs ( struct phantom_nic *phantom ) {
1714
+	uint32_t halt_status;
1715
+
1716
+	halt_status = phantom_readl ( phantom, UNM_PEG_0_HALT_STATUS );
1717
+	phantom_writel ( phantom, halt_status, UNM_PEG_0_HALT_STATUS );
1718
+	halt_status = phantom_readl ( phantom, UNM_PEG_1_HALT_STATUS );
1719
+	phantom_writel ( phantom, halt_status, UNM_PEG_1_HALT_STATUS );
1720
+	halt_status = phantom_readl ( phantom, UNM_PEG_2_HALT_STATUS );
1721
+	phantom_writel ( phantom, halt_status, UNM_PEG_2_HALT_STATUS );
1722
+	halt_status = phantom_readl ( phantom, UNM_PEG_3_HALT_STATUS );
1723
+	phantom_writel ( phantom, halt_status, UNM_PEG_3_HALT_STATUS );
1724
+	halt_status = phantom_readl ( phantom, UNM_PEG_4_HALT_STATUS );
1725
+	phantom_writel ( phantom, halt_status, UNM_PEG_4_HALT_STATUS );
1726
+}
1727
+
1690 1728
 /**
1691 1729
  * Initialise the Phantom command PEG
1692 1730
  *
@@ -1709,6 +1747,11 @@ static int phantom_init_cmdpeg ( struct phantom_nic *phantom ) {
1709 1747
 	if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK ) {
1710 1748
 		DBGC ( phantom, "Phantom %p command PEG already initialized\n",
1711 1749
 		       phantom );
1750
+		/* Unhalt the PEGs.  Previous firmware (e.g. BOFM) may
1751
+		 * have halted the PEGs to prevent internal bus
1752
+		 * collisions when the BIOS re-reads the expansion ROM.
1753
+		 */
1754
+		phantom_unhalt_pegs ( phantom );
1712 1755
 		return 0;
1713 1756
 	}
1714 1757
 
@@ -1942,6 +1985,7 @@ static int phantom_probe ( struct pci_device *pci,
1942 1985
 	for ( ; i >= 0 ; i-- )
1943 1986
 		unregister_netdev ( phantom->netdev[i] );
1944 1987
  err_init_rcvpeg:
1988
+	phantom_halt_pegs ( phantom );
1945 1989
  err_init_cmdpeg:
1946 1990
 	free_dma ( phantom->dma_buf, sizeof ( *(phantom->dma_buf) ) );
1947 1991
 	phantom->dma_buf = NULL;
@@ -1970,6 +2014,7 @@ static void phantom_remove ( struct pci_device *pci ) {
1970 2014
 
1971 2015
 	for ( i = ( phantom->num_ports - 1 ) ; i >= 0 ; i-- )
1972 2016
 		unregister_netdev ( phantom->netdev[i] );
2017
+	phantom_halt_pegs ( phantom );
1973 2018
 	free_dma ( phantom->dma_buf, sizeof ( *(phantom->dma_buf) ) );
1974 2019
 	phantom->dma_buf = NULL;
1975 2020
 	for ( i = ( phantom->num_ports - 1 ) ; i >= 0 ; i-- ) {

+ 25
- 0
src/drivers/net/phantom/phantom.h View File

@@ -80,6 +80,11 @@ enum unm_reg_blocks {
80 80
 	UNM_CRB_BLK_CAM		= 0x22,
81 81
 	UNM_CRB_BLK_ROMUSB	= 0x33,
82 82
 	UNM_CRB_BLK_TEST	= 0x02,
83
+	UNM_CRB_BLK_PEG_0	= 0x11,
84
+	UNM_CRB_BLK_PEG_1	= 0x12,
85
+	UNM_CRB_BLK_PEG_2	= 0x13,
86
+	UNM_CRB_BLK_PEG_3	= 0x14,
87
+	UNM_CRB_BLK_PEG_4	= 0x0f,
83 88
 };
84 89
 #define UNM_CRB_BASE(blk)		( (blk) << 20 )
85 90
 #define UNM_CRB_BLK(reg)		( (reg) >> 20 )
@@ -160,6 +165,26 @@ enum unm_reg_blocks {
160 165
 #define UNM_TEST_RDDATA_LO		( UNM_CRB_TEST + 0x000a8 )
161 166
 #define UNM_TEST_RDDATA_HI		( UNM_CRB_TEST + 0x000ac )
162 167
 
168
+#define UNM_CRB_PEG_0			UNM_CRB_BASE ( UNM_CRB_BLK_PEG_0 )
169
+#define UNM_PEG_0_HALT_STATUS		( UNM_CRB_PEG_0 + 0x00030 )
170
+#define UNM_PEG_0_HALT			( UNM_CRB_PEG_0 + 0x0003c )
171
+
172
+#define UNM_CRB_PEG_1			UNM_CRB_BASE ( UNM_CRB_BLK_PEG_1 )
173
+#define UNM_PEG_1_HALT_STATUS		( UNM_CRB_PEG_1 + 0x00030 )
174
+#define UNM_PEG_1_HALT			( UNM_CRB_PEG_1 + 0x0003c )
175
+
176
+#define UNM_CRB_PEG_2			UNM_CRB_BASE ( UNM_CRB_BLK_PEG_2 )
177
+#define UNM_PEG_2_HALT_STATUS		( UNM_CRB_PEG_2 + 0x00030 )
178
+#define UNM_PEG_2_HALT			( UNM_CRB_PEG_2 + 0x0003c )
179
+
180
+#define UNM_CRB_PEG_3			UNM_CRB_BASE ( UNM_CRB_BLK_PEG_3 )
181
+#define UNM_PEG_3_HALT_STATUS		( UNM_CRB_PEG_3 + 0x00030 )
182
+#define UNM_PEG_3_HALT			( UNM_CRB_PEG_3 + 0x0003c )
183
+
184
+#define UNM_CRB_PEG_4			UNM_CRB_BASE ( UNM_CRB_BLK_PEG_4 )
185
+#define UNM_PEG_4_HALT_STATUS		( UNM_CRB_PEG_4 + 0x00030 )
186
+#define UNM_PEG_4_HALT			( UNM_CRB_PEG_4 + 0x0003c )
187
+
163 188
 /******************************************************************************
164 189
  *
165 190
  * Flash layout

Loading…
Cancel
Save