Skip to content

Commit 901e3f4

Browse files
julianwiedmanndavem330
authored andcommitted
s390/qeth: avoid control IO completion stalls
For control IO, qeth currently tracks the index of the buffer that it expects to complete the next IO on each qeth_channel. If the channel presents an IRQ while this buffer has not yet completed, no completion processing for _any_ completed buffer takes place. So if the 'next buffer' is skipped for any sort of reason* (eg. when it is released due to error conditions, before the IO is started), the buffer obviously won't switch to PROCESSED until it is eventually allocated for a _different_ IO and completes. Until this happens, all completion processing on that channel stalls and pending requests possibly time out. As a fix, remove the whole 'next buffer' logic and simply process any IO buffer right when it completes. A channel will never have more than one IO pending, so there's no risk of processing out-of-sequence. *Note: currently just one location in the code really handles this problem, by advancing the 'next' index manually. Signed-off-by: Julian Wiedmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 686c97e commit 901e3f4

File tree

2 files changed

+5
-19
lines changed

2 files changed

+5
-19
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,6 @@ enum qeth_prot_versions {
557557
enum qeth_cmd_buffer_state {
558558
BUF_STATE_FREE,
559559
BUF_STATE_LOCKED,
560-
BUF_STATE_PROCESSED,
561560
};
562561

563562
enum qeth_cq {
@@ -601,7 +600,6 @@ struct qeth_channel {
601600
struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
602601
atomic_t irq_pending;
603602
int io_buf_no;
604-
int buf_no;
605603
};
606604

607605
/**

drivers/s390/net/qeth_core_main.c

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,6 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel)
818818

819819
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
820820
qeth_release_buffer(channel, &channel->iob[cnt]);
821-
channel->buf_no = 0;
822821
channel->io_buf_no = 0;
823822
}
824823
EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
@@ -924,7 +923,6 @@ static int qeth_setup_channel(struct qeth_channel *channel)
924923
kfree(channel->iob[cnt].data);
925924
return -ENOMEM;
926925
}
927-
channel->buf_no = 0;
928926
channel->io_buf_no = 0;
929927
atomic_set(&channel->irq_pending, 0);
930928
spin_lock_init(&channel->iob_lock);
@@ -1100,11 +1098,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
11001098
{
11011099
int rc;
11021100
int cstat, dstat;
1103-
struct qeth_cmd_buffer *buffer;
11041101
struct qeth_channel *channel;
11051102
struct qeth_card *card;
11061103
struct qeth_cmd_buffer *iob;
1107-
__u8 index;
11081104

11091105
if (__qeth_check_irb_error(cdev, intparm, irb))
11101106
return;
@@ -1182,25 +1178,18 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
11821178
channel->state = CH_STATE_RCD_DONE;
11831179
goto out;
11841180
}
1185-
if (intparm) {
1186-
buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
1187-
buffer->state = BUF_STATE_PROCESSED;
1188-
}
11891181
if (channel == &card->data)
11901182
return;
11911183
if (channel == &card->read &&
11921184
channel->state == CH_STATE_UP)
11931185
__qeth_issue_next_read(card);
11941186

1195-
iob = channel->iob;
1196-
index = channel->buf_no;
1197-
while (iob[index].state == BUF_STATE_PROCESSED) {
1198-
if (iob[index].callback != NULL)
1199-
iob[index].callback(channel, iob + index);
1200-
1201-
index = (index + 1) % QETH_CMD_BUFFER_NO;
1187+
if (intparm) {
1188+
iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
1189+
if (iob->callback)
1190+
iob->callback(iob->channel, iob);
12021191
}
1203-
channel->buf_no = index;
1192+
12041193
out:
12051194
wake_up(&card->wait_q);
12061195
return;
@@ -2214,7 +2203,6 @@ int qeth_send_control_data(struct qeth_card *card, int len,
22142203
error:
22152204
atomic_set(&card->write.irq_pending, 0);
22162205
qeth_release_buffer(iob->channel, iob);
2217-
card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
22182206
rc = reply->rc;
22192207
qeth_put_reply(reply);
22202208
return rc;

0 commit comments

Comments
 (0)