瀏覽代碼

[intel] Add intelxvf driver for Intel 10 GigE virtual function NICs

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 年之前
父節點
當前提交
a91b1f7339
共有 3 個文件被更改,包括 455 次插入0 次删除
  1. 377
    0
      src/drivers/net/intelxvf.c
  2. 77
    0
      src/drivers/net/intelxvf.h
  3. 1
    0
      src/include/ipxe/errfile.h

+ 377
- 0
src/drivers/net/intelxvf.c 查看文件

@@ -0,0 +1,377 @@
1
+/*
2
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
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 (at your option) 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 Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+#include <string.h>
27
+#include <unistd.h>
28
+#include <errno.h>
29
+#include <ipxe/io.h>
30
+#include <ipxe/pci.h>
31
+#include <ipxe/netdevice.h>
32
+#include <ipxe/ethernet.h>
33
+#include "intelxvf.h"
34
+
35
+/** @file
36
+ *
37
+ * Intel 10 Gigabit Ethernet virtual function network card driver
38
+ *
39
+ */
40
+
41
+/******************************************************************************
42
+ *
43
+ * Device reset
44
+ *
45
+ ******************************************************************************
46
+ */
47
+
48
+/**
49
+ * Reset hardware
50
+ *
51
+ * @v intel		Intel device
52
+ */
53
+static void intelxvf_reset ( struct intel_nic *intel ) {
54
+
55
+	/* Perform a function-level reset */
56
+	writel ( INTELXVF_CTRL_RST, intel->regs + INTELXVF_CTRL );
57
+}
58
+
59
+/******************************************************************************
60
+ *
61
+ * Link state
62
+ *
63
+ ******************************************************************************
64
+ */
65
+
66
+/**
67
+ * Check link state
68
+ *
69
+ * @v netdev		Network device
70
+ */
71
+static void intelxvf_check_link ( struct net_device *netdev ) {
72
+	struct intel_nic *intel = netdev->priv;
73
+	uint32_t links;
74
+
75
+	/* Read link status */
76
+	links = readl ( intel->regs + INTELXVF_LINKS );
77
+	DBGC ( intel, "INTEL %p link status is %08x\n", intel, links );
78
+
79
+	/* Update network device */
80
+	if ( links & INTELXVF_LINKS_UP ) {
81
+		netdev_link_up ( netdev );
82
+	} else {
83
+		netdev_link_down ( netdev );
84
+	}
85
+}
86
+
87
+/******************************************************************************
88
+ *
89
+ * Network device interface
90
+ *
91
+ ******************************************************************************
92
+ */
93
+
94
+/**
95
+ * Open network device
96
+ *
97
+ * @v netdev		Network device
98
+ * @ret rc		Return status code
99
+ */
100
+static int intelxvf_open ( struct net_device *netdev ) {
101
+	struct intel_nic *intel = netdev->priv;
102
+	uint32_t srrctl;
103
+	uint32_t dca_rxctrl;
104
+	int rc;
105
+
106
+	/* Reset the function */
107
+	intelxvf_reset ( intel );
108
+
109
+	/* Notify PF that reset is complete */
110
+	if ( ( rc = intelvf_mbox_reset ( intel, NULL ) ) != 0 ) {
111
+		DBGC ( intel, "INTEL %p could not reset: %s\n",
112
+		       intel, strerror ( rc ) );
113
+		goto err_mbox_reset;
114
+	}
115
+
116
+	/* Set MAC address */
117
+	if ( ( rc = intelvf_mbox_set_mac ( intel, netdev->ll_addr ) ) != 0 ) {
118
+		DBGC ( intel, "INTEL %p could not set MAC address: %s\n",
119
+		       intel, strerror ( rc ) );
120
+		goto err_mbox_set_mac;
121
+	}
122
+
123
+	/* Create transmit descriptor ring */
124
+	if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
125
+		goto err_create_tx;
126
+
127
+	/* Create receive descriptor ring */
128
+	if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 )
129
+		goto err_create_rx;
130
+
131
+	/* Allocate interrupt vectors */
132
+	writel ( ( INTELXVF_IVAR_RX0_DEFAULT | INTELXVF_IVAR_RX0_VALID |
133
+		   INTELXVF_IVAR_TX0_DEFAULT | INTELXVF_IVAR_TX0_VALID ),
134
+		 intel->regs + INTELXVF_IVAR );
135
+	writel ( ( INTELXVF_IVARM_MBOX_DEFAULT | INTELXVF_IVARM_MBOX_VALID ),
136
+		 intel->regs + INTELXVF_IVARM );
137
+
138
+	/* Configure receive buffer sizes and set receive descriptor type */
139
+	srrctl = readl ( intel->regs + INTELXVF_SRRCTL );
140
+	srrctl &= ~( INTELXVF_SRRCTL_BSIZE_MASK |
141
+		     INTELXVF_SRRCTL_DESCTYPE_MASK );
142
+	srrctl |= ( INTELXVF_SRRCTL_BSIZE_DEFAULT |
143
+		    INTELXVF_SRRCTL_DESCTYPE_DEFAULT );
144
+	writel ( srrctl, intel->regs + INTELXVF_SRRCTL );
145
+
146
+	/* Clear "must-be-zero" bit for direct cache access (DCA).  We
147
+	 * leave DCA disabled anyway, but if we do not clear this bit
148
+	 * then the received packets contain garbage data.
149
+	 */
150
+	dca_rxctrl = readl ( intel->regs + INTELXVF_DCA_RXCTRL );
151
+	dca_rxctrl &= ~INTELXVF_DCA_RXCTRL_MUST_BE_ZERO;
152
+	writel ( dca_rxctrl, intel->regs + INTELXVF_DCA_RXCTRL );
153
+
154
+	/* Fill receive ring */
155
+	intel_refill_rx ( intel );
156
+
157
+	/* Update link state */
158
+	intelxvf_check_link ( netdev );
159
+
160
+	return 0;
161
+
162
+	intel_destroy_ring ( intel, &intel->rx );
163
+ err_create_rx:
164
+	intel_destroy_ring ( intel, &intel->tx );
165
+ err_create_tx:
166
+ err_mbox_set_mac:
167
+ err_mbox_reset:
168
+	intelxvf_reset ( intel );
169
+	return rc;
170
+}
171
+
172
+/**
173
+ * Close network device
174
+ *
175
+ * @v netdev		Network device
176
+ */
177
+static void intelxvf_close ( struct net_device *netdev ) {
178
+	struct intel_nic *intel = netdev->priv;
179
+
180
+	/* Destroy receive descriptor ring */
181
+	intel_destroy_ring ( intel, &intel->rx );
182
+
183
+	/* Discard any unused receive buffers */
184
+	intel_empty_rx ( intel );
185
+
186
+	/* Destroy transmit descriptor ring */
187
+	intel_destroy_ring ( intel, &intel->tx );
188
+
189
+	/* Reset the function */
190
+	intelxvf_reset ( intel );
191
+}
192
+
193
+/**
194
+ * Poll for completed and received packets
195
+ *
196
+ * @v netdev		Network device
197
+ */
198
+static void intelxvf_poll ( struct net_device *netdev ) {
199
+	struct intel_nic *intel = netdev->priv;
200
+	uint32_t eicr;
201
+	int rc;
202
+
203
+	/* Check for and acknowledge interrupts */
204
+	eicr = readl ( intel->regs + INTELXVF_EICR );
205
+	if ( ! eicr )
206
+		return;
207
+
208
+	/* Poll for TX completions, if applicable */
209
+	if ( eicr & INTELXVF_EIRQ_TX0 )
210
+		intel_poll_tx ( netdev );
211
+
212
+	/* Poll for RX completions, if applicable */
213
+	if ( eicr & INTELXVF_EIRQ_RX0 )
214
+		intel_poll_rx ( netdev );
215
+
216
+	/* Poll for mailbox messages, if applicable */
217
+	if ( eicr & INTELXVF_EIRQ_MBOX ) {
218
+
219
+		/* Poll mailbox */
220
+		if ( ( rc = intelvf_mbox_poll ( intel ) ) != 0 ) {
221
+			DBGC ( intel, "INTEL %p mailbox poll failed!\n",
222
+			       intel );
223
+			netdev_rx_err ( netdev, NULL, rc );
224
+		}
225
+
226
+		/* Update link state */
227
+		intelxvf_check_link ( netdev );
228
+	}
229
+
230
+	/* Refill RX ring */
231
+	intel_refill_rx ( intel );
232
+}
233
+
234
+/**
235
+ * Enable or disable interrupts
236
+ *
237
+ * @v netdev		Network device
238
+ * @v enable		Interrupts should be enabled
239
+ */
240
+static void intelxvf_irq ( struct net_device *netdev, int enable ) {
241
+	struct intel_nic *intel = netdev->priv;
242
+	uint32_t mask;
243
+
244
+	mask = ( INTELXVF_EIRQ_MBOX | INTELXVF_EIRQ_TX0 | INTELXVF_EIRQ_RX0 );
245
+	if ( enable ) {
246
+		writel ( mask, intel->regs + INTELXVF_EIMS );
247
+	} else {
248
+		writel ( mask, intel->regs + INTELXVF_EIMC );
249
+	}
250
+}
251
+
252
+/** Network device operations */
253
+static struct net_device_operations intelxvf_operations = {
254
+	.open		= intelxvf_open,
255
+	.close		= intelxvf_close,
256
+	.transmit	= intel_transmit,
257
+	.poll		= intelxvf_poll,
258
+	.irq		= intelxvf_irq,
259
+};
260
+
261
+/******************************************************************************
262
+ *
263
+ * PCI interface
264
+ *
265
+ ******************************************************************************
266
+ */
267
+
268
+/**
269
+ * Probe PCI device
270
+ *
271
+ * @v pci		PCI device
272
+ * @ret rc		Return status code
273
+ */
274
+static int intelxvf_probe ( struct pci_device *pci ) {
275
+	struct net_device *netdev;
276
+	struct intel_nic *intel;
277
+	int rc;
278
+
279
+	/* Allocate and initialise net device */
280
+	netdev = alloc_etherdev ( sizeof ( *intel ) );
281
+	if ( ! netdev ) {
282
+		rc = -ENOMEM;
283
+		goto err_alloc;
284
+	}
285
+	netdev_init ( netdev, &intelxvf_operations );
286
+	intel = netdev->priv;
287
+	pci_set_drvdata ( pci, netdev );
288
+	netdev->dev = &pci->dev;
289
+	memset ( intel, 0, sizeof ( *intel ) );
290
+	intel_init_mbox ( &intel->mbox, INTELXVF_MBCTRL, INTELXVF_MBMEM );
291
+	intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELXVF_TD,
292
+			  intel_describe_tx_adv );
293
+	intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELXVF_RD,
294
+			  intel_describe_rx );
295
+
296
+	/* Fix up PCI device */
297
+	adjust_pci_device ( pci );
298
+
299
+	/* Map registers */
300
+	intel->regs = ioremap ( pci->membase, INTELVF_BAR_SIZE );
301
+	if ( ! intel->regs ) {
302
+		rc = -ENODEV;
303
+		goto err_ioremap;
304
+	}
305
+
306
+	/* Reset the function */
307
+	intelxvf_reset ( intel );
308
+
309
+	/* Send reset message and fetch MAC address */
310
+	if ( ( rc = intelvf_mbox_reset ( intel, netdev->hw_addr ) ) != 0 ) {
311
+		DBGC ( intel, "INTEL %p could not reset and fetch MAC: %s\n",
312
+		       intel, strerror ( rc ) );
313
+		goto err_mbox_reset;
314
+	}
315
+
316
+	/* Reset the function (since we will not respond to Control
317
+	 * ("ping") mailbox messages until the network device is opened.
318
+	 */
319
+	intelxvf_reset ( intel );
320
+
321
+	/* Register network device */
322
+	if ( ( rc = register_netdev ( netdev ) ) != 0 )
323
+		goto err_register_netdev;
324
+
325
+	/* Set initial link state */
326
+	intelxvf_check_link ( netdev );
327
+
328
+	return 0;
329
+
330
+	unregister_netdev ( netdev );
331
+ err_register_netdev:
332
+ err_mbox_reset:
333
+	intelxvf_reset ( intel );
334
+	iounmap ( intel->regs );
335
+ err_ioremap:
336
+	netdev_nullify ( netdev );
337
+	netdev_put ( netdev );
338
+ err_alloc:
339
+	return rc;
340
+}
341
+
342
+/**
343
+ * Remove PCI device
344
+ *
345
+ * @v pci		PCI device
346
+ */
347
+static void intelxvf_remove ( struct pci_device *pci ) {
348
+	struct net_device *netdev = pci_get_drvdata ( pci );
349
+	struct intel_nic *intel = netdev->priv;
350
+
351
+	/* Unregister network device */
352
+	unregister_netdev ( netdev );
353
+
354
+	/* Reset the NIC */
355
+	intelxvf_reset ( intel );
356
+
357
+	/* Free network device */
358
+	iounmap ( intel->regs );
359
+	netdev_nullify ( netdev );
360
+	netdev_put ( netdev );
361
+}
362
+
363
+/** PCI device IDs */
364
+static struct pci_device_id intelxvf_nics[] = {
365
+	PCI_ROM ( 0x8086, 0x10ed, "82599-vf", "82599 VF", 0 ),
366
+	PCI_ROM ( 0x8086, 0x1515, "x540-vf", "X540 VF", 0 ),
367
+	PCI_ROM ( 0x8086, 0x1565, "x550-vf", "X550 VF", 0 ),
368
+	PCI_ROM ( 0x8086, 0x15a8, "x552-vf", "X552 VF", 0 ),
369
+};
370
+
371
+/** PCI driver */
372
+struct pci_driver intelxvf_driver __pci_driver = {
373
+	.ids = intelxvf_nics,
374
+	.id_count = ( sizeof ( intelxvf_nics ) / sizeof ( intelxvf_nics[0] ) ),
375
+	.probe = intelxvf_probe,
376
+	.remove = intelxvf_remove,
377
+};

