Browse Source

[efi] Rewrite SNP NIC driver

Rewrite the SNP NIC driver to use non-blocking and deferrable
transmissions, to provide link status detection, to provide
information about the underlying (PCI) hardware device, and to avoid
unnecessary I/O buffer allocations during receive polling.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
d0cfbd01f5

+ 2
- 144
src/drivers/net/efi/snp.c View File

@@ -19,17 +19,12 @@
19 19
 
20 20
 FILE_LICENCE ( GPL2_OR_LATER );
21 21
 
22
-#include <stdlib.h>
23
-#include <stdio.h>
24
-#include <string.h>
25 22
 #include <errno.h>
26 23
 #include <ipxe/efi/efi.h>
27 24
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
28 25
 #include <ipxe/efi/efi_driver.h>
29 26
 #include <ipxe/efi/efi_snp.h>
30
-#include <ipxe/efi/efi_pci.h>
31 27
 #include "snpnet.h"
32
-#include "snp.h"
33 28
 
34 29
 /** @file
35 30
  *
@@ -41,10 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
41 36
 static EFI_GUID efi_simple_network_protocol_guid
42 37
 	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
43 38
 
44
-/** EFI PCI I/O protocol GUID */
45
-static EFI_GUID efi_pci_io_protocol_guid
46
-	= EFI_PCI_IO_PROTOCOL_GUID;
47
-
48 39
 /**
49 40
  * Check to see if driver supports a device
50 41
  *
@@ -77,143 +68,10 @@ static int snp_supported ( EFI_HANDLE device ) {
77 68
 	return 0;
78 69
 }
79 70
 
80
-/**
81
- * Get underlying PCI device information
82
- *
83
- * @v snpdev		SNP device
84
- * @ret rc		Return status code
85
- */
86
-static int snp_pci_info ( struct snp_device *snpdev ) {
87
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
88
-	struct efi_device *efidev = snpdev->efidev;
89
-	EFI_DEVICE_PATH_PROTOCOL *devpath = efidev->path;
90
-	struct pci_device pci;
91
-	EFI_HANDLE device;
92
-	EFI_STATUS efirc;
93
-	int rc;
94
-
95
-	/* Check for presence of PCI I/O protocol */
96
-	if ( ( efirc = bs->LocateDevicePath ( &efi_pci_io_protocol_guid,
97
-					      &devpath, &device ) ) != 0 ) {
98
-		DBGC ( efidev->device, "SNP %p %s is not a PCI device\n",
99
-		       efidev->device, efi_devpath_text ( efidev->path ) );
100
-		return -EEFI ( efirc );
101
-	}
102
-
103
-	/* Get PCI device information */
104
-	if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) {
105
-		DBGC ( efidev->device, "SNP %p %s could not get PCI "
106
-		       "information: %s\n", efidev->device,
107
-		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
108
-		return rc;
109
-	}
110
-
111
-	/* Populate SNP device information */
112
-	memcpy ( &snpdev->dev.desc, &pci.dev.desc, sizeof ( snpdev->dev.desc ));
113
-	snprintf ( snpdev->dev.name, sizeof ( snpdev->dev.name ), "SNP-%s",
114
-		   pci.dev.name );
115
-
116
-	return 0;
117
-}
118
-
119
-/**
120
- * Attach driver to device
121
- *
122
- * @v efidev		EFI device
123
- * @ret rc		Return status code
124
- */
125
-static int snp_start ( struct efi_device *efidev ) {
126
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
127
-	EFI_HANDLE device = efidev->device;
128
-	struct snp_device *snpdev;
129
-	union {
130
-		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
131
-		void *interface;
132
-	} snp;
133
-	EFI_STATUS efirc;
134
-	int rc;
135
-
136
-	/* Check that this is not a device we are providing ourselves */
137
-	if ( find_snpdev ( efidev->device ) != NULL ) {
138
-		DBGCP ( device, "SNP %p %s is provided by this binary\n",
139
-			device, efi_devpath_text ( efidev->path ) );
140
-		rc = -ENOTTY;
141
-		goto err_own;
142
-	}
143
-
144
-	/* Allocate and initialise structure */
145
-	snpdev = zalloc ( sizeof ( *snpdev ) );
146
-	if ( ! snpdev ) {
147
-		rc = -ENOMEM;
148
-		goto err_alloc;
149
-	}
150
-	snpdev->efidev = efidev;
151
-	snpdev->dev.driver_name = "SNP";
152
-	INIT_LIST_HEAD ( &snpdev->dev.children );
153
-
154
-	/* See if device is an SNP device */
155
-	if ( ( efirc = bs->OpenProtocol ( device,
156
-					  &efi_simple_network_protocol_guid,
157
-					  &snp.interface, efi_image_handle,
158
-					  device,
159
-					  ( EFI_OPEN_PROTOCOL_BY_DRIVER |
160
-					    EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
161
-		rc = -EEFI ( efirc );
162
-		DBGCP ( device, "SNP %p %s cannot open SNP protocol: %s\n",
163
-			device, efi_devpath_text ( efidev->path ),
164
-			strerror ( rc ) );
165
-		goto err_open_protocol;
166
-	}
167
-	snpdev->snp = snp.snp;
168
-
169
-	/* Get underlying device information */
170
-	if ( ( rc = snp_pci_info ( snpdev ) ) != 0 )
171
-		goto err_info;
172
-
173
-	/* Mark SNP device as a child of the EFI device */
174
-	snpdev->dev.parent = &efidev->dev;
175
-	list_add ( &snpdev->dev.siblings, &efidev->dev.children );
176
-
177
-	/* Create SNP network device */
178
-	if ( ( rc = snpnet_probe ( snpdev ) ) != 0 )
179
-		goto err_probe;
180
-
181
-	efidev_set_drvdata ( efidev, snpdev );
182
-	return 0;
183
-
184
-	snpnet_remove ( snpdev );
185
- err_probe:
186
-	list_del ( &snpdev->dev.siblings );
187
- err_info:
188
-	bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
189
-			    efi_image_handle, device );
190
- err_open_protocol:
191
-	free ( snpdev );
192
- err_alloc:
193
- err_own:
194
-	return rc;
195
-}
196
-
197
-/**
198
- * Detach driver from device
199
- *
200
- * @v efidev		EFI device
201
-  */
202
-static void snp_stop ( struct efi_device *efidev ) {
203
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
204
-	struct snp_device *snpdev = efidev_get_drvdata ( efidev );
205
-
206
-	snpnet_remove ( snpdev );
207
-	list_del ( &snpdev->dev.siblings );
208
-	bs->CloseProtocol ( efidev->device, &efi_simple_network_protocol_guid,
209
-			    efi_image_handle, efidev->device );
210
-	free ( snpdev );
211
-}
212
-
213 71
 /** EFI SNP driver */
214 72
 struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
215 73
 	.name = "SNP",
216 74
 	.supported = snp_supported,
217
-	.start = snp_start,
218
-	.stop = snp_stop,
75
+	.start = snpnet_start,
76
+	.stop = snpnet_stop,
219 77
 };

+ 0
- 48
src/drivers/net/efi/snp.h View File

@@ -1,48 +0,0 @@
1
-/*
2
- * Copyright (C) 2010 VMware, Inc.  All Rights Reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation; either version 2 of the
7
- * License, or any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful, but
10
- * WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
- * General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
- */
18
-
19
-#ifndef _SNP_H
20
-#define _SNP_H
21
-
22
-/** @file
23
- *
24
- * SNP driver
25
- *
26
- */
27
-
28
-FILE_LICENCE ( GPL2_OR_LATER );
29
-
30
-#include <ipxe/device.h>
31
-#include <ipxe/efi/efi.h>
32
-#include <ipxe/efi/Protocol/SimpleNetwork.h>
33
-
34
-/** An SNP device */
35
-struct snp_device {
36
-	/** EFI device */
37
-	struct efi_device *efidev;
38
-	/** Simple network protocol */
39
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp;
40
-	/** Generic device */
41
-	struct device dev;
42
-	/** Network device */
43
-	struct net_device *netdev;
44
-	/** State to restore when removing the device */
45
-	UINT32 removal_state;
46
-};
47
-
48
-#endif /* _SNP_H */

+ 392
- 204
src/drivers/net/efi/snpnet.c View File

@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (C) 2010 VMware, Inc.  All Rights Reserved.
2
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 3
  *
4 4
  * This program is free software; you can redistribute it and/or
5 5
  * modify it under the terms of the GNU General Public License as
@@ -13,38 +13,85 @@
13 13
  *
14 14
  * You should have received a copy of the GNU General Public License
15 15
  * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
17 18
  */
18 19
 
19 20
 FILE_LICENCE ( GPL2_OR_LATER );
20 21
 
21
-#include <errno.h>
22
+#include <stdlib.h>
23
+#include <stdio.h>
22 24
 #include <string.h>
23
-#include <ipxe/io.h>
25
+#include <errno.h>
24 26
 #include <ipxe/iobuf.h>
25 27
 #include <ipxe/netdevice.h>
26
-#include <ipxe/if_ether.h>
27 28
 #include <ipxe/ethernet.h>
28 29
 #include <ipxe/efi/efi.h>
29 30
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
30
-#include "snp.h"
31
+#include <ipxe/efi/efi_driver.h>
32
+#include <ipxe/efi/efi_pci.h>
31 33
 #include "snpnet.h"
32 34
 
33 35
 /** @file
34 36
  *
35
- * SNP network device driver
37
+ * SNP NIC driver
36 38
  *
37 39
  */
38 40
 
39
-/** SNP net device structure */
40
-struct snpnet_device {
41
-	/** The underlying simple network protocol */
41
+/** An SNP NIC */
42
+struct snp_nic {
43
+	/** EFI device */
44
+	struct efi_device *efidev;
45
+	/** Simple network protocol */
42 46
 	EFI_SIMPLE_NETWORK_PROTOCOL *snp;
47
+	/** Generic device */
48
+	struct device dev;
49
+
50
+	/** Maximum packet size
51
+	 *
52
+	 * This is calculated as the sum of MediaHeaderSize and
53
+	 * MaxPacketSize, and may therefore be an overestimate.
54
+	 */
55
+	size_t mtu;
43 56
 
44
-	/** State that the SNP should be in after close */
45
-	UINT32 close_state;
57
+	/** Current transmit buffer */
58
+	struct io_buffer *txbuf;
59
+	/** Current receive buffer */
60
+	struct io_buffer *rxbuf;
46 61
 };
47 62
 
63
+/** Maximum number of received packets per poll */
64
+#define SNP_RX_QUOTA 4
65
+
66
+/** EFI simple network protocol GUID */
67
+static EFI_GUID efi_simple_network_protocol_guid
68
+	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
69
+
70
+/** EFI PCI I/O protocol GUID */
71
+static EFI_GUID efi_pci_io_protocol_guid
72
+	= EFI_PCI_IO_PROTOCOL_GUID;
73
+
74
+/**
75
+ * Check link state
76
+ *
77
+ * @v netdev		Network device
78
+ */
79
+static void snpnet_check_link ( struct net_device *netdev ) {
80
+	struct snp_nic *snp = netdev_priv ( netdev );
81
+	EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
82
+
83
+	/* Do nothing unless media presence detection is supported */
84
+	if ( ! mode->MediaPresentSupported )
85
+		return;
86
+
87
+	/* Report any link status change */
88
+	if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) {
89
+		netdev_link_up ( netdev );
90
+	} else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) {
91
+		netdev_link_down ( netdev );
92
+	}
93
+}
94
+
48 95
 /**
49 96
  * Transmit packet
50 97
  *
@@ -54,297 +101,438 @@ struct snpnet_device {
54 101
  */
