Skip to content

Commit 782e4a7

Browse files
julianwiedmanndavem330
authored andcommitted
s390/qeth: don't poll for cmd IO completion
All callers are running in process context now, so we can safely sleep in qeth_send_control_data() while waiting for a cmd to complete. Signed-off-by: Julian Wiedmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent df2a2a5 commit 782e4a7

File tree

3 files changed

+35
-41
lines changed

3 files changed

+35
-41
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef __QETH_CORE_H__
1111
#define __QETH_CORE_H__
1212

13+
#include <linux/completion.h>
1314
#include <linux/if.h>
1415
#include <linux/if_arp.h>
1516
#include <linux/etherdevice.h>
@@ -21,6 +22,7 @@
2122
#include <linux/hashtable.h>
2223
#include <linux/ip.h>
2324
#include <linux/refcount.h>
25+
#include <linux/wait.h>
2426
#include <linux/workqueue.h>
2527

2628
#include <net/ipv6.h>
@@ -585,6 +587,7 @@ struct qeth_cmd_buffer {
585587
enum qeth_cmd_buffer_state state;
586588
struct qeth_channel *channel;
587589
struct qeth_reply *reply;
590+
long timeout;
588591
unsigned char *data;
589592
void (*callback)(struct qeth_card *card, struct qeth_channel *channel,
590593
struct qeth_cmd_buffer *iob);
@@ -610,6 +613,11 @@ struct qeth_channel {
610613
int io_buf_no;
611614
};
612615

616+
static inline bool qeth_trylock_channel(struct qeth_channel *channel)
617+
{
618+
return atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0;
619+
}
620+
613621
/**
614622
* OSA card related definitions
615623
*/
@@ -636,12 +644,11 @@ struct qeth_seqno {
636644

637645
struct qeth_reply {
638646
struct list_head list;
639-
wait_queue_head_t wait_q;
647+
struct completion received;
640648
int (*callback)(struct qeth_card *, struct qeth_reply *,
641649
unsigned long);
642650
u32 seqno;
643651
unsigned long offset;
644-
atomic_t received;
645652
int rc;
646653
void *param;
647654
refcount_t refcnt;

drivers/s390/net/qeth_core_main.c

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,10 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
542542
{
543543
struct qeth_reply *reply;
544544

545-
reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
545+
reply = kzalloc(sizeof(*reply), GFP_KERNEL);
546546
if (reply) {
547547
refcount_set(&reply->refcnt, 1);
548-
atomic_set(&reply->received, 0);
549-
init_waitqueue_head(&reply->wait_q);
548+
init_completion(&reply->received);
550549
}
551550
return reply;
552551
}
@@ -578,8 +577,7 @@ static void qeth_dequeue_reply(struct qeth_card *card, struct qeth_reply *reply)
578577

579578
static void qeth_notify_reply(struct qeth_reply *reply)
580579
{
581-
atomic_inc(&reply->received);
582-
wake_up(&reply->wait_q);
580+
complete(&reply->received);
583581
}
584582

585583
static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
@@ -704,6 +702,7 @@ static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
704702
do {
705703
if (channel->iob[index].state == BUF_STATE_FREE) {
706704
channel->iob[index].state = BUF_STATE_LOCKED;
705+
channel->iob[index].timeout = QETH_TIMEOUT;
707706
channel->io_buf_no = (channel->io_buf_no + 1) %
708707
QETH_CMD_BUFFER_NO;
709708
memset(channel->iob[index].data, 0, QETH_BUFSIZE);
@@ -1786,8 +1785,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card,
17861785
iob->callback = reply_cb;
17871786
qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
17881787

1789-
wait_event(card->wait_q,
1790-
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
1788+
wait_event(card->wait_q, qeth_trylock_channel(channel));
17911789
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
17921790
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
17931791
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
@@ -1855,8 +1853,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
18551853
temp = (card->info.cula << 8) + card->info.unit_addr2;
18561854
memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
18571855

1858-
wait_event(card->wait_q,
1859-
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
1856+
wait_event(card->wait_q, qeth_trylock_channel(channel));
18601857
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
18611858
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
18621859
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
@@ -2034,9 +2031,9 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
20342031
void *reply_param)
20352032
{
20362033
struct qeth_channel *channel = iob->channel;
2034+
long timeout = iob->timeout;
20372035
int rc;
20382036
struct qeth_reply *reply = NULL;
2039-
unsigned long timeout, event_timeout;
20402037
struct qeth_ipa_cmd *cmd = NULL;
20412038

20422039
QETH_CARD_TEXT(card, 2, "sendctl");
@@ -2057,27 +2054,30 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
20572054
qeth_get_reply(reply);
20582055
iob->reply = reply;
20592056

2060-
while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ;
2057+
timeout = wait_event_interruptible_timeout(card->wait_q,
2058+
qeth_trylock_channel(channel),
2059+
timeout);
2060+
if (timeout <= 0) {
2061+
qeth_put_reply(reply);
2062+
qeth_release_buffer(channel, iob);
2063+
return (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
2064+
}
20612065

20622066
if (IS_IPA(iob->data)) {
20632067
cmd = __ipa_cmd(iob);
20642068
cmd->hdr.seqno = card->seqno.ipa++;
20652069
reply->seqno = cmd->hdr.seqno;
2066-
event_timeout = QETH_IPA_TIMEOUT;
20672070
} else {
20682071
reply->seqno = QETH_IDX_COMMAND_SEQNO;
2069-
event_timeout = QETH_TIMEOUT;
20702072
}
20712073
qeth_prepare_control_data(card, len, iob);
20722074

20732075
qeth_enqueue_reply(card, reply);
20742076

2075-
timeout = jiffies + event_timeout;
2076-
20772077
QETH_CARD_TEXT(card, 6, "noirqpnd");
20782078
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
20792079
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
2080-
(addr_t) iob, 0, 0, event_timeout);
2080+
(addr_t) iob, 0, 0, timeout);
20812081
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
20822082
if (rc) {
20832083
QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
@@ -2091,30 +2091,16 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
20912091
return rc;
20922092
}
20932093

2094-
/* we have only one long running ipassist, since we can ensure
2095-
process context of this command we can sleep */
2096-
if (cmd && cmd->hdr.command == IPA_CMD_SETIP &&
2097-
cmd->hdr.prot_version == QETH_PROT_IPV4) {
2098-
if (!wait_event_timeout(reply->wait_q,
2099-
atomic_read(&reply->received), event_timeout))
2100-
goto time_err;
2101-
} else {
2102-
while (!atomic_read(&reply->received)) {
2103-
if (time_after(jiffies, timeout))
2104-
goto time_err;
2105-
cpu_relax();
2106-
}
2107-
}
2094+
timeout = wait_for_completion_interruptible_timeout(&reply->received,
2095+
timeout);
2096+
if (timeout <= 0)
2097+
rc = (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
21082098

21092099
qeth_dequeue_reply(card, reply);
2110-
rc = reply->rc;
2100+
if (!rc)
2101+
rc = reply->rc;
21112102
qeth_put_reply(reply);
21122103
return rc;
2113-
2114-
time_err:
2115-
qeth_dequeue_reply(card, reply);
2116-
qeth_put_reply(reply);
2117-
return -ETIME;
21182104
}
21192105

21202106
static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
@@ -2810,6 +2796,8 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
28102796
u16 total_length = IPA_PDU_HEADER_SIZE + cmd_length;
28112797
u8 prot_type = qeth_mpc_select_prot_type(card);
28122798

2799+
iob->timeout = QETH_IPA_TIMEOUT;
2800+
28132801
memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
28142802
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2);
28152803
memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);

drivers/s390/net/qeth_l2_main.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,13 +1050,12 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
10501050

10511051
QETH_CARD_TEXT(card, 5, "osndctrd");
10521052

1053-
wait_event(card->wait_q,
1054-
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
1053+
wait_event(card->wait_q, qeth_trylock_channel(channel));
10551054
qeth_prepare_control_data(card, len, iob);
10561055
QETH_CARD_TEXT(card, 6, "osnoirqp");
10571056
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
10581057
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
1059-
(addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
1058+
(addr_t) iob, 0, 0, iob->timeout);
10601059
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
10611060
if (rc) {
10621061
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "

0 commit comments

Comments
 (0)