Commit 3f217cce authored by Stefan Haberland's avatar Stefan Haberland Committed by Jens Axboe
Browse files

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: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarJan Hoeppner <hoeppner@linux.ibm.com>
Link: https://lore.kernel.org/r/20220920192616.808070-3-sth@linux.ibm.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 2b43bf06
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -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
+6 −0
Original line number Diff line number Diff line
@@ -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
 */
+32 −0
Original line number Diff line number Diff line
@@ -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;