summaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
commit01a69402cf9d38ff180345d55c2ee51c7e89fbc7 (patch)
treeb406c5242a088c4f59c6e4b719b783f43aca6ae9 /drivers/s390/crypto
parentAdding upstream version 6.7.12. (diff)
downloadlinux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.tar.xz
linux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.zip
Adding upstream version 6.8.9.upstream/6.8.9
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r--drivers/s390/crypto/ap_bus.c72
-rw-r--r--drivers/s390/crypto/ap_bus.h22
-rw-r--r--drivers/s390/crypto/ap_card.c18
-rw-r--r--drivers/s390/crypto/ap_queue.c200
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c13
-rw-r--r--drivers/s390/crypto/zcrypt_api.c16
-rw-r--r--drivers/s390/crypto/zcrypt_cex4.c31
7 files changed, 212 insertions, 160 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5dd33155d5..f46dd6abac 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -357,13 +357,12 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
* -1 invalid APQN, TAPQ error or AP queue status which
* indicates there is no APQN.
*/
-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)
+static int ap_queue_info(ap_qid_t qid, struct ap_tapq_hwinfo *hwinfo,
+ bool *decfg, bool *cstop)
{
struct ap_queue_status status;
- struct ap_tapq_gr2 tapq_info;
- tapq_info.value = 0;
+ hwinfo->value = 0;
/* make sure we don't run into a specifiation exception */
if (AP_QID_CARD(qid) > ap_max_adapter_id ||
@@ -371,7 +370,7 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
return -1;
/* call TAPQ on this APQN */
- status = ap_test_queue(qid, ap_apft_available(), &tapq_info);
+ status = ap_test_queue(qid, ap_apft_available(), hwinfo);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
@@ -389,15 +388,11 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
}
/* There should be at least one of the mode bits set */
- if (WARN_ON_ONCE(!tapq_info.value))
+ if (WARN_ON_ONCE(!hwinfo->value))
return 0;
- *q_type = tapq_info.at;
- *q_fac = tapq_info.fac;
- *q_depth = tapq_info.qd;
- *q_ml = tapq_info.ml;
- *q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
- *q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;
+ *decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
+ *cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;
return 1;
}
@@ -642,11 +637,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
return rc;
/* Add MODE=<accel|cca|ep11> */
- if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL))
+ if (ac->hwinfo.accel)
rc = add_uevent_var(env, "MODE=accel");
- else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+ else if (ac->hwinfo.cca)
rc = add_uevent_var(env, "MODE=cca");
- else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+ else if (ac->hwinfo.ep11)
rc = add_uevent_var(env, "MODE=ep11");
if (rc)
return rc;
@@ -654,11 +649,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
struct ap_queue *aq = to_ap_queue(&ap_dev->device);
/* Add MODE=<accel|cca|ep11> */
- if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL))
+ if (aq->card->hwinfo.accel)
rc = add_uevent_var(env, "MODE=accel");
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+ else if (aq->card->hwinfo.cca)
rc = add_uevent_var(env, "MODE=cca");
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+ else if (aq->card->hwinfo.ep11)
rc = add_uevent_var(env, "MODE=ep11");
if (rc)
return rc;
@@ -1799,12 +1794,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;
+ struct ap_tapq_hwinfo hwinfo;
bool decfg, chkstop;
struct ap_queue *aq;
struct device *dev;
- unsigned int func;
ap_qid_t qid;
+ int rc, dom;
/*
* Go through the configuration for the domains and compare them
@@ -1827,8 +1822,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
goto put_dev_and_continue;
}
/* domain is valid, get info from this APQN */
- rc = ap_queue_info(qid, &type, &func, &depth,
- &ml, &decfg, &chkstop);
+ rc = ap_queue_info(qid, &hwinfo, &decfg, &chkstop);
switch (rc) {
case -1:
if (dev) {
@@ -1853,6 +1847,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
aq->card = ac;
aq->config = !decfg;
aq->chkstop = chkstop;
+ aq->se_bstate = hwinfo.bs;
dev = &aq->ap_dev.device;
dev->bus = &ap_bus_type;
dev->parent = &ac->ap_dev.device;
@@ -1882,6 +1877,8 @@ static inline void ap_scan_domains(struct ap_card *ac)
}
/* handle state changes on already existing queue device */
spin_lock_bh(&aq->lock);
+ /* SE bind state */
+ aq->se_bstate = hwinfo.bs;
/* checkstop state */
if (chkstop && !aq->chkstop) {
/* checkstop on */
@@ -1955,11 +1952,11 @@ put_dev_and_continue:
*/
static inline void ap_scan_adapter(int ap)
{
- int rc, dom, depth, type, comp_type, ml;
+ struct ap_tapq_hwinfo hwinfo;
+ int rc, dom, comp_type;
bool decfg, chkstop;
struct ap_card *ac;
struct device *dev;
- unsigned int func;
ap_qid_t qid;
/* Is there currently a card device for this adapter ? */
@@ -1989,8 +1986,7 @@ 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, &chkstop) > 0)
+ if (ap_queue_info(qid, &hwinfo, &decfg, &chkstop) > 0)
break;
}
if (dom > ap_max_domain_id) {
@@ -2006,7 +2002,7 @@ static inline void ap_scan_adapter(int ap)
}
return;
}
- if (!type) {
+ if (!hwinfo.at) {
/* No apdater type info available, an unusable adapter */
if (ac) {
AP_DBF_INFO("%s(%d) no valid type (0) info, rm card and queue devs\n",
@@ -2019,18 +2015,18 @@ static inline void ap_scan_adapter(int ap)
}
return;
}
+ hwinfo.value &= TAPQ_CARD_HWINFO_MASK; /* filter card specific hwinfo */
if (ac) {
/* Check APQN against existing card device for changes */
- if (ac->raw_hwtype != type) {
+ if (ac->hwinfo.at != hwinfo.at) {
AP_DBF_INFO("%s(%d) hwtype %d changed, rm card and queue devs\n",
- __func__, ap, type);
+ __func__, ap, hwinfo.at);
ap_scan_rm_card_dev_and_queue_devs(ac);
put_device(dev);
ac = NULL;
- } else if ((ac->functions & TAPQ_CARD_FUNC_CMP_MASK) !=
- (func & TAPQ_CARD_FUNC_CMP_MASK)) {
+ } else if (ac->hwinfo.fac != hwinfo.fac) {
AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devs\n",
- __func__, ap, func);
+ __func__, ap, hwinfo.fac);
ap_scan_rm_card_dev_and_queue_devs(ac);
put_device(dev);
ac = NULL;
@@ -2064,13 +2060,13 @@ static inline void ap_scan_adapter(int ap)
if (!ac) {
/* Build a new card device */
- comp_type = ap_get_compatible_type(qid, type, func);
+ comp_type = ap_get_compatible_type(qid, hwinfo.at, hwinfo.fac);
if (!comp_type) {
AP_DBF_WARN("%s(%d) type %d, can't get compatibility type\n",
- __func__, ap, type);
+ __func__, ap, hwinfo.at);
return;
}
- ac = ap_card_create(ap, depth, type, comp_type, func, ml);
+ ac = ap_card_create(ap, hwinfo, comp_type);
if (!ac) {
AP_DBF_WARN("%s(%d) ap_card_create() failed\n",
__func__, ap);
@@ -2101,13 +2097,13 @@ static inline void ap_scan_adapter(int ap)
get_device(dev);
if (decfg)
AP_DBF_INFO("%s(%d) new (decfg) card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
else if (chkstop)
AP_DBF_INFO("%s(%d) new (chkstop) card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
else
AP_DBF_INFO("%s(%d) new card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
}
/* Verify the domains and the queue devices for this card */
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index b0771ca084..98814839ef 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -76,16 +76,6 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX8 14
/*
- * Known function facilities
- */
-#define AP_FUNC_MEX4K 1
-#define AP_FUNC_CRT4K 2
-#define AP_FUNC_COPRO 3
-#define AP_FUNC_ACCEL 4
-#define AP_FUNC_EP11 5
-#define AP_FUNC_APXA 6
-
-/*
* AP queue state machine states
*/
enum ap_sm_state {
@@ -182,9 +172,7 @@ struct ap_device {
struct ap_card {
struct ap_device ap_dev;
- int raw_hwtype; /* AP raw hardware type. */
- unsigned int functions; /* TAPQ GR2 upper 32 facility bits */
- int queue_depth; /* AP queue depth.*/
+ struct ap_tapq_hwinfo hwinfo; /* TAPQ GR2 content */
int id; /* AP card number. */
unsigned int maxmsgsize; /* AP msg limit for this card */
bool config; /* configured state */
@@ -192,7 +180,7 @@ struct ap_card {
atomic64_t total_request_count; /* # requests ever for this AP device.*/
};
-#define TAPQ_CARD_FUNC_CMP_MASK 0xFFFF0000
+#define TAPQ_CARD_HWINFO_MASK 0xFEFF0000FFFF0F0FUL
#define ASSOC_IDX_INVALID 0x10000
#define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
@@ -206,7 +194,7 @@ struct ap_queue {
bool config; /* configured state */
bool chkstop; /* checkstop state */
ap_qid_t qid; /* AP queue id. */
- bool se_bound; /* SE bound state */
+ unsigned int se_bstate; /* SE bind state (BS) */
unsigned int assoc_idx; /* SE association index */
int queue_count; /* # messages currently on AP queue. */
int pendingq_count; /* # requests on pendingq list. */
@@ -290,8 +278,8 @@ void ap_queue_remove(struct ap_queue *aq);
void ap_queue_init_state(struct ap_queue *aq);
void _ap_queue_init_state(struct ap_queue *aq);
-struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
- int comp_type, unsigned int functions, int ml);
+struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo info,
+ int comp_type);
#define APMASKSIZE (BITS_TO_LONGS(AP_DEVICES) * sizeof(unsigned long))
#define AQMASKSIZE (BITS_TO_LONGS(AP_DOMAINS) * sizeof(unsigned long))
diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c
index b2bd477659..ce953cbbd5 100644
--- a/drivers/s390/crypto/ap_card.c
+++ b/drivers/s390/crypto/ap_card.c
@@ -34,7 +34,7 @@ static ssize_t raw_hwtype_show(struct device *dev,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "%d\n", ac->raw_hwtype);
+ return sysfs_emit(buf, "%d\n", ac->hwinfo.at);
}
static DEVICE_ATTR_RO(raw_hwtype);
@@ -44,7 +44,7 @@ static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "%d\n", ac->queue_depth);
+ return sysfs_emit(buf, "%d\n", ac->hwinfo.qd);
}
static DEVICE_ATTR_RO(depth);
@@ -54,7 +54,7 @@ static ssize_t ap_functions_show(struct device *dev,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "0x%08X\n", ac->functions);
+ return sysfs_emit(buf, "0x%08X\n", ac->hwinfo.fac);
}
static DEVICE_ATTR_RO(ap_functions);
@@ -229,8 +229,8 @@ static void ap_card_device_release(struct device *dev)
kfree(ac);
}
-struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
- int comp_type, unsigned int functions, int ml)
+struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo hwinfo,
+ int comp_type)
{
struct ap_card *ac;
@@ -240,12 +240,10 @@ struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
ac->ap_dev.device.release = ap_card_device_release;
ac->ap_dev.device.type = &ap_card_type;
ac->ap_dev.device_type = comp_type;
- ac->raw_hwtype = raw_type;
- ac->queue_depth = queue_depth;
- ac->functions = functions;
+ ac->hwinfo = hwinfo;
ac->id = id;
- ac->maxmsgsize = ml > 0 ?
- ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
+ ac->maxmsgsize = hwinfo.ml > 0 ?
+ hwinfo.ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
return ac;
}
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 3934a0cc13..6825954431 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -24,13 +24,12 @@ static void __ap_flush_queue(struct ap_queue *aq);
static inline bool ap_q_supports_bind(struct ap_queue *aq)
{
- return ap_test_bit(&aq->card->functions, AP_FUNC_EP11) ||
- ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL);
+ return aq->card->hwinfo.ep11 || aq->card->hwinfo.accel;
}
static inline bool ap_q_supports_assoc(struct ap_queue *aq)
{
- return ap_test_bit(&aq->card->functions, AP_FUNC_EP11);
+ return aq->card->hwinfo.ep11;
}
static inline bool ap_q_needs_bind(struct ap_queue *aq)
@@ -257,7 +256,7 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
list_move_tail(&ap_msg->list, &aq->pendingq);
aq->requestq_count--;
aq->pendingq_count++;
- if (aq->queue_count < aq->card->queue_depth) {
+ if (aq->queue_count < aq->card->hwinfo.qd) {
aq->sm_state = AP_SM_STATE_WORKING;
return AP_SM_WAIT_AGAIN;
}
@@ -318,7 +317,6 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
case AP_RESPONSE_RESET_IN_PROGRESS:
aq->sm_state = AP_SM_STATE_RESET_WAIT;
aq->rapq_fbit = 0;
- aq->se_bound = false;
return AP_SM_WAIT_LOW_TIMEOUT;
default:
aq->dev_state = AP_DEV_STATE_ERROR;
@@ -339,17 +337,15 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq)
{
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
void *lsi_ptr;
- if (aq->queue_count > 0 && aq->reply)
- /* Try to read a completed message and get the status */
- status = ap_sm_recv(aq);
- else
- /* Get the status with TAPQ */
- status = ap_tapq(aq->qid, NULL);
+ /* Get the status with TAPQ */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
+ aq->se_bstate = hwinfo.bs;
lsi_ptr = ap_airq_ptr();
if (lsi_ptr && ap_queue_enable_irq(aq, lsi_ptr) == 0)
aq->sm_state = AP_SM_STATE_SETIRQ_WAIT;
@@ -421,9 +417,9 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
{
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
/* handle asynchronous error on this queue */
if (status.async && status.response_code) {
aq->dev_state = AP_DEV_STATE_ERROR;
@@ -442,8 +438,11 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
return AP_SM_WAIT_NONE;
}
+ /* update queue's SE bind state */
+ aq->se_bstate = hwinfo.bs;
+
/* check bs bits */
- switch (info.bs) {
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
/* association is through */
aq->sm_state = AP_SM_STATE_IDLE;
@@ -460,7 +459,7 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s bs 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
- __func__, info.bs,
+ __func__, hwinfo.bs,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
@@ -687,9 +686,9 @@ static ssize_t ap_functions_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
@@ -697,7 +696,7 @@ static ssize_t ap_functions_show(struct device *dev,
return -EIO;
}
- return sysfs_emit(buf, "0x%08X\n", info.fac);
+ return sysfs_emit(buf, "0x%08X\n", hwinfo.fac);
}
static DEVICE_ATTR_RO(ap_functions);
@@ -840,19 +839,25 @@ static ssize_t se_bind_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
if (!ap_q_supports_bind(aq))
return sysfs_emit(buf, "-\n");
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return -EIO;
}
- switch (info.bs) {
+
+ /* update queue's SE bind state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ spin_unlock_bh(&aq->lock);
+
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
case AP_BS_Q_USABLE_NO_SECURE_KEY:
return sysfs_emit(buf, "bound\n");
@@ -867,6 +872,7 @@ static ssize_t se_bind_store(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
bool value;
int rc;
@@ -878,39 +884,80 @@ static ssize_t se_bind_store(struct device *dev,
if (rc)
return rc;
- if (value) {
- /* bind, do BAPQ */
- spin_lock_bh(&aq->lock);
- if (aq->sm_state < AP_SM_STATE_IDLE) {
- spin_unlock_bh(&aq->lock);
- return -EBUSY;
- }
- status = ap_bapq(aq->qid);
- spin_unlock_bh(&aq->lock);
- if (!status.response_code) {
- aq->se_bound = true;
- AP_DBF_INFO("%s bapq(0x%02x.%04x) success\n", __func__,
- AP_QID_CARD(aq->qid),
- AP_QID_QUEUE(aq->qid));
- } else {
- AP_DBF_WARN("%s RC 0x%02x on bapq(0x%02x.%04x)\n",
- __func__, status.response_code,
- AP_QID_CARD(aq->qid),
- AP_QID_QUEUE(aq->qid));
- return -EIO;
- }
- } else {
- /* unbind, set F bit arg and trigger RAPQ */
+ if (!value) {
+ /* Unbind. Set F bit arg and trigger RAPQ */
spin_lock_bh(&aq->lock);
__ap_flush_queue(aq);
aq->rapq_fbit = 1;
- aq->assoc_idx = ASSOC_IDX_INVALID;
- aq->sm_state = AP_SM_STATE_RESET_START;
- ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
- spin_unlock_bh(&aq->lock);
+ _ap_queue_init_state(aq);
+ rc = count;
+ goto out;
}
- return count;
+ /* Bind. Check current SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ return -EIO;
+ }
+
+ /* Update BS state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ if (hwinfo.bs != AP_BS_Q_AVAIL_FOR_BINDING) {
+ AP_DBF_WARN("%s bind attempt with bs %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Check SM state */
+ if (aq->sm_state < AP_SM_STATE_IDLE) {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ /* invoke BAPQ */
+ status = ap_bapq(aq->qid);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on bapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+ aq->assoc_idx = ASSOC_IDX_INVALID;
+
+ /* verify SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+ aq->se_bstate = hwinfo.bs;
+ if (!(hwinfo.bs == AP_BS_Q_USABLE ||
+ hwinfo.bs == AP_BS_Q_USABLE_NO_SECURE_KEY)) {
+ AP_DBF_WARN("%s BAPQ success, but bs shows %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+
+ /* SE bind was successful */
+ AP_DBF_INFO("%s bapq(0x%02x.%04x) success\n", __func__,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = count;
+
+out:
+ spin_unlock_bh(&aq->lock);
+ return rc;
}
static DEVICE_ATTR_RW(se_bind);
@@ -920,12 +967,12 @@ static ssize_t se_associate_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
if (!ap_q_supports_assoc(aq))
return sysfs_emit(buf, "-\n");
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
@@ -933,7 +980,12 @@ static ssize_t se_associate_show(struct device *dev,
return -EIO;
}
- switch (info.bs) {
+ /* update queue's SE bind state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ spin_unlock_bh(&aq->lock);
+
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
if (aq->assoc_idx == ASSOC_IDX_INVALID) {
AP_DBF_WARN("%s AP_BS_Q_USABLE but invalid assoc_idx\n", __func__);
@@ -955,6 +1007,7 @@ static ssize_t se_associate_store(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
unsigned int value;
int rc;
@@ -968,18 +1021,28 @@ static ssize_t se_associate_store(struct device *dev,
if (value >= ASSOC_IDX_INVALID)
return -EINVAL;
+ /* check current SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ return -EIO;
+ }
spin_lock_bh(&aq->lock);
-
- /* sm should be in idle state */
- if (aq->sm_state != AP_SM_STATE_IDLE) {
- spin_unlock_bh(&aq->lock);
- return -EBUSY;
+ aq->se_bstate = hwinfo.bs;
+ if (hwinfo.bs != AP_BS_Q_USABLE_NO_SECURE_KEY) {
+ AP_DBF_WARN("%s association attempt with bs %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EINVAL;
+ goto out;
}
- /* already associated or association pending ? */
- if (aq->assoc_idx != ASSOC_IDX_INVALID) {
- spin_unlock_bh(&aq->lock);
- return -EINVAL;
+ /* check SM state */
+ if (aq->sm_state != AP_SM_STATE_IDLE) {
+ rc = -EBUSY;
+ goto out;
}
/* trigger the asynchronous association request */
@@ -990,17 +1053,20 @@ static ssize_t se_associate_store(struct device *dev,
aq->sm_state = AP_SM_STATE_ASSOC_WAIT;
aq->assoc_idx = value;
ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
- spin_unlock_bh(&aq->lock);
break;
default:
- spin_unlock_bh(&aq->lock);
AP_DBF_WARN("%s RC 0x%02x on aapq(0x%02x.%04x)\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
- return -EIO;
+ rc = -EIO;
+ goto out;
}
- return count;
+ rc = count;
+
+out:
+ spin_unlock_bh(&aq->lock);
+ return rc;
}
static DEVICE_ATTR_RW(se_associate);
@@ -1123,7 +1189,9 @@ bool ap_queue_usable(struct ap_queue *aq)
}
/* SE guest's queues additionally need to be bound */
- if (ap_q_needs_bind(aq) && !aq->se_bound)
+ if (ap_q_needs_bind(aq) &&
+ !(aq->se_bstate == AP_BS_Q_USABLE ||
+ aq->se_bstate == AP_BS_Q_USABLE_NO_SECURE_KEY))
rc = false;
unlock_and_out:
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 76429585c1..983b3b1619 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -394,8 +394,8 @@ static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
* Register the guest ISC to GIB interface and retrieve the
* host ISC to issue the host side PQAP/AQIC
*
- * Response.status may be set to AP_RESPONSE_INVALID_ADDRESS in case the
- * vfio_pin_pages failed.
+ * status.response_code may be set to AP_RESPONSE_INVALID_ADDRESS in case the
+ * vfio_pin_pages or kvm_s390_gisc_register failed.
*
* Otherwise return the ap_queue_status returned by the ap_aqic(),
* all retry handling will be done by the guest.
@@ -459,7 +459,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
__func__, nisc, isc, q->apqn);
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
- status.response_code = AP_RESPONSE_INVALID_GISA;
+ status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
}
@@ -477,8 +477,11 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
break;
case AP_RESPONSE_OTHERWISE_CHANGED:
/* We could not modify IRQ settings: clear new configuration */
+ ret = kvm_s390_gisc_unregister(kvm, isc);
+ if (ret)
+ VFIO_AP_DBF_WARN("%s: kvm_s390_gisc_unregister: rc=%d isc=%d, apqn=%#04x\n",
+ __func__, ret, isc, q->apqn);
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
- kvm_s390_gisc_unregister(kvm, isc);
break;
default:
pr_warn("%s: apqn %04x: response: %02x\n", __func__, q->apqn,
@@ -2407,7 +2410,7 @@ static void vfio_ap_filter_apid_by_qtype(unsigned long *apm, unsigned long *aqm)
bool apid_cleared;
struct ap_queue_status status;
unsigned long apid, apqi;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo info;
for_each_set_bit_inv(apid, apm, AP_DEVICES) {
apid_cleared = false;
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 973aa93753..53ddae5ad8 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -675,7 +675,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x18000000))
+ !(zc->card->hwinfo.accel || zc->card->hwinfo.cca))
continue;
/* Check for size limits */
if (zc->min_mod_size > mex->inputdatalength ||
@@ -780,7 +780,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x18000000))
+ !(zc->card->hwinfo.accel || zc->card->hwinfo.cca))
continue;
/* Check for size limits */
if (zc->min_mod_size > crt->inputdatalength ||
@@ -895,7 +895,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x10000000))
+ !zc->card->hwinfo.cca)
continue;
/* Check for user selected CCA card */
if (xcrb->user_defined != AUTOSELECT &&
@@ -1066,7 +1066,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable EP11 card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x04000000))
+ !zc->card->hwinfo.ep11)
continue;
/* Check for user selected EP11 card */
if (targets &&
@@ -1179,7 +1179,7 @@ static long zcrypt_rng(char *buffer)
for_each_zcrypt_card(zc) {
/* Check for usable CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x10000000))
+ !zc->card->hwinfo.cca)
continue;
/* get weight index of the card device */
wgt = zc->speed_rating[func_code];
@@ -1240,7 +1240,7 @@ static void zcrypt_device_status_mask(struct zcrypt_device_status *devstatus)
queue = AP_QID_QUEUE(zq->queue->qid);
stat = &devstatus[card * AP_DOMAINS + queue];
stat->hwtype = zc->card->ap_dev.device_type;
- stat->functions = zc->card->functions >> 26;
+ stat->functions = zc->card->hwinfo.fac >> 26;
stat->qid = zq->queue->qid;
stat->online = zq->online ? 0x01 : 0x00;
}
@@ -1265,7 +1265,7 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus)
queue = AP_QID_QUEUE(zq->queue->qid);
stat = &devstatus[card * AP_DOMAINS + queue];
stat->hwtype = zc->card->ap_dev.device_type;
- stat->functions = zc->card->functions >> 26;
+ stat->functions = zc->card->hwinfo.fac >> 26;
stat->qid = zq->queue->qid;
stat->online = zq->online ? 0x01 : 0x00;
}
@@ -1288,7 +1288,7 @@ int zcrypt_device_status_ext(int card, int queue,
if (card == AP_QID_CARD(zq->queue->qid) &&
queue == AP_QID_QUEUE(zq->queue->qid)) {
devstat->hwtype = zc->card->ap_dev.device_type;
- devstat->functions = zc->card->functions >> 26;
+ devstat->functions = zc->card->hwinfo.fac >> 26;
devstat->qid = zq->queue->qid;
devstat->online = zq->online ? 0x01 : 0x00;
spin_unlock(&zcrypt_list_lock);
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
index 5c4532ab00..64df7d2f62 100644
--- a/drivers/s390/crypto/zcrypt_cex4.c
+++ b/drivers/s390/crypto/zcrypt_cex4.c
@@ -477,7 +477,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
return -ENOMEM;
zc->card = ac;
dev_set_drvdata(&ap_dev->device, zc);
- if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) {
+ if (ac->hwinfo.accel) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4A";
zc->user_space_type = ZCRYPT_CEX4;
@@ -506,8 +506,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->user_space_type = ZCRYPT_CEX6;
}
zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
- if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
- ap_test_bit(&ac->functions, AP_FUNC_CRT4K)) {
+ if (ac->hwinfo.mex4k && ac->hwinfo.crt4k) {
zc->max_mod_size = CEX4A_MAX_MOD_SIZE_4K;
zc->max_exp_bit_length =
CEX4A_MAX_MOD_SIZE_4K;
@@ -516,7 +515,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->max_exp_bit_length =
CEX4A_MAX_MOD_SIZE_2K;
}
- } else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
+ } else if (ac->hwinfo.cca) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4C";
zc->speed_rating = CEX4C_SPEED_IDX;
@@ -556,7 +555,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
- } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
+ } else if (ac->hwinfo.ep11) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4P";
zc->user_space_type = ZCRYPT_CEX4;
@@ -599,14 +598,14 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
return rc;
}
- if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
+ if (ac->hwinfo.cca) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&cca_card_attr_grp);
if (rc) {
zcrypt_card_unregister(zc);
zcrypt_card_free(zc);
}
- } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
+ } else if (ac->hwinfo.ep11) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&ep11_card_attr_grp);
if (rc) {
@@ -627,9 +626,9 @@ static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
struct zcrypt_card *zc = dev_get_drvdata(&ap_dev->device);
struct ap_card *ac = to_ap_card(&ap_dev->device);
- if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+ if (ac->hwinfo.cca)
sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp);
- else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+ else if (ac->hwinfo.ep11)
sysfs_remove_group(&ap_dev->device.kobj, &ep11_card_attr_grp);
zcrypt_card_unregister(zc);
@@ -654,19 +653,19 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
struct zcrypt_queue *zq;
int rc;
- if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) {
+ if (aq->card->hwinfo.accel) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
MSGTYPE50_VARIANT_DEFAULT);
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
+ } else if (aq->card->hwinfo.cca) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
MSGTYPE06_VARIANT_DEFAULT);
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
+ } else if (aq->card->hwinfo.ep11) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
@@ -689,14 +688,14 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
return rc;
}
- if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
+ if (aq->card->hwinfo.cca) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&cca_queue_attr_grp);
if (rc) {
zcrypt_queue_unregister(zq);
zcrypt_queue_free(zq);
}
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
+ } else if (aq->card->hwinfo.ep11) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&ep11_queue_attr_grp);
if (rc) {
@@ -717,9 +716,9 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
struct zcrypt_queue *zq = dev_get_drvdata(&ap_dev->device);
struct ap_queue *aq = to_ap_queue(&ap_dev->device);
- if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+ if (aq->card->hwinfo.cca)
sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp);
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+ else if (aq->card->hwinfo.ep11)
sysfs_remove_group(&ap_dev->device.kobj, &ep11_queue_attr_grp);
zcrypt_queue_unregister(zq);