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:
parent
2b43bf061b
commit
3f217cceb6
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user