55 102
 static int snpnet_transmit ( struct net_device *netdev,
56 103
 			     struct io_buffer *iobuf ) {
57
-	struct snpnet_device *snpnetdev = netdev->priv;
58
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
59
-	void *txbuf=NULL;
60
-	size_t len = iob_len ( iobuf );
104
+	struct snp_nic *snp = netdev_priv ( netdev );
61 105
 	EFI_STATUS efirc;
62 106
 	int rc;
63 107
 
64
-	if ( ( efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL,
65
-				       NULL ) ) != 0 ) {
66
-		return -EEFI ( efirc );
108
+	/* Defer the packet if there is already a transmission in progress */
109
+	if ( snp->txbuf ) {
110
+		netdev_tx_defer ( netdev, iobuf );
111
+		return 0;
67 112
 	}
68
-	/* since GetStatus is so inconsistent, don't try more than one outstanding transmit at a time */
69
-	while ( txbuf == NULL ) {
70
-		if ( ( efirc = snp->GetStatus ( snp, NULL, &txbuf ) ) != 0 ) {
71
-			rc = -EEFI ( efirc );
72
-			DBGC ( snp, "SNP %p could not get status %s\n", snp,
73
-			       strerror ( rc ) );
74
-			break;
75
-		}
76 113
 
114
+	/* Transmit packet */
115
+	if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
116
+					    iobuf->data, NULL, NULL,
117
+					    NULL ) ) != 0 ) {
118
+		rc = -EEFI ( efirc );
119
+		DBGC ( snp, "SNP %s could not transmit: %s\n",
120
+		       netdev->name, strerror ( rc ) );
121
+		return rc;
77 122
 	}
