in block/dasd.c [1386:1492]
int dasd_start_IO(struct dasd_ccw_req *cqr)
{
struct dasd_device *device;
int rc;
char errorstring[ERRORLENGTH];
/* Check the cqr */
rc = dasd_check_cqr(cqr);
if (rc) {
cqr->intrc = rc;
return rc;
}
device = (struct dasd_device *) cqr->startdev;
if (((cqr->block &&
test_bit(DASD_FLAG_LOCK_STOLEN, &cqr->block->base->flags)) ||
test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags)) &&
!test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
DBF_DEV_EVENT(DBF_DEBUG, device, "start_IO: return request %p "
"because of stolen lock", cqr);
cqr->status = DASD_CQR_ERROR;
cqr->intrc = -EPERM;
return -EPERM;
}
if (cqr->retries < 0) {
/* internal error 14 - start_IO run out of retries */
sprintf(errorstring, "14 %p", cqr);
dev_err(&device->cdev->dev, "An error occurred in the DASD "
"device driver, reason=%s\n", errorstring);
cqr->status = DASD_CQR_ERROR;
return -EIO;
}
cqr->startclk = get_tod_clock();
cqr->starttime = jiffies;
cqr->retries--;
if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
cqr->lpm &= dasd_path_get_opm(device);
if (!cqr->lpm)
cqr->lpm = dasd_path_get_opm(device);
}
if (cqr->cpmode == 1) {
rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
(long) cqr, cqr->lpm);
} else {
rc = ccw_device_start(device->cdev, cqr->cpaddr,
(long) cqr, cqr->lpm, 0);
}
switch (rc) {
case 0:
cqr->status = DASD_CQR_IN_IO;
break;
case -EBUSY:
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"start_IO: device busy, retry later");
break;
case -EACCES:
/* -EACCES indicates that the request used only a subset of the
* available paths and all these paths are gone. If the lpm of
* this request was only a subset of the opm (e.g. the ppm) then
* we just do a retry with all available paths.
* If we already use the full opm, something is amiss, and we
* need a full path verification.
*/
if (test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
DBF_DEV_EVENT(DBF_WARNING, device,
"start_IO: selected paths gone (%x)",
cqr->lpm);
} else if (cqr->lpm != dasd_path_get_opm(device)) {
cqr->lpm = dasd_path_get_opm(device);
DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
"start_IO: selected paths gone,"
" retry on all paths");
} else {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"start_IO: all paths in opm gone,"
" do path verification");
dasd_generic_last_path_gone(device);
dasd_path_no_path(device);
dasd_path_set_tbvpm(device,
ccw_device_get_path_mask(
device->cdev));
}
break;
case -ENODEV:
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"start_IO: -ENODEV device gone, retry");
break;
case -EIO:
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"start_IO: -EIO device gone, retry");
break;
case -EINVAL:
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"start_IO: -EINVAL device currently "
"not accessible");
break;
default:
/* internal error 11 - unknown rc */
snprintf(errorstring, ERRORLENGTH, "11 %d", rc);
dev_err(&device->cdev->dev,
"An error occurred in the DASD device driver, "
"reason=%s\n", errorstring);
BUG();
break;
}
cqr->intrc = rc;
return rc;
}