aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto/ap_bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r--drivers/s390/crypto/ap_bus.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index d2560186d771..8d3a1d84a757 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -61,6 +61,9 @@ static char *aqm_str;
module_param_named(aqmask, aqm_str, charp, 0440);
MODULE_PARM_DESC(aqmask, "AP bus domain mask.");
+atomic_t ap_max_msg_size = ATOMIC_INIT(AP_DEFAULT_MAX_MSG_SIZE);
+EXPORT_SYMBOL(ap_max_msg_size);
+
static struct device *ap_root_device;
/* Hashtable of all queue devices on the AP bus */
@@ -316,11 +319,24 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
* Returns true if TAPQ succeeded and the info is filled or
* false otherwise.
*/
-static bool ap_queue_info(ap_qid_t qid, int *q_type,
- unsigned int *q_fac, int *q_depth, bool *q_decfg)
+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)
{
struct ap_queue_status status;
- unsigned long info = 0;
+ union {
+ unsigned long value;
+ struct {
+ unsigned int fac : 32; /* facility bits */
+ unsigned int at : 8; /* ap type */
+ unsigned int _res1 : 8;
+ unsigned int _res2 : 4;
+ unsigned int ml : 4; /* apxl ml */
+ unsigned int _res3 : 4;
+ unsigned int qd : 4; /* queue depth */
+ } tapq_gr2;
+ } tapq_info;
+
+ tapq_info.value = 0;
/* make sure we don't run into a specifiation exception */
if (AP_QID_CARD(qid) > ap_max_adapter_id ||
@@ -328,7 +344,7 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type,
return false;
/* call TAPQ on this APQN */
- status = ap_test_queue(qid, ap_apft_available(), &info);
+ status = ap_test_queue(qid, ap_apft_available(), &tapq_info.value);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
case AP_RESPONSE_RESET_IN_PROGRESS:
@@ -340,11 +356,12 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type,
* info should be filled. All bits 0 is not possible as
* there is at least one of the mode bits set.
*/
- if (WARN_ON_ONCE(!info))
+ if (WARN_ON_ONCE(!tapq_info.value))
return false;
- *q_type = (int)((info >> 24) & 0xff);
- *q_fac = (unsigned int)(info >> 32);
- *q_depth = (int)(info & 0xff);
+ *q_type = tapq_info.tapq_gr2.at;
+ *q_fac = tapq_info.tapq_gr2.fac;
+ *q_depth = tapq_info.tapq_gr2.qd;
+ *q_ml = tapq_info.tapq_gr2.ml;
*q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
switch (*q_type) {
/* For CEX2 and CEX3 the available functions
@@ -1516,7 +1533,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
unsigned int func;
struct device *dev;
struct ap_queue *aq;
- int rc, dom, depth, type;
+ int rc, dom, depth, type, ml;
/*
* Go through the configuration for the domains and compare them
@@ -1540,7 +1557,7 @@ 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, &decfg)) {
+ if (!ap_queue_info(qid, &type, &func, &depth, &ml, &decfg)) {
if (aq) {
AP_DBF_INFO(
"%s(%d,%d) ap_queue_info() not successful, rm queue device\n",
@@ -1639,7 +1656,7 @@ static inline void ap_scan_adapter(int ap)
unsigned int func;
struct device *dev;
struct ap_card *ac;
- int rc, dom, depth, type, comp_type;
+ int rc, dom, depth, type, comp_type, ml;
/* Is there currently a card device for this adapter ? */
dev = bus_find_device(&ap_bus_type, NULL,
@@ -1668,7 +1685,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, &decfg))
+ if (ap_queue_info(qid, &type, &func,
+ &depth, &ml, &decfg))
break;
}
if (dom > ap_max_domain_id) {
@@ -1737,7 +1755,7 @@ static inline void ap_scan_adapter(int ap)
__func__, ap, type);
return;
}
- ac = ap_card_create(ap, depth, type, comp_type, func);
+ ac = ap_card_create(ap, depth, type, comp_type, func, ml);
if (!ac) {
AP_DBF_WARN("%s(%d) ap_card_create() failed\n",
__func__, ap);
@@ -1748,6 +1766,12 @@ static inline void ap_scan_adapter(int ap)
dev->bus = &ap_bus_type;
dev->parent = ap_root_device;
dev_set_name(dev, "card%02x", ap);
+ /* maybe enlarge ap_max_msg_size to support this card */
+ if (ac->maxmsgsize > atomic_read(&ap_max_msg_size)) {
+ atomic_set(&ap_max_msg_size, ac->maxmsgsize);
+ AP_DBF_INFO("%s(%d) ap_max_msg_size update to %d byte\n",
+ __func__, ap, atomic_read(&ap_max_msg_size));
+ }
/* Register the new card device with AP bus */
rc = device_register(dev);
if (rc) {