78
-	netdev_tx_complete ( netdev, iobuf );
123
+	snp->txbuf = iobuf;
124
+
79 125
 	return 0;
80 126
 }
81 127
 
128
+/**
129
+ * Poll for completed packets
130
+ *
131
+ * @v netdev		Network device
132
+ */
133
+static void snpnet_poll_tx ( struct net_device *netdev ) {
134
+	struct snp_nic *snp = netdev->priv;
135
+	UINT32 irq;
136
+	VOID *txbuf;
137
+	EFI_STATUS efirc;
138
+	int rc;
139
+
140
+	/* Get status */
141
+	if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
142
+		rc = -EEFI ( efirc );
143
+		DBGC ( snp, "SNP %s could not get status: %s\n",
144
+		       netdev->name, strerror ( rc ) );
145
+		netdev_rx_err ( netdev, NULL, rc );
146
+		return;
147
+	}
148
+
149
+	/* Do nothing unless we have a completion */
150
+	if ( ! txbuf )
151
+		return;
152
+
153
+	/* Sanity check */
154
+	if ( ! snp->txbuf ) {
155
+		DBGC ( snp, "SNP %s reported spurious TX completion\n",
156
+		       netdev->name );
157
+		netdev_tx_err ( netdev, NULL, -EPIPE );
158
+		return;
159
+	}
160
+
161
+	/* Complete transmission */
162
+	netdev_tx_complete ( netdev, snp->txbuf );
163
+	snp->txbuf = NULL;
164
+}
165
+
82 166
 /**
83 167
  * Poll for received packets
84 168
  *
85 169
  * @v netdev		Network device
86 170
  */
