Merge tag 's390-6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-block.git] / drivers / s390 / crypto / ap_bus.c
index 5a99e0b1828975c06a76fae93facaabe20c35ba4..8d6b9a52bf3cbd1a711ab75df24e032acaeb8385 100644 (file)
@@ -122,7 +122,13 @@ static struct hrtimer ap_poll_timer;
  * In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
  * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.
  */
-static unsigned long long poll_timeout = 250000;
+static unsigned long poll_high_timeout = 250000UL;
+
+/*
+ * Some state machine states only require a low frequency polling.
+ * We use 25 Hz frequency for these.
+ */
+static unsigned long poll_low_timeout = 40000000UL;
 
 /* Maximum domain id, if not given via qci */
 static int ap_max_domain_id = 15;
@@ -200,6 +206,18 @@ static inline int ap_qact_available(void)
        return 0;
 }
 
+/*
+ * ap_sb_available(): Test if the AP secure binding facility is available.
+ *
+ * Returns 1 if secure binding facility is available.
+ */
+int ap_sb_available(void)
+{
+       if (ap_qci_info)
+               return ap_qci_info->apsb;
+       return 0;
+}
+
 /*
  * ap_fetch_qci_info(): Fetch cryptographic config info
  *
@@ -248,13 +266,13 @@ static void __init ap_init_qci_info(void)
        AP_DBF_INFO("%s successful fetched initial qci info\n", __func__);
 
        if (ap_qci_info->apxa) {
-               if (ap_qci_info->Na) {
-                       ap_max_adapter_id = ap_qci_info->Na;
+               if (ap_qci_info->na) {
+                       ap_max_adapter_id = ap_qci_info->na;
                        AP_DBF_INFO("%s new ap_max_adapter_id is %d\n",
                                    __func__, ap_max_adapter_id);
                }
-               if (ap_qci_info->Nd) {
-                       ap_max_domain_id = ap_qci_info->Nd;
+               if (ap_qci_info->nd) {
+                       ap_max_domain_id = ap_qci_info->nd;
                        AP_DBF_INFO("%s new ap_max_domain_id is %d\n",
                                    __func__, ap_max_domain_id);
                }
@@ -324,35 +342,32 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
 
 /*
  * ap_queue_info(): Check and get AP queue info.
- * Returns true if TAPQ succeeded and the info is filled or
- * false otherwise.
+ * Returns: 1 if APQN exists and info is filled,
+ *         0 if APQN seems to exit but there is no info
+ *           available (eg. caused by an asynch pending error)
+ *        -1 invalid APQN, TAPQ error or AP queue status which
+ *           indicates there is no APQN.
  */
-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, bool *q_cstop)
+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)
 {
        struct ap_queue_status status;
-       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;
+       struct ap_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 ||
            AP_QID_QUEUE(qid) > ap_max_domain_id)
-               return false;
+               return -1;
 
        /* call TAPQ on this APQN */
-       status = ap_test_queue(qid, ap_apft_available(), &tapq_info.value);
+       status = ap_test_queue(qid, ap_apft_available(), &tapq_info);
+
+       /* handle pending async error with return 'no info available' */
+       if (status.async)
+               return 0;
+
        switch (status.response_code) {
        case AP_RESPONSE_NORMAL:
        case AP_RESPONSE_RESET_IN_PROGRESS:
@@ -365,11 +380,11 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
                 * there is at least one of the mode bits set.
                 */
                if (WARN_ON_ONCE(!tapq_info.value))
-                       return false;
-               *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;
+                       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;
                switch (*q_type) {
@@ -389,12 +404,12 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
                default:
                        break;
                }
-               return true;
+               return 1;
        default:
                /*
                 * A response code which indicates, there is no info available.
                 */
-               return false;
+               return -1;
        }
 }
 
@@ -412,10 +427,13 @@ void ap_wait(enum ap_sm_wait wait)
                        break;
                }
                fallthrough;
-       case AP_SM_WAIT_TIMEOUT:
+       case AP_SM_WAIT_LOW_TIMEOUT:
+       case AP_SM_WAIT_HIGH_TIMEOUT:
                spin_lock_bh(&ap_poll_timer_lock);
                if (!hrtimer_is_queued(&ap_poll_timer)) {
-                       hr_time = poll_timeout;
+                       hr_time =
+                               wait == AP_SM_WAIT_LOW_TIMEOUT ?
+                               poll_low_timeout : poll_high_timeout;
                        hrtimer_forward_now(&ap_poll_timer, hr_time);
                        hrtimer_restart(&ap_poll_timer);
                }
@@ -1168,7 +1186,7 @@ EXPORT_SYMBOL(ap_parse_mask_str);
 
 static ssize_t ap_domain_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
