s390/qeth: schedule TX NAPI on QAOB completion
[ Upstream commit 3e83d467a08e25b27c44c885f511624a71c84f7c ] When a QAOB notifies us that a pending TX buffer has been delivered, the actual TX completion processing by qeth_tx_complete_pending_bufs() is done within the context of a TX NAPI instance. We shouldn't rely on this instance being scheduled by some other TX event, but just do it ourselves. qeth_qdio_handle_aob() is called from qeth_poll(), ie. our main NAPI instance. To avoid touching the TX queue's NAPI instance before/after it is (un-)registered, reorder the code in qeth_open() and qeth_stop() accordingly. Fixes: 0da9581ddb0f ("qeth: exploit asynchronous delivery of storage blocks") Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
f3f6765fd0
commit
e8e99acd08
@ -470,6 +470,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
|
||||
struct qaob *aob;
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
enum iucv_tx_notify notification;
|
||||
struct qeth_qdio_out_q *queue;
|
||||
unsigned int i;
|
||||
|
||||
aob = (struct qaob *) phys_to_virt(phys_aob_addr);
|
||||
@ -511,7 +512,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
|
||||
kmem_cache_free(qeth_core_header_cache, data);
|
||||
}
|
||||
|
||||
queue = buffer->q;
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY);
|
||||
napi_schedule(&queue->napi);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
@ -7013,9 +7016,7 @@ int qeth_open(struct net_device *dev)
|
||||
card->data.state = CH_STATE_UP;
|
||||
netif_tx_start_all_queues(dev);
|
||||
|
||||
napi_enable(&card->napi);
|
||||
local_bh_disable();
|
||||
napi_schedule(&card->napi);
|
||||
if (IS_IQD(card)) {
|
||||
struct qeth_qdio_out_q *queue;
|
||||
unsigned int i;
|
||||
@ -7027,8 +7028,12 @@ int qeth_open(struct net_device *dev)
|
||||
napi_schedule(&queue->napi);
|
||||
}
|
||||
}
|
||||
|
||||
napi_enable(&card->napi);
|
||||
napi_schedule(&card->napi);
|
||||
/* kick-start the NAPI softirq: */
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_open);
|
||||
@ -7038,6 +7043,11 @@ int qeth_stop(struct net_device *dev)
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "qethstop");
|
||||
|
||||
napi_disable(&card->napi);
|
||||
cancel_delayed_work_sync(&card->buffer_reclaim_work);
|
||||
qdio_stop_irq(CARD_DDEV(card));
|
||||
|
||||
if (IS_IQD(card)) {
|
||||
struct qeth_qdio_out_q *queue;
|
||||
unsigned int i;
|
||||
@ -7058,10 +7068,6 @@ int qeth_stop(struct net_device *dev)
|
||||
netif_tx_disable(dev);
|
||||
}
|
||||
|
||||
napi_disable(&card->napi);
|
||||
cancel_delayed_work_sync(&card->buffer_reclaim_work);
|
||||
qdio_stop_irq(CARD_DDEV(card));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_stop);
|
||||
|
Loading…
x
Reference in New Issue
Block a user