diff options
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 50 |
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) { |