+       return sysfs_emit(buf, "%d\n", ap_domain_index);
 }
 
 static ssize_t ap_domain_store(const struct bus_type *bus,
@@ -1196,14 +1214,13 @@ static BUS_ATTR_RW(ap_domain);
 static ssize_t ap_control_domain_mask_show(const struct bus_type *bus, char *buf)
 {
        if (!ap_qci_info)       /* QCI not supported */
-               return scnprintf(buf, PAGE_SIZE, "not supported\n");
+               return sysfs_emit(buf, "not supported\n");
 
-       return scnprintf(buf, PAGE_SIZE,
-                        "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-                        ap_qci_info->adm[0], ap_qci_info->adm[1],
-                        ap_qci_info->adm[2], ap_qci_info->adm[3],
-                        ap_qci_info->adm[4], ap_qci_info->adm[5],
-                        ap_qci_info->adm[6], ap_qci_info->adm[7]);
+       return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+                         ap_qci_info->adm[0], ap_qci_info->adm[1],
+                         ap_qci_info->adm[2], ap_qci_info->adm[3],
+                         ap_qci_info->adm[4], ap_qci_info->adm[5],
+                         ap_qci_info->adm[6], ap_qci_info->adm[7]);
 }
 
 static BUS_ATTR_RO(ap_control_domain_mask);
@@ -1211,14 +1228,13 @@ static BUS_ATTR_RO(ap_control_domain_mask);
 static ssize_t ap_usage_domain_mask_show(const struct bus_type *bus, char *buf)
 {
        if (!ap_qci_info)       /* QCI not supported */
-               return scnprintf(buf, PAGE_SIZE, "not supported\n");
+               return sysfs_emit(buf, "not supported\n");
 
-       return scnprintf(buf, PAGE_SIZE,
-                        "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-                        ap_qci_info->aqm[0], ap_qci_info->aqm[1],
-                        ap_qci_info->aqm[2], ap_qci_info->aqm[3],
-                        ap_qci_info->aqm[4], ap_qci_info->aqm[5],
-                        ap_qci_info->aqm[6], ap_qci_info->aqm[7]);
+       return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+                         ap_qci_info->aqm[0], ap_qci_info->aqm[1],
+                         ap_qci_info->aqm[2], ap_qci_info->aqm[3],
+                         ap_qci_info->aqm[4], ap_qci_info->aqm[5],
+                         ap_qci_info->aqm[6], ap_qci_info->aqm[7]);
 }
 
 static BUS_ATTR_RO(ap_usage_domain_mask);
@@ -1226,29 +1242,27 @@ static BUS_ATTR_RO(ap_usage_domain_mask);
 static ssize_t ap_adapter_mask_show(const struct bus_type *bus, char *buf)
 {
        if (!ap_qci_info)       /* QCI not supported */
-               return scnprintf(buf, PAGE_SIZE, "not supported\n");
+               return sysfs_emit(buf, "not supported\n");
 
-       return scnprintf(buf, PAGE_SIZE,
-                        "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-                        ap_qci_info->apm[0], ap_qci_info->apm[1],
-                        ap_qci_info->apm[2], ap_qci_info->apm[3],
-                        ap_qci_info->apm[4], ap_qci_info->apm[5],
-                        ap_qci_info->apm[6], ap_qci_info->apm[7]);
+       return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+                         ap_qci_info->apm[0], ap_qci_info->apm[1],
+                         ap_qci_info->apm[2], ap_qci_info->apm[3],
+                         ap_qci_info->apm[4], ap_qci_info->apm[5],
+                         ap_qci_info->apm[6], ap_qci_info->apm[7]);
 }
 
 static BUS_ATTR_RO(ap_adapter_mask);
 
 static ssize_t ap_interrupts_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n",
-                        ap_irq_flag ? 1 : 0);
+       return sysfs_emit(buf, "%d\n", ap_irq_flag ? 1 : 0);
 }
 
 static BUS_ATTR_RO(ap_interrupts);
 
 static ssize_t config_time_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
