diff options
| author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-05-14 15:38:15 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-05-17 20:43:14 -0400 |
| commit | 50432cb534b566c4fd9e371fb37464a65ccd2391 (patch) | |
| tree | b9967313ebf46d37650fbbc66fb35240be1825c0 | |
| parent | 84787e3fc38a4847e5d75388d5a7fb3cf6bd7834 (diff) | |
sky2: memory barriers change
Do some memory barrier changes for safety/perfomance:
Don't need read after update to index, mmiowb() followed by read at end
of irq is sufficient.
Signed-off-by: Stephn Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -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 { |
