|
@@ -82,6 +82,14 @@ static struct ccw_driver dasd_eckd_driver; /* see below */
|
|
|
#define INIT_CQR_UNFORMATTED 1
|
|
|
#define INIT_CQR_ERROR 2
|
|
|
|
|
|
+/* emergency request for reserve/release */
|
|
|
+static struct {
|
|
|
+ struct dasd_ccw_req cqr;
|
|
|
+ struct ccw1 ccw;
|
|
|
+ char data[32];
|
|
|
+} *dasd_reserve_req;
|
|
|
+static DEFINE_MUTEX(dasd_reserve_mutex);
|
|
|
+
|
|
|
|
|
|
/* initial attempt at a probe function. this can be simplified once
|
|
|
* the other detection code is gone */
|
|
@@ -2645,15 +2653,23 @@ dasd_eckd_release(struct dasd_device *device)
|
|
|
struct dasd_ccw_req *cqr;
|
|
|
int rc;
|
|
|
struct ccw1 *ccw;
|
|
|
+ int useglobal;
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
return -EACCES;
|
|
|
|
|
|
+ useglobal = 0;
|
|
|
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
|
|
|
if (IS_ERR(cqr)) {
|
|
|
- DBF_DEV_EVENT(DBF_WARNING, device, "%s",
|
|
|
- "Could not allocate initialization request");
|
|
|
- return PTR_ERR(cqr);
|
|
|
+ mutex_lock(&dasd_reserve_mutex);
|
|
|
+ useglobal = 1;
|
|
|
+ cqr = &dasd_reserve_req->cqr;
|
|
|
+ memset(cqr, 0, sizeof(*cqr));
|
|
|
+ memset(&dasd_reserve_req->ccw, 0,
|
|
|
+ sizeof(dasd_reserve_req->ccw));
|
|
|
+ cqr->cpaddr = &dasd_reserve_req->ccw;
|
|
|
+ cqr->data = &dasd_reserve_req->data;
|
|
|
+ cqr->magic = DASD_ECKD_MAGIC;
|
|
|
}
|
|
|
ccw = cqr->cpaddr;
|
|
|
ccw->cmd_code = DASD_ECKD_CCW_RELEASE;
|
|
@@ -2671,7 +2687,10 @@ dasd_eckd_release(struct dasd_device *device)
|
|
|
|
|
|
rc = dasd_sleep_on_immediatly(cqr);
|
|
|
|
|
|
- dasd_sfree_request(cqr, cqr->memdev);
|
|
|
+ if (useglobal)
|
|
|
+ mutex_unlock(&dasd_reserve_mutex);
|
|
|
+ else
|
|
|
+ dasd_sfree_request(cqr, cqr->memdev);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2687,15 +2706,23 @@ dasd_eckd_reserve(struct dasd_device *device)
|
|
|
struct dasd_ccw_req *cqr;
|
|
|
int rc;
|
|
|
struct ccw1 *ccw;
|
|
|
+ int useglobal;
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
return -EACCES;
|
|
|
|
|
|
+ useglobal = 0;
|
|
|
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
|
|
|
if (IS_ERR(cqr)) {
|
|
|
- DBF_DEV_EVENT(DBF_WARNING, device, "%s",
|
|
|
- "Could not allocate initialization request");
|
|
|
- return PTR_ERR(cqr);
|
|
|
+ mutex_lock(&dasd_reserve_mutex);
|
|
|
+ useglobal = 1;
|
|
|
+ cqr = &dasd_reserve_req->cqr;
|
|
|
+ memset(cqr, 0, sizeof(*cqr));
|
|
|
+ memset(&dasd_reserve_req->ccw, 0,
|
|
|
+ sizeof(dasd_reserve_req->ccw));
|
|
|
+ cqr->cpaddr = &dasd_reserve_req->ccw;
|
|
|
+ cqr->data = &dasd_reserve_req->data;
|
|
|
+ cqr->magic = DASD_ECKD_MAGIC;
|
|
|
}
|
|
|
ccw = cqr->cpaddr;
|
|
|
ccw->cmd_code = DASD_ECKD_CCW_RESERVE;
|
|
@@ -2713,7 +2740,10 @@ dasd_eckd_reserve(struct dasd_device *device)
|
|
|
|
|
|
rc = dasd_sleep_on_immediatly(cqr);
|
|
|
|
|
|
- dasd_sfree_request(cqr, cqr->memdev);
|
|
|
+ if (useglobal)
|
|
|
+ mutex_unlock(&dasd_reserve_mutex);
|
|
|
+ else
|
|
|
+ dasd_sfree_request(cqr, cqr->memdev);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2728,15 +2758,23 @@ dasd_eckd_steal_lock(struct dasd_device *device)
|
|
|
struct dasd_ccw_req *cqr;
|
|
|
int rc;
|
|
|
struct ccw1 *ccw;
|
|
|
+ int useglobal;
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
return -EACCES;
|
|
|
|
|
|
+ useglobal = 0;
|
|
|
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
|
|
|
if (IS_ERR(cqr)) {
|
|
|
- DBF_DEV_EVENT(DBF_WARNING, device, "%s",
|
|
|
- "Could not allocate initialization request");
|
|
|
- return PTR_ERR(cqr);
|
|
|
+ mutex_lock(&dasd_reserve_mutex);
|
|
|
+ useglobal = 1;
|
|
|
+ cqr = &dasd_reserve_req->cqr;
|
|
|
+ memset(cqr, 0, sizeof(*cqr));
|
|
|
+ memset(&dasd_reserve_req->ccw, 0,
|
|
|
+ sizeof(dasd_reserve_req->ccw));
|
|
|
+ cqr->cpaddr = &dasd_reserve_req->ccw;
|
|
|
+ cqr->data = &dasd_reserve_req->data;
|
|
|
+ cqr->magic = DASD_ECKD_MAGIC;
|
|
|
}
|
|
|
ccw = cqr->cpaddr;
|
|
|
ccw->cmd_code = DASD_ECKD_CCW_SLCK;
|
|
@@ -2754,7 +2792,10 @@ dasd_eckd_steal_lock(struct dasd_device *device)
|
|
|
|
|
|
rc = dasd_sleep_on_immediatly(cqr);
|
|
|
|
|
|
- dasd_sfree_request(cqr, cqr->memdev);
|
|
|
+ if (useglobal)
|
|
|
+ mutex_unlock(&dasd_reserve_mutex);
|
|
|
+ else
|
|
|
+ dasd_sfree_request(cqr, cqr->memdev);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -3488,10 +3529,15 @@ dasd_eckd_init(void)
|
|
|
int ret;
|
|
|
|
|
|
ASCEBC(dasd_eckd_discipline.ebcname, 4);
|
|
|
+ dasd_reserve_req = kmalloc(sizeof(*dasd_reserve_req),
|
|
|
+ GFP_KERNEL | GFP_DMA);
|
|
|
+ if (!dasd_reserve_req)
|
|
|
+ return -ENOMEM;
|
|
|
ret = ccw_driver_register(&dasd_eckd_driver);
|
|
|
if (!ret)
|
|
|
wait_for_device_probe();
|
|
|
-
|
|
|
+ else
|
|
|
+ kfree(dasd_reserve_req);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -3499,6 +3545,7 @@ static void __exit
|
|
|
dasd_eckd_cleanup(void)
|
|
|
{
|
|
|
ccw_driver_unregister(&dasd_eckd_driver);
|
|
|
+ kfree(dasd_reserve_req);
|
|
|
}
|
|
|
|
|
|
module_init(dasd_eckd_init);
|