Skip to content

Commit

Permalink
s390/qeth: make cmd/reply matching more flexible
Browse files Browse the repository at this point in the history
When data is received on the READ channel, the matching logic for cmds
that are waiting for a reply is currently hard-coded into the channel's
main IO callback.
Move this into a per-cmd callback, so that we can apply custom matching
logic for each individual cmd.

This also allows us to remove the coarse-grained check for unexpected
non-IPA replies, since they will no longer match against _all_ pending
cmds.

Note that IDX cmds use _no_ matcher, since their reply is synchronously
received as part of the cmd's IO.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Julian Wiedmann authored and David S. Miller committed Jan 26, 2020
1 parent 91003f3 commit 7f92316
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
14 changes: 13 additions & 1 deletion drivers/s390/net/qeth_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ struct qeth_cmd_buffer {
long timeout;
unsigned char *data;
void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob);
bool (*match)(struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *reply);
void (*callback)(struct qeth_card *card, struct qeth_cmd_buffer *iob,
unsigned int data_length);
int rc;
Expand All @@ -618,6 +620,14 @@ static inline void qeth_get_cmd(struct qeth_cmd_buffer *iob)
refcount_inc(&iob->ref_count);
}

static inline struct qeth_ipa_cmd *__ipa_reply(struct qeth_cmd_buffer *iob)
{
if (!IS_IPA(iob->data))
return NULL;

return (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
}

static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob)
{
return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
Expand Down Expand Up @@ -1023,7 +1033,9 @@ void qeth_setadp_promisc_mode(struct qeth_card *card, bool enable);
int qeth_setadpparms_change_macaddr(struct qeth_card *);
void qeth_tx_timeout(struct net_device *, unsigned int txqueue);
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
u16 cmd_length);
u16 cmd_length,
bool (*match)(struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *reply));
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
Expand Down
34 changes: 24 additions & 10 deletions drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,8 +748,8 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
goto out;
}

if (IS_IPA(iob->data)) {
cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
cmd = __ipa_reply(iob);
if (cmd) {
cmd = qeth_check_ipa_data(card, cmd);
if (!cmd)
goto out;
Expand All @@ -758,17 +758,12 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
card->osn_info.assist_cb(card->dev, cmd);
goto out;
}
} else {
/* non-IPA commands should only flow during initialization */
if (card->state != CARD_STATE_DOWN)
goto out;
}

/* match against pending cmd requests */
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(tmp, &card->cmd_waiter_list, list) {
if (!IS_IPA(tmp->data) ||
__ipa_cmd(tmp)->hdr.seqno == cmd->hdr.seqno) {
if (tmp->match && tmp->match(tmp, iob)) {
request = tmp;
/* take the object outside the lock */
qeth_get_cmd(request);
Expand Down Expand Up @@ -1688,6 +1683,13 @@ static void qeth_mpc_finalize_cmd(struct qeth_card *card,
iob->callback = qeth_release_buffer_cb;
}

static bool qeth_mpc_match_reply(struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *reply)
{
/* MPC cmds are issued strictly in sequence. */
return !IS_IPA(reply->data);
}

static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card,
void *data,
unsigned int data_length)
Expand All @@ -1702,6 +1704,7 @@ static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card,
qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, data_length,
iob->data);
iob->finalize = qeth_mpc_finalize_cmd;
iob->match = qeth_mpc_match_reply;
return iob;
}

Expand Down Expand Up @@ -2722,14 +2725,17 @@ static void qeth_ipa_finalize_cmd(struct qeth_card *card,
}

void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
u16 cmd_length)
u16 cmd_length,
bool (*match)(struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *reply))
{
u8 prot_type = qeth_mpc_select_prot_type(card);
u16 total_length = iob->length;

qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, total_length,
iob->data);
iob->finalize = qeth_ipa_finalize_cmd;
iob->match = match;

memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2);
Expand All @@ -2742,6 +2748,14 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
}
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);

static bool qeth_ipa_match_reply(struct qeth_cmd_buffer *iob,
struct qeth_cmd_buffer *reply)
{
struct qeth_ipa_cmd *ipa_reply = __ipa_reply(reply);

return ipa_reply && (__ipa_cmd(iob)->hdr.seqno == ipa_reply->hdr.seqno);
}

struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
enum qeth_ipa_cmds cmd_code,
enum qeth_prot_versions prot,
Expand All @@ -2757,7 +2771,7 @@ struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
if (!iob)
return NULL;

qeth_prepare_ipa_cmd(card, iob, data_length);
qeth_prepare_ipa_cmd(card, iob, data_length, qeth_ipa_match_reply);

hdr = &__ipa_cmd(iob)->hdr;
hdr->command = cmd_code;
Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/net/qeth_l2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
if (!iob)
return -ENOMEM;

qeth_prepare_ipa_cmd(card, iob, (u16) data_len);
qeth_prepare_ipa_cmd(card, iob, (u16) data_len, NULL);

memcpy(__ipa_cmd(iob), data, data_len);
iob->callback = qeth_osn_assist_cb;
return qeth_send_ipa_cmd(card, iob, NULL, NULL);
Expand Down

0 comments on commit 7f92316

Please sign in to comment.