aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-07-09 18:33:37 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-10 12:22:29 -0400
commit55c9dd35d3299dbd6e437c1a0bd86fffcb17080b (patch)
treeba5d05205513effffc7f51dde1341b3f852fc5cf /drivers/net/sky2.c
parent5c11ce700f77fada15b6264417d72462da4bbb1c (diff)
sky2: receive fill
Simplify receive buffer refill logic. Rather than trying to update incrementally; do receive ring refill at end of receive processing. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c36
1 files changed, 14 insertions, 22 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index c8e51cf5af7..b0950e1c4b6 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -65,7 +65,6 @@
65#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) 65#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2)
66#define RX_DEF_PENDING RX_MAX_PENDING 66#define RX_DEF_PENDING RX_MAX_PENDING
67#define RX_SKB_ALIGN 8 67#define RX_SKB_ALIGN 8
68#define RX_BUF_WRITE 16
69 68
70#define TX_RING_SIZE 512 69#define TX_RING_SIZE 512
71#define TX_DEF_PENDING (TX_RING_SIZE - 1) 70#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -1138,6 +1137,11 @@ nomem:
1138 return NULL; 1137 return NULL;
1139} 1138}
1140 1139
1140static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
1141{
1142 sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
1143}
1144
1141/* 1145/*
1142 * Allocate and setup receiver buffer pool. 1146 * Allocate and setup receiver buffer pool.
1143 * Normal case this ends up creating one list element for skb 1147 * Normal case this ends up creating one list element for skb
@@ -1229,7 +1233,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
1229 } 1233 }
1230 1234
1231 /* Tell chip about available buffers */ 1235 /* Tell chip about available buffers */
1232 sky2_put_idx(hw, rxq, sky2->rx_put); 1236 sky2_rx_update(sky2, rxq);
1233 return 0; 1237 return 0;
1234nomem: 1238nomem:
1235 sky2_rx_clean(sky2); 1239 sky2_rx_clean(sky2);
@@ -2147,14 +2151,14 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
2147/* Process status response ring */ 2151/* Process status response ring */
2148static int sky2_status_intr(struct sky2_hw *hw, int to_do) 2152static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2149{ 2153{
2150 struct sky2_port *sky2;
2151 int work_done = 0; 2154 int work_done = 0;
2152 unsigned buf_write[2] = { 0, 0 }; 2155 unsigned rx[2] = { 0, 0 };
2153 u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); 2156 u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
2154 2157
2155 rmb(); 2158 rmb();
2156 2159
2157 while (hw->st_idx != hwidx) { 2160 while (hw->st_idx != hwidx) {
2161 struct sky2_port *sky2;
2158 struct sky2_status_le *le = hw->st_le + hw->st_idx; 2162 struct sky2_status_le *le = hw->st_le + hw->st_idx;
2159 unsigned port = le->css & CSS_LINK_BIT; 2163 unsigned port = le->css & CSS_LINK_BIT;
2160 struct net_device *dev; 2164 struct net_device *dev;
@@ -2171,10 +2175,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2171 2175
2172 switch (le->opcode & ~HW_OWNER) { 2176 switch (le->opcode & ~HW_OWNER) {
2173 case OP_RXSTAT: 2177 case OP_RXSTAT:
2178 ++rx[port];
2174 skb = sky2_receive(dev, length, status); 2179 skb = sky2_receive(dev, length, status);
2175 if (unlikely(!skb)) { 2180 if (unlikely(!skb)) {
2176 sky2->net_stats.rx_dropped++; 2181 sky2->net_stats.rx_dropped++;
2177 goto force_update; 2182 break;
2178 } 2183 }
2179 2184
2180 /* This chip reports checksum status differently */ 2185 /* This chip reports checksum status differently */
@@ -2201,13 +2206,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2201#endif 2206#endif
2202 netif_receive_skb(skb); 2207 netif_receive_skb(skb);
2203 2208
2204 /* Update receiver after 16 frames */
2205 if (++buf_write[port] == RX_BUF_WRITE) {
2206force_update:
2207 sky2_put_idx(hw, rxqaddr[port], sky2->rx_put);
2208 buf_write[port] = 0;
2209 }
2210
2211 /* Stop after net poll weight */ 2209 /* Stop after net poll weight */
2212 if (++work_done >= to_do) 2210 if (++work_done >= to_do)
2213 goto exit_loop; 2211 goto exit_loop;
@@ -2263,24 +2261,18 @@ force_update:
2263 if (net_ratelimit()) 2261 if (net_ratelimit())
2264 printk(KERN_WARNING PFX 2262 printk(KERN_WARNING PFX
2265 "unknown status opcode 0x%x\n", le->opcode); 2263 "unknown status opcode 0x%x\n", le->opcode);
2266 goto exit_loop;
2267 } 2264 }
2268 } 2265 }
2269 2266
2270 /* Fully processed status ring so clear irq */ 2267 /* Fully processed status ring so clear irq */
2271 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); 2268 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
2272 mmiowb();
2273 2269
2274exit_loop: 2270exit_loop:
2275 if (buf_write[0]) { 2271 if (rx[0])
2276 sky2 = netdev_priv(hw->dev[0]); 2272 sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
2277 sky2_put_idx(hw, Q_R1, sky2->rx_put);
2278 }
2279 2273
2280 if (buf_write[1]) { 2274 if (rx[1])
2281 sky2 = netdev_priv(hw->dev[1]); 2275 sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
2282 sky2_put_idx(hw, Q_R2, sky2->rx_put);
2283 }
2284 2276
2285 return work_done; 2277 return work_done;
2286} 2278}