aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2009-03-12 17:14:09 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-13 14:30:45 -0400
commitfc88219601aa3f94def89433a6afde154e8faa8c (patch)
tree8c921807f947ba25c7ce188c9ec586aa57b0a0f9
parent42c8ea17e8f78752ed5a354791b0ea1697dc3480 (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>
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c50
-rw-r--r--drivers/net/cxgb3/regs.h8
-rw-r--r--drivers/net/cxgb3/sge.c3
-rw-r--r--drivers/net/cxgb3/t3_hw.c30
4 files changed, 86 insertions, 5 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index c32f514c41a..9ff0452fcdd 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)
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index a035d5c2444..aa08550ee99 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -170,6 +170,10 @@
170 170
171#define S_RSPQ0DISABLED 8 171#define S_RSPQ0DISABLED 8
172 172
173#define S_FL0EMPTY 16
174#define V_FL0EMPTY(x) ((x) << S_FL0EMPTY)
175#define F_FL0EMPTY V_FL0EMPTY(1U)
176
173#define A_SG_EGR_RCQ_DRB_THRSH 0x54 177#define A_SG_EGR_RCQ_DRB_THRSH 0x54
174 178
175#define S_HIRCQDRBTHRSH 16 179#define S_HIRCQDRBTHRSH 16
@@ -258,6 +262,10 @@
258#define V_RSPQCREDITOVERFOW(x) ((x) << S_RSPQCREDITOVERFOW) 262#define V_RSPQCREDITOVERFOW(x) ((x) << S_RSPQCREDITOVERFOW)
259#define F_RSPQCREDITOVERFOW V_RSPQCREDITOVERFOW(1U) 263#define F_RSPQCREDITOVERFOW V_RSPQCREDITOVERFOW(1U)
260 264
265#define S_FLEMPTY 1
266#define V_FLEMPTY(x) ((x) << S_FLEMPTY)
267#define F_FLEMPTY V_FLEMPTY(1U)
268
261#define A_SG_INT_ENABLE 0x60 269#define A_SG_INT_ENABLE 0x60
262 270
263#define A_SG_CMDQ_CREDIT_TH 0x64 271#define A_SG_CMDQ_CREDIT_TH 0x64
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 7d779d18e13..a7555cb3fa4 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2725,7 +2725,8 @@ irq_handler_t t3_intr_handler(struct adapter *adap, int polling)
2725 */ 2725 */
2726void t3_sge_err_intr_handler(struct adapter *adapter) 2726void t3_sge_err_intr_handler(struct adapter *adapter)
2727{ 2727{
2728 unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE); 2728 unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE) &
2729 ~F_FLEMPTY;
2729 2730
2730 if (status & SGE_PARERR) 2731 if (status & SGE_PARERR)
2731 CH_ALERT(adapter, "SGE parity error (0x%x)\n", 2732 CH_ALERT(adapter, "SGE parity error (0x%x)\n",
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index ac2a974dfe3..7c6ee0c9b6f 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -1323,7 +1323,7 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
1323#define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE)) 1323#define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE))
1324#define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ 1324#define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \
1325 V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \ 1325 V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \
1326 F_TXFIFO_UNDERRUN | F_RXFIFO_OVERFLOW) 1326 F_TXFIFO_UNDERRUN)
1327#define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \ 1327#define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \
1328 F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \ 1328 F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \
1329 F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \ 1329 F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \
@@ -1695,7 +1695,14 @@ static void mc7_intr_handler(struct mc7 *mc7)
1695static int mac_intr_handler(struct adapter *adap, unsigned int idx) 1695static int mac_intr_handler(struct adapter *adap, unsigned int idx)
1696{ 1696{
1697 struct cmac *mac = &adap2pinfo(adap, idx)->mac; 1697 struct cmac *mac = &adap2pinfo(adap, idx)->mac;
1698 u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset); 1698 /*
1699 * We mask out interrupt causes for which we're not taking interrupts.
1700 * This allows us to use polling logic to monitor some of the other
1701 * conditions when taking interrupts would impose too much load on the
1702 * system.
1703 */
1704 u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset) &
1705 ~F_RXFIFO_OVERFLOW;
1699 1706
1700 if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) { 1707 if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) {
1701 mac->stats.tx_fifo_parity_err++; 1708 mac->stats.tx_fifo_parity_err++;
@@ -3617,7 +3624,15 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
3617 adapter->params.info = ai; 3624 adapter->params.info = ai;
3618 adapter->params.nports = ai->nports; 3625 adapter->params.nports = ai->nports;
3619 adapter->params.rev = t3_read_reg(adapter, A_PL_REV); 3626 adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
3620 adapter->params.linkpoll_period = 0; 3627 /*
3628 * We used to only run the "adapter check task" once a second if
3629 * we had PHYs which didn't support interrupts (we would check
3630 * their link status once a second). Now we check other conditions
3631 * in that routine which could potentially impose a very high
3632 * interrupt load on the system. As such, we now always scan the
3633 * adapter state once a second ...
3634 */
3635 adapter->params.linkpoll_period = 10;
3621 adapter->params.stats_update_period = is_10G(adapter) ? 3636 adapter->params.stats_update_period = is_10G(adapter) ?
3622 MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10); 3637 MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
3623 adapter->params.pci.vpd_cap_addr = 3638 adapter->params.pci.vpd_cap_addr =
@@ -3707,7 +3722,14 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
3707 ETH_ALEN); 3722 ETH_ALEN);
3708 init_link_config(&p->link_config, p->phy.caps); 3723 init_link_config(&p->link_config, p->phy.caps);
3709 p->phy.ops->power_down(&p->phy, 1); 3724 p->phy.ops->power_down(&p->phy, 1);
3710 if (!(p->phy.caps & SUPPORTED_IRQ)) 3725
3726 /*
3727 * If the PHY doesn't support interrupts for link status
3728 * changes, schedule a scan of the adapter links at least
3729 * once a second.
3730 */
3731 if (!(p->phy.caps & SUPPORTED_IRQ) &&
3732 adapter->params.linkpoll_period > 10)
3711 adapter->params.linkpoll_period = 10; 3733 adapter->params.linkpoll_period = 10;
3712 } 3734 }
3713 3735