87
-static void snpnet_poll ( struct net_device *netdev ) {
88
-	struct snpnet_device *snpnetdev = netdev->priv;
89
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
90
-	struct io_buffer *iobuf = NULL;
171
+static void snpnet_poll_rx ( struct net_device *netdev ) {
172
+	struct snp_nic *snp = netdev->priv;
91 173
 	UINTN len;
174
+	unsigned int quota;
92 175
 	EFI_STATUS efirc;
93 176
 	int rc;
94 177
 
95
-	/* Process received packets */
96
-	while ( 1 ) {
97
-		/* The spec is not clear if the max packet size refers to the
98
-		 * payload or the entire packet including headers. The Receive
99
-		 * function needs a buffer large enough to contain the headers,
100
-		 * and potentially a 4-byte CRC and 4-byte VLAN tag (?), so add
101
-		 * some breathing room.
102
-		 */
103
-		len = snp->Mode->MaxPacketSize + ETH_HLEN + 8;
104
-		iobuf = alloc_iob ( len );
105
-		if ( iobuf == NULL ) {
106
-			netdev_rx_err ( netdev, NULL, -ENOMEM );
107
-			break;
178
+	/* Retrieve up to SNP_RX_QUOTA packets */
179
+	for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) {
180
+
181
+		/* Allocate buffer, if required */
182
+		if ( ! snp->rxbuf ) {
183
+			snp->rxbuf = alloc_iob ( snp->mtu );
184
+			if ( ! snp->rxbuf ) {
185
+				/* Leave for next poll */
186
+				break;
187
+			}
108 188
 		}
109 189
 
110
-		efirc = snp->Receive ( snp, NULL, &len, iobuf->data,
111
-				       NULL, NULL, NULL );
190
+		/* Receive packet */
191
+		len = iob_tailroom ( snp->rxbuf );
192
+		if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len,
193
+						   snp->rxbuf->data, NULL,
194
+						   NULL, NULL ) ) != 0 ) {
112 195
 
113
-		/* No packets left? */
114
-		if ( efirc == EFI_NOT_READY ) {
115
-			free_iob ( iobuf );
116
-			break;
117
-		}
196
+			/* EFI_NOT_READY is just the usual "no packet"
197
+			 * status indication; ignore it.
198
+			 */
199
+			if ( efirc == EFI_NOT_READY )
200
+				break;
118 201
 
119
-		/* Other error? */
120
-		if ( efirc != 0 ) {
202
+			/* Anything else is an error */
121 203
 			rc = -EEFI ( efirc );
122
-			DBGC ( snp, "SNP %p receive packet error: %s "
123
-				    "(len was %zd, is now %zd)\n",
124
-			       snp, strerror ( rc ), iob_len(iobuf),
125
-			       (size_t)len );
126
-			netdev_rx_err ( netdev, iobuf, rc );
204
+			DBGC ( snp, "SNP %s could not receive: %s\n",
205
+			       netdev->name, strerror ( rc ) );
206
+			netdev_rx_err ( netdev, NULL, rc );
127 207
 			break;
128 208
 		}
129 209
 
130
-		/* Packet is valid, deliver it */
131
-		iob_put ( iobuf, len );
132
-		netdev_rx ( netdev, iob_disown ( iobuf ) );
210
+		/* Hand off to network stack */
211
+		iob_put ( snp->rxbuf, len );
212
+		netdev_rx ( netdev, snp->rxbuf );
213
+		snp->rxbuf = NULL;
133 214
 	}
134 215
 }
135 216
 
136 217
 /**
137
- * Open NIC
218
+ * Poll for completed packets
138 219
  *
139
- * @v netdev		Net device
220
+ * @v netdev		Network device
221
+ */
222
+static void snpnet_poll ( struct net_device *netdev ) {
223
+
224
+	/* Process any TX completions */
225
+	snpnet_poll_tx ( netdev );
226
+
227
+	/* Process any RX completions */
228
+	snpnet_poll_rx ( netdev );
229
+
230
+	/* Check for link state changes */
231
+	snpnet_check_link ( netdev );
232
+}
233
+
234
+/**
235
+ * Open network device
236
+ *
237
+ * @v netdev		Network device
140 238
  * @ret rc		Return status code
141 239
  */
142 240
 static int snpnet_open ( struct net_device *netdev ) {
143
-	struct snpnet_device *snpnetdev = netdev->priv;
144
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
145
-	EFI_MAC_ADDRESS *mac;
146
-	UINT32 enableFlags, disableFlags;
241
+	struct snp_nic *snp = netdev->priv;
242
+	EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
243
+	UINT32 filters;
147 244
 	EFI_STATUS efirc;
148 245
 	int rc;
149 246
 
150
-	snpnetdev->close_state = snp->Mode->State;
151
-	if ( snp->Mode->State != EfiSimpleNetworkInitialized ) {
152
-		if ( ( efirc = snp->Initialize ( snp, 0, 0 ) ) != 0 ) {
153
-			rc = -EEFI ( efirc );
154
-			DBGC ( snp, "SNP %p could not initialize: %s\n",
155
-			       snp, strerror ( rc ) );
156
-			return rc;
157
-		}
247
+	/* Try setting MAC address (before initialising) */
248
+	if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
249
+		rc = -EEFI ( efirc );
250
+		DBGC ( snp, "SNP %s could not set station address before "
251
+		       "initialising: %s\n", netdev->name, strerror ( rc ) );
252
+		/* Ignore error */
158 253
 	}
159 254
 
160
-        /* Use the default MAC address */
161
-	mac = ( ( void * ) netdev->ll_addr );
162
-	if ( ( efirc = snp->StationAddress ( snp, FALSE, mac ) ) != 0 ) {
255
+	/* Initialise NIC */
256
+	if ( ( efirc = snp->snp->Initialize ( snp->snp, 0, 0 ) ) != 0 ) {
163 257
 		rc = -EEFI ( efirc );
164
-		DBGC ( snp, "SNP %p could not reset station address: %s\n",
165
-		       snp, strerror ( rc ) );
258
+		DBGC ( snp, "SNP %s could not initialise: %s\n",
259
+		       netdev->name, strerror ( rc ) );
260
+		return rc;
166 261
 	}
167 262
 
168
-	/* Set up receive filters to receive unicast and broadcast packets
169
-	 * always. Also, enable either promiscuous multicast (if possible) or
170
-	 * promiscuous operation, in order to catch all multicast packets.
171
-	 */
172
-	enableFlags = snp->Mode->ReceiveFilterMask &
173
-		      ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
174
-			EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
175
-	disableFlags = snp->Mode->ReceiveFilterMask &
176
-		       ( EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
177
-			 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
178
-			 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST );
179
-	if ( snp->Mode->ReceiveFilterMask &
180
-	     EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST ) {
181
-		enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
182
-	} else if ( snp->Mode->ReceiveFilterMask &
183
-		    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS ) {
184
-		enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
263
+	/* Try setting MAC address (after initialising) */
264
+	if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
265
+		rc = -EEFI ( efirc );
266
+		DBGC ( snp, "SNP %s could not set station address after "
267
+		       "initialising: %s\n", netdev->name, strerror ( rc ) );
268
+		/* Ignore error */
185 269
 	}
186
-	disableFlags &= ~enableFlags;
187
-	if ( ( efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags,
188
-					     FALSE, 0, NULL ) ) != 0 ) {
270
+
271
+	/* Set receive filters */
272
+	filters = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
273
+		    EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
274
+		    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
275
+		    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
276
+		    EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST );
277
+	if ( ( efirc = snp->snp->ReceiveFilters ( snp->snp, filters, 0, FALSE,
278
+						  0, NULL ) ) != 0 ) {
189 279
 		rc = -EEFI ( efirc );
190
-		DBGC ( snp, "SNP %p could not set receive filters: %s\n",
191
-		       snp, strerror ( rc ) );
280
+		DBGC ( snp, "SNP %s could not set receive filters: %s\n",
281
+		       netdev->name, strerror ( rc ) );
282
+		/* Ignore error */
192 283
 	}
193 284
 
194
-	DBGC ( snp, "SNP %p opened\n", snp );
195 285
 	return 0;
196 286
 }
