Skip to content

Commit

Permalink
s390/ap: add error response code field for ap queue devices
Browse files Browse the repository at this point in the history
On AP instruction failures the last response code is now
kept in the struct ap_queue. There is also a new sysfs
attribute showing this field (enabled only on debug kernels).

Also slight rework of the AP_DBF macros to get some more
content into one debug feature message line.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
  • Loading branch information
Harald Freudenberger authored and Vasily Gorbik committed Oct 7, 2020
1 parent 0b641cb commit 2ea2a60
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 26 deletions.
54 changes: 28 additions & 26 deletions drivers/s390/crypto/ap_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static inline int ap_fetch_qci_info(struct ap_config_info *info)
static void __init ap_init_qci_info(void)
{
if (!ap_qci_available()) {
AP_DBF(DBF_INFO, "%s QCI not supported\n", __func__);
AP_DBF_INFO("%s QCI not supported\n", __func__);
return;
}

Expand All @@ -226,18 +226,18 @@ static void __init ap_init_qci_info(void)
ap_qci_info = NULL;
return;
}
AP_DBF(DBF_INFO, "%s successful fetched initial qci info\n", __func__);
AP_DBF_INFO("%s successful fetched initial qci info\n", __func__);

if (ap_qci_info->apxa) {
if (ap_qci_info->Na) {
ap_max_adapter_id = ap_qci_info->Na;
AP_DBF(DBF_INFO, "%s new ap_max_adapter_id is %d\n",
__func__, ap_max_adapter_id);
AP_DBF_INFO("%s new ap_max_adapter_id is %d\n",
__func__, ap_max_adapter_id);
}
if (ap_qci_info->Nd) {
ap_max_domain_id = ap_qci_info->Nd;
AP_DBF(DBF_INFO, "%s new ap_max_domain_id is %d\n",
__func__, ap_max_domain_id);
AP_DBF_INFO("%s new ap_max_domain_id is %d\n",
__func__, ap_max_domain_id);
}
}
}
Expand Down Expand Up @@ -618,8 +618,8 @@ static int __ap_revise_reserved(struct device *dev, void *dummy)
drvres = to_ap_drv(dev->driver)->flags
& AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres) {
AP_DBF(DBF_DEBUG, "reprobing queue=%02x.%04x\n",
card, queue);
AP_DBF_DBG("reprobing queue=%02x.%04x\n",
card, queue);
rc = device_reprobe(dev);
}
}
Expand Down Expand Up @@ -796,7 +796,7 @@ EXPORT_SYMBOL(ap_bus_force_rescan);
*/
void ap_bus_cfg_chg(void)
{
AP_DBF(DBF_INFO, "%s config change, forcing bus rescan\n", __func__);
AP_DBF_DBG("%s config change, forcing bus rescan\n", __func__);

ap_bus_force_rescan();
}
Expand Down Expand Up @@ -947,7 +947,7 @@ static ssize_t ap_domain_store(struct bus_type *bus,
ap_domain_index = domain;
spin_unlock_bh(&ap_domain_lock);

AP_DBF(DBF_INFO, "stored new default domain=%d\n", domain);
AP_DBF_INFO("stored new default domain=%d\n", domain);

return count;
}
Expand Down Expand Up @@ -1208,8 +1208,8 @@ static void ap_select_domain(void)
}
if (dom <= ap_max_domain_id) {
ap_domain_index = dom;
AP_DBF(DBF_DEBUG, "%s new default domain is %d\n",
__func__, ap_domain_index);
AP_DBF_INFO("%s new default domain is %d\n",
__func__, ap_domain_index);
}
out:
spin_unlock_bh(&ap_domain_lock);
Expand All @@ -1225,8 +1225,11 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
int comp_type = 0;

