drivers/s390/cio/ccwreq.c

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

File Facts

System
Linux kernel
Corpus path
drivers/s390/cio/ccwreq.c
Extension
.c
Size
8524 bytes
Lines
368
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: implementation source
Status
source 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

if (req->retries-- == 0) {
			/* Retries exhausted, try next path. */
			ccwreq_next_path(cdev);
			continue;
		}
		/* Perform start function. */
		memset(&cdev->private->dma_area->irb, 0, sizeof(struct irb));
		rc = cio_start(sch, cp, (u8) req->mask);
		if (rc == 0) {
			/* I/O started successfully. */
			ccw_device_set_timeout(cdev, req->timeout);
			return;
		}
		if (rc == -ENODEV) {
			/* Permanent device error. */
			break;
		}
		if (rc == -EACCES) {
			/* Permant path error. */
			ccwreq_next_path(cdev);
			continue;
		}
		/* Temporary improper status. */
		rc = cio_clear(sch);
		if (rc)
			break;
		return;
	}
	ccwreq_stop(cdev, rc);
}

/**
 * ccw_request_start - perform I/O request
 * @cdev: ccw device
 *
 * Perform the I/O request specified by cdev->req.
 */
void ccw_request_start(struct ccw_device *cdev)
{
	struct ccw_request *req = &cdev->private->req;

	if (req->singlepath) {
		/* Try all paths twice to counter link flapping. */
		req->mask = 0x8080;
	} else
		req->mask = req->lpm;

	req->retries	= req->maxretries;
	req->mask	= lpm_adjust(req->mask, req->lpm);
	req->drc	= 0;
	req->done	= 0;
	req->cancel	= 0;
	if (!req->mask)
		goto out_nopath;
	ccwreq_do(cdev);
	return;

out_nopath:
	ccwreq_stop(cdev, -EACCES);
}

/**
 * ccw_request_cancel - cancel running I/O request
 * @cdev: ccw device
 *
 * Cancel the I/O request specified by cdev->req. Return non-zero if request
 * has already finished, zero otherwise.
 */
int ccw_request_cancel(struct ccw_device *cdev)
{
	struct subchannel *sch = to_subchannel(cdev->dev.parent);
	struct ccw_request *req = &cdev->private->req;
	int rc;

	if (req->done)
		return 1;
	req->cancel = 1;
	rc = cio_clear(sch);
	if (rc)
		ccwreq_stop(cdev, rc);
	return 0;
}

/*
 * Return the status of the internal I/O started on the specified ccw device.
 * Perform BASIC SENSE if required.
 */
static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
{
	struct irb *irb = &cdev->private->dma_area->irb;

Annotation

Implementation Notes