diff options
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 62 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_queue.c | 12 |
2 files changed, 49 insertions, 25 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 35250fd3fa91..70855af8c281 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -342,11 +342,14 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain); /* * ap_queue_info(): Check and get AP queue info. - * Returns true if TAPQ succeeded and the info is filled or - * false otherwise. + * Returns: 1 if APQN exists and info is filled, + * 0 if APQN seems to exit but there is no info + * available (eg. caused by an asynch pending error) + * -1 invalid APQN, TAPQ error or AP queue status which + * indicates there is no APQN. */ -static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, - int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop) +static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, + int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop) { struct ap_queue_status status; struct ap_tapq_gr2 tapq_info; @@ -356,10 +359,15 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, /* make sure we don't run into a specifiation exception */ if (AP_QID_CARD(qid) > ap_max_adapter_id || AP_QID_QUEUE(qid) > ap_max_domain_id) - return false; + return -1; /* call TAPQ on this APQN */ status = ap_test_queue(qid, ap_apft_available(), &tapq_info); + + /* handle pending async error with return 'no info available' */ + if (status.async) + return 0; + switch (status.response_code) { case AP_RESPONSE_NORMAL: case AP_RESPONSE_RESET_IN_PROGRESS: @@ -372,7 +380,7 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, * there is at least one of the mode bits set. */ if (WARN_ON_ONCE(!tapq_info.value)) - return false; + return 0; *q_type = tapq_info.at; *q_fac = tapq_info.fac; *q_depth = tapq_info.qd; @@ -396,12 +404,12 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, default: break; } - return true; + return 1; default: /* * A response code which indicates, there is no info available. */ - return false; + return -1; } } @@ -1798,12 +1806,12 @@ static inline void ap_scan_rm_card_dev_and_queue_devs(struct ap_card *ac) */ static inline void ap_scan_domains(struct ap_card *ac) { + int rc, dom, depth, type, ml; bool decfg, chkstop; - ap_qid_t qid; - unsigned int func; - struct device *dev; struct ap_queue *aq; - int rc, dom, depth, type, ml; + struct device *dev; + unsigned int func; + ap_qid_t qid; /* * Go through the configuration for the domains and compare them @@ -1822,20 +1830,24 @@ static inline void ap_scan_domains(struct ap_card *ac) AP_DBF_INFO("%s(%d,%d) not in config anymore, rm queue dev\n", __func__, ac->id, dom); device_unregister(dev); - put_device(dev); } - continue; + goto put_dev_and_continue; } /* domain is valid, get info from this APQN */ - if (!ap_queue_info(qid, &type, &func, &depth, - &ml, &decfg, &chkstop)) { - if (aq) { + rc = ap_queue_info(qid, &type, &func, &depth, + &ml, &decfg, &chkstop); + switch (rc) { + case -1: + if (dev) { AP_DBF_INFO("%s(%d,%d) queue_info() failed, rm queue dev\n", __func__, ac->id, dom); device_unregister(dev); - put_device(dev); } - continue; + fallthrough; + case 0: + goto put_dev_and_continue; + default: + break; } /* if no queue device exists, create a new one */ if (!aq) { @@ -1951,12 +1963,12 @@ put_dev_and_continue: */ static inline void ap_scan_adapter(int ap) { + int rc, dom, depth, type, comp_type, ml; bool decfg, chkstop; - ap_qid_t qid; - unsigned int func; - struct device *dev; struct ap_card *ac; - int rc, dom, depth, type, comp_type, ml; + struct device *dev; + unsigned int func; + ap_qid_t qid; /* Is there currently a card device for this adapter ? */ dev = bus_find_device(&ap_bus_type, NULL, @@ -1986,11 +1998,11 @@ static inline void ap_scan_adapter(int ap) if (ap_test_config_usage_domain(dom)) { qid = AP_MKQID(ap, dom); if (ap_queue_info(qid, &type, &func, &depth, - &ml, &decfg, &chkstop)) + &ml, &decfg, &chkstop) > 0) break; } if (dom > ap_max_domain_id) { - /* Could not find a valid APQN for this adapter */ + /* Could not find one valid APQN for this adapter */ if (ac) { AP_DBF_INFO("%s(%d) no type info (no APQN found), rm card and queue devs\n", __func__, ap); diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 2be63f2554bd..ed8f813653fe 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -50,6 +50,8 @@ static int ap_queue_enable_irq(struct ap_queue *aq, void *ind) qirqctrl.ir = 1; qirqctrl.isc = AP_ISC; status = ap_aqic(aq->qid, qirqctrl, virt_to_phys(ind)); + if (status.async) + return -EPERM; switch (status.response_code) { case AP_RESPONSE_NORMAL: case AP_RESPONSE_OTHERWISE_CHANGED: @@ -96,6 +98,8 @@ int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen) struct ap_queue_status status; status = __ap_send(qid, psmid, msg, msglen, 0); + if (status.async) + return -EPERM; switch (status.response_code) { case AP_RESPONSE_NORMAL: return 0; @@ -117,6 +121,8 @@ int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t msglen) if (!msg) return -EINVAL; status = ap_dqap(qid, psmid, msg, msglen, NULL, NULL, NULL); + if (status.async) + return -EPERM; switch (status.response_code) { case AP_RESPONSE_NORMAL: return 0; @@ -225,6 +231,8 @@ static enum ap_sm_wait ap_sm_read(struct ap_queue *aq) if (!aq->reply) return AP_SM_WAIT_NONE; status = ap_sm_recv(aq); + if (status.async) + return AP_SM_WAIT_NONE; switch (status.response_code) { case AP_RESPONSE_NORMAL: if (aq->queue_count > 0) { @@ -276,6 +284,8 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq) status = __ap_send(qid, ap_msg->psmid, ap_msg->msg, ap_msg->len, ap_msg->flags & AP_MSG_FLAG_SPECIAL); + if (status.async) + return AP_SM_WAIT_NONE; switch (status.response_code) { case AP_RESPONSE_NORMAL: aq->queue_count = max_t(int, 1, aq->queue_count + 1); @@ -338,6 +348,8 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq) struct ap_queue_status status; status = ap_rapq(aq->qid, aq->rapq_fbit); + if (status.async) + return AP_SM_WAIT_NONE; switch (status.response_code) { case AP_RESPONSE_NORMAL: case AP_RESPONSE_RESET_IN_PROGRESS: |