+       return sysfs_emit(buf, "%d\n", ap_config_time);
 }
 
 static ssize_t config_time_store(const struct bus_type *bus,
@@ -1267,17 +1281,20 @@ static BUS_ATTR_RW(config_time);
 
 static ssize_t poll_thread_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
+       return sysfs_emit(buf, "%d\n", ap_poll_kthread ? 1 : 0);
 }
 
 static ssize_t poll_thread_store(const struct bus_type *bus,
                                 const char *buf, size_t count)
 {
-       int flag, rc;
+       bool value;
+       int rc;
 
-       if (sscanf(buf, "%d\n", &flag) != 1)
-               return -EINVAL;
-       if (flag) {
+       rc = kstrtobool(buf, &value);
+       if (rc)
+               return rc;
+
+       if (value) {
                rc = ap_poll_thread_start();
                if (rc)
                        count = rc;
@@ -1291,21 +1308,25 @@ static BUS_ATTR_RW(poll_thread);
 
 static ssize_t poll_timeout_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
+       return sysfs_emit(buf, "%lu\n", poll_high_timeout);
 }
 
 static ssize_t poll_timeout_store(const struct bus_type *bus, const char *buf,
                                  size_t count)
 {
-       unsigned long long time;
+       unsigned long value;
        ktime_t hr_time;
+       int rc;
+
+       rc = kstrtoul(buf, 0, &value);
+       if (rc)
+               return rc;
 
        /* 120 seconds = maximum poll interval */
-       if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
-           time > 120000000000ULL)
+       if (value > 120000000000UL)
                return -EINVAL;
-       poll_timeout = time;
-       hr_time = poll_timeout;
+       poll_high_timeout = value;
+       hr_time = poll_high_timeout;
 
        spin_lock_bh(&ap_poll_timer_lock);
        hrtimer_cancel(&ap_poll_timer);
@@ -1320,14 +1341,14 @@ static BUS_ATTR_RW(poll_timeout);
 
 static ssize_t ap_max_domain_id_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id);
+       return sysfs_emit(buf, "%d\n", ap_max_domain_id);
 }
 
 static BUS_ATTR_RO(ap_max_domain_id);
 
 static ssize_t ap_max_adapter_id_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_adapter_id);
+       return sysfs_emit(buf, "%d\n", ap_max_adapter_id);
 }
 
 static BUS_ATTR_RO(ap_max_adapter_id);
@@ -1338,10 +1359,9 @@ static ssize_t apmask_show(const struct bus_type *bus, char *buf)
 
        if (mutex_lock_interruptible(&ap_perms_mutex))
                return -ERESTARTSYS;
-       rc = scnprintf(buf, PAGE_SIZE,
-                      "0x%016lx%016lx%016lx%016lx\n",
-                      ap_perms.apm[0], ap_perms.apm[1],
-                      ap_perms.apm[2], ap_perms.apm[3]);
+       rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n",
+                       ap_perms.apm[0], ap_perms.apm[1],
+                       ap_perms.apm[2], ap_perms.apm[3]);
        mutex_unlock(&ap_perms_mutex);
 
        return rc;
@@ -1431,10 +1451,9 @@ static ssize_t aqmask_show(const struct bus_type *bus, char *buf)
 
        if (mutex_lock_interruptible(&ap_perms_mutex))
                return -ERESTARTSYS;
-       rc = scnprintf(buf, PAGE_SIZE,
-                      "0x%016lx%016lx%016lx%016lx\n",
-                      ap_perms.aqm[0], ap_perms.aqm[1],
-                      ap_perms.aqm[2], ap_perms.aqm[3]);
+       rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n",
+                       ap_perms.aqm[0], ap_perms.aqm[1],
+                       ap_perms.aqm[2], ap_perms.aqm[3]);
        mutex_unlock(&ap_perms_mutex);
 
        return rc;
@@ -1520,8 +1539,7 @@ static BUS_ATTR_RW(aqmask);
 
 static ssize_t scans_show(const struct bus_type *bus, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%llu\n",
-                        atomic64_read(&ap_scan_bus_count));
+       return sysfs_emit(buf, "%llu\n", atomic64_read(&ap_scan_bus_count));
 }
 
 static ssize_t scans_store(const struct bus_type *bus, const char *buf,
@@ -1543,15 +1561,40 @@ static ssize_t bindings_show(const struct bus_type *bus, char *buf)
 
        ap_calc_bound_apqns(&apqns, &n);
        if (atomic64_read(&ap_scan_bus_count) >= 1 && n == apqns)
-               rc = scnprintf(buf, PAGE_SIZE, "%u/%u (complete)\n", n, apqns);
+               rc = sysfs_emit(buf, "%u/%u (complete)\n", n, apqns);
        else
-               rc = scnprintf(buf, PAGE_SIZE, "%u/%u\n", n, apqns);
+               rc = sysfs_emit(buf, "%u/%u\n", n, apqns);
 
        return rc;
 }
 
 static BUS_ATTR_RO(bindings);
 
