aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshemminger@osdl.org <shemminger@osdl.org>2005-09-27 18:02:56 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-28 11:49:32 -0400
commitd11c13e752c4e34777d33579ee0378e0178ef52d (patch)
tree71b877e71e9c8b03b478a160b07f4a2e0d62cfe9
parent6b1a3aefd897fd9be410d192f950656ef2b59694 (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>
-rw-r--r--drivers/net/sky2.c65
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 */
1043static void sky2_tx_complete(struct net_device *dev, u16 done) 1043static 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 */
1087static inline void sky2_tx_clean(struct sky2_port *sky2) 1088static 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 */
1424static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port, 1425static 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
1479resubmit: 1482resubmit:
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 */
1520static int sky2_poll(struct net_device *dev, int *budget) 1524static 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;