]> git.itanic.dy.fi Git - linux-stable/commitdiff
s390/dasd: add query PPRC function
authorStefan Haberland <sth@linux.ibm.com>
Tue, 20 Sep 2022 19:26:11 +0000 (21:26 +0200)
committerJens Axboe <axboe@kernel.dk>
Wed, 21 Sep 2022 14:32:50 +0000 (08:32 -0600)
Add function to query the Peer-to-Peer-Remote-Copy (PPRC) state of a
device by reading the related structure through a read subsystem data call.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Link: https://lore.kernel.org/r/20220920192616.808070-3-sth@linux.ibm.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_int.h

index bdb4207d5aa260f3d24f5a375a7df58f1b0da9c0..600606d8d03887303cdce8c7a993dd1fd6b83c2e 100644 (file)
@@ -6086,6 +6086,71 @@ static int dasd_hosts_print(struct dasd_device *device, struct seq_file *m)
        return 0;
 }
 
+/*
+ * Perform Subsystem Function - Peer-to-Peer Remote Copy Extended Query
+ */
+static int dasd_eckd_query_pprc_status(struct dasd_device *device,
+                                      struct dasd_pprc_data_sc4 *data)
+{
+       struct dasd_pprc_data_sc4 *pprc_data;
+       struct dasd_psf_prssd_data *prssdp;
+       struct dasd_ccw_req *cqr;
+       struct ccw1 *ccw;
+       int rc;
+
+       cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
+                                  sizeof(*prssdp) + sizeof(*pprc_data) + 1,
+                                  device, NULL);
+       if (IS_ERR(cqr)) {
+               DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+                               "Could not allocate query PPRC status request");
+               return PTR_ERR(cqr);
+       }
+       cqr->startdev = device;
+       cqr->memdev = device;
+       cqr->block = NULL;
+       cqr->retries = 256;
+       cqr->expires = 10 * HZ;
+
+       /* Prepare for Read Subsystem Data */
+       prssdp = (struct dasd_psf_prssd_data *)cqr->data;
+       memset(prssdp, 0, sizeof(struct dasd_psf_prssd_data));
+       prssdp->order = PSF_ORDER_PRSSD;
+       prssdp->suborder = PSF_SUBORDER_PPRCEQ;
+       prssdp->varies[0] = PPRCEQ_SCOPE_4;
+       pprc_data = (struct dasd_pprc_data_sc4 *)(prssdp + 1);
+
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_PSF;
+       ccw->count = sizeof(struct dasd_psf_prssd_data);
+       ccw->flags |= CCW_FLAG_CC;
+       ccw->flags |= CCW_FLAG_SLI;
+       ccw->cda = (__u32)(addr_t)prssdp;
+
+       /* Read Subsystem Data - query host access */
+       ccw++;
+       ccw->cmd_code = DASD_ECKD_CCW_RSSD;
+       ccw->count = sizeof(*pprc_data);
+       ccw->flags |= CCW_FLAG_SLI;
+       ccw->cda = (__u32)(addr_t)pprc_data;
+
+       cqr->buildclk = get_tod_clock();
+       cqr->status = DASD_CQR_FILLED;
+
+       rc = dasd_sleep_on_interruptible(cqr);
+       if (rc == 0) {
+               *data = *pprc_data;
+       } else {
+               DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+                               "PPRC Extended Query failed with rc=%d\n",
+                               rc);
+               rc = -EOPNOTSUPP;
+       }
+
+       dasd_sfree_request(cqr, cqr->memdev);
+       return rc;
+}
+
 /*
  * Perform Subsystem Function - CUIR response
  */
@@ -6705,6 +6770,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .ext_pool_exhaust = dasd_eckd_ext_pool_exhaust,
        .ese_format = dasd_eckd_ese_format,
        .ese_read = dasd_eckd_ese_read,
+       .pprc_status = dasd_eckd_query_pprc_status,
 };
 
 static int __init
index a91b265441cc4f425531aac2c1af59f04a471717..ecf25b985aa8e2bf7c3f13a0072b91632c477307 100644 (file)
  * Perform Subsystem Function / Sub-Orders
  */
 #define PSF_SUBORDER_QHA                0x1C /* Query Host Access */
+#define PSF_SUBORDER_PPRCEQ             0x50 /* PPRC Extended Query */
 #define PSF_SUBORDER_VSQ                0x52 /* Volume Storage Query */
 #define PSF_SUBORDER_LCQ                0x53 /* Logical Configuration Query */
 
+/*
+ * PPRC Extended Query Scopes
+ */
+#define PPRCEQ_SCOPE_4                  0x04 /* Scope 4 for PPRC Extended Query */
+
 /*
  * CUIR response condition codes
  */
index 333a399f754ec00fa5d78342e352ed81a900489d..39316020529d65c50d774c8b4eaae8acdb5bfc4a 100644 (file)
@@ -259,6 +259,37 @@ struct dasd_uid {
        char vduit[33];
 };
 
+/*
+ * PPRC Status data
+ */
+struct dasd_pprc_header {
+       __u8 entries;           /* 0     Number of device entries */
+       __u8 unused;            /* 1     unused */
+       __u16 entry_length;     /* 2-3   Length of device entry */
+       __u32 unused2;          /* 4-7   unused */
+} __packed;
+
+struct dasd_pprc_dev_info {
+       __u8 state;             /* 0       Copy State */
+       __u8 flags;             /* 1       Flags */
+       __u8 reserved1[2];      /* 2-3     reserved */
+       __u8 prim_lss;          /* 4       Primary device LSS */
+       __u8 primary;           /* 5       Primary device address */
+       __u8 sec_lss;           /* 6       Secondary device LSS */
+       __u8 secondary;         /* 7       Secondary device address */
+       __u16 pprc_id;          /* 8-9     Peer-to-Peer Remote Copy ID */
+       __u8 reserved2[12];     /* 10-21   reserved */
+       __u16 prim_cu_ssid;     /* 22-23   Pimary Control Unit SSID */
+       __u8 reserved3[12];     /* 24-35   reserved */
+       __u16 sec_cu_ssid;      /* 36-37   Secondary Control Unit SSID */
+       __u8 reserved4[90];     /* 38-127  reserved */
+} __packed;
+
+struct dasd_pprc_data_sc4 {
+       struct dasd_pprc_header header;
+       struct dasd_pprc_dev_info dev_info[5];
+} __packed;
+
 /*
  * the struct dasd_discipline is
  * sth like a table of virtual functions, if you think of dasd_eckd
@@ -387,6 +418,7 @@ struct dasd_discipline {
        struct dasd_ccw_req *(*ese_format)(struct dasd_device *,
                                           struct dasd_ccw_req *, struct irb *);
        int (*ese_read)(struct dasd_ccw_req *, struct irb *);
+       int (*pprc_status)(struct dasd_device *, struct dasd_pprc_data_sc4 *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;