diff options
Diffstat (limited to 'drivers/net/mac89x0.c')
-rw-r--r-- | drivers/net/mac89x0.c | 88 |
1 files changed, 32 insertions, 56 deletions
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 90e695d53266..26a3b45a4a34 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c | |||
@@ -128,7 +128,7 @@ struct net_local { | |||
128 | extern void reset_chip(struct net_device *dev); | 128 | extern void reset_chip(struct net_device *dev); |
129 | #endif | 129 | #endif |
130 | static int net_open(struct net_device *dev); | 130 | static int net_open(struct net_device *dev); |
131 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev); | 131 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev); |
132 | static irqreturn_t net_interrupt(int irq, void *dev_id); | 132 | static irqreturn_t net_interrupt(int irq, void *dev_id); |
133 | static void set_multicast_list(struct net_device *dev); | 133 | static void set_multicast_list(struct net_device *dev); |
134 | static void net_rx(struct net_device *dev); | 134 | static void net_rx(struct net_device *dev); |
@@ -374,56 +374,39 @@ net_open(struct net_device *dev) | |||
374 | static int | 374 | static int |
375 | net_send_packet(struct sk_buff *skb, struct net_device *dev) | 375 | net_send_packet(struct sk_buff *skb, struct net_device *dev) |
376 | { | 376 | { |
377 | if (dev->tbusy) { | 377 | struct net_local *lp = netdev_priv(dev); |
378 | /* If we get here, some higher level has decided we are broken. | 378 | unsigned long flags; |
379 | There should really be a "kick me" function call instead. */ | ||
380 | int tickssofar = jiffies - dev->trans_start; | ||
381 | if (tickssofar < 5) | ||
382 | return 1; | ||
383 | if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name, | ||
384 | tx_done(dev) ? "IRQ conflict" : "network cable problem"); | ||
385 | /* Try to restart the adaptor. */ | ||
386 | dev->tbusy=0; | ||
387 | dev->trans_start = jiffies; | ||
388 | } | ||
389 | |||
390 | /* Block a timer-based transmit from overlapping. This could better be | ||
391 | done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ | ||
392 | if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) | ||
393 | printk("%s: Transmitter access conflict.\n", dev->name); | ||
394 | else { | ||
395 | struct net_local *lp = netdev_priv(dev); | ||
396 | unsigned long flags; | ||
397 | |||
398 | if (net_debug > 3) | ||
399 | printk("%s: sent %d byte packet of type %x\n", | ||
400 | dev->name, skb->len, | ||
401 | (skb->data[ETH_ALEN+ETH_ALEN] << 8) | ||
402 | | skb->data[ETH_ALEN+ETH_ALEN+1]); | ||
403 | |||
404 | /* keep the upload from being interrupted, since we | ||
405 | ask the chip to start transmitting before the | ||
406 | whole packet has been completely uploaded. */ | ||
407 | local_irq_save(flags); | ||
408 | 379 | ||
409 | /* initiate a transmit sequence */ | 380 | if (net_debug > 3) |
410 | writereg(dev, PP_TxCMD, lp->send_cmd); | 381 | printk("%s: sent %d byte packet of type %x\n", |
411 | writereg(dev, PP_TxLength, skb->len); | 382 | dev->name, skb->len, |
383 | (skb->data[ETH_ALEN+ETH_ALEN] << 8) | ||
384 | | skb->data[ETH_ALEN+ETH_ALEN+1]); | ||
412 | 385 | ||
413 | /* Test to see if the chip has allocated memory for the packet */ | 386 | /* keep the upload from being interrupted, since we |
414 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { | 387 | ask the chip to start transmitting before the |
415 | /* Gasp! It hasn't. But that shouldn't happen since | 388 | whole packet has been completely uploaded. */ |
416 | we're waiting for TxOk, so return 1 and requeue this packet. */ | 389 | local_irq_save(flags); |
417 | local_irq_restore(flags); | 390 | netif_stop_queue(dev); |
418 | return 1; | ||
419 | } | ||
420 | 391 | ||
421 | /* Write the contents of the packet */ | 392 | /* initiate a transmit sequence */ |
422 | memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1); | 393 | writereg(dev, PP_TxCMD, lp->send_cmd); |
394 | writereg(dev, PP_TxLength, skb->len); | ||
423 | 395 | ||
396 | /* Test to see if the chip has allocated memory for the packet */ | ||
397 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { | ||
398 | /* Gasp! It hasn't. But that shouldn't happen since | ||
399 | we're waiting for TxOk, so return 1 and requeue this packet. */ | ||
424 | local_irq_restore(flags); | 400 | local_irq_restore(flags); |
425 | dev->trans_start = jiffies; | 401 | return 1; |
426 | } | 402 | } |
403 | |||
404 | /* Write the contents of the packet */ | ||
405 | skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame), | ||
406 | skb->len+1); | ||
407 | |||
408 | local_irq_restore(flags); | ||
409 | dev->trans_start = jiffies; | ||
427 | dev_kfree_skb (skb); | 410 | dev_kfree_skb (skb); |
428 | 411 | ||
429 | return 0; | 412 | return 0; |
@@ -441,9 +424,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
441 | printk ("net_interrupt(): irq %d for unknown device.\n", irq); | 424 | printk ("net_interrupt(): irq %d for unknown device.\n", irq); |
442 | return IRQ_NONE; | 425 | return IRQ_NONE; |
443 | } | 426 | } |
444 | if (dev->interrupt) | ||
445 | printk("%s: Re-entering the interrupt handler.\n", dev->name); | ||
446 | dev->interrupt = 1; | ||
447 | 427 | ||
448 | ioaddr = dev->base_addr; | 428 | ioaddr = dev->base_addr; |
449 | lp = netdev_priv(dev); | 429 | lp = netdev_priv(dev); |
@@ -464,8 +444,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
464 | break; | 444 | break; |
465 | case ISQ_TRANSMITTER_EVENT: | 445 | case ISQ_TRANSMITTER_EVENT: |
466 | lp->stats.tx_packets++; | 446 | lp->stats.tx_packets++; |
467 | dev->tbusy = 0; | 447 | netif_wake_queue(dev); |
468 | mark_bh(NET_BH); /* Inform upper layers. */ | ||
469 | if ((status & TX_OK) == 0) lp->stats.tx_errors++; | 448 | if ((status & TX_OK) == 0) lp->stats.tx_errors++; |
470 | if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; | 449 | if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; |
471 | if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; | 450 | if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; |
@@ -479,8 +458,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
479 | That shouldn't happen since we only ever | 458 | That shouldn't happen since we only ever |
480 | load one packet. Shrug. Do the right | 459 | load one packet. Shrug. Do the right |
481 | thing anyway. */ | 460 | thing anyway. */ |
482 | dev->tbusy = 0; | 461 | netif_wake_queue(dev); |
483 | mark_bh(NET_BH); /* Inform upper layers. */ | ||
484 | } | 462 | } |
485 | if (status & TX_UNDERRUN) { | 463 | if (status & TX_UNDERRUN) { |
486 | if (net_debug > 0) printk("%s: transmit underrun\n", dev->name); | 464 | if (net_debug > 0) printk("%s: transmit underrun\n", dev->name); |
@@ -497,7 +475,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
497 | break; | 475 | break; |
498 | } | 476 | } |
499 | } | 477 | } |
500 | dev->interrupt = 0; | ||
501 | return IRQ_HANDLED; | 478 | return IRQ_HANDLED; |
502 | } | 479 | } |
503 | 480 | ||
@@ -531,7 +508,8 @@ net_rx(struct net_device *dev) | |||
531 | } | 508 | } |
532 | skb_put(skb, length); | 509 | skb_put(skb, length); |
533 | 510 | ||
534 | memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length); | 511 | skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame), |
512 | length); | ||
535 | 513 | ||
536 | if (net_debug > 3)printk("%s: received %d byte packet of type %x\n", | 514 | if (net_debug > 3)printk("%s: received %d byte packet of type %x\n", |
537 | dev->name, length, | 515 | dev->name, length, |
@@ -610,8 +588,6 @@ static void set_multicast_list(struct net_device *dev) | |||
610 | static int set_mac_address(struct net_device *dev, void *addr) | 588 | static int set_mac_address(struct net_device *dev, void *addr) |
611 | { | 589 | { |
612 | int i; | 590 | int i; |
613 | if (dev->start) | ||
614 | return -EBUSY; | ||
615 | printk("%s: Setting MAC address to ", dev->name); | 591 | printk("%s: Setting MAC address to ", dev->name); |
616 | for (i = 0; i < 6; i++) | 592 | for (i = 0; i < 6; i++) |
617 | printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); | 593 | printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); |