[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>
This commit is contained in:
committed by
Jeff Garzik
parent
6b1a3aefd8
commit
d11c13e752
@@ -1040,13 +1040,14 @@ out_unlock:
|
|||||||
* NB: the hardware will tell us about partial completion of multi-part
|
* NB: the hardware will tell us about partial completion of multi-part
|
||||||
* buffers; these are defered until completion.
|
* buffers; these are defered until completion.
|
||||||
*/
|
*/
|
||||||
static void sky2_tx_complete(struct net_device *dev, u16 done)
|
static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
|
||||||
{
|
{
|
||||||
struct sky2_port *sky2 = netdev_priv(dev);
|
struct net_device *dev = sky2->netdev;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if (netif_msg_tx_done(sky2))
|
if (unlikely(netif_msg_tx_done(sky2)))
|
||||||
printk(KERN_DEBUG "%s: tx done, upto %u\n", dev->name, done);
|
printk(KERN_DEBUG "%s: tx done, upto %u\n",
|
||||||
|
dev->name, done);
|
||||||
|
|
||||||
spin_lock(&sky2->tx_lock);
|
spin_lock(&sky2->tx_lock);
|
||||||
|
|
||||||
@@ -1086,7 +1087,7 @@ out:
|
|||||||
/* Cleanup all untransmitted buffers, assume transmitter not running */
|
/* Cleanup all untransmitted buffers, assume transmitter not running */
|
||||||
static inline void sky2_tx_clean(struct sky2_port *sky2)
|
static inline void sky2_tx_clean(struct sky2_port *sky2)
|
||||||
{
|
{
|
||||||
sky2_tx_complete(sky2->netdev, sky2->tx_prod);
|
sky2_tx_complete(sky2, sky2->tx_prod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Network shutdown */
|
/* Network shutdown */
|
||||||
@@ -1421,18 +1422,17 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
|
|||||||
* For small packets or errors, just reuse existing skb.
|
* For small packets or errors, just reuse existing skb.
|
||||||
* For larger pakects, get new buffer.
|
* For larger pakects, get new buffer.
|
||||||
*/
|
*/
|
||||||
static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port,
|
static struct sk_buff *sky2_receive(struct sky2_port *sky2,
|
||||||
u16 length, u32 status)
|
u16 length, u32 status)
|
||||||
{
|
{
|
||||||
struct net_device *dev = hw->dev[port];
|
|
||||||
struct sky2_port *sky2 = netdev_priv(dev);
|
|
||||||
struct ring_info *re = sky2->rx_ring + sky2->rx_next;
|
struct ring_info *re = sky2->rx_ring + sky2->rx_next;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
|
struct net_device *dev;
|
||||||
const unsigned int bufsize = rx_size(sky2);
|
const unsigned int bufsize = rx_size(sky2);
|
||||||
|
|
||||||
if (unlikely(netif_msg_rx_status(sky2)))
|
if (unlikely(netif_msg_rx_status(sky2)))
|
||||||
printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
|
printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
|
||||||
dev->name, sky2->rx_next, status, length);
|
sky2->netdev->name, sky2->rx_next, status, length);
|
||||||
|
|
||||||
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
|
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
|
||||||
|
|
||||||
@@ -1451,6 +1451,8 @@ static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port,
|
|||||||
pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr,
|
pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr,
|
||||||
length, PCI_DMA_FROMDEVICE);
|
length, PCI_DMA_FROMDEVICE);
|
||||||
memcpy(skb->data, re->skb->data, length);
|
memcpy(skb->data, re->skb->data, length);
|
||||||
|
skb->ip_summed = re->skb->ip_summed;
|
||||||
|
skb->csum = re->skb->csum;
|
||||||
pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr,
|
pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr,
|
||||||
length, PCI_DMA_FROMDEVICE);
|
length, PCI_DMA_FROMDEVICE);
|
||||||
} else {
|
} else {
|
||||||
@@ -1471,12 +1473,14 @@ static struct sk_buff *sky2_receive(struct sky2_hw *hw, unsigned port,
|
|||||||
re->maplen = bufsize;
|
re->maplen = bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb->dev = dev;
|
|
||||||
skb_put(skb, length);
|
skb_put(skb, length);
|
||||||
|
dev = sky2->netdev;
|
||||||
|
skb->dev = dev;
|
||||||
skb->protocol = eth_type_trans(skb, dev);
|
skb->protocol = eth_type_trans(skb, dev);
|
||||||
dev->last_rx = jiffies;
|
dev->last_rx = jiffies;
|
||||||
|
|
||||||
resubmit:
|
resubmit:
|
||||||
|
re->skb->ip_summed = CHECKSUM_NONE;
|
||||||
sky2_rx_add(sky2, re);
|
sky2_rx_add(sky2, re);
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
@@ -1517,59 +1521,46 @@ static inline u16 tx_index(u8 port, u32 status, u16 len)
|
|||||||
* Both ports share the same status interrupt, therefore there is only
|
* Both ports share the same status interrupt, therefore there is only
|
||||||
* one poll routine.
|
* one poll routine.
|
||||||
*/
|
*/
|
||||||
static int sky2_poll(struct net_device *dev, int *budget)
|
static int sky2_poll(struct net_device *dev0, int *budget)
|
||||||
{
|
{
|
||||||
struct sky2_port *sky2 = netdev_priv(dev);
|
struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
|
||||||
struct sky2_hw *hw = sky2->hw;
|
unsigned int to_do = min(dev0->quota, *budget);
|
||||||
unsigned int to_do = min(dev->quota, *budget);
|
|
||||||
unsigned int work_done = 0;
|
unsigned int work_done = 0;
|
||||||
u16 hwidx;
|
u16 hwidx;
|
||||||
unsigned char summed[2] = { CHECKSUM_NONE, CHECKSUM_NONE };
|
|
||||||
unsigned int csum[2];
|
|
||||||
|
|
||||||
hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
||||||
BUG_ON(hwidx >= STATUS_RING_SIZE);
|
BUG_ON(hwidx >= STATUS_RING_SIZE);
|
||||||
rmb();
|
rmb();
|
||||||
while (hw->st_idx != hwidx && work_done < to_do) {
|
while (hw->st_idx != hwidx && work_done < to_do) {
|
||||||
struct sky2_status_le *le = hw->st_le + hw->st_idx;
|
struct sky2_status_le *le = hw->st_le + hw->st_idx;
|
||||||
|
struct sky2_port *sky2;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u8 port;
|
|
||||||
u32 status;
|
u32 status;
|
||||||
u16 length;
|
u16 length;
|
||||||
|
|
||||||
|
BUG_ON(le->link >= hw->ports);
|
||||||
|
sky2 = netdev_priv(hw->dev[le->link]);
|
||||||
status = le32_to_cpu(le->status);
|
status = le32_to_cpu(le->status);
|
||||||
length = le16_to_cpu(le->length);
|
length = le16_to_cpu(le->length);
|
||||||
port = le->link;
|
|
||||||
|
|
||||||
BUG_ON(port >= hw->ports || hw->dev[port] == NULL);
|
|
||||||
|
|
||||||
switch (le->opcode & ~HW_OWNER) {
|
switch (le->opcode & ~HW_OWNER) {
|
||||||
case OP_RXSTAT:
|
case OP_RXSTAT:
|
||||||
skb = sky2_receive(hw, port, length, status);
|
skb = sky2_receive(sky2, length, status);
|
||||||
if (likely(skb)) {
|
if (likely(skb)) {
|
||||||
/* Add hw checksum if available */
|
|
||||||
skb->ip_summed = summed[port];
|
|
||||||
skb->csum = csum[port];
|
|
||||||
|
|
||||||
netif_receive_skb(skb);
|
netif_receive_skb(skb);
|
||||||
++work_done;
|
++work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear for next packet */
|
|
||||||
csum[port] = 0;
|
|
||||||
summed[port] = CHECKSUM_NONE;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RXCHKS:
|
case OP_RXCHKS:
|
||||||
/* Save computed checksum for next rx */
|
skb = sky2->rx_ring[sky2->rx_next].skb;
|
||||||
csum[port] = le16_to_cpu(status & 0xffff);
|
skb->ip_summed = CHECKSUM_HW;
|
||||||
summed[port] = CHECKSUM_HW;
|
skb->csum = le16_to_cpu(status);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_TXINDEXLE:
|
case OP_TXINDEXLE:
|
||||||
sky2_tx_complete(hw->dev[port],
|
sky2_tx_complete(sky2,
|
||||||
tx_index(port, status, length));
|
tx_index(sky2->port, status, length));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RXTIMESTAMP:
|
case OP_RXTIMESTAMP:
|
||||||
@@ -1599,7 +1590,7 @@ static int sky2_poll(struct net_device *dev, int *budget)
|
|||||||
rx_set_put(hw->dev[1]);
|
rx_set_put(hw->dev[1]);
|
||||||
|
|
||||||
*budget -= work_done;
|
*budget -= work_done;
|
||||||
dev->quota -= work_done;
|
dev0->quota -= work_done;
|
||||||
if (work_done < to_do) {
|
if (work_done < to_do) {
|
||||||
/*
|
/*
|
||||||
* Another chip workaround, need to restart TX timer if status
|
* Another chip workaround, need to restart TX timer if status
|
||||||
@@ -1613,7 +1604,7 @@ static int sky2_poll(struct net_device *dev, int *budget)
|
|||||||
hw->intr_mask |= Y2_IS_STAT_BMU;
|
hw->intr_mask |= Y2_IS_STAT_BMU;
|
||||||
sky2_write32(hw, B0_IMSK, hw->intr_mask);
|
sky2_write32(hw, B0_IMSK, hw->intr_mask);
|
||||||
sky2_read32(hw, B0_IMSK);
|
sky2_read32(hw, B0_IMSK);
|
||||||
netif_rx_complete(dev);
|
netif_rx_complete(dev0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return work_done >= to_do;
|
return work_done >= to_do;
|
||||||
|
Reference in New Issue
Block a user