Commit 4f2fcccd authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/ap: add card/queue deconfig state

This patch adds a new config state to the ap card and queue
devices. This state reflects the response code
0x03 "AP deconfigured" on TQAP invocation and is tracked with
every ap bus scan.

Together with this new state now a card/queue device which
is 'deconfigured' is not disposed any more. However, for backward
compatibility the online state now needs to take this state into
account. So a card/queue is offline when the device is not configured.
Furthermore a device can't get switched from offline to online state
when not configured.

The config state is shown in sysfs at
  /sys/devices/ap/cardxx/config
for the card and
  /sys/devices/ap/cardxx/xx.yyyy/config
for each queue within each card.
It is a read-only attribute reflecting the negation of the
'AP deconfig' state as it is noted in the AP documents.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 2ea2a609
This diff is collapsed.
......@@ -166,6 +166,7 @@ struct ap_card {
unsigned int functions; /* AP device function bitfield. */
int queue_depth; /* AP queue depth.*/
int id; /* AP card number. */
bool config; /* configured state */
atomic64_t total_request_count; /* # requests ever for this AP device.*/
};
......@@ -178,6 +179,7 @@ struct ap_queue {
spinlock_t lock; /* Per device lock. */
void *private; /* ap driver private pointer. */
enum ap_dev_state dev_state; /* queue device state */
bool config; /* configured state */
ap_qid_t qid; /* AP queue id. */
int interrupt; /* indicate if interrupts are enabled */
int queue_count; /* # messages currently on AP queue. */
......
......@@ -139,6 +139,16 @@ static ssize_t modalias_show(struct device *dev,
static DEVICE_ATTR_RO(modalias);
static ssize_t config_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->config ? 1 : 0);
}
static DEVICE_ATTR_RO(config);
static struct attribute *ap_card_dev_attrs[] = {
&dev_attr_hwtype.attr,
&dev_attr_raw_hwtype.attr,
......@@ -148,6 +158,7 @@ static struct attribute *ap_card_dev_attrs[] = {
&dev_attr_requestq_count.attr,
&dev_attr_pendingq_count.attr,
&dev_attr_modalias.attr,
&dev_attr_config.attr,
NULL
};
......
......@@ -563,6 +563,20 @@ static ssize_t interrupt_show(struct device *dev,
static DEVICE_ATTR_RO(interrupt);
static ssize_t config_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->config ? 1 : 0);
spin_unlock_bh(&aq->lock);
return rc;
}
static DEVICE_ATTR_RO(config);
#ifdef CONFIG_ZCRYPT_DEBUG
static ssize_t states_show(struct device *dev,
struct device_attribute *attr, char *buf)
......@@ -676,6 +690,7 @@ static struct attribute *ap_queue_dev_attrs[] = {
&dev_attr_pendingq_count.attr,
&dev_attr_reset.attr,
&dev_attr_interrupt.attr,
&dev_attr_config.attr,
#ifdef CONFIG_ZCRYPT_DEBUG
&dev_attr_states.attr,
&dev_attr_last_err_rc.attr,
......
......@@ -663,8 +663,9 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for online accelarator and CCA cards */
if (!zc->online || !(zc->card->functions & 0x18000000))
/* Check for useable accelarator or CCA card */
if (!zc->online || !zc->card->config ||
!(zc->card->functions & 0x18000000))
continue;
/* Check for size limits */
if (zc->min_mod_size > mex->inputdatalength ||
......@@ -682,8 +683,9 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */
if (!zq->online || !zq->ops->rsa_modexpo)
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rsa_modexpo ||
!zq->queue->config)
continue;
/* check if device node has admission for this queue */
if (!zcrypt_check_queue(perms,
......@@ -760,8 +762,9 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for online accelarator and CCA cards */
if (!zc->online || !(zc->card->functions & 0x18000000))
/* Check for useable accelarator or CCA card */
if (!zc->online || !zc->card->config ||
!(zc->card->functions & 0x18000000))
continue;
/* Check for size limits */
if (zc->min_mod_size > crt->inputdatalength ||
......@@ -779,8 +782,9 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */
if (!zq->online || !zq->ops->rsa_modexpo_crt)
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rsa_modexpo_crt ||
!zq->queue->config)
continue;
/* check if device node has admission for this queue */
if (!zcrypt_check_queue(perms,
......@@ -859,8 +863,9 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for online CCA cards */
if (!zc->online || !(zc->card->functions & 0x10000000))
/* Check for useable CCA card */
if (!zc->online || !zc->card->config ||
!(zc->card->functions & 0x10000000))
continue;
/* Check for user selected CCA card */
if (xcRB->user_defined != AUTOSELECT &&
......@@ -878,9 +883,10 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */
/* check for device useable and eligible */
if (!zq->online ||
!zq->ops->send_cprb ||
!zq->queue->config ||
(tdom != AUTOSEL_DOM &&
tdom != AP_QID_QUEUE(zq->queue->qid)))
continue;
......@@ -1012,8 +1018,9 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for online EP11 cards */
if (!zc->online || !(zc->card->functions & 0x04000000))
/* Check for useable EP11 card */
if (!zc->online || !zc->card->config ||
!(zc->card->functions & 0x04000000))
continue;
/* Check for user selected EP11 card */
if (targets &&
......@@ -1031,9 +1038,10 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */
/* check if device is useable and eligible */
if (!zq->online ||
!zq->ops->send_ep11_cprb ||
!zq->queue->config ||
(targets &&
!is_desired_ep11_queue(zq->queue->qid,
target_num, targets)))
......@@ -1110,16 +1118,18 @@ static long zcrypt_rng(char *buffer)
pref_zq = NULL;
spin_lock(&zcrypt_list_lock);
for_each_zcrypt_card(zc) {
/* Check for online CCA cards */
if (!zc->online || !(zc->card->functions & 0x10000000))
/* Check for useable CCA card */
if (!zc->online || !zc->card->config ||
!(zc->card->functions & 0x10000000))
continue;
/* get weight index of the card device */
wgt = zc->speed_rating[func_code];
if (!zcrypt_card_compare(zc, pref_zc, wgt, pref_wgt))
continue;
for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */
if (!zq->online || !zq->ops->rng)
/* check if device is useable and eligible */
if (!zq->online || !zq->ops->rng ||
!zq->queue->config)
continue;
if (!zcrypt_queue_compare(zq, pref_zq, wgt, pref_wgt))
continue;
......
......@@ -50,22 +50,28 @@ static ssize_t online_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zcrypt_card *zc = to_ap_card(dev)->private;
struct ap_card *ac = to_ap_card(dev);
struct zcrypt_card *zc = ac->private;
int online = ac->config && zc->online ? 1 : 0;
return scnprintf(buf, PAGE_SIZE, "%d\n", zc->online);
return scnprintf(buf, PAGE_SIZE, "%d\n", online);
}
static ssize_t online_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct zcrypt_card *zc = to_ap_card(dev)->private;
struct ap_card *ac = to_ap_card(dev);
struct zcrypt_card *zc = ac->private;
struct zcrypt_queue *zq;
int online, id;
if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
return -EINVAL;
if (online && !ac->config)
return -ENODEV;
zc->online = online;
id = zc->card->id;
......
......@@ -40,22 +40,27 @@ static ssize_t online_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zcrypt_queue *zq = to_ap_queue(dev)->private;
struct ap_queue *aq = to_ap_queue(dev);
struct zcrypt_queue *zq = aq->private;
int online = aq->config && zq->online ? 1 : 0;
return scnprintf(buf, PAGE_SIZE, "%d\n", zq->online);
return scnprintf(buf, PAGE_SIZE, "%d\n", online);
}
static ssize_t online_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct zcrypt_queue *zq = to_ap_queue(dev)->private;
struct ap_queue *aq = to_ap_queue(dev);
struct zcrypt_queue *zq = aq->private;
struct zcrypt_card *zc = zq->zcard;
int online;
if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
return -EINVAL;
if (online && (!aq->config || !aq->card->config))
return -ENODEV;
if (online && !zc->online)
return -EINVAL;
zq->online = online;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment