diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-07-09 18:33:37 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 12:22:29 -0400 |
commit | 55c9dd35d3299dbd6e437c1a0bd86fffcb17080b (patch) | |
tree | ba5d05205513effffc7f51dde1341b3f852fc5cf /drivers/net/sky2.c | |
parent | 5c11ce700f77fada15b6264417d72462da4bbb1c (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.c | 36 |
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 | ||
1140 | static 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; |
1234 | nomem: | 1238 | nomem: |
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 */ |
2148 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 2152 | static 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) { | ||
2206 | force_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 | ||
2274 | exit_loop: | 2270 | exit_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 | } |