diff options
-rw-r--r-- | drivers/net/sky2.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ccbd8c2674b0..832fd69a0e59 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -844,10 +844,12 @@ static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | |||
844 | /* Update chip's next pointer */ | 844 | /* Update chip's next pointer */ |
845 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) | 845 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) |
846 | { | 846 | { |
847 | q = Y2_QADDR(q, PREF_UNIT_PUT_IDX); | 847 | /* Make sure write' to descriptors are complete before we tell hardware */ |
848 | wmb(); | 848 | wmb(); |
849 | sky2_write16(hw, q, idx); | 849 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); |
850 | sky2_read16(hw, q); | 850 | |
851 | /* Synchronize I/O on since next processor may write to tail */ | ||
852 | mmiowb(); | ||
851 | } | 853 | } |
852 | 854 | ||
853 | 855 | ||
@@ -979,6 +981,7 @@ stopped: | |||
979 | 981 | ||
980 | /* reset the Rx prefetch unit */ | 982 | /* reset the Rx prefetch unit */ |
981 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 983 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); |
984 | mmiowb(); | ||
982 | } | 985 | } |
983 | 986 | ||
984 | /* Clean out receive buffer area, assumes receiver hardware stopped */ | 987 | /* Clean out receive buffer area, assumes receiver hardware stopped */ |
@@ -1198,7 +1201,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1198 | } | 1201 | } |
1199 | 1202 | ||
1200 | /* Tell chip about available buffers */ | 1203 | /* Tell chip about available buffers */ |
1201 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1204 | sky2_put_idx(hw, rxq, sky2->rx_put); |
1202 | return 0; | 1205 | return 0; |
1203 | nomem: | 1206 | nomem: |
1204 | sky2_rx_clean(sky2); | 1207 | sky2_rx_clean(sky2); |
@@ -1540,6 +1543,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1540 | } | 1543 | } |
1541 | 1544 | ||
1542 | sky2->tx_cons = idx; | 1545 | sky2->tx_cons = idx; |
1546 | smp_mb(); | ||
1547 | |||
1543 | if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) | 1548 | if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) |
1544 | netif_wake_queue(dev); | 1549 | netif_wake_queue(dev); |
1545 | } | 1550 | } |
@@ -2218,6 +2223,7 @@ force_update: | |||
2218 | 2223 | ||
2219 | /* Fully processed status ring so clear irq */ | 2224 | /* Fully processed status ring so clear irq */ |
2220 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2225 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2226 | mmiowb(); | ||
2221 | 2227 | ||
2222 | exit_loop: | 2228 | exit_loop: |
2223 | if (buf_write[0]) { | 2229 | if (buf_write[0]) { |
@@ -2442,6 +2448,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2442 | if (work_done < work_limit) { | 2448 | if (work_done < work_limit) { |
2443 | netif_rx_complete(dev0); | 2449 | netif_rx_complete(dev0); |
2444 | 2450 | ||
2451 | /* end of interrupt, re-enables also acts as I/O synchronization */ | ||
2445 | sky2_read32(hw, B0_Y2_SP_LISR); | 2452 | sky2_read32(hw, B0_Y2_SP_LISR); |
2446 | return 0; | 2453 | return 0; |
2447 | } else { | 2454 | } else { |