Browse Source

Use net_device_operations structure and netdev_nullify() to allow for

safe dropping of the netdev ref by the driver while other refs still
exist.

Add netdev_irq() method.  Net device open()/close() methods should no
longer enable or disable IRQs.

Remove rx_quota; it wasn't used anywhere and added too much complexity
to implementing correct interrupt-masking behaviour in pxe_undi.c.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
4c418d2100

+ 28
- 10
src/arch/i386/drivers/net/undinet.c View File

@@ -394,7 +394,6 @@ static int undinet_transmit ( struct net_device *netdev,
394 394
  * Poll for received packets
395 395
  *
396 396
  * @v netdev		Network device
397
- * @v rx_quota		Maximum number of packets to receive
398 397
  *
399 398
  * Fun, fun, fun.  UNDI drivers don't use polling; they use
400 399
  * interrupts.  We therefore cheat and pretend that an interrupt has
@@ -412,7 +411,7 @@ static int undinet_transmit ( struct net_device *netdev,
412 411
  * of installing a genuine interrupt service routine and dealing with
413 412
  * the wonderful 8259 Programmable Interrupt Controller.  Joy.
414 413
  */
415
-static void undinet_poll ( struct net_device *netdev, unsigned int rx_quota ) {
414
+static void undinet_poll ( struct net_device *netdev ) {
416 415
 	struct undi_nic *undinic = netdev->priv;
417 416
 	struct s_PXENV_UNDI_ISR undi_isr;
418 417
 	struct io_buffer *iobuf = NULL;
@@ -454,7 +453,7 @@ static void undinet_poll ( struct net_device *netdev, unsigned int rx_quota ) {
454 453
 	}
455 454
 
456 455
 	/* Run through the ISR loop */
457
-	while ( rx_quota ) {
456
+	while ( 1 ) {
458 457
 		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
459 458
 					   sizeof ( undi_isr ) ) ) != 0 )
460 459
 			break;
@@ -487,7 +486,6 @@ static void undinet_poll ( struct net_device *netdev, unsigned int rx_quota ) {
487 486
 				/* Whole packet received; deliver it */
488 487
 				netdev_rx ( netdev, iobuf );
489 488
 				iobuf = NULL;
490
-				--rx_quota;
491 489
 				/* Etherboot 5.4 fails to return all packets
492 490
 				 * under mild load; pretend it retriggered.
493 491
 				 */
@@ -599,6 +597,29 @@ static void undinet_close ( struct net_device *netdev ) {
599 597
 	DBGC ( undinic, "UNDINIC %p closed\n", undinic );
600 598
 }
601 599
 
600
+/**
601
+ * Enable/disable interrupts
602
+ *
603
+ * @v netdev		Net device
604
+ * @v enable		Interrupts should be enabled
605
+ */
606
+static void undinet_irq ( struct net_device *netdev, int enable ) {
607
+	struct undi_nic *undinic = netdev->priv;
608
+
609
+	/* Cannot support interrupts yet */
610
+	DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
611
+	       undinic, ( enable ? "enable" : "disable" ) );
612
+}
613
+
614
+/** UNDI network device operations */
615
+static struct net_device_operations undinet_operations = {
616
+	.open		= undinet_open,
617
+	.close		= undinet_close,
618
+	.transmit	= undinet_transmit,
619
+	.poll		= undinet_poll,
620
+	.irq   		= undinet_irq,
621
+};
622
+
602 623
 /**
603 624
  * Probe UNDI device
604 625
  *
@@ -622,6 +643,7 @@ int undinet_probe ( struct undi_device *undi ) {
622 643
 	netdev = alloc_etherdev ( sizeof ( *undinic ) );
623 644
 	if ( ! netdev )
624 645
 		return -ENOMEM;
646
+	netdev_init ( netdev, &undinet_operations );
625 647
 	undinic = netdev->priv;
626 648
 	undi_set_drvdata ( undi, netdev );
627 649
 	netdev->dev = &undi->dev;
@@ -685,12 +707,6 @@ int undinet_probe ( struct undi_device *undi ) {
685 707
 		undinic->hacks |= UNDI_HACK_EB54;
686 708
 	}
687 709
 
688
-	/* Point to NIC specific routines */
689
-	netdev->open	 = undinet_open;
690
-	netdev->close	 = undinet_close;
691
-	netdev->transmit = undinet_transmit;
692
-	netdev->poll	 = undinet_poll;
693
-
694 710
 	/* Register network device */
695 711
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
696 712
 		goto err_register;
@@ -716,6 +732,7 @@ int undinet_probe ( struct undi_device *undi ) {
716 732
 	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
717 733
 		       sizeof ( stop_undi ) );
718 734
  err_start_undi:
735
+	netdev_nullify ( netdev );
719 736
 	netdev_put ( netdev );
720 737
 	undi_set_drvdata ( undi, NULL );
721 738
 	return rc;
@@ -751,6 +768,7 @@ void undinet_remove ( struct undi_device *undi ) {
751 768
 	undi->flags &= ~UNDI_FL_STARTED;
752 769
 
753 770
 	/* Free network device */
771
+	netdev_nullify ( netdev );
754 772
 	netdev_put ( netdev );
755 773
 
756 774
 	DBGC ( undinic, "UNDINIC %p removed\n", undinic );

+ 30
- 21
src/drivers/net/legacy.c View File

@@ -36,13 +36,10 @@ static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf
36 36
 	return 0;
37 37
 }
38 38
 
39
-static void legacy_poll ( struct net_device *netdev, unsigned int rx_quota ) {
39
+static void legacy_poll ( struct net_device *netdev ) {
40 40
 	struct nic *nic = netdev->priv;
41 41
 	struct io_buffer *iobuf;
42 42
 
43
-	if ( ! rx_quota )
44
-		return;
45
-
46 43
 	iobuf = alloc_iob ( ETH_FRAME_LEN );
47 44
 	if ( ! iobuf )
48 45
 		return;
@@ -57,19 +54,29 @@ static void legacy_poll ( struct net_device *netdev, unsigned int rx_quota ) {
57 54
 	}
58 55
 }
59 56
 
60
-static int legacy_open ( struct net_device *netdev ) {
61
-	struct nic *nic = netdev->priv;
62
-
63
-	nic->nic_op->irq ( nic, ENABLE );
57
+static int legacy_open ( struct net_device *netdev __unused ) {
58
+	/* Nothing to do */
64 59
 	return 0;
65 60
 }
66 61
 
67
-static void legacy_close ( struct net_device *netdev ) {
62
+static void legacy_close ( struct net_device *netdev __unused ) {
63
+	/* Nothing to do */
64
+}
65
+
66
+static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
68 67
 	struct nic *nic = netdev->priv;
69 68
 
70
-	nic->nic_op->irq ( nic, DISABLE );
69
+	nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
71 70
 }
72 71
 
72
+static struct net_device_operations legacy_operations = {
73
+	.open		= legacy_open,
74
+	.close		= legacy_close,
75
+	.transmit	= legacy_transmit,
76
+	.poll		= legacy_poll,
77
+	.irq   		= legacy_irq,
78
+};
79
+
73 80
 int legacy_probe ( void *hwdev,
74 81
 		   void ( * set_drvdata ) ( void *hwdev, void *priv ),
75 82
 		   struct device *dev,
@@ -84,27 +91,21 @@ int legacy_probe ( void *hwdev,
84 91
 	netdev = alloc_etherdev ( 0 );
85 92
 	if ( ! netdev )
86 93
 		return -ENOMEM;
94
+	netdev_init ( netdev, &legacy_operations );
87 95
 	netdev->priv = &nic;
88 96
 	memset ( &nic, 0, sizeof ( nic ) );
89 97
 	set_drvdata ( hwdev, netdev );
90 98
 	netdev->dev = dev;
91 99
 
92
-	netdev->open = legacy_open;
93
-	netdev->close = legacy_close;
94
-	netdev->transmit = legacy_transmit;
95
-	netdev->poll = legacy_poll;
96 100
 	nic.node_addr = netdev->ll_addr;
97 101
 
98 102
 	if ( ! probe ( &nic, hwdev ) ) {
99
-		netdev_put ( netdev );
100
-		return -ENODEV;
103
+		rc = -ENODEV;
104
+		goto err_probe;
101 105
 	}
102 106
 
103
-	if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
104
-		disable ( &nic, hwdev );
105
-		netdev_put ( netdev );
106
-		return rc;
107
-	}
107
+	if ( ( rc = register_netdev ( netdev ) ) != 0 )
108
+		goto err_register;
108 109
 
109 110
 	/* Do not remove this message */
110 111
 	printf ( "WARNING: Using legacy NIC wrapper on %s\n",
@@ -112,6 +113,13 @@ int legacy_probe ( void *hwdev,
112 113
 
113 114
 	legacy_registered = 1;
114 115
 	return 0;
116
+
117
+ err_register:
118
+	disable ( &nic, hwdev );
119
+ err_probe:
120
+	netdev_nullify ( netdev );
121
+	netdev_put ( netdev );
122
+	return rc;
115 123
 }
116 124
 
117 125
 void legacy_remove ( void *hwdev,
@@ -122,6 +130,7 @@ void legacy_remove ( void *hwdev,
122 130
 
123 131
 	unregister_netdev ( netdev );
124 132
 	disable ( nic, hwdev );
133
+	netdev_nullify ( netdev );
125 134
 	netdev_put ( netdev );
126 135
 	legacy_registered = 0;
127 136
 }

+ 34
- 27
src/drivers/net/pnic.c View File

@@ -112,35 +112,34 @@ static int pnic_api_check ( uint16_t api_version ) {
112 112
 /**************************************************************************
113 113
 POLL - Wait for a frame
114 114
 ***************************************************************************/
115
-static void pnic_poll ( struct net_device *netdev, unsigned int rx_quota ) {
115
+static void pnic_poll ( struct net_device *netdev ) {
116 116
 	struct pnic *pnic = netdev->priv;
117 117
 	struct io_buffer *iobuf;
118 118
 	uint16_t length;
119 119
 	uint16_t qlen;
120 120
 
121 121
 	/* Fetch all available packets */
122
-	while ( rx_quota ) {
122
+	while ( 1 ) {
123 123
 		if ( pnic_command ( pnic, PNIC_CMD_RECV_QLEN, NULL, 0,
124 124
 				    &qlen, sizeof ( qlen ), NULL )
125 125
 		     != PNIC_STATUS_OK )
126
-			break;
126
+			return;
127 127
 		if ( qlen == 0 )
128
-			break;
128
+			return;
129 129
 		iobuf = alloc_iob ( ETH_FRAME_LEN );
130 130
 		if ( ! iobuf ) {
131 131
 			DBG ( "could not allocate buffer\n" );
132 132
 			netdev_rx_err ( netdev, NULL, -ENOMEM );
133
-			break;
133
+			return;
134 134
 		}
135 135
 		if ( pnic_command ( pnic, PNIC_CMD_RECV, NULL, 0,
136 136
 				    iobuf->data, ETH_FRAME_LEN, &length )
137 137
 		     != PNIC_STATUS_OK ) {
138 138
 			netdev_rx_err ( netdev, iobuf, -EIO );
139
-			break;
139
+			return;
140 140
 		}
141 141
 		iob_put ( iobuf, length );
142 142
 		netdev_rx ( netdev, iobuf );
143
-		--rx_quota;
144 143
 	}
145 144
 }
146 145
 
@@ -164,29 +163,40 @@ static int pnic_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
164 163
 /**************************************************************************
165 164
 OPEN - Open network device
166 165
 ***************************************************************************/
167
-static int pnic_open ( struct net_device *netdev ) {
168
-	struct pnic *pnic = netdev->priv;
169
-	static const uint8_t enable = 1;
170
-
171
-	/* Enable interrupts */
172
-	pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &enable,
173
-		       sizeof ( enable ), NULL, 0, NULL );
174
-	
166
+static int pnic_open ( struct net_device *netdev __unused ) {
167
+	/* Nothing to do */
175 168
 	return 0;
176 169
 }
177 170
 
178 171
 /**************************************************************************
179 172
 CLOSE - Close network device
180 173
 ***************************************************************************/
181
-static void pnic_close ( struct net_device *netdev ) {
182
-	struct pnic *pnic = netdev->priv;
183
-	static const uint8_t disable = 0;
174
+static void pnic_close ( struct net_device *netdev __unused ) {
175
+	/* Nothing to do */
176
+}
184 177
 
185
-	/* Disable interrupts */
186
-	pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &disable,
187
-		       sizeof ( disable ), NULL, 0, NULL );
178
+/**************************************************************************
179
+IRQ - Enable/disable interrupts
180
+***************************************************************************/
181
+static void pnic_irq ( struct net_device *netdev, int enable ) {
182
+	struct pnic *pnic = netdev->priv;
183
+	uint8_t mask = ( enable ? 1 : 0 );
184
+	
185
+	pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &mask, sizeof ( mask ),
186
+		       NULL, 0, NULL );
188 187
 }
189 188
 
189
+/**************************************************************************
190
+OPERATIONS TABLE
191
+***************************************************************************/
192
+static struct net_device_operations pnic_operations = {
193
+	.open		= pnic_open,
194
+	.close		= pnic_close,
195
+	.transmit	= pnic_transmit,
196
+	.poll		= pnic_poll,
197
+	.irq   		= pnic_irq,
198
+};
199
+
190 200
 /**************************************************************************
191 201
 DISABLE - Turn off ethernet interface
192 202
 ***************************************************************************/
@@ -196,6 +206,7 @@ static void pnic_remove ( struct pci_device *pci ) {
196 206
 
197 207
 	unregister_netdev ( netdev );
198 208
 	pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL );
209
+	netdev_nullify ( netdev );
199 210
 	netdev_put ( netdev );
200 211
 }
201 212
 
@@ -214,6 +225,7 @@ static int pnic_probe ( struct pci_device *pci,
214 225
 	netdev = alloc_etherdev ( sizeof ( *pnic ) );
215 226
 	if ( ! netdev )
216 227
 		return -ENOMEM;
228
+	netdev_init ( netdev, &pnic_operations );
217 229
 	pnic = netdev->priv;
218 230
 	pci_set_drvdata ( pci, netdev );
219 231
 	netdev->dev = &pci->dev;
@@ -238,12 +250,6 @@ static int pnic_probe ( struct pci_device *pci,
238 250
 	status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
239 251
 				netdev->ll_addr, ETH_ALEN, NULL );
240 252
 
241
-	/* Point to NIC specific routines */
242
-	netdev->open	 = pnic_open;
243
-	netdev->close	 = pnic_close;
244
-	netdev->poll	 = pnic_poll;
245
-	netdev->transmit = pnic_transmit;
246
-
247 253
 	/* Register network device */
248 254
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
249 255
 		goto err;
@@ -252,6 +258,7 @@ static int pnic_probe ( struct pci_device *pci,
252 258
 
253 259
  err:
254 260
 	/* Free net device */
261
+	netdev_nullify ( netdev );
255 262
 	netdev_put ( netdev );
256 263
 	return rc;
257 264
 }

+ 28
- 20
src/drivers/net/rtl8139.c View File

@@ -302,12 +302,6 @@ static struct nvo_fragment rtl_nvo_fragments[] = {
302 302
  */
303 303
 static void rtl_reset ( struct rtl8139_nic *rtl ) {
304 304
 
305
-	/* Disable interrupts.  May not be necessary, but datasheet
306
-	 * doesn't say that the reset command also resets the
307
-	 * interrupt mask.
308
-	 */
309
-	outw ( 0, rtl->ioaddr + IntrMask );
310
-
311 305
 	/* Reset chip */
312 306
 	outb ( CmdReset, rtl->ioaddr + ChipCmd );
313 307
 	mdelay ( 10 );
@@ -346,9 +340,6 @@ static int rtl_open ( struct net_device *netdev ) {
346 340
 	outl ( ( ( TX_DMA_BURST << 8 ) | ( TX_IPG << 24 ) ),
347 341
 	       rtl->ioaddr + TxConfig );
348 342
 
349
-	/* Enable interrupts */
350
-	outw ( ( ROK | RER | TOK | TER ), rtl->ioaddr + IntrMask );
351
-
352 343
 	return 0;
353 344
 }
354 345
 
@@ -400,13 +391,12 @@ static int rtl_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
400 391
 	return 0;
401 392
 }
402 393
 
403
-/** 
394
+/**
404 395
  * Poll for received packets
405 396
  *
406 397
  * @v netdev	Network device
407
- * @v rx_quota	Maximum number of packets to receive
408 398
  */
409
-static void rtl_poll ( struct net_device *netdev, unsigned int rx_quota ) {
399
+static void rtl_poll ( struct net_device *netdev ) {
410 400
 	struct rtl8139_nic *rtl = netdev->priv;
411 401
 	unsigned int status;
412 402
 	unsigned int tsad;
@@ -433,7 +423,7 @@ static void rtl_poll ( struct net_device *netdev, unsigned int rx_quota ) {
433 423
 	}
434 424
 
435 425
 	/* Handle received packets */
436
-	while ( rx_quota && ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ){
426
+	while ( ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ) {
437 427
 		rx_status = * ( ( uint16_t * )
438 428
 				( rtl->rx.ring + rtl->rx.offset ) );
439 429
 		rx_len = * ( ( uint16_t * )
@@ -461,7 +451,6 @@ static void rtl_poll ( struct net_device *netdev, unsigned int rx_quota ) {
461 451
 				 rtl->rx.ring, wrapped_len );
462 452
 
463 453
 			netdev_rx ( netdev, rx_iob );
464
-			rx_quota--;
465 454
 		} else {
466 455
 			DBG ( "RX bad packet (status %#04x len %d)\n",
467 456
 			      rx_status, rx_len );
@@ -473,6 +462,28 @@ static void rtl_poll ( struct net_device *netdev, unsigned int rx_quota ) {
473 462
 	}
474 463
 }
475 464
 
465
+/**
466
+ * Enable/disable interrupts
467
+ *
468
+ * @v netdev	Network device
469
+ * @v enable	Interrupts should be enabled
470
+ */
471
+static void rtl_irq ( struct net_device *netdev, int enable ) {
472
+	struct rtl8139_nic *rtl = netdev->priv;
473
+	
474
+	outw ( ( enable ? ( ROK | RER | TOK | TER ) : 0 ),
475
+	       rtl->ioaddr + IntrMask );
476
+}
477
+
478
+/** RTL8139 net device operations */
479
+static struct net_device_operations rtl_operations = {
480
+	.open		= rtl_open,
481
+	.close		= rtl_close,
482
+	.transmit	= rtl_transmit,
483
+	.poll		= rtl_poll,
484
+	.irq		= rtl_irq,
485
+};
486
+
476 487
 /**
477 488
  * Probe PCI device
478 489
  *
@@ -490,6 +501,7 @@ static int rtl_probe ( struct pci_device *pci,
490 501
 	netdev = alloc_etherdev ( sizeof ( *rtl ) );
491 502
 	if ( ! netdev )
492 503
 		return -ENOMEM;
504
+	netdev_init ( netdev, &rtl_operations );
493 505
 	rtl = netdev->priv;
494 506
 	pci_set_drvdata ( pci, netdev );
495 507
 	netdev->dev = &pci->dev;
@@ -504,12 +516,6 @@ static int rtl_probe ( struct pci_device *pci,
504 516
 	rtl_init_eeprom ( rtl );
505 517
 	nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
506 518
 	
507
-	/* Point to NIC specific routines */
508
-	netdev->open	 = rtl_open;
509
-	netdev->close	 = rtl_close;
510
-	netdev->transmit = rtl_transmit;
511
-	netdev->poll	 = rtl_poll;
512
-
513 519
 	/* Register network device */
514 520
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
515 521
 		goto err_register_netdev;
@@ -526,6 +532,7 @@ static int rtl_probe ( struct pci_device *pci,
526 532
 	unregister_netdev ( netdev );
527 533
  err_register_netdev:
528 534
 	rtl_reset ( rtl );
535
+	netdev_nullify ( netdev );
529 536
 	netdev_put ( netdev );
530 537
 	return rc;
531 538
 }
@@ -543,6 +550,7 @@ static void rtl_remove ( struct pci_device *pci ) {
543 550
 		nvo_unregister ( &rtl->nvo );
544 551
 	unregister_netdev ( netdev );
545 552
 	rtl_reset ( rtl );
553
+	netdev_nullify ( netdev );
546 554
 	netdev_put ( netdev );
547 555
 }
548 556
 

+ 77
- 43
src/include/gpxe/netdevice.h View File

@@ -128,41 +128,8 @@ struct ll_protocol {
128 128
 	const uint8_t *ll_broadcast;
129 129
 };
130 130
 
131
-/**
132
- * Network device statistics
133
- *
134
- */
135
-struct net_device_stats {
136
-	/** Count of successfully completed transmissions */
137
-	unsigned int tx_ok;
138
-	/** Count of transmission errors */
139
-	unsigned int tx_err;
140
-	/** Count of successfully received packets */
141
-	unsigned int rx_ok;
142
-	/** Count of reception errors */
143
-	unsigned int rx_err;
144
-};
145
-
146
-/**
147
- * A network device
148
- *
149
- * This structure represents a piece of networking hardware.  It has
150
- * properties such as a link-layer address and methods for
151
- * transmitting and receiving raw packets.
152
- *
153
- * Note that this structure must represent a generic network device,
154
- * not just an Ethernet device.
155
- */
156
-struct net_device {
157
-	/** Reference counter */
158
-	struct refcnt refcnt;
159
-	/** List of network devices */
160
-	struct list_head list;
161
-	/** Name of this network device */
162
-	char name[8];
163
-	/** Underlying hardware device */
164
-	struct device *dev;
165
-
131
+/** Network device operations */
132
+struct net_device_operations {
166 133
 	/** Open network device
167 134
 	 *
168 135
 	 * @v netdev	Network device
@@ -199,20 +166,62 @@ struct net_device {
199 166
 	 * This method is guaranteed to be called only when the device
200 167
 	 * is open.
201 168
 	 */
202
-	int ( * transmit ) ( struct net_device *netdev, struct io_buffer *iobuf );
203
-	/** Poll for received packet
169
+	int ( * transmit ) ( struct net_device *netdev,
170
+			     struct io_buffer *iobuf );
171
+	/** Poll for completed and received packets
204 172
 	 *
205 173
 	 * @v netdev	Network device
206
-	 * @v rx_quota	Maximum number of packets to receive
207 174
 	 *
208
-	 * This method should cause the hardware to check for received
209
-	 * packets.  Any received packets should be delivered via
210
-	 * netdev_rx(), up to a maximum of @c rx_quota packets.
175
+	 * This method should cause the hardware to check for
176
+	 * completed transmissions and received packets.  Any received
177
+	 * packets should be delivered via netdev_rx().
211 178
 	 *
212 179
 	 * This method is guaranteed to be called only when the device
213 180
 	 * is open.
214 181
 	 */
215
-	void ( * poll ) ( struct net_device *netdev, unsigned int rx_quota );
182
+	void ( * poll ) ( struct net_device *netdev );
183
+	/** Enable or disable interrupts
184
+	 *
185
+	 * @v netdev	Network device
186
+	 * @v enable	Interrupts should be enabled
187
+	 */
188
+	void ( * irq ) ( struct net_device *netdev, int enable );
189
+};
190
+
191
+/** Network device statistics */
192
+struct net_device_stats {
193
+	/** Count of successfully completed transmissions */
194
+	unsigned int tx_ok;
195
+	/** Count of transmission errors */
196
+	unsigned int tx_err;
197
+	/** Count of successfully received packets */
198
+	unsigned int rx_ok;
199
+	/** Count of reception errors */
200
+	unsigned int rx_err;
201
+};
202
+
203
+/**
204
+ * A network device
205
+ *
206
+ * This structure represents a piece of networking hardware.  It has
207
+ * properties such as a link-layer address and methods for
208
+ * transmitting and receiving raw packets.
209
+ *
210
+ * Note that this structure must represent a generic network device,
211
+ * not just an Ethernet device.
212
+ */
213
+struct net_device {
214
+	/** Reference counter */
215
+	struct refcnt refcnt;
216
+	/** List of network devices */
217
+	struct list_head list;
218
+	/** Name of this network device */
219
+	char name[8];
220
+	/** Underlying hardware device */
221
+	struct device *dev;
222
+
223
+	/** Network device operations */
224
+	struct net_device_operations *op;
216 225
 
217 226
 	/** Link-layer protocol */
218 227
 	struct ll_protocol *ll_protocol;
@@ -248,6 +257,30 @@ struct net_device {
248 257
 #define __net_protocol __table ( struct net_protocol, net_protocols, 01 )
249 258
 
250 259
 extern struct list_head net_devices;
260
+extern struct net_device_operations null_netdev_operations;
261
+
262
+/**
263
+ * Initialise a network device
264
+ *
265
+ * @v netdev		Network device
266
+ * @v op		Network device operations
267
+ */
268
+static inline void netdev_init ( struct net_device *netdev,
269
+				 struct net_device_operations *op ) {
270
+	netdev->op = op;
271
+}
272
+
273
+/**
274
+ * Stop using a network device
275
+ *
276
+ * @v netdev		Network device
277
+ *
278
+ * Drivers should call this method immediately before the final call
279
+ * to netdev_put().
280
+ */
281
+static inline void netdev_nullify ( struct net_device *netdev ) {
282
+	netdev->op = &null_netdev_operations;
283
+}
251 284
 
252 285
 /**
253 286
  * Get printable network device hardware address
@@ -300,13 +333,14 @@ extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
300 333
 extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
301 334
 extern void netdev_rx_err ( struct net_device *netdev,
302 335
 			    struct io_buffer *iobuf, int rc );
303
-extern int netdev_poll ( struct net_device *netdev, unsigned int rx_quota );
336
+extern void netdev_poll ( struct net_device *netdev );
304 337
 extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
305 338
 extern struct net_device * alloc_netdev ( size_t priv_size );
306 339
 extern int register_netdev ( struct net_device *netdev );
307 340
 extern int netdev_open ( struct net_device *netdev );
308 341
 extern void netdev_close ( struct net_device *netdev );
309 342
 extern void unregister_netdev ( struct net_device *netdev );
343
+extern void netdev_irq ( struct net_device *netdev, int enable );
310 344
 extern struct net_device * find_netdev ( const char *name );
311 345
 extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
312 346
 						     unsigned int location );

+ 17
- 9
src/interface/pxe/pxe_undi.c View File

@@ -69,7 +69,13 @@ void pxe_set_netdev ( struct net_device *netdev ) {
69 69
  * @ret rc		Return status code
70 70
  */
71 71
 static int pxe_netdev_open ( void ) {
72
-	return netdev_open ( pxe_netdev );
72
+	int rc;
73
+
74
+	if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
75
+		return rc;
76
+
77
+	netdev_irq ( pxe_netdev, 1 );
78
+	return 0;
73 79
 }
74 80
 
75 81
 /**
@@ -77,6 +83,7 @@ static int pxe_netdev_open ( void ) {
77 83
  *
78 84
  */
79 85
 static void pxe_netdev_close ( void ) {
86
+	netdev_irq ( pxe_netdev, 0 );
80 87
 	netdev_close ( pxe_netdev );
81 88
 	undi_tx_count = 0;
82 89
 }
@@ -543,14 +550,13 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
543 550
 		/* Call poll().  This should acknowledge the device
544 551
 		 * interrupt and queue up any received packet.
545 552
 		 */
546
-		if ( netdev_poll ( pxe_netdev, -1U ) ) {
547
-			/* Packet waiting in queue */
548
-			DBG ( " OURS" );
549
-			undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
550
-		} else {
551
-			DBG ( " NOT_OURS" );
552
-			undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_NOT_OURS;
553
-		}
553
+		netdev_poll ( pxe_netdev );
554
+
555
+		/* Disable interrupts to avoid interrupt storm */
556
+		netdev_irq ( pxe_netdev, 0 );
557
+
558
+		/* Always say it was ours for the sake of simplicity */
559
+		undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
554 560
 		break;
555 561
 	case PXENV_UNDI_ISR_IN_PROCESS :
556 562
 	case PXENV_UNDI_ISR_IN_GET_NEXT :
@@ -570,6 +576,8 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
570 576
 		if ( ! iobuf ) {
571 577
 			/* No more packets remaining */
572 578
 			undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
579
+			/* Re-enable interrupts */
580
+			netdev_irq ( pxe_netdev, 1 );
573 581
 			break;
574 582
 		}
575 583
 

+ 19
- 14
src/net/netdevice.c View File

@@ -68,7 +68,7 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
68 68
 		goto err;
69 69
 	}
70 70
 		
71
-	if ( ( rc = netdev->transmit ( netdev, iobuf ) ) != 0 )
71
+	if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
72 72
 		goto err;
73 73
 
74 74
 	return 0;
@@ -187,22 +187,18 @@ void netdev_rx_err ( struct net_device *netdev,
187 187
 }
188 188
 
189 189
 /**
190
- * Poll for packet on network device
190
+ * Poll for completed and received packets on network device
191 191
  *
192 192
  * @v netdev		Network device
193
- * @v rx_quota		Maximum number of packets to receive
194
- * @ret True		There are packets present in the receive queue
195
- * @ret False		There are no packets present in the receive queue
196 193
  *
197
- * Polls the network device for received packets.  Any received
198
- * packets will be added to the RX packet queue via netdev_rx().
194
+ * Polls the network device for completed transmissions and received
195
+ * packets.  Any received packets will be added to the RX packet queue
196
+ * via netdev_rx().
199 197
  */
200
-int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ) {
198
+void netdev_poll ( struct net_device *netdev ) {
201 199
 
202 200
 	if ( netdev->state & NETDEV_OPEN )
203
-		netdev->poll ( netdev, rx_quota );
204
-
205
-	return ( ! list_empty ( &netdev->rx_queue ) );
201
+		netdev->op->poll ( netdev );
206 202
 }
207 203
 
208 204
 /**
@@ -317,7 +313,7 @@ int netdev_open ( struct net_device *netdev ) {
317 313
 	DBGC ( netdev, "NETDEV %p opening\n", netdev );
318 314
 
319 315
 	/* Open the device */
320
-	if ( ( rc = netdev->open ( netdev ) ) != 0 )
316
+	if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
321 317
 		return rc;
322 318
 
323 319
 	/* Mark as opened */
@@ -339,7 +335,7 @@ void netdev_close ( struct net_device *netdev ) {
339 335
 	DBGC ( netdev, "NETDEV %p closing\n", netdev );
340 336
 
341 337
 	/* Close the device */
342
-	netdev->close ( netdev );
338
+	netdev->op->close ( netdev );
343 339
 
344 340
 	/* Flush TX and RX queues */
345 341
 	netdev_tx_flush ( netdev );
@@ -367,6 +363,15 @@ void unregister_netdev ( struct net_device *netdev ) {
367 363
 	DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
368 364
 }
369 365
 
366
+/** Enable or disable interrupts
367
+ *
368
+ * @v netdev		Network device
369
+ * @v enable		Interrupts should be enabled
370
+ */
371
+void netdev_irq ( struct net_device *netdev, int enable ) {
372
+	netdev->op->irq ( netdev, enable );
373
+}
374
+
370 375
 /**
371 376
  * Get network device by name
372 377
  *
@@ -462,7 +467,7 @@ static void net_step ( struct process *process __unused ) {
462 467
 	list_for_each_entry ( netdev, &net_devices, list ) {
463 468
 
464 469
 		/* Poll for new packets */
465
-		netdev_poll ( netdev, -1U );
470
+		netdev_poll ( netdev );
466 471
 
467 472
 		/* Process at most one received packet.  Give priority
468 473
 		 * to getting packets out of the NIC over processing

+ 57
- 0
src/net/nullnet.c View File

@@ -0,0 +1,57 @@
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
+#include <stdint.h>
20
+#include <gpxe/iobuf.h>
21
+#include <gpxe/netdevice.h>
22
+
23
+/** @file
24
+ *
25
+ * Null network device
26
+ *
27
+ */
28
+
29
+static int null_open ( struct net_device *netdev __unused ) {
30
+	return -ENODEV;
31
+};
32
+
33
+static void null_close ( struct net_device *netdev __unused ) {
34
+	/* Do nothing */
35
+};
36
+
37
+static int null_transmit ( struct net_device *netdev __unused,
38
+			   struct io_buffer *iobuf __unused ) {
39
+	return -ENODEV;
40
+};
41
+
42
+static void null_poll ( struct net_device *netdev __unused ) {
43
+	/* Do nothing */
44
+}
45
+
46
+static void null_irq ( struct net_device *netdev __unused,
47
+		       int enable __unused ) {
48
+	/* Do nothing */
49
+}
50
+
51
+struct net_device_operations null_netdev_operations = {
52
+	.open		= null_open,
53
+	.close		= null_close,
54
+	.transmit	= null_transmit,
55
+	.poll		= null_poll,
56
+	.irq   		= null_irq,
57
+};

Loading…
Cancel
Save