Commit 3e83d467 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller

s390/qeth: schedule TX NAPI on QAOB completion

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: 0da9581d ("qeth: exploit asynchronous delivery of storage blocks")
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c20383ad
...@@ -470,6 +470,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, ...@@ -470,6 +470,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
struct qaob *aob; struct qaob *aob;
struct qeth_qdio_out_buffer *buffer; struct qeth_qdio_out_buffer *buffer;
enum iucv_tx_notify notification; enum iucv_tx_notify notification;
struct qeth_qdio_out_q *queue;
unsigned int i; unsigned int i;
aob = (struct qaob *) phys_to_virt(phys_aob_addr); aob = (struct qaob *) phys_to_virt(phys_aob_addr);
...@@ -512,7 +513,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, ...@@ -512,7 +513,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
buffer->is_header[i] = 0; buffer->is_header[i] = 0;
} }
queue = buffer->q;
atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY); atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY);
napi_schedule(&queue->napi);
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
...@@ -7235,9 +7238,7 @@ int qeth_open(struct net_device *dev) ...@@ -7235,9 +7238,7 @@ int qeth_open(struct net_device *dev)
card->data.state = CH_STATE_UP; card->data.state = CH_STATE_UP;
netif_tx_start_all_queues(dev); netif_tx_start_all_queues(dev);
napi_enable(&card->napi);
local_bh_disable(); local_bh_disable();
napi_schedule(&card->napi);
if (IS_IQD(card)) { if (IS_IQD(card)) {
struct qeth_qdio_out_q *queue; struct qeth_qdio_out_q *queue;
unsigned int i; unsigned int i;
...@@ -7249,8 +7250,12 @@ int qeth_open(struct net_device *dev) ...@@ -7249,8 +7250,12 @@ int qeth_open(struct net_device *dev)
napi_schedule(&queue->napi); napi_schedule(&queue->napi);
} }
} }
napi_enable(&card->napi);
napi_schedule(&card->napi);
/* kick-start the NAPI softirq: */ /* kick-start the NAPI softirq: */
local_bh_enable(); local_bh_enable();
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(qeth_open); EXPORT_SYMBOL_GPL(qeth_open);
...@@ -7260,6 +7265,11 @@ int qeth_stop(struct net_device *dev) ...@@ -7260,6 +7265,11 @@ int qeth_stop(struct net_device *dev)
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
QETH_CARD_TEXT(card, 4, "qethstop"); 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)) { if (IS_IQD(card)) {
struct qeth_qdio_out_q *queue; struct qeth_qdio_out_q *queue;
unsigned int i; unsigned int i;
...@@ -7280,10 +7290,6 @@ int qeth_stop(struct net_device *dev) ...@@ -7280,10 +7290,6 @@ int qeth_stop(struct net_device *dev)
netif_tx_disable(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; return 0;
} }
EXPORT_SYMBOL_GPL(qeth_stop); EXPORT_SYMBOL_GPL(qeth_stop);
......
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