s390/dasd: add query PPRC function

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>
This commit is contained in:
Stefan Haberland 2022-09-20 21:26:11 +02:00 committed by Jens Axboe
parent 2b43bf061b
commit 3f217cceb6
3 changed files with 104 additions and 0 deletions

View 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

View File

@ -66,9 +66,15 @@
* 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
*/

View 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;