diff options
author | shemminger@osdl.org <shemminger@osdl.org> | 2005-09-27 18:02:56 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-28 11:49:32 -0400 |
commit | d11c13e752c4e34777d33579ee0378e0178ef52d (patch) | |
tree | 71b877e71e9c8b03b478a160b07f4a2e0d62cfe9 /drivers/net/sky2.c | |
parent | 6b1a3aefd897fd9be410d192f950656ef2b59694 (diff) |
[PATCH] sky2: cleanup interrupt processing
The receive processing can be cleaned up by not using local variables
to store checksum status, instead just put it directly onto the expected
skb.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 65 |
1 files changed, 28 insertions, 37 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0cc57293faf9..8527a49e3ff7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1040,13 +1040,14 @@ out_unlock: | |||
1040 | * NB: the hardware will tell us about partial completion of multi-part | 1040 | * NB: the hardware will tell us about partial completion of multi-part |
1041 | * buffers; these are defered until completion. | 1041 | * buffers; these are defered until completion. |
1042 | */ | 1042 | */ |
1043 | static void sky2_tx_complete(struct net_device *dev, u16 done) | 1043 | static void sky2_tx_complete(struct sky2_port *sky2, u16 done) |
1044 | { | 1044 | { |
1045 | struct sky2_port *sky2 = netdev_priv(dev); | 1045 | struct net_device *dev = sky2->netdev; |
1046 | unsigned i; | 1046 | unsigned i; |
1047 | 1047 | ||
1048 | if (netif_msg_tx_done(sky2)) | 1048 | if (unlikely(netif_msg_tx_done(sky2))) |
1049 | printk(KERN_DEBUG "%s: tx done, upto %u\n", dev->name, done); | 1049 | printk(KERN_DEBUG "%s: tx done, upto %u\n", |
1050 | dev->name, done); | ||
1050 | 1051 | ||
1051 | spin_lock(&sky2->tx_lock); | 1052 | spin_lock(&sky2->tx_lock); |
1052 | 1053 | ||
@@ -1086,7 +1087,7 @@ out: | |||
1086 | /* Cleanup all untransmitted buffers, assume transmitter not running */ | 1087 | /* Cleanup all untransmitted buffers, assume transmitter not running */ |
1087 | static inline void sky2_tx_clean(struct sky2_port *sky2) | 1088 | static inline void sky2_tx_clean(struct sky2_port *sky2) |
1088 | { | 1089 | { |
1089 | sky2_tx_complete(sky2->netdev, sky2->tx_prod); | 1090 | sky2_tx_complete(sky2, sky2->tx_prod); |
1090 | } | 1091 | } |
1091 | 1092 | ||
1092 | /* Network shutdown */ | 1093 | /* Network shutdown */ |
@@ -1421,18 +1422,17 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1421 | * For small packets or errors, just reuse existing skb. | 1422 | * For small packets or errors, just reuse existing skb. |
1422 | * For larger pakects, get new buffer. | 1423 | * For larger pakects, get new buffer. |
1423 | */ | 1424 | */ |
1424 | static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port, | 1425 | static struct sk_buff *sky2_receive(struct sky2_port *sky2, |
1425 | u16 length, u32 status) | 1426 | u16 length, u32 status) |
1426 | { | 1427 | { |
1427 | struct net_device *dev = hw->dev[port]; | ||
1428 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1429 | struct ring_info *re = sky2->rx_ring + sky2->rx_next; | 1428 | struct ring_info *re = sky2->rx_ring + sky2->rx_next; |
1430 | struct sk_buff *skb = NULL; | 1429 | struct sk_buff *skb = NULL; |
1430 | struct net_device *dev; | ||
1431 | const unsigned int bufsize = rx_size(sky2); | 1431 | const unsigned int bufsize = rx_size(sky2); |
1432 | 1432 | ||
1433 | if (unlikely(netif_msg_rx_status(sky2))) | 1433 | if (unlikely(netif_msg_rx_status(sky2))) |
1434 | printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", | 1434 | printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", |
1435 | dev->name, sky2->rx_next, status, length); | 1435 | sky2->netdev->name, sky2->rx_next, status, length); |
1436 | 1436 | ||
1437 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | 1437 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; |
1438 | 1438 | ||
@@ -1451,6 +1451,8 @@ static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port, | |||
1451 | pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr, | 1451 | pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr, |
1452 | length, PCI_DMA_FROMDEVICE); | 1452 | length, PCI_DMA_FROMDEVICE); |
1453 | memcpy(skb->data, re->skb->data, length); | 1453 | memcpy(skb->data, re->skb->data, length); |
1454 | skb->ip_summed = re->skb->ip_summed; | ||
1455 | skb->csum = re->skb->csum; | ||
1454 | pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr, | 1456 | pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr, |
1455 | length, PCI_DMA_FROMDEVICE); | 1457 | length, PCI_DMA_FROMDEVICE); |
1456 | } else { | 1458 | } else { |
@@ -1471,12 +1473,14 @@ static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port, | |||
1471 | re->maplen = bufsize; | 1473 | re->maplen = bufsize; |
1472 | } | 1474 | } |
1473 | 1475 | ||
1474 | skb->dev = dev; | ||
1475 | skb_put(skb, length); | 1476 | skb_put(skb, length); |
1477 | dev = sky2->netdev; | ||
1478 | skb->dev = dev; | ||
1476 | skb->protocol = eth_type_trans(skb, dev); | 1479 | skb->protocol = eth_type_trans(skb, dev); |
1477 | dev->last_rx = jiffies; | 1480 | dev->last_rx = jiffies; |
1478 | 1481 | ||
1479 | resubmit: | 1482 | resubmit: |
1483 | re->skb->ip_summed = CHECKSUM_NONE; | ||
1480 | sky2_rx_add(sky2, re); | 1484 | sky2_rx_add(sky2, re); |
1481 | 1485 | ||
1482 | return skb; | 1486 | return skb; |
@@ -1517,59 +1521,46 @@ static inline u16 tx_index(u8 port, u32 status, u16 len) | |||
1517 | * Both ports share the same status interrupt, therefore there is only | 1521 | * Both ports share the same status interrupt, therefore there is only |
1518 | * one poll routine. | 1522 | * one poll routine. |
1519 | */ | 1523 | */ |
1520 | static int sky2_poll(struct net_device *dev, int *budget) | 1524 | static int sky2_poll(struct net_device *dev0, int *budget) |
1521 | { | 1525 | { |
1522 | struct sky2_port *sky2 = netdev_priv(dev); | 1526 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
1523 | struct sky2_hw *hw = sky2->hw; | 1527 | unsigned int to_do = min(dev0->quota, *budget); |
1524 | unsigned int to_do = min(dev->quota, *budget); | ||
1525 | unsigned int work_done = 0; | 1528 | unsigned int work_done = 0; |
1526 | u16 hwidx; | 1529 | u16 hwidx; |
1527 | unsigned char summed[2] = { CHECKSUM_NONE, CHECKSUM_NONE }; | ||
1528 | unsigned int csum[2]; | ||
1529 | 1530 | ||
1530 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | 1531 | hwidx = sky2_read16(hw, STAT_PUT_IDX); |
1531 | BUG_ON(hwidx >= STATUS_RING_SIZE); | 1532 | BUG_ON(hwidx >= STATUS_RING_SIZE); |
1532 | rmb(); | 1533 | rmb(); |
1533 | while (hw->st_idx != hwidx && work_done < to_do) { | 1534 | while (hw->st_idx != hwidx && work_done < to_do) { |
1534 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1535 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1536 | struct sky2_port *sky2; | ||
1535 | struct sk_buff *skb; | 1537 | struct sk_buff *skb; |
1536 | u8 port; | ||
1537 | u32 status; | 1538 | u32 status; |
1538 | u16 length; | 1539 | u16 length; |
1539 | 1540 | ||
1541 | BUG_ON(le->link >= hw->ports); | ||
1542 | sky2 = netdev_priv(hw->dev[le->link]); | ||
1540 | status = le32_to_cpu(le->status); | 1543 | status = le32_to_cpu(le->status); |
1541 | length = le16_to_cpu(le->length); | 1544 | length = le16_to_cpu(le->length); |
1542 | port = le->link; | ||
1543 | |||
1544 | BUG_ON(port >= hw->ports || hw->dev[port] == NULL); | ||
1545 | 1545 | ||
1546 | switch (le->opcode & ~HW_OWNER) { | 1546 | switch (le->opcode & ~HW_OWNER) { |
1547 | case OP_RXSTAT: | 1547 | case OP_RXSTAT: |
1548 | skb = sky2_receive(hw, port, length, status); | 1548 | skb = sky2_receive(sky2, length, status); |
1549 | if (likely(skb)) { | 1549 | if (likely(skb)) { |
1550 | /* Add hw checksum if available */ | ||
1551 | skb->ip_summed = summed[port]; | ||
1552 | skb->csum = csum[port]; | ||
1553 | |||
1554 | netif_receive_skb(skb); | 1550 | netif_receive_skb(skb); |
1555 | ++work_done; | 1551 | ++work_done; |
1556 | } | 1552 | } |
1557 | |||
1558 | /* Clear for next packet */ | ||
1559 | csum[port] = 0; | ||
1560 | summed[port] = CHECKSUM_NONE; | ||
1561 | |||
1562 | break; | 1553 | break; |
1563 | 1554 | ||
1564 | case OP_RXCHKS: | 1555 | case OP_RXCHKS: |
1565 | /* Save computed checksum for next rx */ | 1556 | skb = sky2->rx_ring[sky2->rx_next].skb; |
1566 | csum[port] = le16_to_cpu(status & 0xffff); | 1557 | skb->ip_summed = CHECKSUM_HW; |
1567 | summed[port] = CHECKSUM_HW; | 1558 | skb->csum = le16_to_cpu(status); |
1568 | break; | 1559 | break; |
1569 | 1560 | ||
1570 | case OP_TXINDEXLE: | 1561 | case OP_TXINDEXLE: |
1571 | sky2_tx_complete(hw->dev[port], | 1562 | sky2_tx_complete(sky2, |
1572 | tx_index(port, status, length)); | 1563 | tx_index(sky2->port, status, length)); |
1573 | break; | 1564 | break; |
1574 | 1565 | ||
1575 | case OP_RXTIMESTAMP: | 1566 | case OP_RXTIMESTAMP: |
@@ -1599,7 +1590,7 @@ static int sky2_poll(struct net_device *dev, int *budget) | |||
1599 | rx_set_put(hw->dev[1]); | 1590 | rx_set_put(hw->dev[1]); |
1600 | 1591 | ||
1601 | *budget -= work_done; | 1592 | *budget -= work_done; |
1602 | dev->quota -= work_done; | 1593 | dev0->quota -= work_done; |
1603 | if (work_done < to_do) { | 1594 | if (work_done < to_do) { |
1604 | /* | 1595 | /* |
1605 | * Another chip workaround, need to restart TX timer if status | 1596 | * Another chip workaround, need to restart TX timer if status |
@@ -1613,7 +1604,7 @@ static int sky2_poll(struct net_device *dev, int *budget) | |||
1613 | hw->intr_mask |= Y2_IS_STAT_BMU; | 1604 | hw->intr_mask |= Y2_IS_STAT_BMU; |
1614 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1605 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
1615 | sky2_read32(hw, B0_IMSK); | 1606 | sky2_read32(hw, B0_IMSK); |
1616 | netif_rx_complete(dev); | 1607 | netif_rx_complete(dev0); |
1617 | } | 1608 | } |
1618 | 1609 | ||
1619 | return work_done >= to_do; | 1610 | return work_done >= to_do; |