提交 ca93ca42 编写于 作者: J Jeff Garzik

Revert "[netdrvr e100] experiment with doing RX in a similar manner to eepro100"

This reverts commit d52df4a3.

This patch attempted to fix e100 for non-cache coherent memory
architectures by using the cb style code that eepro100 had and using
the EL and s bits from the RFD list. Unfortunately the hardware
doesn't work exactly like this and therefore this patch actually
breaks e100. Reverting the change brings it back to the previously
known good state for 2.6.22. The pending rewrite in progress to this
code can then be safely merged later.
Signed-off-by: NAuke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 c0811987
...@@ -285,6 +285,12 @@ enum scb_status { ...@@ -285,6 +285,12 @@ enum scb_status {
rus_mask = 0x3C, rus_mask = 0x3C,
}; };
enum ru_state {
RU_SUSPENDED = 0,
RU_RUNNING = 1,
RU_UNINITIALIZED = -1,
};
enum scb_stat_ack { enum scb_stat_ack {
stat_ack_not_ours = 0x00, stat_ack_not_ours = 0x00,
stat_ack_sw_gen = 0x04, stat_ack_sw_gen = 0x04,
...@@ -526,6 +532,7 @@ struct nic { ...@@ -526,6 +532,7 @@ struct nic {
struct rx *rx_to_use; struct rx *rx_to_use;
struct rx *rx_to_clean; struct rx *rx_to_clean;
struct rfd blank_rfd; struct rfd blank_rfd;
enum ru_state ru_running;
spinlock_t cb_lock ____cacheline_aligned; spinlock_t cb_lock ____cacheline_aligned;
spinlock_t cmd_lock; spinlock_t cmd_lock;
...@@ -947,7 +954,7 @@ static void e100_get_defaults(struct nic *nic) ...@@ -947,7 +954,7 @@ static void e100_get_defaults(struct nic *nic)
((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
/* Template for a freshly allocated RFD */ /* Template for a freshly allocated RFD */
nic->blank_rfd.command = cpu_to_le16(cb_el & cb_s); nic->blank_rfd.command = cpu_to_le16(cb_el);
nic->blank_rfd.rbd = 0xFFFFFFFF; nic->blank_rfd.rbd = 0xFFFFFFFF;
nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
...@@ -1742,11 +1749,19 @@ static int e100_alloc_cbs(struct nic *nic) ...@@ -1742,11 +1749,19 @@ static int e100_alloc_cbs(struct nic *nic)
return 0; return 0;
} }
static inline void e100_start_receiver(struct nic *nic) static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{ {
/* Start if RFA is non-NULL */ if(!nic->rxs) return;
if(nic->rx_to_clean->skb) if(RU_SUSPENDED != nic->ru_running) return;
e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
/* handle init time starts */
if(!rx) rx = nic->rxs;
/* (Re)start RU if suspended or idle and RFA is non-NULL */
if(rx->skb) {
e100_exec_cmd(nic, ruc_start, rx->dma_addr);
nic->ru_running = RU_RUNNING;
}
} }
#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
...@@ -1775,7 +1790,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) ...@@ -1775,7 +1790,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
put_unaligned(cpu_to_le32(rx->dma_addr), put_unaligned(cpu_to_le32(rx->dma_addr),
(u32 *)&prev_rfd->link); (u32 *)&prev_rfd->link);
wmb(); wmb();
prev_rfd->command &= ~cpu_to_le16(cb_el & cb_s); prev_rfd->command &= ~cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
sizeof(struct rfd), PCI_DMA_TODEVICE); sizeof(struct rfd), PCI_DMA_TODEVICE);
} }
...@@ -1813,6 +1828,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, ...@@ -1813,6 +1828,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
pci_unmap_single(nic->pdev, rx->dma_addr, pci_unmap_single(nic->pdev, rx->dma_addr,
RFD_BUF_LEN, PCI_DMA_FROMDEVICE); RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
/* this allows for a fast restart without re-enabling interrupts */
if(le16_to_cpu(rfd->command) & cb_el)
nic->ru_running = RU_SUSPENDED;
/* Pull off the RFD and put the actual data (minus eth hdr) */ /* Pull off the RFD and put the actual data (minus eth hdr) */
skb_reserve(skb, sizeof(struct rfd)); skb_reserve(skb, sizeof(struct rfd));
skb_put(skb, actual_size); skb_put(skb, actual_size);
...@@ -1843,18 +1862,45 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, ...@@ -1843,18 +1862,45 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do) unsigned int work_to_do)
{ {
struct rx *rx; struct rx *rx;
int restart_required = 0;
struct rx *rx_to_start = NULL;
/* are we already rnr? then pay attention!!! this ensures that
* the state machine progression never allows a start with a
* partially cleaned list, avoiding a race between hardware
* and rx_to_clean when in NAPI mode */
if(RU_SUSPENDED == nic->ru_running)
restart_required = 1;
/* Indicate newly arrived packets */ /* Indicate newly arrived packets */
for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
if(e100_rx_indicate(nic, rx, work_done, work_to_do)) int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
if(-EAGAIN == err) {
/* hit quota so have more work to do, restart once
* cleanup is complete */
restart_required = 0;
break;
} else if(-ENODATA == err)
break; /* No more to clean */ break; /* No more to clean */
} }
/* save our starting point as the place we'll restart the receiver */
if(restart_required)
rx_to_start = nic->rx_to_clean;
/* Alloc new skbs to refill list */ /* Alloc new skbs to refill list */
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
if(unlikely(e100_rx_alloc_skb(nic, rx))) if(unlikely(e100_rx_alloc_skb(nic, rx)))
break; /* Better luck next time (see watchdog) */ break; /* Better luck next time (see watchdog) */
} }
if(restart_required) {
// ack the rnr?
writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
e100_start_receiver(nic, rx_to_start);
if(work_done)
(*work_done)++;
}
} }
static void e100_rx_clean_list(struct nic *nic) static void e100_rx_clean_list(struct nic *nic)
...@@ -1862,6 +1908,8 @@ static void e100_rx_clean_list(struct nic *nic) ...@@ -1862,6 +1908,8 @@ static void e100_rx_clean_list(struct nic *nic)
struct rx *rx; struct rx *rx;
unsigned int i, count = nic->params.rfds.count; unsigned int i, count = nic->params.rfds.count;
nic->ru_running = RU_UNINITIALIZED;
if(nic->rxs) { if(nic->rxs) {
for(rx = nic->rxs, i = 0; i < count; rx++, i++) { for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) { if(rx->skb) {
...@@ -1883,6 +1931,7 @@ static int e100_rx_alloc_list(struct nic *nic) ...@@ -1883,6 +1931,7 @@ static int e100_rx_alloc_list(struct nic *nic)
unsigned int i, count = nic->params.rfds.count; unsigned int i, count = nic->params.rfds.count;
nic->rx_to_use = nic->rx_to_clean = NULL; nic->rx_to_use = nic->rx_to_clean = NULL;
nic->ru_running = RU_UNINITIALIZED;
if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
return -ENOMEM; return -ENOMEM;
...@@ -1897,6 +1946,7 @@ static int e100_rx_alloc_list(struct nic *nic) ...@@ -1897,6 +1946,7 @@ static int e100_rx_alloc_list(struct nic *nic)
} }
nic->rx_to_use = nic->rx_to_clean = nic->rxs; nic->rx_to_use = nic->rx_to_clean = nic->rxs;
nic->ru_running = RU_SUSPENDED;
return 0; return 0;
} }
...@@ -1916,6 +1966,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id) ...@@ -1916,6 +1966,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
/* Ack interrupt(s) */ /* Ack interrupt(s) */
iowrite8(stat_ack, &nic->csr->scb.stat_ack); iowrite8(stat_ack, &nic->csr->scb.stat_ack);
/* We hit Receive No Resource (RNR); restart RU after cleaning */
if(stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
if(likely(netif_rx_schedule_prep(netdev))) { if(likely(netif_rx_schedule_prep(netdev))) {
e100_disable_irq(nic); e100_disable_irq(nic);
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev);
...@@ -2007,7 +2061,7 @@ static int e100_up(struct nic *nic) ...@@ -2007,7 +2061,7 @@ static int e100_up(struct nic *nic)
if((err = e100_hw_init(nic))) if((err = e100_hw_init(nic)))
goto err_clean_cbs; goto err_clean_cbs;
e100_set_multicast_list(nic->netdev); e100_set_multicast_list(nic->netdev);
e100_start_receiver(nic); e100_start_receiver(nic, NULL);
mod_timer(&nic->watchdog, jiffies); mod_timer(&nic->watchdog, jiffies);
if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev))) nic->netdev->name, nic->netdev)))
...@@ -2088,7 +2142,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) ...@@ -2088,7 +2142,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK); BMCR_LOOPBACK);
e100_start_receiver(nic); e100_start_receiver(nic, NULL);
if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
err = -ENOMEM; err = -ENOMEM;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册