Commit 7f9dd2fa authored by Casey Leedom's avatar Casey Leedom Committed by David S. Miller

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: default avatarCasey Leedom <leedom@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 84c3b972
...@@ -423,12 +423,13 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp, ...@@ -423,12 +423,13 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
case CPL_SGE_EGR_UPDATE: { case CPL_SGE_EGR_UPDATE: {
/* /*
* We've received an Egress Queue status update message. * We've received an Egress Queue Status Update message. We
* We get these, as the SGE is currently configured, when * get these, if the SGE is configured to send these when the
* the firmware passes certain points in processing our * firmware passes certain points in processing our TX
* TX Ethernet Queue. We use these updates to determine * Ethernet Queue or if we make an explicit request for one.
* when we may need to restart a TX Ethernet Queue which * We use these updates to determine when we may need to
* was stopped for lack of free slots ... * restart a TX Ethernet Queue which was stopped for lack of
* free TX Queue Descriptors ...
*/ */
const struct cpl_sge_egr_update *p = (void *)cpl; const struct cpl_sge_egr_update *p = (void *)cpl;
unsigned int qid = EGR_QID(be32_to_cpu(p->opcode_qid)); 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,7 +437,6 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
struct sge_txq *tq; struct sge_txq *tq;
struct sge_eth_txq *txq; struct sge_eth_txq *txq;
unsigned int eq_idx; unsigned int eq_idx;
int hw_cidx, reclaimable, in_use;
/* /*
* Perform sanity checking on the Queue ID to make sure it * Perform sanity checking on the Queue ID to make sure it
...@@ -465,24 +465,6 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp, ...@@ -465,24 +465,6 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
break; break;
} }
/*
* Skip TX Queues which aren't stopped.
*/
if (likely(!netif_tx_queue_stopped(txq->txq)))
break;
/*
* Skip stopped TX Queues which have more than half of their
* DMA rings occupied with unacknowledged writes.
*/
hw_cidx = be16_to_cpu(txq->q.stat->cidx);
reclaimable = hw_cidx - txq->q.cidx;
if (reclaimable < 0)
reclaimable += txq->q.size;
in_use = txq->q.in_use - reclaimable;
if (in_use >= txq->q.size/2)
break;
/* /*
* Restart a stopped TX Queue which has less than half of its * Restart a stopped TX Queue which has less than half of its
* TX ring in use ... * TX ring in use ...
......
...@@ -1070,6 +1070,7 @@ static inline void txq_advance(struct sge_txq *tq, unsigned int n) ...@@ -1070,6 +1070,7 @@ static inline void txq_advance(struct sge_txq *tq, unsigned int n)
*/ */
int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
u32 wr_mid;
u64 cntrl, *end; u64 cntrl, *end;
int qidx, credits; int qidx, credits;
unsigned int flits, ndesc; unsigned int flits, ndesc;
...@@ -1143,14 +1144,19 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1143,14 +1144,19 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
goto out_free; goto out_free;
} }
wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2));
if (unlikely(credits < ETHTXQ_STOP_THRES)) { if (unlikely(credits < ETHTXQ_STOP_THRES)) {
/* /*
* After we're done injecting the Work Request for this * After we're done injecting the Work Request for this
* packet, we'll be below our "stop threshhold" so stop the TX * packet, we'll be below our "stop threshhold" so stop the TX
* Queue now. The queue will get started later on when the * Queue now and schedule a request for an SGE Egress Queue
* firmware informs us that space has opened up. * Update message. The queue will get started later on when
* the firmware processes this Work Request and sends us an
* Egress Queue Status Update message indicating that space
* has opened up.
*/ */
txq_stop(txq); txq_stop(txq);
wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ;
} }
/* /*
...@@ -1161,7 +1167,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1161,7 +1167,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
*/ */
BUG_ON(DIV_ROUND_UP(ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1); BUG_ON(DIV_ROUND_UP(ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1);
wr = (void *)&txq->q.desc[txq->q.pidx]; wr = (void *)&txq->q.desc[txq->q.pidx];
wr->equiq_to_len16 = cpu_to_be32(FW_WR_LEN16(DIV_ROUND_UP(flits, 2))); wr->equiq_to_len16 = cpu_to_be32(wr_mid);
wr->r3[0] = cpu_to_be64(0); wr->r3[0] = cpu_to_be64(0);
wr->r3[1] = cpu_to_be64(0); wr->r3[1] = cpu_to_be64(0);
skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len); skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment