diff options
author | Divy Le Ray <divy@chelsio.com> | 2009-03-12 17:14:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-13 14:30:45 -0400 |
commit | fc88219601aa3f94def89433a6afde154e8faa8c (patch) | |
tree | 8c921807f947ba25c7ce188c9ec586aa57b0a0f9 /drivers/net/cxgb3/cxgb3_main.c | |
parent | 42c8ea17e8f78752ed5a354791b0ea1697dc3480 (diff) |
cxgb3: disable high freq non-data interrupts
Under RX pressure, The HW might generate a high load of interrupts
to signal mac fifo or free lists overflow.
Disable the interrupts, and poll the relevant status bits
to maintain stats.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index c32f514c41a7..9ff0452fcddd 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -2471,6 +2471,8 @@ static void t3_adap_check_task(struct work_struct *work) | |||
2471 | struct adapter *adapter = container_of(work, struct adapter, | 2471 | struct adapter *adapter = container_of(work, struct adapter, |
2472 | adap_check_task.work); | 2472 | adap_check_task.work); |
2473 | const struct adapter_params *p = &adapter->params; | 2473 | const struct adapter_params *p = &adapter->params; |
2474 | int port; | ||
2475 | unsigned int v, status, reset; | ||
2474 | 2476 | ||
2475 | adapter->check_task_cnt++; | 2477 | adapter->check_task_cnt++; |
2476 | 2478 | ||
@@ -2489,6 +2491,54 @@ static void t3_adap_check_task(struct work_struct *work) | |||
2489 | if (p->rev == T3_REV_B2) | 2491 | if (p->rev == T3_REV_B2) |
2490 | check_t3b2_mac(adapter); | 2492 | check_t3b2_mac(adapter); |
2491 | 2493 | ||
2494 | /* | ||
2495 | * Scan the XGMAC's to check for various conditions which we want to | ||
2496 | * monitor in a periodic polling manner rather than via an interrupt | ||
2497 | * condition. This is used for conditions which would otherwise flood | ||
2498 | * the system with interrupts and we only really need to know that the | ||
2499 | * conditions are "happening" ... For each condition we count the | ||
2500 | * detection of the condition and reset it for the next polling loop. | ||
2501 | */ | ||
2502 | for_each_port(adapter, port) { | ||
2503 | struct cmac *mac = &adap2pinfo(adapter, port)->mac; | ||
2504 | u32 cause; | ||
2505 | |||
2506 | cause = t3_read_reg(adapter, A_XGM_INT_CAUSE + mac->offset); | ||
2507 | reset = 0; | ||
2508 | if (cause & F_RXFIFO_OVERFLOW) { | ||
2509 | mac->stats.rx_fifo_ovfl++; | ||
2510 | reset |= F_RXFIFO_OVERFLOW; | ||
2511 | } | ||
2512 | |||
2513 | t3_write_reg(adapter, A_XGM_INT_CAUSE + mac->offset, reset); | ||
2514 | } | ||
2515 | |||
2516 | /* | ||
2517 | * We do the same as above for FL_EMPTY interrupts. | ||
2518 | */ | ||
2519 | status = t3_read_reg(adapter, A_SG_INT_CAUSE); | ||
2520 | reset = 0; | ||
2521 | |||
2522 | if (status & F_FLEMPTY) { | ||
2523 | struct sge_qset *qs = &adapter->sge.qs[0]; | ||
2524 | int i = 0; | ||
2525 | |||
2526 | reset |= F_FLEMPTY; | ||
2527 | |||
2528 | v = (t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS) >> S_FL0EMPTY) & | ||
2529 | 0xffff; | ||
2530 | |||
2531 | while (v) { | ||
2532 | qs->fl[i].empty += (v & 1); | ||
2533 | if (i) | ||
2534 | qs++; | ||
2535 | i ^= 1; | ||
2536 | v >>= 1; | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | t3_write_reg(adapter, A_SG_INT_CAUSE, reset); | ||
2541 | |||
2492 | /* Schedule the next check update if any port is active. */ | 2542 | /* Schedule the next check update if any port is active. */ |
2493 | spin_lock_irq(&adapter->work_lock); | 2543 | spin_lock_irq(&adapter->work_lock); |
2494 | if (adapter->open_device_map & PORT_MASK) | 2544 | if (adapter->open_device_map & PORT_MASK) |