diff options
author | Olof Johansson <olof@lixom.net> | 2007-11-28 21:56:54 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:04:23 -0500 |
commit | 61cec3bddc79373a246e2f8eb13e5acdc106f46a (patch) | |
tree | 4c2780bc195ed6acce57073101b98813595206c8 /drivers/net/pasemi_mac.c | |
parent | 5c15332bed4c59fff6423f08ef6bd6894af38a99 (diff) |
pasemi_mac: Fix TX cleaning
pasemi_mac: Fix TX cleaning
This is a bit awkward. We don't have a timer-delayed interrupt on TX
complete, but we have a count threshold. So set that reasonably high
(32 packets), and schedule the NAPI poll when it goes off. Also bump a
regular timer that will take care of rotting packets for the last 1..31
ones in case we don't trigger a TX interrupt (and there's no RX activity
that would otherwise trigger the poll).
The longer-term fix is to separate TX from RX NAPI and do two separate
poll loops.
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/pasemi_mac.c')
-rw-r--r-- | drivers/net/pasemi_mac.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index c6e24a8dcf72..683e8de0ac89 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c | |||
@@ -805,27 +805,43 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) | |||
805 | return IRQ_HANDLED; | 805 | return IRQ_HANDLED; |
806 | } | 806 | } |
807 | 807 | ||
808 | #define TX_CLEAN_INTERVAL HZ | ||
809 | |||
810 | static void pasemi_mac_tx_timer(unsigned long data) | ||
811 | { | ||
812 | struct pasemi_mac_txring *txring = (struct pasemi_mac_txring *)data; | ||
813 | struct pasemi_mac *mac = txring->mac; | ||
814 | |||
815 | pasemi_mac_clean_tx(txring); | ||
816 | |||
817 | mod_timer(&txring->clean_timer, jiffies + TX_CLEAN_INTERVAL); | ||
818 | |||
819 | pasemi_mac_restart_tx_intr(mac); | ||
820 | } | ||
821 | |||
808 | static irqreturn_t pasemi_mac_tx_intr(int irq, void *data) | 822 | static irqreturn_t pasemi_mac_tx_intr(int irq, void *data) |
809 | { | 823 | { |
810 | struct pasemi_mac_txring *txring = data; | 824 | struct pasemi_mac_txring *txring = data; |
811 | const struct pasemi_dmachan *chan = &txring->chan; | 825 | const struct pasemi_dmachan *chan = &txring->chan; |
812 | unsigned int reg, pcnt; | 826 | struct pasemi_mac *mac = txring->mac; |
827 | unsigned int reg; | ||
813 | 828 | ||
814 | if (!(*chan->status & PAS_STATUS_CAUSE_M)) | 829 | if (!(*chan->status & PAS_STATUS_CAUSE_M)) |
815 | return IRQ_NONE; | 830 | return IRQ_NONE; |
816 | 831 | ||
817 | pasemi_mac_clean_tx(txring); | 832 | reg = 0; |
818 | |||
819 | pcnt = *chan->status & PAS_STATUS_PCNT_M; | ||
820 | |||
821 | reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC; | ||
822 | 833 | ||
823 | if (*chan->status & PAS_STATUS_SOFT) | 834 | if (*chan->status & PAS_STATUS_SOFT) |
824 | reg |= PAS_IOB_DMA_TXCH_RESET_SINTC; | 835 | reg |= PAS_IOB_DMA_TXCH_RESET_SINTC; |
825 | if (*chan->status & PAS_STATUS_ERROR) | 836 | if (*chan->status & PAS_STATUS_ERROR) |
826 | reg |= PAS_IOB_DMA_TXCH_RESET_DINTC; | 837 | reg |= PAS_IOB_DMA_TXCH_RESET_DINTC; |
827 | 838 | ||
828 | write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg); | 839 | mod_timer(&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL)*2); |
840 | |||
841 | netif_rx_schedule(mac->netdev, &mac->napi); | ||
842 | |||
843 | if (reg) | ||
844 | write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg); | ||
829 | 845 | ||
830 | return IRQ_HANDLED; | 846 | return IRQ_HANDLED; |
831 | } | 847 | } |
@@ -973,7 +989,7 @@ static int pasemi_mac_open(struct net_device *dev) | |||
973 | PAS_IOB_DMA_RXCH_CFG_CNTTH(0)); | 989 | PAS_IOB_DMA_RXCH_CFG_CNTTH(0)); |
974 | 990 | ||
975 | write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno), | 991 | write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno), |
976 | PAS_IOB_DMA_TXCH_CFG_CNTTH(128)); | 992 | PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); |
977 | 993 | ||
978 | write_mac_reg(mac, PAS_MAC_IPC_CHNL, | 994 | write_mac_reg(mac, PAS_MAC_IPC_CHNL, |
979 | PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) | | 995 | PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) | |
@@ -1054,6 +1070,12 @@ static int pasemi_mac_open(struct net_device *dev) | |||
1054 | if (mac->phydev) | 1070 | if (mac->phydev) |
1055 | phy_start(mac->phydev); | 1071 | phy_start(mac->phydev); |
1056 | 1072 | ||
1073 | init_timer(&mac->tx->clean_timer); | ||
1074 | mac->tx->clean_timer.function = pasemi_mac_tx_timer; | ||
1075 | mac->tx->clean_timer.data = (unsigned long)mac->tx; | ||
1076 | mac->tx->clean_timer.expires = jiffies+HZ; | ||
1077 | add_timer(&mac->tx->clean_timer); | ||
1078 | |||
1057 | return 0; | 1079 | return 0; |
1058 | 1080 | ||
1059 | out_rx_int: | 1081 | out_rx_int: |
@@ -1087,6 +1109,8 @@ static int pasemi_mac_close(struct net_device *dev) | |||
1087 | phy_disconnect(mac->phydev); | 1109 | phy_disconnect(mac->phydev); |
1088 | } | 1110 | } |
1089 | 1111 | ||
1112 | del_timer_sync(&mac->tx->clean_timer); | ||
1113 | |||
1090 | netif_stop_queue(dev); | 1114 | netif_stop_queue(dev); |
1091 | napi_disable(&mac->napi); | 1115 | napi_disable(&mac->napi); |
1092 | 1116 | ||
@@ -1304,6 +1328,7 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget) | |||
1304 | netif_rx_complete(dev, napi); | 1328 | netif_rx_complete(dev, napi); |
1305 | 1329 | ||
1306 | pasemi_mac_restart_rx_intr(mac); | 1330 | pasemi_mac_restart_rx_intr(mac); |
1331 | pasemi_mac_restart_tx_intr(mac); | ||
1307 | } | 1332 | } |
1308 | return pkts; | 1333 | return pkts; |
1309 | } | 1334 | } |