|
@@ -43,6 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
43
|
43
|
|
44
|
44
|
/** An UNDI NIC */
|
45
|
45
|
struct undi_nic {
|
|
46
|
+ /** Device supports IRQs */
|
|
47
|
+ int irq_supported;
|
46
|
48
|
/** Assigned IRQ number */
|
47
|
49
|
unsigned int irq;
|
48
|
50
|
/** Currently processing ISR */
|
|
@@ -251,8 +253,10 @@ static void undinet_poll ( struct net_device *netdev ) {
|
251
|
253
|
int rc;
|
252
|
254
|
|
253
|
255
|
if ( ! undinic->isr_processing ) {
|
254
|
|
- /* Do nothing unless ISR has been triggered */
|
255
|
|
- if ( ! undinet_isr_triggered() ) {
|
|
256
|
+ /* If interrupts are supported, then do nothing unless
|
|
257
|
+ * the ISR has been triggered.
|
|
258
|
+ */
|
|
259
|
+ if ( undinic->irq_supported && ( ! undinet_isr_triggered() ) ){
|
256
|
260
|
/* Allow interrupt to occur */
|
257
|
261
|
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
|
258
|
262
|
"nop\n\t"
|
|
@@ -357,10 +361,12 @@ static int undinet_open ( struct net_device *netdev ) {
|
357
|
361
|
struct s_PXENV_UNDI_OPEN undi_open;
|
358
|
362
|
int rc;
|
359
|
363
|
|
360
|
|
- /* Hook interrupt service routine and enable interrupt */
|
361
|
|
- undinet_hook_isr ( undinic->irq );
|
362
|
|
- enable_irq ( undinic->irq );
|
363
|
|
- send_eoi ( undinic->irq );
|
|
364
|
+ /* Hook interrupt service routine and enable interrupt if supported */
|
|
365
|
+ if ( undinic->irq_supported ) {
|
|
366
|
+ undinet_hook_isr ( undinic->irq );
|
|
367
|
+ enable_irq ( undinic->irq );
|
|
368
|
+ send_eoi ( undinic->irq );
|
|
369
|
+ }
|
364
|
370
|
|
365
|
371
|
/* Set station address. Required for some PXE stacks; will
|
366
|
372
|
* spuriously fail on others. Ignore failures. We only ever
|
|
@@ -425,9 +431,11 @@ static void undinet_close ( struct net_device *netdev ) {
|
425
|
431
|
pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
|
426
|
432
|
&undi_close, sizeof ( undi_close ) );
|
427
|
433
|
|
428
|
|
- /* Disable interrupt and unhook ISR */
|
429
|
|
- disable_irq ( undinic->irq );
|
430
|
|
- undinet_unhook_isr ( undinic->irq );
|
|
434
|
+ /* Disable interrupt and unhook ISR if supported */
|
|
435
|
+ if ( undinic->irq_supported ) {
|
|
436
|
+ disable_irq ( undinic->irq );
|
|
437
|
+ undinet_unhook_isr ( undinic->irq );
|
|
438
|
+ }
|
431
|
439
|
|
432
|
440
|
DBGC ( undinic, "UNDINIC %p closed\n", undinic );
|
433
|
441
|
}
|
|
@@ -524,13 +532,8 @@ int undinet_probe ( struct undi_device *undi ) {
|
524
|
532
|
goto err_undi_get_information;
|
525
|
533
|
memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
|
526
|
534
|
undinic->irq = undi_info.IntNumber;
|
527
|
|
- if ( undinic->irq > IRQ_MAX ) {
|
528
|
|
- DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n",
|
529
|
|
- undinic, undinic->irq );
|
530
|
|
- goto err_bad_irq;
|
531
|
|
- }
|
532
|
|
- DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
|
533
|
|
- undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
|
|
535
|
+ DBGC ( undinic, "UNDINIC %p has MAC address %s\n",
|
|
536
|
+ undinic, eth_ntoa ( netdev->hw_addr ) );
|
534
|
537
|
|
535
|
538
|
/* Get interface information */
|
536
|
539
|
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
|
|
@@ -541,6 +544,17 @@ int undinet_probe ( struct undi_device *undi ) {
|
541
|
544
|
DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
|
542
|
545
|
undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
|
543
|
546
|
undi_iface.ServiceFlags );
|
|
547
|
+ if ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) {
|
|
548
|
+ if ( undinic->irq > IRQ_MAX ) {
|
|
549
|
+ DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n",
|
|
550
|
+ undinic, undinic->irq );
|
|
551
|
+ rc = -EINVAL;
|
|
552
|
+ goto err_bad_irq;
|
|
553
|
+ }
|
|
554
|
+ undinic->irq_supported = 1;
|
|
555
|
+ DBGC ( undinic, "UNDINIC %p uses IRQ %d\n",
|
|
556
|
+ undinic, undinic->irq );
|
|
557
|
+ }
|
544
|
558
|
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
|
545
|
559
|
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
|
546
|
560
|
DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
|
|
@@ -559,8 +573,8 @@ int undinet_probe ( struct undi_device *undi ) {
|
559
|
573
|
return 0;
|
560
|
574
|
|
561
|
575
|
err_register:
|
562
|
|
- err_undi_get_iface_info:
|
563
|
576
|
err_bad_irq:
|
|
577
|
+ err_undi_get_iface_info:
|
564
|
578
|
err_undi_get_information:
|
565
|
579
|
err_undi_initialize:
|
566
|
580
|
/* Shut down UNDI stack */
|