diff options
author | Mike McCormack <mikem@ring3k.org> | 2009-08-14 01:15:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-14 18:29:55 -0400 |
commit | 9b289c3374d2891aac6c12de58e49a16cfbcb6b1 (patch) | |
tree | 78943955fe3f116c8d33577d2a77a9fd51ee7dfa /drivers/net/sky2.c | |
parent | a8519de4a030d130e0d18147a2af3112b7951e0b (diff) |
sky2: Avoid rewinding sky2->tx_prod
Keep sky2->tx_prod consistent since int might be examined by
an softirq poll or restart.
Signed-off-by: Mike McCormack <mikem@ring3k.org>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1415a8375093..a52b86317837 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -989,11 +989,11 @@ static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr, | |||
989 | sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL)); | 989 | sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL)); |
990 | } | 990 | } |
991 | 991 | ||
992 | static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | 992 | static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot) |
993 | { | 993 | { |
994 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; | 994 | struct sky2_tx_le *le = sky2->tx_le + *slot; |
995 | 995 | ||
996 | sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE); | 996 | *slot = RING_NEXT(*slot, TX_RING_SIZE); |
997 | le->ctrl = 0; | 997 | le->ctrl = 0; |
998 | return le; | 998 | return le; |
999 | } | 999 | } |
@@ -1006,7 +1006,7 @@ static void tx_init(struct sky2_port *sky2) | |||
1006 | sky2->tx_tcpsum = 0; | 1006 | sky2->tx_tcpsum = 0; |
1007 | sky2->tx_last_mss = 0; | 1007 | sky2->tx_last_mss = 0; |
1008 | 1008 | ||
1009 | le = get_tx_le(sky2); | 1009 | le = get_tx_le(sky2, &sky2->tx_prod); |
1010 | le->addr = 0; | 1010 | le->addr = 0; |
1011 | le->opcode = OP_ADDR64 | HW_OWNER; | 1011 | le->opcode = OP_ADDR64 | HW_OWNER; |
1012 | } | 1012 | } |
@@ -1572,7 +1572,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1572 | struct sky2_hw *hw = sky2->hw; | 1572 | struct sky2_hw *hw = sky2->hw; |
1573 | struct sky2_tx_le *le = NULL; | 1573 | struct sky2_tx_le *le = NULL; |
1574 | struct tx_ring_info *re; | 1574 | struct tx_ring_info *re; |
1575 | unsigned i, len, first_slot; | 1575 | unsigned i, len; |
1576 | u16 slot; | ||
1576 | dma_addr_t mapping; | 1577 | dma_addr_t mapping; |
1577 | u16 mss; | 1578 | u16 mss; |
1578 | u8 ctrl; | 1579 | u8 ctrl; |
@@ -1586,14 +1587,14 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1586 | if (pci_dma_mapping_error(hw->pdev, mapping)) | 1587 | if (pci_dma_mapping_error(hw->pdev, mapping)) |
1587 | goto mapping_error; | 1588 | goto mapping_error; |
1588 | 1589 | ||
1589 | first_slot = sky2->tx_prod; | 1590 | slot = sky2->tx_prod; |
1590 | if (unlikely(netif_msg_tx_queued(sky2))) | 1591 | if (unlikely(netif_msg_tx_queued(sky2))) |
1591 | printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", | 1592 | printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", |
1592 | dev->name, first_slot, skb->len); | 1593 | dev->name, slot, skb->len); |
1593 | 1594 | ||
1594 | /* Send high bits if needed */ | 1595 | /* Send high bits if needed */ |
1595 | if (sizeof(dma_addr_t) > sizeof(u32)) { | 1596 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
1596 | le = get_tx_le(sky2); | 1597 | le = get_tx_le(sky2, &slot); |
1597 | le->addr = cpu_to_le32(upper_32_bits(mapping)); | 1598 | le->addr = cpu_to_le32(upper_32_bits(mapping)); |
1598 | le->opcode = OP_ADDR64 | HW_OWNER; | 1599 | le->opcode = OP_ADDR64 | HW_OWNER; |
1599 | } | 1600 | } |
@@ -1606,7 +1607,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1606 | mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); | 1607 | mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); |
1607 | 1608 | ||
1608 | if (mss != sky2->tx_last_mss) { | 1609 | if (mss != sky2->tx_last_mss) { |
1609 | le = get_tx_le(sky2); | 1610 | le = get_tx_le(sky2, &slot); |
1610 | le->addr = cpu_to_le32(mss); | 1611 | le->addr = cpu_to_le32(mss); |
1611 | 1612 | ||
1612 | if (hw->flags & SKY2_HW_NEW_LE) | 1613 | if (hw->flags & SKY2_HW_NEW_LE) |
@@ -1622,7 +1623,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1622 | /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */ | 1623 | /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */ |
1623 | if (sky2->vlgrp && vlan_tx_tag_present(skb)) { | 1624 | if (sky2->vlgrp && vlan_tx_tag_present(skb)) { |
1624 | if (!le) { | 1625 | if (!le) { |
1625 | le = get_tx_le(sky2); | 1626 | le = get_tx_le(sky2, &slot); |
1626 | le->addr = 0; | 1627 | le->addr = 0; |
1627 | le->opcode = OP_VLAN|HW_OWNER; | 1628 | le->opcode = OP_VLAN|HW_OWNER; |
1628 | } else | 1629 | } else |
@@ -1651,7 +1652,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1651 | if (tcpsum != sky2->tx_tcpsum) { | 1652 | if (tcpsum != sky2->tx_tcpsum) { |
1652 | sky2->tx_tcpsum = tcpsum; | 1653 | sky2->tx_tcpsum = tcpsum; |
1653 | 1654 | ||
1654 | le = get_tx_le(sky2); | 1655 | le = get_tx_le(sky2, &slot); |
1655 | le->addr = cpu_to_le32(tcpsum); | 1656 | le->addr = cpu_to_le32(tcpsum); |
1656 | le->length = 0; /* initial checksum value */ | 1657 | le->length = 0; /* initial checksum value */ |
1657 | le->ctrl = 1; /* one packet */ | 1658 | le->ctrl = 1; /* one packet */ |
@@ -1660,7 +1661,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1660 | } | 1661 | } |
1661 | } | 1662 | } |
1662 | 1663 | ||
1663 | le = get_tx_le(sky2); | 1664 | le = get_tx_le(sky2, &slot); |
1664 | le->addr = cpu_to_le32((u32) mapping); | 1665 | le->addr = cpu_to_le32((u32) mapping); |
1665 | le->length = cpu_to_le16(len); | 1666 | le->length = cpu_to_le16(len); |
1666 | le->ctrl = ctrl; | 1667 | le->ctrl = ctrl; |
@@ -1681,13 +1682,13 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1681 | goto mapping_unwind; | 1682 | goto mapping_unwind; |
1682 | 1683 | ||
1683 | if (sizeof(dma_addr_t) > sizeof(u32)) { | 1684 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
1684 | le = get_tx_le(sky2); | 1685 | le = get_tx_le(sky2, &slot); |
1685 | le->addr = cpu_to_le32(upper_32_bits(mapping)); | 1686 | le->addr = cpu_to_le32(upper_32_bits(mapping)); |
1686 | le->ctrl = 0; | 1687 | le->ctrl = 0; |
1687 | le->opcode = OP_ADDR64 | HW_OWNER; | 1688 | le->opcode = OP_ADDR64 | HW_OWNER; |
1688 | } | 1689 | } |
1689 | 1690 | ||
1690 | le = get_tx_le(sky2); | 1691 | le = get_tx_le(sky2, &slot); |
1691 | le->addr = cpu_to_le32((u32) mapping); | 1692 | le->addr = cpu_to_le32((u32) mapping); |
1692 | le->length = cpu_to_le16(frag->size); | 1693 | le->length = cpu_to_le16(frag->size); |
1693 | le->ctrl = ctrl; | 1694 | le->ctrl = ctrl; |
@@ -1701,6 +1702,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1701 | 1702 | ||
1702 | le->ctrl |= EOP; | 1703 | le->ctrl |= EOP; |
1703 | 1704 | ||
1705 | sky2->tx_prod = slot; | ||
1706 | |||
1704 | if (tx_avail(sky2) <= MAX_SKB_TX_LE) | 1707 | if (tx_avail(sky2) <= MAX_SKB_TX_LE) |
1705 | netif_stop_queue(dev); | 1708 | netif_stop_queue(dev); |
1706 | 1709 | ||
@@ -1709,7 +1712,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1709 | return NETDEV_TX_OK; | 1712 | return NETDEV_TX_OK; |
1710 | 1713 | ||
1711 | mapping_unwind: | 1714 | mapping_unwind: |
1712 | for (i = first_slot; i != sky2->tx_prod; i = RING_NEXT(i, TX_RING_SIZE)) { | 1715 | for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, TX_RING_SIZE)) { |
1713 | le = sky2->tx_le + i; | 1716 | le = sky2->tx_le + i; |
1714 | re = sky2->tx_ring + i; | 1717 | re = sky2->tx_ring + i; |
1715 | 1718 | ||
@@ -1729,7 +1732,6 @@ mapping_unwind: | |||
1729 | } | 1732 | } |
1730 | } | 1733 | } |
1731 | 1734 | ||
1732 | sky2->tx_prod = first_slot; | ||
1733 | mapping_error: | 1735 | mapping_error: |
1734 | if (net_ratelimit()) | 1736 | if (net_ratelimit()) |
1735 | dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); | 1737 | dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); |