s390/qeth: stop/wake TX queues based on their fill level
Current xmit code only stops the txq after attempting to fill an IO buffer that hasn't been TX-completed yet. In many-connection scenarios, this can result in frequent rejected TX attempts, requeuing of skbs with NETDEV_TX_BUSY and extra overhead. Now that we have a proper 1-to-1 relation between stack-side txqs and our HW Queues, overhaul the stop/wake logic so that the xmit code stops the txq as needed. Given that we might map multiple skbs into a single buffer, it's crucial to ensure that the queue always provides an _entirely_ empty IO buffer. Otherwise large skbs (eg TSO) might not fit into the last available buffer. So whenever qeth_do_send_packet() first utilizes an _empty_ buffer, it updates & checks the used_buffers count. This now ensures that an skb passed to qeth_xmit() can always be mapped into an IO buffer, so remove all of the -EBUSY roll-back handling in the TX path. We preserve the minimal safety-checks ("Is this IO buffer really available?"), just in case some nasty future bug ever attempts to corrupt an in-use buffer. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

vanhempi
e6c15b5f34
commit
54a50941b7
@@ -607,11 +607,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
||||
int rc;
|
||||
|
||||
if (IS_IQD(card))
|
||||
queue = card->qdio.out_qs[qeth_iqd_translate_txq(dev, txq)];
|
||||
else
|
||||
queue = card->qdio.out_qs[txq];
|
||||
|
||||
netif_stop_subqueue(dev, txq);
|
||||
txq = qeth_iqd_translate_txq(dev, txq);
|
||||
queue = card->qdio.out_qs[txq];
|
||||
|
||||
if (IS_OSN(card))
|
||||
rc = qeth_l2_xmit_osn(card, skb, queue);
|
||||
@@ -622,15 +619,11 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
||||
if (!rc) {
|
||||
QETH_TXQ_STAT_INC(queue, tx_packets);
|
||||
QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes);
|
||||
netif_wake_subqueue(dev, txq);
|
||||
return NETDEV_TX_OK;
|
||||
} else if (rc == -EBUSY) {
|
||||
return NETDEV_TX_BUSY;
|
||||
} /* else fall through */
|
||||
}
|
||||
|
||||
QETH_TXQ_STAT_INC(queue, tx_dropped);
|
||||
kfree_skb(skb);
|
||||
netif_wake_subqueue(dev, txq);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
Viittaa uudesa ongelmassa
Block a user