+ 77
- 0
src/drivers/net/intelxvf.h 查看文件

@@ -0,0 +1,77 @@
1
+#ifndef _INTELXVF_H
2
+#define _INTELXVF_H
3
+
4
+/** @file
5
+ *
6
+ * Intel 10 Gigabit Ethernet virtual function network card driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include "intelvf.h"
13
+
14
+/** Control Register */
15
+#define INTELXVF_CTRL 0x0000UL
16
+#define INTELXVF_CTRL_RST	0x04000000UL	/**< Function-level reset */
17
+
18
+/** Link Status Register */
19
+#define INTELXVF_LINKS 0x0010UL
20
+#define INTELXVF_LINKS_UP	0x40000000UL	/**< Link up */
21
+
22
+/** Extended Interrupt Cause Read Register */
23
+#define INTELXVF_EICR 0x0100UL
24
+#define INTELXVF_EIRQ_RX0	0x00000001UL	/**< RX queue 0 (via IVAR) */
25
+#define INTELXVF_EIRQ_TX0	0x00000002UL	/**< TX queue 0 (via IVAR) */
26
+#define INTELXVF_EIRQ_MBOX	0x00000004UL	/**< Mailbox (via IVARM) */
27
+
28
+/** Extended Interrupt Mask Set/Read Register */
29
+#define INTELXVF_EIMS 0x0108UL
30
+
31
+/** Extended Interrupt Mask Clear Register */
32
+#define INTELXVF_EIMC 0x010cUL
33
+
34
+/** Interrupt Vector Allocation Register */
35
+#define INTELXVF_IVAR 0x0120UL
36
+#define INTELXVF_IVAR_RX0(bit)	( (bit) << 0 )	/**< RX queue 0 allocation */
37
+#define INTELXVF_IVAR_RX0_DEFAULT INTELXVF_IVAR_RX0 ( 0x00 )
38
+#define INTELXVF_IVAR_RX0_MASK	INTELXVF_IVAR_RX0 ( 0x01 )
39
+#define INTELXVF_IVAR_RX0_VALID	0x00000080UL	/**< RX queue 0 valid */
40
+#define INTELXVF_IVAR_TX0(bit)	( (bit) << 8 )	/**< TX queue 0 allocation */
41
+#define INTELXVF_IVAR_TX0_DEFAULT INTELXVF_IVAR_TX0 ( 0x01 )
42
+#define INTELXVF_IVAR_TX0_MASK	INTELXVF_IVAR_TX0 ( 0x01 )
43
+#define INTELXVF_IVAR_TX0_VALID	0x00008000UL	/**< TX queue 0 valid */
44
+
45
+/** Interrupt Vector Allocation Miscellaneous Register */
46
+#define INTELXVF_IVARM 0x0140UL
47
+#define INTELXVF_IVARM_MBOX(bit) ( (bit) << 0 )	/**< Mailbox allocation */
48
+#define INTELXVF_IVARM_MBOX_DEFAULT INTELXVF_IVARM_MBOX ( 0x02 )
49
+#define INTELXVF_IVARM_MBOX_MASK INTELXVF_IVARM_MBOX ( 0x03 )
50
+#define INTELXVF_IVARM_MBOX_VALID 0x00000080UL	/**< Mailbox valid */
51
+
52
+/** Mailbox Memory Register Base */
53
+#define INTELXVF_MBMEM 0x0200UL
54
+
55
+/** Mailbox Control Register */
56
+#define INTELXVF_MBCTRL 0x02fcUL
57
+
58
+/** Receive Descriptor register block */
59
+#define INTELXVF_RD 0x1000UL
60
+
61
+/** RX DCA Control Register */
62
+#define INTELXVF_DCA_RXCTRL 0x100cUL
63
+#define INTELXVF_DCA_RXCTRL_MUST_BE_ZERO 0x00001000UL /**< Must be zero */
64
+
65
+/** Split Receive Control Register */
66
+#define INTELXVF_SRRCTL 0x1014UL
67
+#define INTELXVF_SRRCTL_BSIZE(kb) ( (kb) << 0 )	/**< Receive buffer size */
68
+#define INTELXVF_SRRCTL_BSIZE_DEFAULT INTELXVF_SRRCTL_BSIZE ( 0x02 )
69
+#define INTELXVF_SRRCTL_BSIZE_MASK INTELXVF_SRRCTL_BSIZE ( 0x1f )
70
+#define INTELXVF_SRRCTL_DESCTYPE(typ) ( (typ) << 25 ) /**< Descriptor type */
71
+#define INTELXVF_SRRCTL_DESCTYPE_DEFAULT INTELXVF_SRRCTL_DESCTYPE ( 0x00 )
72
+#define INTELXVF_SRRCTL_DESCTYPE_MASK INTELXVF_SRRCTL_DESCTYPE ( 0x07 )
73
+
74
+/** Transmit Descriptor register block */
75
+#define INTELXVF_TD 0x2000UL
76
+
77
+#endif /* _INTELXVF_H */

+ 1
- 0
src/include/ipxe/errfile.h 查看文件

@@ -178,6 +178,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
178 178
 #define ERRFILE_qib7322		     ( ERRFILE_DRIVER | 0x00760000 )
179 179
 #define ERRFILE_smsc75xx	     ( ERRFILE_DRIVER | 0x00770000 )
180 180
 #define ERRFILE_intelvf		     ( ERRFILE_DRIVER | 0x00780000 )
181
+#define ERRFILE_intelxvf	     ( ERRFILE_DRIVER | 0x00790000 )
181 182
 
182 183
 #define ERRFILE_aoe			( ERRFILE_NET | 0x00000000 )
183 184
 #define ERRFILE_arp			( ERRFILE_NET | 0x00010000 )

Loading…
取消
儲存