197 287
 
198 288
 /**
199
- * Close NIC
289
+ * Close network device
200 290
  *
201
- * @v netdev		Net device
291
+ * @v netdev		Network device
202 292
  */
203 293
 static void snpnet_close ( struct net_device *netdev ) {
204
-	struct snpnet_device *snpnetdev = netdev->priv;
205
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
294
+	struct snp_nic *snp = netdev->priv;
206 295
 	EFI_STATUS efirc;
207 296
 	int rc;
208 297
 
209
-	if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) {
210
-		if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) {
211
-			rc = -EEFI ( efirc );
212
-			DBGC ( snp, "SNP %p could not shut down: %s\n",
213
-			       snp, strerror ( rc ) );
214
-		}
298
+	/* Shut down NIC */
299
+	if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) {
300
+		rc = -EEFI ( efirc );
301
+		DBGC ( snp, "SNP %s could not shut down: %s\n",
302
+		       netdev->name, strerror ( rc ) );
303
+		/* Nothing we can do about this */
215 304
 	}
216
-}
217 305
 
218
-/**
219
- * Enable/disable interrupts
220
- *
221
- * @v netdev		Net device
222
- * @v enable		Interrupts should be enabled
223
- */
224
-static void snpnet_irq ( struct net_device *netdev, int enable ) {
225
-	struct snpnet_device *snpnetdev = netdev->priv;
226
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp;
306
+	/* Discard transmit buffer, if applicable */
307
+	if ( snp->txbuf ) {
308
+		netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED );
309
+		snp->txbuf = NULL;
310
+	}
227 311
 
228
-	/* On EFI, interrupts are never necessary. (This function is only
229
-	 * required for BIOS PXE.) If interrupts were required, they could be
230
-	 * simulated using a fast timer.
231
-	 */
232
-	DBGC ( snp, "SNP %p cannot %s interrupts\n",
233
-	       snp, ( enable ? "enable" : "disable" ) );
312
+	/* Discard receive buffer, if applicable */
313
+	if ( snp->rxbuf ) {
314
+		free_iob ( snp->rxbuf );
315
+		snp->rxbuf = NULL;
316
+	}
234 317
 }
235 318
 
236 319
 /** SNP network device operations */
237 320
 static struct net_device_operations snpnet_operations = {
238
-	.open		= snpnet_open,
239
-	.close		= snpnet_close,
240
-	.transmit	= snpnet_transmit,
241
-	.poll		= snpnet_poll,
242
-	.irq   		= snpnet_irq,
321
+	.open = snpnet_open,
322
+	.close = snpnet_close,
323
+	.transmit = snpnet_transmit,
324
+	.poll = snpnet_poll,
243 325
 };
244 326
 
245 327
 /**
246
- * Probe SNP device
328
+ * Get underlying PCI device information
247 329
  *
248
- * @v snpdev		SNP device
330
+ * @v efidev		EFI device
331
+ * @v dev		Generic device to fill in
249 332
  * @ret rc		Return status code
250 333
  */
