These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / intelxvf.c
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  * Diagnostics
44  *
45  ******************************************************************************
46  */
47
48 /**
49  * Dump statistics
50  *
51  * @v intel             Intel device
52  */
53 static __attribute__ (( unused )) void
54 intelxvf_stats ( struct intel_nic *intel ) {
55
56         DBGC ( intel, "INTEL %p TX %d (%#x%08x) RX %d (%#x%08x) multi %d\n",
57                intel, readl ( intel->regs + INTELXVF_GPTC ),
58                readl ( intel->regs + INTELXVF_GOTCH ),
59                readl ( intel->regs + INTELXVF_GOTCL ),
60                readl ( intel->regs + INTELXVF_GPRC ),
61                readl ( intel->regs + INTELXVF_GORCH ),
62                readl ( intel->regs + INTELXVF_GORCL ),
63                readl ( intel->regs + INTELXVF_MPRC ) );
64 }
65
66 /******************************************************************************
67  *
68  * Device reset
69  *
70  ******************************************************************************
71  */
72
73 /**
74  * Reset hardware
75  *
76  * @v intel             Intel device
77  */
78 static void intelxvf_reset ( struct intel_nic *intel ) {
79
80         /* Perform a function-level reset */
81         writel ( INTELXVF_CTRL_RST, intel->regs + INTELXVF_CTRL );
82 }
83
84 /******************************************************************************
85  *
86  * Link state
87  *
88  ******************************************************************************
89  */
90
91 /**
92  * Check link state
93  *
94  * @v netdev            Network device
95  */
96 static void intelxvf_check_link ( struct net_device *netdev ) {
97         struct intel_nic *intel = netdev->priv;
98         uint32_t links;
99
100         /* Read link status */
101         links = readl ( intel->regs + INTELXVF_LINKS );
102         DBGC ( intel, "INTEL %p link status is %08x\n", intel, links );
103
104         /* Update network device */
105         if ( links & INTELXVF_LINKS_UP ) {
106                 netdev_link_up ( netdev );
107         } else {
108                 netdev_link_down ( netdev );
109         }
110 }
111
112 /******************************************************************************
113  *
114  * Mailbox messages
115  *
116  ******************************************************************************
117  */
118
119 /**
120  * Send negotiate API version message
121  *
122  * @v intel             Intel device
123  * @v version           Requested version
124  * @ret rc              Return status code
125  */
126 static int intelxvf_mbox_version ( struct intel_nic *intel,
127                                    unsigned int version ) {
128         union intelvf_msg msg;
129         int rc;
130
131         /* Send set MTU message */
132         memset ( &msg, 0, sizeof ( msg ) );
133         msg.hdr = INTELXVF_MSG_TYPE_VERSION;
134         msg.version.version = version;
135         if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
136                 DBGC ( intel, "INTEL %p negotiate API version failed: %s\n",
137                        intel, strerror ( rc ) );
138                 return rc;
139         }
140
141         /* Check response */
142         if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELXVF_MSG_TYPE_VERSION ){
143                 DBGC ( intel, "INTEL %p negotiate API version unexpected "
144                        "response:\n", intel );
145                 DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
146                 return -EPROTO;
147         }
148
149         /* Check that this version is supported */
150         if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
151                 DBGC ( intel, "INTEL %p negotiate API version failed\n",
152                        intel );
153                 return -EPERM;
154         }
155
156         return 0;
157 }
158
159 /******************************************************************************
160  *
161  * Network device interface
162  *
163  ******************************************************************************
164  */
165
166 /**
167  * Open network device
168  *
169  * @v netdev            Network device
170  * @ret rc              Return status code
171  */
172 static int intelxvf_open ( struct net_device *netdev ) {
173         struct intel_nic *intel = netdev->priv;
174         uint32_t srrctl;
175         uint32_t dca_rxctrl;
176         int rc;
177
178         /* Reset the function */
179         intelxvf_reset ( intel );
180
181         /* Notify PF that reset is complete */
182         if ( ( rc = intelvf_mbox_reset ( intel, NULL ) ) != 0 ) {
183                 DBGC ( intel, "INTEL %p could not reset: %s\n",
184                        intel, strerror ( rc ) );
185                 goto err_mbox_reset;
186         }
187
188         /* Negotiate API version 1.1.  If we do not negotiate at least
189          * this version, then the RX datapath will remain disabled if
190          * the PF has jumbo frames enabled.
191          *
192          * Ignore failures, since the host may not actually support
193          * v1.1.
194          */
195         intelxvf_mbox_version ( intel, INTELXVF_MSG_VERSION_1_1 );
196
197         /* Set MAC address */
198         if ( ( rc = intelvf_mbox_set_mac ( intel, netdev->ll_addr ) ) != 0 ) {
199                 DBGC ( intel, "INTEL %p could not set MAC address: %s\n",
200                        intel, strerror ( rc ) );
201                 goto err_mbox_set_mac;
202         }
203
204         /* Set MTU */
205         if ( ( rc = intelvf_mbox_set_mtu ( intel, netdev->max_pkt_len ) ) != 0){
206                 DBGC ( intel, "INTEL %p could not set MTU %zd: %s\n",
207                        intel, netdev->max_pkt_len, strerror ( rc ) );
208                 goto err_mbox_set_mtu;
209         }
210
211         /* Create transmit descriptor ring */
212         if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
213                 goto err_create_tx;
214
215         /* Create receive descriptor ring */
216         if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 )
217                 goto err_create_rx;
218
219         /* Allocate interrupt vectors */
220         writel ( ( INTELXVF_IVAR_RX0_DEFAULT | INTELXVF_IVAR_RX0_VALID |
221                    INTELXVF_IVAR_TX0_DEFAULT | INTELXVF_IVAR_TX0_VALID ),
222                  intel->regs + INTELXVF_IVAR );
223         writel ( ( INTELXVF_IVARM_MBOX_DEFAULT | INTELXVF_IVARM_MBOX_VALID ),
224                  intel->regs + INTELXVF_IVARM );
225
226         /* Configure receive buffer sizes and set receive descriptor type */
227         srrctl = readl ( intel->regs + INTELXVF_SRRCTL );
228         srrctl &= ~( INTELXVF_SRRCTL_BSIZE_MASK |
229                      INTELXVF_SRRCTL_DESCTYPE_MASK );
230         srrctl |= ( INTELXVF_SRRCTL_BSIZE_DEFAULT |
231                     INTELXVF_SRRCTL_DESCTYPE_DEFAULT );
232         writel ( srrctl, intel->regs + INTELXVF_SRRCTL );
233
234         /* Clear "must-be-zero" bit for direct cache access (DCA).  We
235          * leave DCA disabled anyway, but if we do not clear this bit
236          * then the received packets contain garbage data.
237          */
238         dca_rxctrl = readl ( intel->regs + INTELXVF_DCA_RXCTRL );
239         dca_rxctrl &= ~INTELXVF_DCA_RXCTRL_MUST_BE_ZERO;
240         writel ( dca_rxctrl, intel->regs + INTELXVF_DCA_RXCTRL );
241
242         /* Fill receive ring */
243         intel_refill_rx ( intel );
244
245         /* Update link state */
246         intelxvf_check_link ( netdev );
247
248         return 0;
249
250         intel_destroy_ring ( intel, &intel->rx );
251  err_create_rx:
252         intel_destroy_ring ( intel, &intel->tx );
253  err_create_tx:
254  err_mbox_set_mtu:
255  err_mbox_set_mac:
256  err_mbox_reset:
257         intelxvf_reset ( intel );
258         return rc;
259 }
260
261 /**
262  * Close network device
263  *
264  * @v netdev            Network device
265  */
266 static void intelxvf_close ( struct net_device *netdev ) {
267         struct intel_nic *intel = netdev->priv;
268
269         /* Destroy receive descriptor ring */
270         intel_destroy_ring ( intel, &intel->rx );
271
272         /* Discard any unused receive buffers */
273         intel_empty_rx ( intel );
274
275         /* Destroy transmit descriptor ring */
276         intel_destroy_ring ( intel, &intel->tx );
277
278         /* Reset the function */
279         intelxvf_reset ( intel );
280 }
281
282 /**
283  * Poll for completed and received packets
284  *
285  * @v netdev            Network device
286  */
287 static void intelxvf_poll ( struct net_device *netdev ) {
288         struct intel_nic *intel = netdev->priv;
289         uint32_t eicr;
290         int rc;
291
292         /* Check for and acknowledge interrupts */
293         eicr = readl ( intel->regs + INTELXVF_EICR );
294         if ( ! eicr )
295                 return;
296
297         /* Poll for TX completions, if applicable */
298         if ( eicr & INTELXVF_EIRQ_TX0 )
299                 intel_poll_tx ( netdev );
300
301         /* Poll for RX completions, if applicable */
302         if ( eicr & INTELXVF_EIRQ_RX0 )
303                 intel_poll_rx ( netdev );
304
305         /* Poll for mailbox messages, if applicable */
306         if ( eicr & INTELXVF_EIRQ_MBOX ) {
307
308                 /* Poll mailbox */
309                 if ( ( rc = intelvf_mbox_poll ( intel ) ) != 0 ) {
310                         DBGC ( intel, "INTEL %p mailbox poll failed!\n",
311                                intel );
312                         netdev_rx_err ( netdev, NULL, rc );
313                 }
314
315                 /* Update link state */
316                 intelxvf_check_link ( netdev );
317         }
318
319         /* Refill RX ring */
320         intel_refill_rx ( intel );
321 }
322
323 /**
324  * Enable or disable interrupts
325  *
326  * @v netdev            Network device
327  * @v enable            Interrupts should be enabled
328  */
329 static void intelxvf_irq ( struct net_device *netdev, int enable ) {
330         struct intel_nic *intel = netdev->priv;
331         uint32_t mask;
332
333         mask = ( INTELXVF_EIRQ_MBOX | INTELXVF_EIRQ_TX0 | INTELXVF_EIRQ_RX0 );
334         if ( enable ) {
335                 writel ( mask, intel->regs + INTELXVF_EIMS );
336         } else {
337                 writel ( mask, intel->regs + INTELXVF_EIMC );
338         }
339 }
340
341 /** Network device operations */
342 static struct net_device_operations intelxvf_operations = {
343         .open           = intelxvf_open,
344         .close          = intelxvf_close,
345         .transmit       = intel_transmit,
346         .poll           = intelxvf_poll,
347         .irq            = intelxvf_irq,
348 };
349
350 /******************************************************************************
351  *
352  * PCI interface
353  *
354  ******************************************************************************
355  */
356
357 /**
358  * Probe PCI device
359  *
360  * @v pci               PCI device
361  * @ret rc              Return status code
362  */
363 static int intelxvf_probe ( struct pci_device *pci ) {
364         struct net_device *netdev;
365         struct intel_nic *intel;
366         int rc;
367
368         /* Allocate and initialise net device */
369         netdev = alloc_etherdev ( sizeof ( *intel ) );
370         if ( ! netdev ) {
371                 rc = -ENOMEM;
372                 goto err_alloc;
373         }
374         netdev_init ( netdev, &intelxvf_operations );
375         intel = netdev->priv;
376         pci_set_drvdata ( pci, netdev );
377         netdev->dev = &pci->dev;
378         memset ( intel, 0, sizeof ( *intel ) );
379         intel_init_mbox ( &intel->mbox, INTELXVF_MBCTRL, INTELXVF_MBMEM );
380         intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELXVF_TD,
381                           intel_describe_tx_adv );
382         intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELXVF_RD,
383                           intel_describe_rx );
384
385         /* Fix up PCI device */
386         adjust_pci_device ( pci );
387
388         /* Map registers */
389         intel->regs = ioremap ( pci->membase, INTELVF_BAR_SIZE );
390         if ( ! intel->regs ) {
391                 rc = -ENODEV;
392                 goto err_ioremap;
393         }
394
395         /* Reset the function */
396         intelxvf_reset ( intel );
397
398         /* Send reset message and fetch MAC address */
399         if ( ( rc = intelvf_mbox_reset ( intel, netdev->hw_addr ) ) != 0 ) {
400                 DBGC ( intel, "INTEL %p could not reset and fetch MAC: %s\n",
401                        intel, strerror ( rc ) );
402                 goto err_mbox_reset;
403         }
404
405         /* Reset the function (since we will not respond to Control
406          * ("ping") mailbox messages until the network device is opened.
407          */
408         intelxvf_reset ( intel );
409
410         /* Register network device */
411         if ( ( rc = register_netdev ( netdev ) ) != 0 )
412                 goto err_register_netdev;
413
414         /* Set initial link state */
415         intelxvf_check_link ( netdev );
416
417         return 0;
418
419         unregister_netdev ( netdev );
420  err_register_netdev:
421  err_mbox_reset:
422         intelxvf_reset ( intel );
423         iounmap ( intel->regs );
424  err_ioremap:
425         netdev_nullify ( netdev );
426         netdev_put ( netdev );
427  err_alloc:
428         return rc;
429 }
430
431 /**
432  * Remove PCI device
433  *
434  * @v pci               PCI device
435  */
436 static void intelxvf_remove ( struct pci_device *pci ) {
437         struct net_device *netdev = pci_get_drvdata ( pci );
438         struct intel_nic *intel = netdev->priv;
439
440         /* Unregister network device */
441         unregister_netdev ( netdev );
442
443         /* Reset the NIC */
444         intelxvf_reset ( intel );
445
446         /* Free network device */
447         iounmap ( intel->regs );
448         netdev_nullify ( netdev );
449         netdev_put ( netdev );
450 }
451
452 /** PCI device IDs */
453 static struct pci_device_id intelxvf_nics[] = {
454         PCI_ROM ( 0x8086, 0x10ed, "82599-vf", "82599 VF", 0 ),
455         PCI_ROM ( 0x8086, 0x1515, "x540-vf", "X540 VF", 0 ),
456         PCI_ROM ( 0x8086, 0x1565, "x550-vf", "X550 VF", 0 ),
457         PCI_ROM ( 0x8086, 0x15a8, "x552-vf", "X552 VF", 0 ),
458 };
459
460 /** PCI driver */
461 struct pci_driver intelxvf_driver __pci_driver = {
462         .ids = intelxvf_nics,
463         .id_count = ( sizeof ( intelxvf_nics ) / sizeof ( intelxvf_nics[0] ) ),
464         .probe = intelxvf_probe,
465         .remove = intelxvf_remove,
466 };