[netdevice] Record whether or not interrupts are currently enabled
[people/pcmattman/gpxe.git] / src / net / netdevice.c
1 /*
2  * Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <byteswap.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <gpxe/if_ether.h>
28 #include <gpxe/iobuf.h>
29 #include <gpxe/tables.h>
30 #include <gpxe/process.h>
31 #include <gpxe/init.h>
32 #include <gpxe/device.h>
33 #include <gpxe/errortab.h>
34 #include <gpxe/netdevice.h>
35
36 /** @file
37  *
38  * Network device management
39  *
40  */
41
42 /** List of network devices */
43 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
44
45 /** List of open network devices, in reverse order of opening */
46 static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
47
48 /** Default link status code */
49 #define EUNKNOWN_LINK_STATUS EINPROGRESS
50
51 /** Human-readable message for the default link status */
52 struct errortab netdev_errors[] __errortab = {
53         { EUNKNOWN_LINK_STATUS, "Unknown" },
54 };
55
56 /**
57  * Mark network device as having link down
58  *
59  * @v netdev            Network device
60  */
61 void netdev_link_down ( struct net_device *netdev ) {
62
63         switch ( netdev->link_rc ) {
64         case 0:
65         case -EUNKNOWN_LINK_STATUS:
66                 netdev->link_rc = -ENOTCONN;
67                 break;
68         default:
69                 /* Avoid clobbering a more detailed link status code,
70                  * if one is already set.
71                  */
72                 break;
73         }
74 }
75
76 /**
77  * Record network device statistic
78  *
79  * @v stats             Network device statistics
80  * @v rc                Status code
81  */
82 static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
83         struct net_device_error *error;
84         struct net_device_error *least_common_error;
85         unsigned int i;
86
87         /* If this is not an error, just update the good counter */
88         if ( rc == 0 ) {
89                 stats->good++;
90                 return;
91         }
92
93         /* Update the bad counter */
94         stats->bad++;
95
96         /* Locate the appropriate error record */
97         least_common_error = &stats->errors[0];
98         for ( i = 0 ; i < ( sizeof ( stats->errors ) /
99                             sizeof ( stats->errors[0] ) ) ; i++ ) {
100                 error = &stats->errors[i];
101                 /* Update matching record, if found */
102                 if ( error->rc == rc ) {
103                         error->count++;
104                         return;
105                 }
106                 if ( error->count < least_common_error->count )
107                         least_common_error = error;
108         }
109
110         /* Overwrite the least common error record */
111         least_common_error->rc = rc;
112         least_common_error->count = 1;
113 }
114
115 /**
116  * Transmit raw packet via network device
117  *
118  * @v netdev            Network device
119  * @v iobuf             I/O buffer
120  * @ret rc              Return status code
121  *
122  * Transmits the packet via the specified network device.  This
123  * function takes ownership of the I/O buffer.
124  */
125 int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
126         int rc;
127
128         DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
129                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
130
131         list_add_tail ( &iobuf->list, &netdev->tx_queue );
132
133         if ( ! netdev_is_open ( netdev ) ) {
134                 rc = -ENETUNREACH;
135                 goto err;
136         }
137                 
138         if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
139                 goto err;
140
141         return 0;
142
143  err:
144         netdev_tx_complete_err ( netdev, iobuf, rc );
145         return rc;
146 }
147
148 /**
149  * Complete network transmission
150  *
151  * @v netdev            Network device
152  * @v iobuf             I/O buffer
153  * @v rc                Packet status code
154  *
155  * The packet must currently be in the network device's TX queue.
156  */
157 void netdev_tx_complete_err ( struct net_device *netdev,
158                               struct io_buffer *iobuf, int rc ) {
159
160         /* Update statistics counter */
161         netdev_record_stat ( &netdev->tx_stats, rc );
162         if ( rc == 0 ) {
163                 DBGC ( netdev, "NETDEV %p transmission %p complete\n",
164                        netdev, iobuf );
165         } else {
166                 DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
167                        netdev, iobuf, strerror ( rc ) );
168         }
169
170         /* Catch data corruption as early as possible */
171         assert ( iobuf->list.next != NULL );
172         assert ( iobuf->list.prev != NULL );
173
174         /* Dequeue and free I/O buffer */
175         list_del ( &iobuf->list );
176         free_iob ( iobuf );
177 }
178
179 /**
180  * Complete network transmission
181  *
182  * @v netdev            Network device
183  * @v rc                Packet status code
184  *
185  * Completes the oldest outstanding packet in the TX queue.
186  */
187 void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
188         struct io_buffer *iobuf;
189
190         list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
191                 netdev_tx_complete_err ( netdev, iobuf, rc );
192                 return;
193         }
194 }
195
196 /**
197  * Flush device's transmit queue
198  *
199  * @v netdev            Network device
200  */
201 static void netdev_tx_flush ( struct net_device *netdev ) {
202
203         /* Discard any packets in the TX queue */
204         while ( ! list_empty ( &netdev->tx_queue ) ) {
205                 netdev_tx_complete_next_err ( netdev, -ECANCELED );
206         }
207 }
208
209 /**
210  * Add packet to receive queue
211  *
212  * @v netdev            Network device
213  * @v iobuf             I/O buffer, or NULL
214  *
215  * The packet is added to the network device's RX queue.  This
216  * function takes ownership of the I/O buffer.
217  */
218 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
219
220         DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
221                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
222
223         /* Enqueue packet */
224         list_add_tail ( &iobuf->list, &netdev->rx_queue );
225
226         /* Update statistics counter */
227         netdev_record_stat ( &netdev->rx_stats, 0 );
228 }
229
230 /**
231  * Discard received packet
232  *
233  * @v netdev            Network device
234  * @v iobuf             I/O buffer, or NULL
235  * @v rc                Packet status code
236  *
237  * The packet is discarded and an RX error is recorded.  This function
238  * takes ownership of the I/O buffer.  @c iobuf may be NULL if, for
239  * example, the net device wishes to report an error due to being
240  * unable to allocate an I/O buffer.
241  */
242 void netdev_rx_err ( struct net_device *netdev,
243                      struct io_buffer *iobuf, int rc ) {
244
245         DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
246                netdev, iobuf, strerror ( rc ) );
247
248         /* Discard packet */
249         free_iob ( iobuf );
250
251         /* Update statistics counter */
252         netdev_record_stat ( &netdev->rx_stats, rc );
253 }
254
255 /**
256  * Poll for completed and received packets on network device
257  *
258  * @v netdev            Network device
259  *
260  * Polls the network device for completed transmissions and received
261  * packets.  Any received packets will be added to the RX packet queue
262  * via netdev_rx().
263  */
264 void netdev_poll ( struct net_device *netdev ) {
265
266         if ( netdev_is_open ( netdev ) )
267                 netdev->op->poll ( netdev );
268 }
269
270 /**
271  * Remove packet from device's receive queue
272  *
273  * @v netdev            Network device
274  * @ret iobuf           I/O buffer, or NULL
275  *
276  * Removes the first packet from the device's RX queue and returns it.
277  * Ownership of the packet is transferred to the caller.
278  */
279 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
280         struct io_buffer *iobuf;
281
282         list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
283                 list_del ( &iobuf->list );
284                 return iobuf;
285         }
286         return NULL;
287 }
288
289 /**
290  * Flush device's receive queue
291  *
292  * @v netdev            Network device
293  */
294 static void netdev_rx_flush ( struct net_device *netdev ) {
295         struct io_buffer *iobuf;
296
297         /* Discard any packets in the RX queue */
298         while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
299                 netdev_rx_err ( netdev, iobuf, -ECANCELED );
300         }
301 }
302
303 /**
304  * Free network device
305  *
306  * @v refcnt            Network device reference counter
307  */
308 static void free_netdev ( struct refcnt *refcnt ) {
309         struct net_device *netdev =
310                 container_of ( refcnt, struct net_device, refcnt );
311         
312         netdev_tx_flush ( netdev );
313         netdev_rx_flush ( netdev );
314         clear_settings ( netdev_settings ( netdev ) );
315         free ( netdev );
316 }
317
318 /**
319  * Allocate network device
320  *
321  * @v priv_size         Size of private data area (net_device::priv)
322  * @ret netdev          Network device, or NULL
323  *
324  * Allocates space for a network device and its private data area.
325  */
326 struct net_device * alloc_netdev ( size_t priv_size ) {
327         struct net_device *netdev;
328         size_t total_len;
329
330         total_len = ( sizeof ( *netdev ) + priv_size );
331         netdev = zalloc ( total_len );
332         if ( netdev ) {
333                 netdev->refcnt.free = free_netdev;
334                 netdev->link_rc = -EUNKNOWN_LINK_STATUS;
335                 INIT_LIST_HEAD ( &netdev->tx_queue );
336                 INIT_LIST_HEAD ( &netdev->rx_queue );
337                 netdev_settings_init ( netdev );
338                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
339         }
340         return netdev;
341 }
342
343 /**
344  * Register network device
345  *
346  * @v netdev            Network device
347  * @ret rc              Return status code
348  *
349  * Gives the network device a name and adds it to the list of network
350  * devices.
351  */
352 int register_netdev ( struct net_device *netdev ) {
353         static unsigned int ifindex = 0;
354         int rc;
355
356         /* Create device name */
357         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
358                    ifindex++ );
359
360         /* Set initial link-layer address */
361         netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
362
363         /* Register per-netdev configuration settings */
364         if ( ( rc = register_settings ( netdev_settings ( netdev ),
365                                         NULL ) ) != 0 ) {
366                 DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
367                        netdev, strerror ( rc ) );
368                 return rc;
369         }
370
371         /* Add to device list */
372         netdev_get ( netdev );
373         list_add_tail ( &netdev->list, &net_devices );
374         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
375                netdev, netdev->name, netdev->dev->name,
376                netdev_addr ( netdev ) );
377
378         return 0;
379 }
380
381 /**
382  * Open network device
383  *
384  * @v netdev            Network device
385  * @ret rc              Return status code
386  */
387 int netdev_open ( struct net_device *netdev ) {
388         int rc;
389
390         /* Do nothing if device is already open */
391         if ( netdev->state & NETDEV_OPEN )
392                 return 0;
393
394         DBGC ( netdev, "NETDEV %p opening\n", netdev );
395
396         /* Open the device */
397         if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
398                 return rc;
399
400         /* Mark as opened */
401         netdev->state |= NETDEV_OPEN;
402
403         /* Add to head of open devices list */
404         list_add ( &netdev->open_list, &open_net_devices );
405
406         return 0;
407 }
408
409 /**
410  * Close network device
411  *
412  * @v netdev            Network device
413  */
414 void netdev_close ( struct net_device *netdev ) {
415
416         /* Do nothing if device is already closed */
417         if ( ! ( netdev->state & NETDEV_OPEN ) )
418                 return;
419
420         DBGC ( netdev, "NETDEV %p closing\n", netdev );
421
422         /* Close the device */
423         netdev->op->close ( netdev );
424
425         /* Flush TX and RX queues */
426         netdev_tx_flush ( netdev );
427         netdev_rx_flush ( netdev );
428
429         /* Mark as closed */
430         netdev->state &= ~NETDEV_OPEN;
431
432         /* Remove from open devices list */
433         list_del ( &netdev->open_list );
434 }
435
436 /**
437  * Unregister network device
438  *
439  * @v netdev            Network device
440  *
441  * Removes the network device from the list of network devices.
442  */
443 void unregister_netdev ( struct net_device *netdev ) {
444
445         /* Ensure device is closed */
446         netdev_close ( netdev );
447
448         /* Unregister per-netdev configuration settings */
449         unregister_settings ( netdev_settings ( netdev ) );
450
451         /* Remove from device list */
452         list_del ( &netdev->list );
453         netdev_put ( netdev );
454         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
455 }
456
457 /** Enable or disable interrupts
458  *
459  * @v netdev            Network device
460  * @v enable            Interrupts should be enabled
461  */
462 void netdev_irq ( struct net_device *netdev, int enable ) {
463
464         /* Enable or disable device interrupts */
465         netdev->op->irq ( netdev, enable );
466
467         /* Record interrupt enabled state */
468         netdev->state &= ~NETDEV_IRQ_ENABLED;
469         if ( enable )
470                 netdev->state |= NETDEV_IRQ_ENABLED;
471 }
472
473 /**
474  * Get network device by name
475  *
476  * @v name              Network device name
477  * @ret netdev          Network device, or NULL
478  */
479 struct net_device * find_netdev ( const char *name ) {
480         struct net_device *netdev;
481
482         list_for_each_entry ( netdev, &net_devices, list ) {
483                 if ( strcmp ( netdev->name, name ) == 0 )
484                         return netdev;
485         }
486
487         return NULL;
488 }
489
490 /**
491  * Get network device by PCI bus:dev.fn address
492  *
493  * @v bus_type          Bus type
494  * @v location          Bus location
495  * @ret netdev          Network device, or NULL
496  */
497 struct net_device * find_netdev_by_location ( unsigned int bus_type,
498                                               unsigned int location ) {
499         struct net_device *netdev;
500
501         list_for_each_entry ( netdev, &net_devices, list ) {
502                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
503                      ( netdev->dev->desc.location == location ) )
504                         return netdev;
505         }
506
507         return NULL;    
508 }
509
510 /**
511  * Get most recently opened network device
512  *
513  * @ret netdev          Most recently opened network device, or NULL
514  */
515 struct net_device * last_opened_netdev ( void ) {
516         struct net_device *netdev;
517
518         list_for_each_entry ( netdev, &open_net_devices, open_list ) {
519                 assert ( netdev_is_open ( netdev ) );
520                 return netdev;
521         }
522
523         return NULL;
524 }
525
526 /**
527  * Transmit network-layer packet
528  *
529  * @v iobuf             I/O buffer
530  * @v netdev            Network device
531  * @v net_protocol      Network-layer protocol
532  * @v ll_dest           Destination link-layer address
533  * @ret rc              Return status code
534  *
535  * Prepends link-layer headers to the I/O buffer and transmits the
536  * packet via the specified network device.  This function takes
537  * ownership of the I/O buffer.
538  */
539 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
540              struct net_protocol *net_protocol, const void *ll_dest ) {
541         struct ll_protocol *ll_protocol = netdev->ll_protocol;
542         int rc;
543
544         /* Force a poll on the netdevice to (potentially) clear any
545          * backed-up TX completions.  This is needed on some network
546          * devices to avoid excessive losses due to small TX ring
547          * sizes.
548          */
549         netdev_poll ( netdev );
550
551         /* Add link-layer header */
552         if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, netdev->ll_addr,
553                                         net_protocol->net_proto ) ) != 0 ) {
554                 free_iob ( iobuf );
555                 return rc;
556         }
557
558         /* Transmit packet */
559         return netdev_tx ( netdev, iobuf );
560 }
561
562 /**
563  * Process received network-layer packet
564  *
565  * @v iobuf             I/O buffer
566  * @v netdev            Network device
567  * @v net_proto         Network-layer protocol, in network-byte order
568  * @v ll_source         Source link-layer address
569  * @ret rc              Return status code
570  */
571 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
572              uint16_t net_proto, const void *ll_source ) {
573         struct net_protocol *net_protocol;
574
575         /* Hand off to network-layer protocol, if any */
576         for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
577                 if ( net_protocol->net_proto == net_proto )
578                         return net_protocol->rx ( iobuf, netdev, ll_source );
579         }
580
581         DBGC ( netdev, "NETDEV %p unknown network protocol %04x\n",
582                netdev, ntohs ( net_proto ) );
583         free_iob ( iobuf );
584         return 0;
585 }
586
587 /**
588  * Single-step the network stack
589  *
590  * @v process           Network stack process
591  *
592  * This polls all interfaces for received packets, and processes
593  * packets from the RX queue.
594  */
595 static void net_step ( struct process *process __unused ) {
596         struct net_device *netdev;
597         struct io_buffer *iobuf;
598         struct ll_protocol *ll_protocol;
599         const void *ll_dest;
600         const void *ll_source;
601         uint16_t net_proto;
602         int rc;
603
604         /* Poll and process each network device */
605         list_for_each_entry ( netdev, &net_devices, list ) {
606
607                 /* Poll for new packets */
608                 netdev_poll ( netdev );
609
610                 /* Process at most one received packet.  Give priority
611                  * to getting packets out of the NIC over processing
612                  * the received packets, because we advertise a window
613                  * that assumes that we can receive packets from the
614                  * NIC faster than they arrive.
615                  */
616                 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
617
618                         DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
619                                netdev, iobuf, iobuf->data,
620                                iob_len ( iobuf ) );
621
622                         /* Remove link-layer header */
623                         ll_protocol = netdev->ll_protocol;
624                         if ( ( rc = ll_protocol->pull ( netdev, iobuf,
625                                                         &ll_dest, &ll_source,
626                                                         &net_proto ) ) != 0 ) {
627                                 free_iob ( iobuf );
628                                 continue;
629                         }
630
631                         net_rx ( iobuf, netdev, net_proto, ll_source );
632                 }
633         }
634 }
635
636 /** Networking stack process */
637 struct process net_process __permanent_process = {
638         .list = LIST_HEAD_INIT ( net_process.list ),
639         .step = net_step,
640 };