Skip to content

Commit

Permalink
s390/zcrypt: handle checkstopped cards with new state
Browse files Browse the repository at this point in the history
A crypto card may be in checkstopped state. With this
patch this is handled as a new state in the ap card and
ap queue structs. There is also a new card sysfs attribute

  /sys/devices/ap/cardxx/chkstop

and a new queue sysfs attribute

  /sys/devices/ap/cardxx/xx.yyyy/chkstop

displaying the checkstop state of the card or queue. Please
note that the queue's checkstop state is only a copy of the
card's checkstop state but makes maintenance much easier.

The checkstop state expressed here is the result of an
RC 0x04 (CHECKSTOP) during an AP command, mostly the
PQAP(TAPQ) command which is 'testing' the queue.

Signed-off-by: Harald Freudenberger <[email protected]>
Reviewed-by: Jürgen Christ <[email protected]>
Signed-off-by: Vasily Gorbik <[email protected]>
  • Loading branch information
hfreude authored and Vasily Gorbik committed Mar 7, 2022
1 parent 985214a commit a7e701d
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 30 deletions.
78 changes: 63 additions & 15 deletions drivers/s390/crypto/ap_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
* false otherwise.
*/
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)
int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop)
{
struct ap_queue_status status;
union {
Expand Down Expand Up @@ -366,6 +366,7 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
*q_depth = tapq_info.tapq_gr2.qd;
*q_ml = tapq_info.tapq_gr2.ml;
*q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
*q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;
switch (*q_type) {
/* For CEX2 and CEX3 the available functions
* are not reflected by the facilities bits.
Expand Down Expand Up @@ -1710,7 +1711,7 @@ 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)
{
bool decfg;
bool decfg, chkstop;
ap_qid_t qid;
unsigned int func;
struct device *dev;
Expand Down Expand Up @@ -1739,7 +1740,8 @@ static inline void ap_scan_domains(struct ap_card *ac)
continue;
}
/* domain is valid, get info from this APQN */
if (!ap_queue_info(qid, &type, &func, &depth, &ml, &decfg)) {
if (!ap_queue_info(qid, &type, &func, &depth,
&ml, &decfg, &chkstop)) {
if (aq) {
AP_DBF_INFO("%s(%d,%d) queue_info() failed, rm queue dev\n",
__func__, ac->id, dom);
Expand All @@ -1758,6 +1760,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
}
aq->card = ac;
aq->config = !decfg;
aq->chkstop = chkstop;
dev = &aq->ap_dev.device;
dev->bus = &ap_bus_type;
dev->parent = &ac->ap_dev.device;
Expand All @@ -1774,13 +1777,43 @@ static inline void ap_scan_domains(struct ap_card *ac)
if (decfg)
AP_DBF_INFO("%s(%d,%d) new (decfg) queue dev created\n",
__func__, ac->id, dom);
else if (chkstop)
AP_DBF_INFO("%s(%d,%d) new (chkstop) queue dev created\n",
__func__, ac->id, dom);
else
AP_DBF_INFO("%s(%d,%d) new queue dev created\n",
__func__, ac->id, dom);
goto put_dev_and_continue;
}
/* Check config state on the already existing queue device */
/* handle state changes on already existing queue device */
spin_lock_bh(&aq->lock);
/* checkstop state */
if (chkstop && !aq->chkstop) {
/* checkstop on */
aq->chkstop = true;
if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = AP_RESPONSE_CHECKSTOPPED;
}
spin_unlock_bh(&aq->lock);
AP_DBF_DBG("%s(%d,%d) queue dev checkstop on\n",
__func__, ac->id, dom);
/* 'receive' pending messages with -EAGAIN */
ap_flush_queue(aq);
goto put_dev_and_continue;
} else if (!chkstop && aq->chkstop) {
/* checkstop off */
aq->chkstop = false;
if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
aq->dev_state = AP_DEV_STATE_OPERATING;
aq->sm_state = AP_SM_STATE_RESET_START;
}
spin_unlock_bh(&aq->lock);
AP_DBF_DBG("%s(%d,%d) queue dev checkstop off\n",
__func__, ac->id, dom);
goto put_dev_and_continue;
}
/* config state change */
if (decfg && aq->config) {
/* config off this queue device */
aq->config = false;
Expand All @@ -1789,23 +1822,22 @@ static inline void ap_scan_domains(struct ap_card *ac)
aq->last_err_rc = AP_RESPONSE_DECONFIGURED;
}
spin_unlock_bh(&aq->lock);
AP_DBF_INFO("%s(%d,%d) queue dev config off\n",
__func__, ac->id, dom);
AP_DBF_DBG("%s(%d,%d) queue dev config off\n",
__func__, ac->id, dom);
ap_send_config_uevent(&aq->ap_dev, aq->config);
/* 'receive' pending messages with -EAGAIN */
ap_flush_queue(aq);
goto put_dev_and_continue;
}
if (!decfg && !aq->config) {
} else if (!decfg && !aq->config) {
/* config on this queue device */
aq->config = true;
if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
aq->dev_state = AP_DEV_STATE_OPERATING;
aq->sm_state = AP_SM_STATE_RESET_START;
}
spin_unlock_bh(&aq->lock);
AP_DBF_INFO("%s(%d,%d) queue dev config on\n",
__func__, ac->id, dom);
AP_DBF_DBG("%s(%d,%d) queue dev config on\n",
__func__, ac->id, dom);
ap_send_config_uevent(&aq->ap_dev, aq->config);
goto put_dev_and_continue;
}
Expand All @@ -1832,7 +1864,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
*/
static inline void ap_scan_adapter(int ap)
{
bool decfg;
bool decfg, chkstop;
ap_qid_t qid;
unsigned int func;
struct device *dev;
Expand Down Expand Up @@ -1866,8 +1898,8 @@ static inline void ap_scan_adapter(int ap)
for (dom = 0; dom <= ap_max_domain_id; dom++)
if (ap_test_config_usage_domain(dom)) {
qid = AP_MKQID(ap, dom);
if (ap_queue_info(qid, &type, &func,
&depth, &ml, &decfg))
if (ap_queue_info(qid, &type, &func, &depth,
&ml, &decfg, &chkstop))
break;
}
if (dom > ap_max_domain_id) {
Expand Down Expand Up @@ -1912,13 +1944,25 @@ static inline void ap_scan_adapter(int ap)
put_device(dev);
ac = NULL;
} else {
/* handle checkstop state change */
if (chkstop && !ac->chkstop) {
/* checkstop on */
ac->chkstop = true;
AP_DBF_INFO("%s(%d) card dev checkstop on\n",
__func__, ap);
} else if (!chkstop && ac->chkstop) {
/* checkstop off */
ac->chkstop = false;
AP_DBF_INFO("%s(%d) card dev checkstop off\n",
__func__, ap);
}
/* handle config state change */
if (decfg && ac->config) {
ac->config = false;
AP_DBF_INFO("%s(%d) card dev config off\n",
__func__, ap);
ap_send_config_uevent(&ac->ap_dev, ac->config);
}
if (!decfg && !ac->config) {
} else if (!decfg && !ac->config) {
ac->config = true;
AP_DBF_INFO("%s(%d) card dev config on\n",
__func__, ap);
Expand All @@ -1942,6 +1986,7 @@ static inline void ap_scan_adapter(int ap)
return;
}
ac->config = !decfg;
ac->chkstop = chkstop;
dev = &ac->ap_dev.device;
dev->bus = &ap_bus_type;
dev->parent = ap_root_device;
Expand All @@ -1966,6 +2011,9 @@ static inline void ap_scan_adapter(int ap)
if (decfg)
AP_DBF_INFO("%s(%d) new (decfg) card dev type=%d func=0x%08x created\n",
__func__, ap, type, func);
else if (chkstop)
AP_DBF_INFO("%s(%d) new (chkstop) card dev type=%d func=0x%08x created\n",
__func__, ap, type, func);
else
AP_DBF_INFO("%s(%d) new card dev type=%d func=0x%08x created\n",
__func__, ap, type, func);
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/crypto/ap_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ struct ap_card {
int id; /* AP card number. */
unsigned int maxmsgsize; /* AP msg limit for this card */
bool config; /* configured state */
bool chkstop; /* checkstop state */
atomic64_t total_request_count; /* # requests ever for this AP device.*/
};

Expand All @@ -191,6 +192,7 @@ struct ap_queue {
spinlock_t lock; /* Per device lock. */
enum ap_dev_state dev_state; /* queue device state */
bool config; /* configured state */
bool chkstop; /* checkstop state */
ap_qid_t qid; /* AP queue id. */
bool interrupt; /* indicate if interrupts are enabled */
int queue_count; /* # messages currently on AP queue. */
Expand Down
11 changes: 11 additions & 0 deletions drivers/s390/crypto/ap_card.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@ static ssize_t config_store(struct device *dev,

static DEVICE_ATTR_RW(config);

static ssize_t chkstop_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ap_card *ac = to_ap_card(dev);

return scnprintf(buf, PAGE_SIZE, "%d\n", ac->chkstop ? 1 : 0);
}

static DEVICE_ATTR_RO(chkstop);

static ssize_t max_msg_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
Expand All @@ -194,6 +204,7 @@ static struct attribute *ap_card_dev_attrs[] = {
&dev_attr_pendingq_count.attr,
&dev_attr_modalias.attr,
&dev_attr_config.attr,
&dev_attr_chkstop.attr,
&dev_attr_max_msg_size.attr,
NULL
};
Expand Down
18 changes: 17 additions & 1 deletion drivers/s390/crypto/ap_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ static ap_func_t *ap_jumptable[NR_AP_SM_STATES][NR_AP_SM_EVENTS] = {

enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event)
{
if (aq->config && aq->dev_state > AP_DEV_STATE_UNINITIATED)
if (aq->config && !aq->chkstop &&
aq->dev_state > AP_DEV_STATE_UNINITIATED)
return ap_jumptable[aq->sm_state][event](aq);
else
return AP_SM_WAIT_NONE;
Expand Down Expand Up @@ -615,6 +616,20 @@ static ssize_t config_show(struct device *dev,

static DEVICE_ATTR_RO(config);

static ssize_t chkstop_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 = scnprintf(buf, PAGE_SIZE, "%d\n", aq->chkstop ? 1 : 0);
spin_unlock_bh(&aq->lock);
return rc;
}

static DEVICE_ATTR_RO(chkstop);

#ifdef CONFIG_ZCRYPT_DEBUG
static ssize_t states_show(struct device *dev,
struct device_attribute *attr, char *buf)
Expand Down Expand Up @@ -729,6 +744,7 @@ static struct attribute *ap_queue_dev_attrs[] = {
&dev_attr_reset.attr,
&dev_attr_interrupt.attr,
&dev_attr_config.attr,
&dev_attr_chkstop.attr,
#ifdef CONFIG_ZCRYPT_DEBUG
&dev_attr_states.attr,
&dev_attr_last_err_rc.attr,
Expand Down
26 changes: 12 additions & 14 deletions drivers/s390/crypto/zcrypt_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for useable accelarator or CCA card */
if (!zc->online || !zc->card->config ||
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x18000000))
continue;
/* Check for size limits */
Expand All @@ -692,7 +692,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
for_each_zcrypt_queue(zq, zc) {
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rsa_modexpo ||
!zq->queue->config)
!zq->queue->config || zq->queue->chkstop)
continue;
/* check if device node has admission for this queue */
if (!zcrypt_check_queue(perms,
Expand Down Expand Up @@ -781,7 +781,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for useable accelarator or CCA card */
if (!zc->online || !zc->card->config ||
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x18000000))
continue;
/* Check for size limits */
Expand All @@ -802,7 +802,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
for_each_zcrypt_queue(zq, zc) {
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rsa_modexpo_crt ||
!zq->queue->config)
!zq->queue->config || zq->queue->chkstop)
continue;
/* check if device node has admission for this queue */
if (!zcrypt_check_queue(perms,
Expand Down Expand Up @@ -895,7 +895,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for useable CCA card */
if (!zc->online || !zc->card->config ||
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x10000000))
continue;
/* Check for user selected CCA card */
Expand All @@ -918,9 +918,8 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
continue;
for_each_zcrypt_queue(zq, zc) {
/* check for device useable and eligible */
if (!zq->online ||
!zq->ops->send_cprb ||
!zq->queue->config ||
if (!zq->online || !zq->ops->send_cprb ||
!zq->queue->config || zq->queue->chkstop ||
(tdom != AUTOSEL_DOM &&
tdom != AP_QID_QUEUE(zq->queue->qid)))
continue;
Expand Down Expand Up @@ -1068,7 +1067,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for useable EP11 card */
if (!zc->online || !zc->card->config ||
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x04000000))
continue;
/* Check for user selected EP11 card */
Expand All @@ -1091,9 +1090,8 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is useable and eligible */
if (!zq->online ||
!zq->ops->send_ep11_cprb ||
!zq->queue->config ||
if (!zq->online || !zq->ops->send_ep11_cprb ||
!zq->queue->config || zq->queue->chkstop ||
(targets &&
!is_desired_ep11_queue(zq->queue->qid,
target_num, targets)))
Expand Down Expand Up @@ -1182,7 +1180,7 @@ static long zcrypt_rng(char *buffer)
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for useable CCA card */
if (!zc->online || !zc->card->config ||
if (!zc->online || !zc->card->config || zc->card->chkstop ||
!(zc->card->functions & 0x10000000))
continue;
/* get weight index of the card device */
Expand All @@ -1192,7 +1190,7 @@ static long zcrypt_rng(char *buffer)
for_each_zcrypt_queue(zq, zc) {
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rng ||
!zq->queue->config)
!zq->queue->config || zq->queue->chkstop)
continue;
if (!zcrypt_queue_compare(zq, pref_zq, wgt, pref_wgt))
continue;
Expand Down

0 comments on commit a7e701d

Please sign in to comment.