drivers/s390/cio/chsc.c

Source file repositories/reference/linux-study-clean/drivers/s390/cio/chsc.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/cio/chsc.c
Extension
.c
Size
38318 bytes
Lines
1607
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct chsc_ssd_area {
	struct chsc_header request;
	u16 :10;
	u16 ssid:2;
	u16 :4;
	u16 f_sch;	  /* first subchannel */
	u16 :16;
	u16 l_sch;	  /* last subchannel */
	u32 :32;
	struct chsc_header response;
	u32 :32;
	u8 sch_valid : 1;
	u8 dev_valid : 1;
	u8 st	     : 3; /* subchannel type */
	u8 zeroes    : 3;
	u8  unit_addr;	  /* unit address */
	u16 devno;	  /* device number */
	u8 path_mask;
	u8 fla_valid_mask;
	u16 sch;	  /* subchannel */
	u8 chpid[8];	  /* chpids 0-7 */
	u16 fla[8];	  /* full link addresses 0-7 */
} __packed __aligned(PAGE_SIZE);

int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
{
	struct chsc_ssd_area *ssd_area;
	unsigned long flags;
	int ccode;
	int ret;
	int i;
	int mask;

	spin_lock_irqsave(&chsc_page_lock, flags);
	memset(chsc_page, 0, PAGE_SIZE);
	ssd_area = chsc_page;
	ssd_area->request.length = 0x0010;
	ssd_area->request.code = 0x0004;
	ssd_area->ssid = schid.ssid;
	ssd_area->f_sch = schid.sch_no;
	ssd_area->l_sch = schid.sch_no;

	ccode = chsc(ssd_area);
	/* Check response. */
	if (ccode > 0) {
		ret = (ccode == 3) ? -ENODEV : -EBUSY;
		goto out;
	}
	ret = chsc_error_from_response(ssd_area->response.code);
	if (ret != 0) {
		CIO_MSG_EVENT(2, "chsc: ssd failed for 0.%x.%04x (rc=%04x)\n",
			      schid.ssid, schid.sch_no,
			      ssd_area->response.code);
		goto out;
	}
	if (!ssd_area->sch_valid) {
		ret = -ENODEV;
		goto out;
	}
	/* Copy data */
	ret = 0;
	memset(ssd, 0, sizeof(struct chsc_ssd_info));
	if ((ssd_area->st != SUBCHANNEL_TYPE_IO) &&
	    (ssd_area->st != SUBCHANNEL_TYPE_MSG))
		goto out;
	ssd->path_mask = ssd_area->path_mask;
	ssd->fla_valid_mask = ssd_area->fla_valid_mask;
	for (i = 0; i < 8; i++) {
		mask = 0x80 >> i;
		if (ssd_area->path_mask & mask) {
			chp_id_init(&ssd->chpid[i]);
			ssd->chpid[i].id = ssd_area->chpid[i];
		}
		if (ssd_area->fla_valid_mask & mask)
			ssd->fla[i] = ssd_area->fla[i];
	}
out:
	spin_unlock_irqrestore(&chsc_page_lock, flags);
	return ret;
}

/**
 * chsc_ssqd() - store subchannel QDIO data (SSQD)
 * @schid: id of the subchannel on which SSQD is performed
 * @ssqd: request and response block for SSQD
 *
 * Returns 0 on success.
 */
int chsc_ssqd(struct subchannel_id schid, struct chsc_ssqd_area *ssqd)
{

Annotation

Implementation Notes