|
@@ -329,17 +329,17 @@ out:
|
|
/*
|
|
/*
|
|
* Enable encryption
|
|
* Enable encryption
|
|
*/
|
|
*/
|
|
-static int tape_3592_enable_crypt(struct tape_device *device)
|
|
|
|
|
|
+static struct tape_request *__tape_3592_enable_crypt(struct tape_device *device)
|
|
{
|
|
{
|
|
struct tape_request *request;
|
|
struct tape_request *request;
|
|
char *data;
|
|
char *data;
|
|
|
|
|
|
DBF_EVENT(6, "tape_3592_enable_crypt\n");
|
|
DBF_EVENT(6, "tape_3592_enable_crypt\n");
|
|
if (!crypt_supported(device))
|
|
if (!crypt_supported(device))
|
|
- return -ENOSYS;
|
|
|
|
|
|
+ return ERR_PTR(-ENOSYS);
|
|
request = tape_alloc_request(2, 72);
|
|
request = tape_alloc_request(2, 72);
|
|
if (IS_ERR(request))
|
|
if (IS_ERR(request))
|
|
- return PTR_ERR(request);
|
|
|
|
|
|
+ return request;
|
|
data = request->cpdata;
|
|
data = request->cpdata;
|
|
memset(data,0,72);
|
|
memset(data,0,72);
|
|
|
|
|
|
@@ -354,23 +354,42 @@ static int tape_3592_enable_crypt(struct tape_device *device)
|
|
request->op = TO_CRYPT_ON;
|
|
request->op = TO_CRYPT_ON;
|
|
tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
|
|
tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
|
|
tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
|
|
tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
|
|
|
|
+ return request;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int tape_3592_enable_crypt(struct tape_device *device)
|
|
|
|
+{
|
|
|
|
+ struct tape_request *request;
|
|
|
|
+
|
|
|
|
+ request = __tape_3592_enable_crypt(device);
|
|
|
|
+ if (IS_ERR(request))
|
|
|
|
+ return PTR_ERR(request);
|
|
return tape_do_io_free(device, request);
|
|
return tape_do_io_free(device, request);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void tape_3592_enable_crypt_async(struct tape_device *device)
|
|
|
|
+{
|
|
|
|
+ struct tape_request *request;
|
|
|
|
+
|
|
|
|
+ request = __tape_3592_enable_crypt(device);
|
|
|
|
+ if (!IS_ERR(request))
|
|
|
|
+ tape_do_io_async_free(device, request);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Disable encryption
|
|
* Disable encryption
|
|
*/
|
|
*/
|
|
-static int tape_3592_disable_crypt(struct tape_device *device)
|
|
|
|
|
|
+static struct tape_request *__tape_3592_disable_crypt(struct tape_device *device)
|
|
{
|
|
{
|
|
struct tape_request *request;
|
|
struct tape_request *request;
|
|
char *data;
|
|
char *data;
|
|
|
|
|
|
DBF_EVENT(6, "tape_3592_disable_crypt\n");
|
|
DBF_EVENT(6, "tape_3592_disable_crypt\n");
|
|
if (!crypt_supported(device))
|
|
if (!crypt_supported(device))
|
|
- return -ENOSYS;
|
|
|
|
|
|
+ return ERR_PTR(-ENOSYS);
|
|
request = tape_alloc_request(2, 72);
|
|
request = tape_alloc_request(2, 72);
|
|
if (IS_ERR(request))
|
|
if (IS_ERR(request))
|
|
- return PTR_ERR(request);
|
|
|
|
|
|
+ return request;
|
|
data = request->cpdata;
|
|
data = request->cpdata;
|
|
memset(data,0,72);
|
|
memset(data,0,72);
|
|
|
|
|
|
@@ -383,9 +402,28 @@ static int tape_3592_disable_crypt(struct tape_device *device)
|
|
tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
|
|
tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
|
|
tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
|
|
tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
|
|
|
|
|
|
|
|
+ return request;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int tape_3592_disable_crypt(struct tape_device *device)
|
|
|
|
+{
|
|
|
|
+ struct tape_request *request;
|
|
|
|
+
|
|
|
|
+ request = __tape_3592_disable_crypt(device);
|
|
|
|
+ if (IS_ERR(request))
|
|
|
|
+ return PTR_ERR(request);
|
|
return tape_do_io_free(device, request);
|
|
return tape_do_io_free(device, request);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void tape_3592_disable_crypt_async(struct tape_device *device)
|
|
|
|
+{
|
|
|
|
+ struct tape_request *request;
|
|
|
|
+
|
|
|
|
+ request = __tape_3592_disable_crypt(device);
|
|
|
|
+ if (!IS_ERR(request))
|
|
|
|
+ tape_do_io_async_free(device, request);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* IOCTL: Set encryption status
|
|
* IOCTL: Set encryption status
|
|
*/
|
|
*/
|
|
@@ -457,8 +495,7 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg)
|
|
/*
|
|
/*
|
|
* SENSE Medium: Get Sense data about medium state
|
|
* SENSE Medium: Get Sense data about medium state
|
|
*/
|
|
*/
|
|
-static int
|
|
|
|
-tape_3590_sense_medium(struct tape_device *device)
|
|
|
|
|
|
+static int tape_3590_sense_medium(struct tape_device *device)
|
|
{
|
|
{
|
|
struct tape_request *request;
|
|
struct tape_request *request;
|
|
|
|
|
|
@@ -470,6 +507,18 @@ tape_3590_sense_medium(struct tape_device *device)
|
|
return tape_do_io_free(device, request);
|
|
return tape_do_io_free(device, request);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void tape_3590_sense_medium_async(struct tape_device *device)
|
|
|
|
+{
|
|
|
|
+ struct tape_request *request;
|
|
|
|
+
|
|
|
|
+ request = tape_alloc_request(1, 128);
|
|
|
|
+ if (IS_ERR(request))
|
|
|
|
+ return;
|
|
|
|
+ request->op = TO_MSEN;
|
|
|
|
+ tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata);
|
|
|
|
+ tape_do_io_async_free(device, request);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* MTTELL: Tell block. Return the number of block relative to current file.
|
|
* MTTELL: Tell block. Return the number of block relative to current file.
|
|
*/
|
|
*/
|
|
@@ -546,15 +595,14 @@ tape_3590_read_opposite(struct tape_device *device,
|
|
* 2. The attention msg is written to the "read subsystem data" buffer.
|
|
* 2. The attention msg is written to the "read subsystem data" buffer.
|
|
* In this case we probably should print it to the console.
|
|
* In this case we probably should print it to the console.
|
|
*/
|
|
*/
|
|
-static int
|
|
|
|
-tape_3590_read_attmsg(struct tape_device *device)
|
|
|
|
|
|
+static void tape_3590_read_attmsg_async(struct tape_device *device)
|
|
{
|
|
{
|
|
struct tape_request *request;
|
|
struct tape_request *request;
|
|
char *buf;
|
|
char *buf;
|
|
|
|
|
|
request = tape_alloc_request(3, 4096);
|
|
request = tape_alloc_request(3, 4096);
|
|
if (IS_ERR(request))
|
|
if (IS_ERR(request))
|
|
- return PTR_ERR(request);
|
|
|
|
|
|
+ return;
|
|
request->op = TO_READ_ATTMSG;
|
|
request->op = TO_READ_ATTMSG;
|
|
buf = request->cpdata;
|
|
buf = request->cpdata;
|
|
buf[0] = PREP_RD_SS_DATA;
|
|
buf[0] = PREP_RD_SS_DATA;
|
|
@@ -562,12 +610,15 @@ tape_3590_read_attmsg(struct tape_device *device)
|
|
tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf);
|
|
tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf);
|
|
tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12);
|
|
tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12);
|
|
tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
|
|
tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
|
|
- return tape_do_io_free(device, request);
|
|
|
|
|
|
+ tape_do_io_async_free(device, request);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
* These functions are used to schedule follow-up actions from within an
|
|
* These functions are used to schedule follow-up actions from within an
|
|
* interrupt context (like unsolicited interrupts).
|
|
* interrupt context (like unsolicited interrupts).
|
|
|
|
+ * Note: the work handler is called by the system work queue. The tape
|
|
|
|
+ * commands started by the handler need to be asynchrounous, otherwise
|
|
|
|
+ * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq).
|
|
*/
|
|
*/
|
|
struct work_handler_data {
|
|
struct work_handler_data {
|
|
struct tape_device *device;
|
|
struct tape_device *device;
|
|
@@ -583,16 +634,16 @@ tape_3590_work_handler(struct work_struct *work)
|
|
|
|
|
|
switch (p->op) {
|
|
switch (p->op) {
|
|
case TO_MSEN:
|
|
case TO_MSEN:
|
|
- tape_3590_sense_medium(p->device);
|
|
|
|
|
|
+ tape_3590_sense_medium_async(p->device);
|
|
break;
|
|
break;
|
|
case TO_READ_ATTMSG:
|
|
case TO_READ_ATTMSG:
|
|
- tape_3590_read_attmsg(p->device);
|
|
|
|
|
|
+ tape_3590_read_attmsg_async(p->device);
|
|
break;
|
|
break;
|
|
case TO_CRYPT_ON:
|
|
case TO_CRYPT_ON:
|
|
- tape_3592_enable_crypt(p->device);
|
|
|
|
|
|
+ tape_3592_enable_crypt_async(p->device);
|
|
break;
|
|
break;
|
|
case TO_CRYPT_OFF:
|
|
case TO_CRYPT_OFF:
|
|
- tape_3592_disable_crypt(p->device);
|
|
|
|
|
|
+ tape_3592_disable_crypt_async(p->device);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
DBF_EVENT(3, "T3590: work handler undefined for "
|
|
DBF_EVENT(3, "T3590: work handler undefined for "
|