/* < CEX2A is not supported */
if (rawtype < AP_DEVICE_TYPE_CEX2A)
if (rawtype < AP_DEVICE_TYPE_CEX2A) {
AP_DBF_WARN("get_comp_type queue=%02x.%04x unsupported type %d\n",
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
return 0;
}
/* up to CEX7 known and fully supported */
if (rawtype <= AP_DEVICE_TYPE_CEX7)
return rawtype;
Expand All @@ -1248,11 +1251,12 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
comp_type = apinfo.cat;
}
if (!comp_type)
AP_DBF(DBF_WARN, "queue=%02x.%04x unable to map type %d\n",
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
AP_DBF_WARN("get_comp_type queue=%02x.%04x unable to map type %d\n",
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
else if (comp_type != rawtype)
AP_DBF(DBF_INFO, "queue=%02x.%04x map type %d to %d\n",
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype, comp_type);
AP_DBF_INFO("get_comp_type queue=%02x.%04x map type %d to %d\n",
AP_QID_CARD(qid), AP_QID_QUEUE(qid),
rawtype, comp_type);
return comp_type;
}

Expand Down Expand Up @@ -1333,11 +1337,11 @@ static void _ap_scan_bus_adapter(int id)
broken = true;
} else if (ac->raw_hwtype != type) {
/* card type has changed */
AP_DBF(DBF_INFO, "card=%02x type changed.\n", id);
AP_DBF_INFO("card=%02x type changed.\n", id);
broken = true;
} else if (ac->functions != func) {
/* card functions have changed */
AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id);
AP_DBF_INFO("card=%02x functions changed.\n", id);
broken = true;
}
if (broken) {
Expand Down Expand Up @@ -1385,9 +1389,8 @@ static void _ap_scan_bus_adapter(int id)
}
if (broken) {
/* Remove broken device */
AP_DBF(DBF_DEBUG,
"removing broken queue=%02x.%04x\n",
id, dom);
AP_DBF_DBG("removing broken queue=%02x.%04x\n",
id, dom);
device_unregister(dev);
}
put_device(dev);
Expand Down Expand Up @@ -1448,7 +1451,7 @@ static void ap_scan_bus(struct work_struct *unused)
ap_fetch_qci_info(ap_qci_info);
ap_select_domain();

AP_DBF(DBF_DEBUG, "%s running\n", __func__);
AP_DBF_DBG("%s running\n", __func__);

/* loop over all possible adapters */
for (id = 0; id < AP_DEVICES; id++)
Expand All @@ -1463,9 +1466,8 @@ static void ap_scan_bus(struct work_struct *unused)
if (dev)
put_device(dev);
else
AP_DBF(DBF_INFO,
"no queue device with default domain %d available\n",
ap_domain_index);
AP_DBF_INFO("no queue device with default domain %d available\n",
ap_domain_index);
}

mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
Expand Down
1 change: 1 addition & 0 deletions drivers/s390/crypto/ap_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ struct ap_queue {
struct list_head requestq; /* List of message yet to be sent. */
struct ap_message *reply; /* Per device reply message. */
enum ap_sm_state sm_state; /* ap queue state machine state */
int last_err_rc; /* last error state response code */
};

#define to_ap_queue(x) container_of((x), struct ap_queue, ap_dev.device)
Expand Down
8 changes: 8 additions & 0 deletions drivers/s390/crypto/ap_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@

