diff options
author | Saeed Bishara <saeed@marvell.com> | 2009-05-05 23:02:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-06 18:33:39 -0400 |
commit | e0ca84105bca8691f39ef7ff221a88046ba11f23 (patch) | |
tree | 9c68d0490a5537dd51aa4d813444e4fe98713ab9 /drivers/net/mv643xx_eth.c | |
parent | 7fd96ce47ff83fc17ab78d465d8e067467a7f51e (diff) |
mv643xx_eth: only unmask RX and TX_END interrupts for available queues
It is not a good idea to blindly unmask the RX and TX_END interrupts
for all eight queues on all mv643xx_eth hardware, since some variations
of the hardware have less than eight transmit/receive queues, and the
RX/TX_END interrupts for the queues they don't have can be in use by
other interrupt sources.
Signed-off-by: Saeed Bishara <saeed@marvell.com>
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 05bb1c55da66..d5838528791f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -123,7 +123,9 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
123 | #define TX_BW_BURST 0x005c | 123 | #define TX_BW_BURST 0x005c |
124 | #define INT_CAUSE 0x0060 | 124 | #define INT_CAUSE 0x0060 |
125 | #define INT_TX_END 0x07f80000 | 125 | #define INT_TX_END 0x07f80000 |
126 | #define INT_TX_END_0 0x00080000 | ||
126 | #define INT_RX 0x000003fc | 127 | #define INT_RX 0x000003fc |
128 | #define INT_RX_0 0x00000004 | ||
127 | #define INT_EXT 0x00000002 | 129 | #define INT_EXT 0x00000002 |
128 | #define INT_CAUSE_EXT 0x0064 | 130 | #define INT_CAUSE_EXT 0x0064 |
129 | #define INT_EXT_LINK_PHY 0x00110000 | 131 | #define INT_EXT_LINK_PHY 0x00110000 |
@@ -392,6 +394,7 @@ struct mv643xx_eth_private { | |||
392 | struct work_struct tx_timeout_task; | 394 | struct work_struct tx_timeout_task; |
393 | 395 | ||
394 | struct napi_struct napi; | 396 | struct napi_struct napi; |
397 | u32 int_mask; | ||
395 | u8 oom; | 398 | u8 oom; |
396 | u8 work_link; | 399 | u8 work_link; |
397 | u8 work_tx; | 400 | u8 work_tx; |
@@ -2058,15 +2061,16 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp) | |||
2058 | u32 int_cause; | 2061 | u32 int_cause; |
2059 | u32 int_cause_ext; | 2062 | u32 int_cause_ext; |
2060 | 2063 | ||
2061 | int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT); | 2064 | int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask; |
2062 | if (int_cause == 0) | 2065 | if (int_cause == 0) |
2063 | return 0; | 2066 | return 0; |
2064 | 2067 | ||
2065 | int_cause_ext = 0; | 2068 | int_cause_ext = 0; |
2066 | if (int_cause & INT_EXT) | 2069 | if (int_cause & INT_EXT) { |
2070 | int_cause &= ~INT_EXT; | ||
2067 | int_cause_ext = rdlp(mp, INT_CAUSE_EXT); | 2071 | int_cause_ext = rdlp(mp, INT_CAUSE_EXT); |
2072 | } | ||
2068 | 2073 | ||
2069 | int_cause &= INT_TX_END | INT_RX; | ||
2070 | if (int_cause) { | 2074 | if (int_cause) { |
2071 | wrlp(mp, INT_CAUSE, ~int_cause); | 2075 | wrlp(mp, INT_CAUSE, ~int_cause); |
2072 | mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & | 2076 | mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & |
@@ -2212,7 +2216,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) | |||
2212 | if (mp->oom) | 2216 | if (mp->oom) |
2213 | mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); | 2217 | mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); |
2214 | napi_complete(napi); | 2218 | napi_complete(napi); |
2215 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2219 | wrlp(mp, INT_MASK, mp->int_mask); |
2216 | } | 2220 | } |
2217 | 2221 | ||
2218 | return work_done; | 2222 | return work_done; |
@@ -2366,6 +2370,8 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2366 | 2370 | ||
2367 | skb_queue_head_init(&mp->rx_recycle); | 2371 | skb_queue_head_init(&mp->rx_recycle); |
2368 | 2372 | ||
2373 | mp->int_mask = INT_EXT; | ||
2374 | |||
2369 | for (i = 0; i < mp->rxq_count; i++) { | 2375 | for (i = 0; i < mp->rxq_count; i++) { |
2370 | err = rxq_init(mp, i); | 2376 | err = rxq_init(mp, i); |
2371 | if (err) { | 2377 | if (err) { |
@@ -2375,6 +2381,7 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2375 | } | 2381 | } |
2376 | 2382 | ||
2377 | rxq_refill(mp->rxq + i, INT_MAX); | 2383 | rxq_refill(mp->rxq + i, INT_MAX); |
2384 | mp->int_mask |= INT_RX_0 << i; | ||
2378 | } | 2385 | } |
2379 | 2386 | ||
2380 | if (mp->oom) { | 2387 | if (mp->oom) { |
@@ -2389,12 +2396,13 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2389 | txq_deinit(mp->txq + i); | 2396 | txq_deinit(mp->txq + i); |
2390 | goto out_free; | 2397 | goto out_free; |
2391 | } | 2398 | } |
2399 | mp->int_mask |= INT_TX_END_0 << i; | ||
2392 | } | 2400 | } |
2393 | 2401 | ||
2394 | port_start(mp); | 2402 | port_start(mp); |
2395 | 2403 | ||
2396 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); | 2404 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); |
2397 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2405 | wrlp(mp, INT_MASK, mp->int_mask); |
2398 | 2406 | ||
2399 | return 0; | 2407 | return 0; |
2400 | 2408 | ||
@@ -2538,7 +2546,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) | |||
2538 | 2546 | ||
2539 | mv643xx_eth_irq(dev->irq, dev); | 2547 | mv643xx_eth_irq(dev->irq, dev); |
2540 | 2548 | ||
2541 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2549 | wrlp(mp, INT_MASK, mp->int_mask); |
2542 | } | 2550 | } |
2543 | #endif | 2551 | #endif |
2544 | 2552 | ||