aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorCasey Leedom <leedom@chelsio.com>2010-07-12 17:39:07 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-12 23:21:41 -0400
commit7f9dd2fa4ac74d35f7e5200b76bd09533afe4e4c (patch)
tree5ce55bc75706f9fa7136a7143bc404e0b55bc00f /drivers
parent84c3b972f37a735dafc25c4c0d5fb98f99e1157a (diff)
cxgb4vf: fix TX Queue restart
Fix up TX Queue Host Flow Control to cause an Egress Queue Status Update to be generated when we run out of TX Queue Descriptors. This will, in turn, allow us to restart a stopped TX Queue. Signed-off-by: Casey Leedom <leedom@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/cxgb4vf/cxgb4vf_main.c32
-rw-r--r--drivers/net/cxgb4vf/sge.c12
2 files changed, 16 insertions, 28 deletions
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index e988031f7e86..d065516c0ffd 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -423,12 +423,13 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
423 423
424 case CPL_SGE_EGR_UPDATE: { 424 case CPL_SGE_EGR_UPDATE: {
425 /* 425 /*
426 * We've received an Egress Queue status update message. 426 * We've received an Egress Queue Status Update message. We
427 * We get these, as the SGE is currently configured, when 427 * get these, if the SGE is configured to send these when the
428 * the firmware passes certain points in processing our 428 * firmware passes certain points in processing our TX
429 * TX Ethernet Queue. We use these updates to determine 429 * Ethernet Queue or if we make an explicit request for one.
430 * when we may need to restart a TX Ethernet Queue which 430 * We use these updates to determine when we may need to
431 * was stopped for lack of free slots ... 431 * restart a TX Ethernet Queue which was stopped for lack of
432 * free TX Queue Descriptors ...
432 */ 433 */
433 const struct cpl_sge_egr_update *p = (void *)cpl; 434 const struct cpl_sge_egr_update *p = (void *)cpl;
434 unsigned int qid = EGR_QID(be32_to_cpu(p->opcode_qid)); 435 unsigned int qid = EGR_QID(be32_to_cpu(p->opcode_qid));
@@ -436,7 +437,6 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
436 struct sge_txq *tq; 437 struct sge_txq *tq;
437 struct sge_eth_txq *txq; 438 struct sge_eth_txq *txq;
438 unsigned int eq_idx; 439 unsigned int eq_idx;
439 int hw_cidx, reclaimable, in_use;
440 440
441 /* 441 /*
442 * Perform sanity checking on the Queue ID to make sure it 442 * Perform sanity checking on the Queue ID to make sure it
@@ -466,24 +466,6 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
466 } 466 }
467 467
468 /* 468 /*
469 * Skip TX Queues which aren't stopped.
470 */
471 if (likely(!netif_tx_queue_stopped(txq->txq)))
472 break;
473
474 /*
475 * Skip stopped TX Queues which have more than half of their
476 * DMA rings occupied with unacknowledged writes.
477 */
478 hw_cidx = be16_to_cpu(txq->q.stat->cidx);
479 reclaimable = hw_cidx - txq->q.cidx;
480 if (reclaimable < 0)
481 reclaimable += txq->q.size;
482 in_use = txq->q.in_use - reclaimable;
483 if (in_use >= txq->q.size/2)
484 break;
485
486 /*
487 * Restart a stopped TX Queue which has less than half of its 469 * Restart a stopped TX Queue which has less than half of its
488 * TX ring in use ... 470 * TX ring in use ...
489 */ 471 */
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c
index 37c6354547c7..f2ee9b0bcc37 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/cxgb4vf/sge.c
@@ -1070,6 +1070,7 @@ static inline void txq_advance(struct sge_txq *tq, unsigned int n)
1070 */ 1070 */
1071int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) 1071int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
1072{ 1072{
1073 u32 wr_mid;
1073 u64 cntrl, *end; 1074 u64 cntrl, *end;
1074 int qidx, credits; 1075 int qidx, credits;
1075 unsigned int flits, ndesc; 1076 unsigned int flits, ndesc;
@@ -1143,14 +1144,19 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
1143 goto out_free; 1144 goto out_free;
1144 } 1145 }
1145 1146
1147 wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2));
1146 if (unlikely(credits < ETHTXQ_STOP_THRES)) { 1148 if (unlikely(credits < ETHTXQ_STOP_THRES)) {
1147 /* 1149 /*
1148 * After we're done injecting the Work Request for this 1150 * After we're done injecting the Work Request for this
1149 * packet, we'll be below our "stop threshhold" so stop the TX 1151 * packet, we'll be below our "stop threshhold" so stop the TX
1150 * Queue now. The queue will get started later on when the 1152 * Queue now and schedule a request for an SGE Egress Queue
1151 * firmware informs us that space has opened up. 1153 * Update message. The queue will get started later on when
1154 * the firmware processes this Work Request and sends us an
1155 * Egress Queue Status Update message indicating that space
1156 * has opened up.
1152 */ 1157 */
1153 txq_stop(txq); 1158 txq_stop(txq);
1159 wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ;
1154 } 1160 }
1155 1161
1156 /* 1162 /*
@@ -1161,7 +1167,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
1161 */ 1167 */
1162 BUG_ON(DIV_ROUND_UP(ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1); 1168 BUG_ON(DIV_ROUND_UP(ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1);
1163 wr = (void *)&txq->q.desc[txq->q.pidx]; 1169 wr = (void *)&txq->q.desc[txq->q.pidx];
1164 wr->equiq_to_len16 = cpu_to_be32(FW_WR_LEN16(DIV_ROUND_UP(flits, 2))); 1170 wr->equiq_to_len16 = cpu_to_be32(wr_mid);
1165 wr->r3[0] = cpu_to_be64(0); 1171 wr->r3[0] = cpu_to_be64(0);
1166 wr->r3[1] = cpu_to_be64(0); 1172 wr->r3[1] = cpu_to_be64(0);
1167 skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len); 1173 skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len);