#define AP_DBF(...) \
debug_sprintf_event(ap_dbf_info, ##__VA_ARGS__)
#define AP_DBF_ERR(...) \
debug_sprintf_event(ap_dbf_info, DBF_ERR, ##__VA_ARGS__)
#define AP_DBF_WARN(...) \
debug_sprintf_event(ap_dbf_info, DBF_WARN, ##__VA_ARGS__)
#define AP_DBF_INFO(...) \
debug_sprintf_event(ap_dbf_info, DBF_INFO, ##__VA_ARGS__)
#define AP_DBF_DBG(...) \
debug_sprintf_event(ap_dbf_info, DBF_DEBUG, ##__VA_ARGS__)

extern debug_info_t *ap_dbf_info;

Expand Down
64 changes: 64 additions & 0 deletions drivers/s390/crypto/ap_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ static enum ap_sm_wait ap_sm_read(struct ap_queue *aq)
return AP_SM_WAIT_NONE;
default:
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s RC 0x%02hhx on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
}
Expand Down Expand Up @@ -246,6 +250,10 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
return AP_SM_WAIT_AGAIN;
default:
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s RC 0x%02hhx on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
}
Expand Down Expand Up @@ -285,6 +293,10 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
case AP_RESPONSE_CHECKSTOPPED:
default:
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s RC 0x%02hhx on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
}
Expand Down Expand Up @@ -324,6 +336,10 @@ static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq)
case AP_RESPONSE_CHECKSTOPPED:
default:
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s RC 0x%02hhx on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
}
Expand Down Expand Up @@ -361,6 +377,10 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
return AP_SM_WAIT_TIMEOUT;
default:
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s RC 0x%02hhx on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
}
Expand Down Expand Up @@ -605,6 +625,49 @@ static ssize_t states_show(struct device *dev,
return rc;
}
static DEVICE_ATTR_RO(states);

static ssize_t last_err_rc_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ap_queue *aq = to_ap_queue(dev);
int rc;

spin_lock_bh(&aq->lock);
rc = aq->last_err_rc;
spin_unlock_bh(&aq->lock);

switch (rc) {
case AP_RESPONSE_NORMAL:
return scnprintf(buf, PAGE_SIZE, "NORMAL\n");
case AP_RESPONSE_Q_NOT_AVAIL:
return scnprintf(buf, PAGE_SIZE, "Q_NOT_AVAIL\n");
case AP_RESPONSE_RESET_IN_PROGRESS:
return scnprintf(buf, PAGE_SIZE, "RESET_IN_PROGRESS\n");
case AP_RESPONSE_DECONFIGURED:
return scnprintf(buf, PAGE_SIZE, "DECONFIGURED\n");
case AP_RESPONSE_CHECKSTOPPED:
return scnprintf(buf, PAGE_SIZE, "CHECKSTOPPED\n");
case AP_RESPONSE_BUSY:
return scnprintf(buf, PAGE_SIZE, "BUSY\n");
case AP_RESPONSE_INVALID_ADDRESS:
return scnprintf(buf, PAGE_SIZE, "INVALID_ADDRESS\n");
case AP_RESPONSE_OTHERWISE_CHANGED:
return scnprintf(buf, PAGE_SIZE, "OTHERWISE_CHANGED\n");
case AP_RESPONSE_Q_FULL:
return scnprintf(buf, PAGE_SIZE, "Q_FULL/NO_PENDING_REPLY\n");
case AP_RESPONSE_INDEX_TOO_BIG:
return scnprintf(buf, PAGE_SIZE, "INDEX_TOO_BIG\n");
case AP_RESPONSE_NO_FIRST_PART:
return scnprintf(buf, PAGE_SIZE, "NO_FIRST_PART\n");
case AP_RESPONSE_MESSAGE_TOO_BIG:
return scnprintf(buf, PAGE_SIZE, "MESSAGE_TOO_BIG\n");
case AP_RESPONSE_REQ_FAC_NOT_INST:
return scnprintf(buf, PAGE_SIZE, "REQ_FAC_NOT_INST\n");
default:
return scnprintf(buf, PAGE_SIZE, "response code %d\n", rc);
}
}
static DEVICE_ATTR_RO(last_err_rc);
#endif

static struct attribute *ap_queue_dev_attrs[] = {
Expand All @@ -615,6 +678,7 @@ static struct attribute *ap_queue_dev_attrs[] = {
&dev_attr_interrupt.attr,
#ifdef CONFIG_ZCRYPT_DEBUG
&dev_attr_states.attr,
&dev_attr_last_err_rc.attr,
#endif
NULL
};
Expand Down

0 comments on commit 2ea2a60

Please sign in to comment.