251
-int snpnet_probe ( struct snp_device *snpdev ) {
252
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
334
+static int snpnet_pci_info ( struct efi_device *efidev, struct device *dev ) {
335
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
336
+	EFI_DEVICE_PATH_PROTOCOL *devpath = efidev->path;
337
+	struct pci_device pci;
338
+	EFI_HANDLE device;
253 339
 	EFI_STATUS efirc;
340
+	int rc;
341
+
342
+	/* Check for presence of PCI I/O protocol */
343
+	if ( ( efirc = bs->LocateDevicePath ( &efi_pci_io_protocol_guid,
344
+					      &devpath, &device ) ) != 0 ) {
345
+		DBGC ( efidev->device, "SNP %p %s is not a PCI device\n",
346
+		       efidev->device, efi_devpath_text ( efidev->path ) );
347
+		return -EEFI ( efirc );
348
+	}
349
+
350
+	/* Get PCI device information */
351
+	if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) {
352
+		DBGC ( efidev->device, "SNP %p %s could not get PCI "
353
+		       "information: %s\n", efidev->device,
354
+		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
355
+		return rc;
356
+	}
357
+
358
+	/* Populate SNP device information */
359
+	memcpy ( &dev->desc, &pci.dev.desc, sizeof ( dev->desc ) );
360
+	snprintf ( dev->name, sizeof ( dev->name ), "SNP-%s", pci.dev.name );
361
+
362
+	return 0;
363
+}
364
+
365
+/**
366
+ * Get underlying device information
367
+ *
368
+ * @v efidev		EFI device
369
+ * @v dev		Generic device to fill in
370
+ * @ret rc		Return status code
371
+ */
372
+static int snpnet_dev_info ( struct efi_device *efidev, struct device *dev ) {
373
+	int rc;
374
+
375
+	/* Try getting underlying PCI device information */
376
+	if ( ( rc = snpnet_pci_info ( efidev, dev ) ) == 0 )
377
+		return 0;
378
+
379
+	DBGC ( efidev->device, "SNP %p %s could not get underlying device "
380
+	       "information\n", efidev->device,
381
+	       efi_devpath_text ( efidev->path ) );
382
+	return -ENOTTY;
383
+}
384
+
385
+/**
386
+ * Attach driver to device
387
+ *
388
+ * @v efidev		EFI device
389
+ * @ret rc		Return status code
390
+ */
391
+int snpnet_start ( struct efi_device *efidev ) {
392
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
393
+	EFI_HANDLE device = efidev->device;
394
+	EFI_SIMPLE_NETWORK_MODE *mode;
254 395
 	struct net_device *netdev;
255
-	struct snpnet_device *snpnetdev;
396
+	struct snp_nic *snp;
397
+	void *interface;
398
+	EFI_STATUS efirc;
256 399
 	int rc;
257 400
 
258
-	DBGC ( snp, "SNP %p probing...\n", snp );
401
+	/* Open SNP protocol */
402
+	if ( ( efirc = bs->OpenProtocol ( device,
403
+					  &efi_simple_network_protocol_guid,
404
+					  &interface, efi_image_handle, device,
405
+					  ( EFI_OPEN_PROTOCOL_BY_DRIVER |
406
+					    EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
407
+		rc = -EEFI ( efirc );
408
+		DBGC ( device, "SNP %p %s cannot open SNP protocol: %s\n",
409
+		       device, efi_devpath_text ( efidev->path ),
410
+		       strerror ( rc ) );
411
+		goto err_open_protocol;
412
+	}
259 413
 
260
-	/* Allocate net device */
261
-	netdev = alloc_etherdev ( sizeof ( struct snpnet_device ) );
262
-	if ( ! netdev )
263
-		return -ENOMEM;
414
+	/* Allocate and initialise structure */
415
+	netdev = alloc_etherdev ( sizeof ( *snp ) );
416
+	if ( ! netdev ) {
417
+		rc = -ENOMEM;
418
+		goto err_alloc;
419
+	}
264 420
 	netdev_init ( netdev, &snpnet_operations );
265
-	netdev->dev = &snpdev->dev;
266
-	snpdev->netdev = netdev;
267
-	snpnetdev = netdev->priv;
268
-	snpnetdev->snp = snp;
269
-	snpdev->removal_state = snp->Mode->State;
270
-
271
-	/* Start the interface */
272
-	if ( snp->Mode->State == EfiSimpleNetworkStopped ) {
273
-		if ( ( efirc = snp->Start ( snp ) ) != 0 ) {
274
-			rc = -EEFI ( efirc );
275
-			DBGC ( snp, "SNP %p could not start: %s\n", snp,
276
-			       strerror ( rc ) );
277
-			goto err_start;
278
-		}
421
+	snp = netdev->priv;
422
+	snp->efidev = efidev;
423
+	snp->snp = interface;
424
+	mode = snp->snp->Mode;
425
+	efidev_set_drvdata ( efidev, netdev );
426
+
427
+	/* Populate underlying device information */
428
+	if ( ( rc = snpnet_dev_info ( efidev, &snp->dev ) ) != 0 )
429
+		goto err_info;
430
+	snp->dev.driver_name = "SNP";
431
+	snp->dev.parent = &efidev->dev;
432
+	list_add ( &snp->dev.siblings, &efidev->dev.children );
433
+	INIT_LIST_HEAD ( &snp->dev.children );
434
+	netdev->dev = &snp->dev;
435
+
436
+	/* Bring to the Started state */
437
+	if ( ( mode->State == EfiSimpleNetworkStopped ) &&
438
+	     ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
439
+		rc = -EEFI ( efirc );
440
+		DBGC ( device, "SNP %p %s could not start: %s\n", device,
441
+		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
442
+		goto err_start;
443
+	}
444
+	if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
445
+	     ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
446
+		rc = -EEFI ( efirc );
447
+		DBGC ( device, "SNP %p %s could not shut down: %s\n", device,
448
+		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
449
+		goto err_shutdown;
279 450
 	}
280 451
 
281
-	if ( snp->Mode->HwAddressSize > sizeof ( netdev->hw_addr ) ) {
282
-		DBGC ( snp, "SNP %p hardware address is too large\n", snp );
283
-		rc = -EINVAL;
284
-		goto err_hwaddr;
452
+	/* Populate network device parameters */
453
+	if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
454
+		DBGC ( device, "SNP %p %s has invalid hardware address "
455
+		       "length %d\n", device, efi_devpath_text ( efidev->path ),
456
+		       mode->HwAddressSize );
457
+		rc = -ENOTSUP;
458
+		goto err_hw_addr_len;
459
+	}
460
+	memcpy ( netdev->hw_addr, &mode->PermanentAddress,
461
+		 netdev->ll_protocol->hw_addr_len );
462
+	if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
463
+		DBGC ( device, "SNP %p %s has invalid link-layer address "
464
+		       "length %d\n", device, efi_devpath_text ( efidev->path ),
465
+		       mode->HwAddressSize );
466
+		rc = -ENOTSUP;
467
+		goto err_ll_addr_len;
285 468
 	}
286
-	memcpy ( netdev->hw_addr, snp->Mode->PermanentAddress.Addr,
287
-		 snp->Mode->HwAddressSize );
469
+	memcpy ( netdev->ll_addr, &mode->CurrentAddress,
470
+		 netdev->ll_protocol->ll_addr_len );
471
+	snp->mtu = ( snp->snp->Mode->MaxPacketSize +
472
+		     snp->snp->Mode->MediaHeaderSize );
288 473
 
289 474
 	/* Register network device */
290 475
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
291
-		goto err_register;
292
-
293
-	/* Mark as link up; we don't handle link state */
294
-	netdev_link_up ( netdev );
476
+		goto err_register_netdev;
477
+	DBGC ( device, "SNP %p %s registered as %s\n", device,
478
+	       efi_devpath_text ( efidev->path ), netdev->name );
479
+
480
+	/* Set initial link state */
481
+	if ( snp->snp->Mode->MediaPresentSupported ) {
482
+		snpnet_check_link ( netdev );
483
+	} else {
484
+		netdev_link_up ( netdev );
485
+	}
295 486
 
296
-	DBGC ( snp, "SNP %p added\n", snp );
297 487
 	return 0;
298 488
 
299
-err_register:
300
-err_hwaddr:
301
-	if ( snpdev->removal_state == EfiSimpleNetworkStopped )
302
-		snp->Stop ( snp );
303
-
304
-err_start:
489
+	unregister_netdev ( netdev );
490
+ err_register_netdev:
491
+ err_ll_addr_len:
492
+ err_hw_addr_len:
493
+ err_shutdown:
494
+ err_start:
495
+	list_del ( &snp->dev.siblings );
496
+ err_info:
305 497
 	netdev_nullify ( netdev );
306 498
 	netdev_put ( netdev );
307
-	snpdev->netdev = NULL;
499
+ err_alloc:
500
+	bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
501
+			    efi_image_handle, device );
502
+ err_open_protocol:
308 503
 	return rc;
309 504
 }
310 505
 
311 506
 /**
312
- * Remove SNP device
507
+ * Detach driver from device
313 508
  *
314
- * @v snpdev		SNP device
315
- */
316
-void snpnet_remove ( struct snp_device *snpdev ) {
317
-	EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp;
318
-	struct net_device *netdev = snpdev->netdev;
509
+ * @v efidev		EFI device
510
+  */
511
+void snpnet_stop ( struct efi_device *efidev ) {
512
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
513
+	struct net_device *netdev = efidev_get_drvdata ( efidev );
514
+	struct snp_nic *snp = netdev->priv;
319 515
 	EFI_STATUS efirc;
320 516
 	int rc;
321 517
 
322
-	if ( snp->Mode->State == EfiSimpleNetworkInitialized &&
323
-	     snpdev->removal_state != EfiSimpleNetworkInitialized ) {
324
-		DBGC ( snp, "SNP %p shutting down\n", snp );
325
-		if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) {
326
-			rc = -EEFI ( efirc );
327
-			DBGC ( snp, "SNP %p could not shut down: %s\n",
328
-			       snp, strerror ( rc ) );
329
-		}
330
-	}
518
+	/* Unregister network device */
519
+	unregister_netdev ( netdev );
331 520
 
332
-	if ( snp->Mode->State == EfiSimpleNetworkStarted &&
333
-	     snpdev->removal_state == EfiSimpleNetworkStopped ) {
334
-		DBGC ( snp, "SNP %p stopping\n", snp );
335
-		if ( ( efirc = snp->Stop ( snp ) ) != 0 ) {
336
-			rc = -EEFI ( efirc );
337
-			DBGC ( snp, "SNP %p could not be stopped: %s\n",
338
-			       snp, strerror ( rc ) );
339
-		}
521
+	/* Stop SNP protocol */
522
+	if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
523
+		rc = -EEFI ( efirc );
524
+		DBGC ( efidev->device, "SNP %p %s could not stop: %s\n",
525
+		       efidev->device, efi_devpath_text ( efidev->path ),
526
+		       strerror ( rc ) );
527
+		/* Nothing we can do about this */
340 528
 	}
341 529
 
342
-	/* Unregister net device */
343
-	unregister_netdev ( netdev );
344
-
345 530
 	/* Free network device */
531
+	list_del ( &snp->dev.siblings );
346 532
 	netdev_nullify ( netdev );
347 533
 	netdev_put ( netdev );
348 534
 
349
-	DBGC ( snp, "SNP %p removed\n", snp );
535
+	/* Close SNP protocol */
536
+	bs->CloseProtocol ( efidev->device, &efi_simple_network_protocol_guid,
537
+			    efi_image_handle, efidev->device );
350 538
 }

+ 4
- 22
src/drivers/net/efi/snpnet.h View File

@@ -1,35 +1,17 @@
1
-/*
2
- * Copyright (C) 2010 VMware, Inc.  All Rights Reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation; either version 2 of the
7
- * License, or any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful, but
10
- * WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
- * General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
- */
18
-
19 1
 #ifndef _SNPNET_H
20 2
 #define _SNPNET_H
21 3
 
22 4
 /** @file
23 5
  *
24
- * EFI Simple Network Protocol network device driver
6
+ * SNP NIC driver
25 7
  *
26 8
  */
27 9
 
28 10
 FILE_LICENCE ( GPL2_OR_LATER );
29 11
 
30
-struct snp_device;
12
+struct efi_device;
31 13
 
32
-extern int snpnet_probe ( struct snp_device *snpdev );
33
-extern void snpnet_remove ( struct snp_device *snpdev );
14
+extern int snpnet_start ( struct efi_device *efidev );
15
+extern void snpnet_stop ( struct efi_device *efidev );
34 16
 
35 17
 #endif /* _SNPNET_H */

+ 20
- 92
src/drivers/net/efi/snponly.c View File

@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (C) 2010 VMware, Inc.  All Rights Reserved.
2
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 3
  *
4 4
  * This program is free software; you can redistribute it and/or
5 5
  * modify it under the terms of the GNU General Public License as
@@ -13,117 +13,45 @@
13 13
  *
14 14
  * You should have received a copy of the GNU General Public License
15 15
  * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
17 18
  */
18 19
 
19 20
 FILE_LICENCE ( GPL2_OR_LATER );
20 21
 
21
-#include <string.h>
22 22
 #include <errno.h>
23
-#include <ipxe/device.h>
24
-#include <ipxe/init.h>
25 23
 #include <ipxe/efi/efi.h>
26
-#include <ipxe/efi/Protocol/SimpleNetwork.h>
27
-#include "snp.h"
24
+#include <ipxe/efi/efi_driver.h>
28 25
 #include "snpnet.h"
29 26
 
30 27
 /** @file
31 28
  *
32
- * Chain-loading Simple Network Protocol Bus Driver
29
+ * SNP chainloaded-device-only driver
33 30
  *
34
- * This bus driver allows iPXE to use the EFI Simple Network Protocol provided
35
- * by the platform to transmit and receive packets. It attaches to only the
36
- * device handle that iPXE was loaded from, that is, it will only use the
37
- * Simple Network Protocol on the current loaded image's device handle.
38
- *
39
- * Eseentially, this driver provides the EFI equivalent of the "undionly"
40
- * driver.
41 31
  */
42 32
 
43
-/** The one and only SNP network device */
44
-static struct snp_device snponly_dev;
45
-
46
-/** EFI simple network protocol GUID */
47
-static EFI_GUID efi_simple_network_protocol_guid
48
-	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
49
-
50 33
 /**
51
- * Probe SNP root bus
34
+ * Check to see if driver supports a device
52 35
  *
53
- * @v rootdev		SNP bus root device
54
- *
55
- * Look at the loaded image's device handle and see if the simple network
56
- * protocol exists. If so, register a driver for it.
36
+ * @v device		EFI device handle
37
+ * @ret rc		Return status code
57 38
  */
58
-static int snpbus_probe ( struct root_device *rootdev ) {
59
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
60
-	EFI_STATUS efirc;
61
-	int rc;
62
-	void *snp;
63
-
64
-	efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
65
-				   &efi_simple_network_protocol_guid,
66
-				   &snp, efi_image_handle, NULL,
67
-				   EFI_OPEN_PROTOCOL_GET_PROTOCOL );
68
-	if ( efirc ) {
69
-		DBG ( "Could not find Simple Network Protocol!\n" );
70
-		return -ENODEV;
71
-	}
72
-	snponly_dev.snp = snp;
39
+static int snponly_supported ( EFI_HANDLE device ) {
73 40
 
74
-	/* Add to device hierarchy */
75
-	strncpy ( snponly_dev.dev.name, "EFI SNP",
76
-		  ( sizeof ( snponly_dev.dev.name ) - 1 ) );
77
-	snponly_dev.dev.parent = &rootdev->dev;
78
-	list_add ( &snponly_dev.dev.siblings, &rootdev->dev.children);
79
-	INIT_LIST_HEAD ( &snponly_dev.dev.children );
41
+	/* Check that this device is our loaded image's device */
42
+	if ( device != efi_loaded_image->DeviceHandle )
43
+		return -ENOTTY;
80 44
 
81
-	/* Create network device */
82
-	if ( ( rc = snpnet_probe ( &snponly_dev ) ) != 0 )
83
-		goto err;
45
+	DBGC ( device, "SNP %p %s is the SNP chainloading device\n",
46
+	       device, efi_handle_devpath_text ( device ) );
84 47
 
85 48
 	return 0;
86
-
87
-err:
88
-	list_del ( &snponly_dev.dev.siblings );
89
-	return rc;
90
-}
91
-
92
-/**
93
- * Remove SNP root bus
94
- *
95
- * @v rootdev		SNP bus root device
96
- */
97
-static void snpbus_remove ( struct root_device *rootdev __unused ) {
98
-	snpnet_remove ( &snponly_dev );
99
-	list_del ( &snponly_dev.dev.siblings );
100
-}
101
-
102
-/** SNP bus root device driver */
103
-static struct root_driver snp_root_driver = {
104
-	.probe = snpbus_probe,
105
-	.remove = snpbus_remove,
106
-};
107
-
108
-/** SNP bus root device */
109
-struct root_device snp_root_device __root_device = {
110
-	.dev = { .name = "EFI SNP" },
111
-	.driver = &snp_root_driver,
112
-};
113
-
114
-/**
115
- * Prepare for exit
116
- *
117
- * @v booting		System is shutting down for OS boot
118
- */
119
-static void snponly_shutdown ( int booting ) {
120
-	/* If we are shutting down to boot an OS, make sure the SNP does not
121
-	 * stay active.
122
-	 */
123
-	if ( booting )
124
-		snponly_dev.removal_state = EfiSimpleNetworkStopped;
125 49
 }
126 50
 
127
-struct startup_fn startup_snponly __startup_fn ( STARTUP_LATE ) = {
128
-	.shutdown = snponly_shutdown,
51
+/** EFI SNP driver */
52
+struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
53
+	.name = "SNPONLY",
54
+	.supported = snponly_supported,
55
+	.start = snpnet_start,
56
+	.stop = snpnet_stop,
129 57
 };

Loading…
Cancel
Save