Merge tag 'gpio-v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux...
[cascardo/linux.git] / drivers / s390 / cio / chsc.c
index c424c0c..940e725 100644 (file)
@@ -907,7 +907,8 @@ int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
        struct chsc_scpd *scpd_area;
        int ccode, ret;
 
-       if ((rfmt == 1) && !css_general_characteristics.fcs)
+       if ((rfmt == 1 || rfmt == 0) && c == 1 &&
+           !css_general_characteristics.fcs)
                return -EINVAL;
        if ((rfmt == 2) && !css_general_characteristics.cib)
                return -EINVAL;
@@ -939,7 +940,6 @@ EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc);
 int chsc_determine_base_channel_path_desc(struct chp_id chpid,
                                          struct channel_path_desc *desc)
 {
-       struct chsc_response_struct *chsc_resp;
        struct chsc_scpd *scpd_area;
        unsigned long flags;
        int ret;
@@ -949,8 +949,8 @@ int chsc_determine_base_channel_path_desc(struct chp_id chpid,
        ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, scpd_area);
        if (ret)
                goto out;
-       chsc_resp = (void *)&scpd_area->response;
-       memcpy(desc, &chsc_resp->data, sizeof(*desc));
+
+       memcpy(desc, scpd_area->data, sizeof(*desc));
 out:
        spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
@@ -959,18 +959,17 @@ out:
 int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
                                          struct channel_path_desc_fmt1 *desc)
 {
-       struct chsc_response_struct *chsc_resp;
        struct chsc_scpd *scpd_area;
        unsigned long flags;
        int ret;
 
        spin_lock_irqsave(&chsc_page_lock, flags);
        scpd_area = chsc_page;
-       ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
+       ret = chsc_determine_channel_path_desc(chpid, 0, 1, 1, 0, scpd_area);
        if (ret)
                goto out;
-       chsc_resp = (void *)&scpd_area->response;
-       memcpy(desc, &chsc_resp->data, sizeof(*desc));
+
+       memcpy(desc, scpd_area->data, sizeof(*desc));
 out:
        spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
@@ -1020,7 +1019,7 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
        chp->cmg = -1;
 
        if (!css_chsc_characteristics.scmc || !css_chsc_characteristics.secm)
-               return 0;
+               return -EINVAL;
 
        spin_lock_irq(&chsc_page_lock);
        memset(chsc_page, 0, PAGE_SIZE);
@@ -1176,7 +1175,7 @@ exit:
 EXPORT_SYMBOL_GPL(css_general_characteristics);
 EXPORT_SYMBOL_GPL(css_chsc_characteristics);
 
-int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
+int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta)
 {
        struct {
                struct chsc_header request;
@@ -1186,7 +1185,9 @@ int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
                unsigned int ctrl : 16;
                unsigned int rsvd2[5];
                struct chsc_header response;
-               unsigned int rsvd3[7];
+               unsigned int rsvd3[3];
+               u64 clock_delta;
+               unsigned int rsvd4[2];
        } __attribute__ ((packed)) *rr;
        int rc;
 
@@ -1200,6 +1201,8 @@ int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
        if (rc)
                return -EIO;
        rc = (rr->response.code == 0x0001) ? 0 : -EIO;
+       if (clock_delta)
+               *clock_delta = rr->clock_delta;
        return rc;
 }