Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 57908
b: refs/heads/master
c: 4c4bd5a
h: refs/heads/master
v: v3
  • Loading branch information
Linas Vepstas authored and Jeff Garzik committed Jun 20, 2007
1 parent 01713bd commit 5f6528a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 83d35145c443d8394aaf1743301e79fa0a8054d7
refs/heads/master: 4c4bd5a97a87670d2c368ed4ed8a8f2c93080605
86 changes: 80 additions & 6 deletions trunk/drivers/net/spider_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,66 @@ static void show_rx_chain(struct spider_net_card *card)
}
#endif

/**
* spider_net_resync_head_ptr - Advance head ptr past empty descrs
*
* If the driver fails to keep up and empty the queue, then the
* hardware wil run out of room to put incoming packets. This
* will cause the hardware to skip descrs that are full (instead
* of halting/retrying). Thus, once the driver runs, it wil need
* to "catch up" to where the hardware chain pointer is at.
*/
static void spider_net_resync_head_ptr(struct spider_net_card *card)
{
unsigned long flags;
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr;
int i, status;

/* Advance head pointer past any empty descrs */
descr = chain->head;
status = spider_net_get_descr_status(descr->hwdescr);

if (status == SPIDER_NET_DESCR_NOT_IN_USE)
return;

spin_lock_irqsave(&chain->lock, flags);

descr = chain->head;
status = spider_net_get_descr_status(descr->hwdescr);
for (i=0; i<chain->num_desc; i++) {
if (status != SPIDER_NET_DESCR_CARDOWNED) break;
descr = descr->next;
status = spider_net_get_descr_status(descr->hwdescr);
}
chain->head = descr;

spin_unlock_irqrestore(&chain->lock, flags);
}

static int spider_net_resync_tail_ptr(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr;
int i, status;

/* Advance tail pointer past any empty and reaped descrs */
descr = chain->tail;
status = spider_net_get_descr_status(descr->hwdescr);

for (i=0; i<chain->num_desc; i++) {
if ((status != SPIDER_NET_DESCR_CARDOWNED) &&
(status != SPIDER_NET_DESCR_NOT_IN_USE)) break;
descr = descr->next;
status = spider_net_get_descr_status(descr->hwdescr);
}
chain->tail = descr;

if ((i == chain->num_desc) || (i == 0))
return 1;
return 0;
}

/**
* spider_net_decode_one_descr - processes an RX descriptor
* @card: card structure
Expand Down Expand Up @@ -1175,6 +1235,12 @@ spider_net_poll(struct net_device *netdev, int *budget)
}
}

if ((packets_done == 0) && (card->num_rx_ints != 0)) {
no_more_packets = spider_net_resync_tail_ptr(card);
spider_net_resync_head_ptr(card);
}
card->num_rx_ints = 0;

netdev->quota -= packets_done;
*budget -= packets_done;
spider_net_refill_rx_chain(card);
Expand Down Expand Up @@ -1421,7 +1487,11 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
if (netif_msg_intr(card) && net_ratelimit())
pr_err("Spider RX RAM full, incoming packets "
"might be discarded!\n");
spider_net_rx_irq_off(card);
/* Could happen when rx chain is full */
spider_net_resync_head_ptr(card);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
netif_rx_schedule(card->netdev);
show_error = 0;
break;
Expand All @@ -1437,12 +1507,11 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDCDCEINT: /* fallthrough */
case SPIDER_NET_GDBDCEINT: /* fallthrough */
case SPIDER_NET_GDADCEINT:
if (netif_msg_intr(card) && net_ratelimit())
pr_err("got descriptor chain end interrupt, "
"restarting DMAC %c.\n",
'D'-(i-SPIDER_NET_GDDDCEINT)/3);
spider_net_resync_head_ptr(card);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
netif_rx_schedule(card->netdev);
show_error = 0;
break;

Expand All @@ -1451,9 +1520,12 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDCINVDINT: /* fallthrough */
case SPIDER_NET_GDBINVDINT: /* fallthrough */
case SPIDER_NET_GDAINVDINT:
/* could happen when rx chain is full */
/* Could happen when rx chain is full */
spider_net_resync_head_ptr(card);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
netif_rx_schedule(card->netdev);
show_error = 0;
break;

Expand Down Expand Up @@ -1546,6 +1618,7 @@ spider_net_interrupt(int irq, void *ptr)
if (status_reg & SPIDER_NET_RXINT ) {
spider_net_rx_irq_off(card);
netif_rx_schedule(netdev);
card->num_rx_ints ++;
}
if (status_reg & SPIDER_NET_TXINT)
netif_rx_schedule(netdev);
Expand Down Expand Up @@ -2191,6 +2264,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
* NETIF_F_HW_VLAN_FILTER */

netdev->irq = card->pdev->irq;
card->num_rx_ints = 0;

dn = pci_device_to_OF_node(card->pdev);
if (!dn)
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/net/spider_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H

#define VERSION "2.0 A"
#define VERSION "2.0 B"

#include "sungem_phy.h"

Expand Down Expand Up @@ -461,6 +461,7 @@ struct spider_net_card {
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
wait_queue_head_t waitq;
int num_rx_ints;

/* for ethtool */
int msg_enable;
Expand Down

0 comments on commit 5f6528a

Please sign in to comment.