+static ssize_t features_show(const struct bus_type *bus, char *buf)
+{
+       int n = 0;
+
+       if (!ap_qci_info)       /* QCI not supported */
+               return sysfs_emit(buf, "-\n");
+
+       if (ap_qci_info->apsc)
+               n += sysfs_emit_at(buf, n, "APSC ");
+       if (ap_qci_info->apxa)
+               n += sysfs_emit_at(buf, n, "APXA ");
+       if (ap_qci_info->qact)
+               n += sysfs_emit_at(buf, n, "QACT ");
+       if (ap_qci_info->rc8a)
+               n += sysfs_emit_at(buf, n, "RC8A ");
+       if (ap_qci_info->apsb)
+               n += sysfs_emit_at(buf, n, "APSB ");
+
+       sysfs_emit_at(buf, n == 0 ? 0 : n - 1, "\n");
+
+       return n;
+}
+
+static BUS_ATTR_RO(features);
+
 static struct attribute *ap_bus_attrs[] = {
        &bus_attr_ap_domain.attr,
        &bus_attr_ap_control_domain_mask.attr,
@@ -1567,6 +1610,7 @@ static struct attribute *ap_bus_attrs[] = {
        &bus_attr_aqmask.attr,
        &bus_attr_scans.attr,
        &bus_attr_bindings.attr,
+       &bus_attr_features.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(ap_bus);
@@ -1762,12 +1806,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;
        bool decfg, chkstop;
-       ap_qid_t qid;
-       unsigned int func;
-       struct device *dev;
        struct ap_queue *aq;
-       int rc, dom, depth, type, ml;
+       struct device *dev;
+       unsigned int func;
+       ap_qid_t qid;
 
        /*
         * Go through the configuration for the domains and compare them
@@ -1786,20 +1830,24 @@ static inline void ap_scan_domains(struct ap_card *ac)
                                AP_DBF_INFO("%s(%d,%d) not in config anymore, rm queue dev\n",
                                            __func__, ac->id, dom);
                                device_unregister(dev);
-                               put_device(dev);
                        }
-                       continue;
+                       goto put_dev_and_continue;
                }
                /* domain is valid, get info from this APQN */
-               if (!ap_queue_info(qid, &type, &func, &depth,
-                                  &ml, &decfg, &chkstop)) {
-                       if (aq) {
+               rc = ap_queue_info(qid, &type, &func, &depth,
+                                  &ml, &decfg, &chkstop);
+               switch (rc) {
+               case -1:
+                       if (dev) {
                                AP_DBF_INFO("%s(%d,%d) queue_info() failed, rm queue dev\n",
                                            __func__, ac->id, dom);
                                device_unregister(dev);
-                               put_device(dev);
                        }
-                       continue;
+                       fallthrough;
+               case 0:
+                       goto put_dev_and_continue;
+               default:
+                       break;
                }
                /* if no queue device exists, create a new one */
                if (!aq) {
@@ -1915,12 +1963,12 @@ put_dev_and_continue:
  */
 static inline void ap_scan_adapter(int ap)
 {
+       int rc, dom, depth, type, comp_type, ml;
        bool decfg, chkstop;
-       ap_qid_t qid;
-       unsigned int func;
-       struct device *dev;
        struct ap_card *ac;
-       int rc, dom, depth, type, comp_type, ml;
+       struct device *dev;
+       unsigned int func;
+       ap_qid_t qid;
 
        /* Is there currently a card device for this adapter ? */
        dev = bus_find_device(&ap_bus_type, NULL,
@@ -1950,11 +1998,11 @@ static inline void ap_scan_adapter(int ap)
                if (ap_test_config_usage_domain(dom)) {
                        qid = AP_MKQID(ap, dom);
                        if (ap_queue_info(qid, &type, &func, &depth,
-                                         &ml, &decfg, &chkstop))
+                                         &ml, &decfg, &chkstop) > 0)
                                break;
                }
        if (dom > ap_max_domain_id) {
-               /* Could not find a valid APQN for this adapter */
+               /* Could not find one valid APQN for this adapter */
                if (ac) {
                        AP_DBF_INFO("%s(%d) no type info (no APQN found), rm card and queue devs\n",
                                    __func__, ap);
@@ -1979,7 +2027,6 @@ static inline void ap_scan_adapter(int ap)
                }
                return;
        }
-
        if (ac) {
                /* Check APQN against existing card device for changes */
                if (ac->raw_hwtype != type) {
@@ -1988,9 +2035,10 @@ static inline void ap_scan_adapter(int ap)
                        ap_scan_rm_card_dev_and_queue_devs(ac);
                        put_device(dev);
                        ac = NULL;
-               } else if (ac->functions != func) {
+               } else if ((ac->functions & TAPQ_CARD_FUNC_CMP_MASK) !=
+                          (func & TAPQ_CARD_FUNC_CMP_MASK)) {
                        AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devs\n",
-                                   __func__, ap, type);
+                                   __func__, ap, func);
                        ap_scan_rm_card_dev_and_queue_devs(ac);
                        put_device(dev);
                        ac = NULL;
@@ -2245,7 +2293,7 @@ static int __init ap_module_init(void)
         * If we are running under z/VM adjust polling to z/VM polling rate.
         */
        if (MACHINE_IS_VM)
-               poll_timeout = 1500000;
+               poll_high_timeout = 1500000;
        hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
        ap_poll_timer.function = ap_poll_timeout;