Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: [S390] tape: deadlock on system work queue [S390] keyboard: integer underflow bug [S390] xpram: remove __initdata attribute from module parameters
This commit is contained in:
@@ -62,8 +62,8 @@ static int xpram_devs;
|
|||||||
/*
|
/*
|
||||||
* Parameter parsing functions.
|
* Parameter parsing functions.
|
||||||
*/
|
*/
|
||||||
static int __initdata devs = XPRAM_DEVS;
|
static int devs = XPRAM_DEVS;
|
||||||
static char __initdata *sizes[XPRAM_MAX_DEVS];
|
static char *sizes[XPRAM_MAX_DEVS];
|
||||||
|
|
||||||
module_param(devs, int, 0);
|
module_param(devs, int, 0);
|
||||||
module_param_array(sizes, charp, NULL, 0);
|
module_param_array(sizes, charp, NULL, 0);
|
||||||
|
@@ -460,7 +460,8 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
|
|||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
void __user *argp;
|
void __user *argp;
|
||||||
int ct, perm;
|
unsigned int ct;
|
||||||
|
int perm;
|
||||||
|
|
||||||
argp = (void __user *)arg;
|
argp = (void __user *)arg;
|
||||||
|
|
||||||
|
@@ -280,6 +280,14 @@ tape_do_io_free(struct tape_device *device, struct tape_request *request)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
tape_do_io_async_free(struct tape_device *device, struct tape_request *request)
|
||||||
|
{
|
||||||
|
request->callback = (void *) tape_free_request;
|
||||||
|
request->callback_data = NULL;
|
||||||
|
tape_do_io_async(device, request);
|
||||||
|
}
|
||||||
|
|
||||||
extern int tape_oper_handler(int irq, int status);
|
extern int tape_oper_handler(int irq, int status);
|
||||||
extern void tape_noper_handler(int irq, int status);
|
extern void tape_noper_handler(int irq, int status);
|
||||||
extern int tape_open(struct tape_device *);
|
extern int tape_open(struct tape_device *);
|
||||||
|
@@ -53,23 +53,11 @@ static void tape_34xx_delete_sbid_from(struct tape_device *, int);
|
|||||||
* Medium sense for 34xx tapes. There is no 'real' medium sense call.
|
* Medium sense for 34xx tapes. There is no 'real' medium sense call.
|
||||||
* So we just do a normal sense.
|
* So we just do a normal sense.
|
||||||
*/
|
*/
|
||||||
static int
|
static void __tape_34xx_medium_sense(struct tape_request *request)
|
||||||
tape_34xx_medium_sense(struct tape_device *device)
|
|
||||||
{
|
{
|
||||||
struct tape_request *request;
|
struct tape_device *device = request->device;
|
||||||
unsigned char *sense;
|
unsigned char *sense;
|
||||||
int rc;
|
|
||||||
|
|
||||||
request = tape_alloc_request(1, 32);
|
|
||||||
if (IS_ERR(request)) {
|
|
||||||
DBF_EXCEPTION(6, "MSEN fail\n");
|
|
||||||
return PTR_ERR(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
request->op = TO_MSEN;
|
|
||||||
tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
|
|
||||||
|
|
||||||
rc = tape_do_io_interruptible(device, request);
|
|
||||||
if (request->rc == 0) {
|
if (request->rc == 0) {
|
||||||
sense = request->cpdata;
|
sense = request->cpdata;
|
||||||
|
|
||||||
@@ -88,15 +76,47 @@ tape_34xx_medium_sense(struct tape_device *device)
|
|||||||
device->tape_generic_status |= GMT_WR_PROT(~0);
|
device->tape_generic_status |= GMT_WR_PROT(~0);
|
||||||
else
|
else
|
||||||
device->tape_generic_status &= ~GMT_WR_PROT(~0);
|
device->tape_generic_status &= ~GMT_WR_PROT(~0);
|
||||||
} else {
|
} else
|
||||||
DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n",
|
DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n",
|
||||||
request->rc);
|
request->rc);
|
||||||
}
|
|
||||||
tape_free_request(request);
|
tape_free_request(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tape_34xx_medium_sense(struct tape_device *device)
|
||||||
|
{
|
||||||
|
struct tape_request *request;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
request = tape_alloc_request(1, 32);
|
||||||
|
if (IS_ERR(request)) {
|
||||||
|
DBF_EXCEPTION(6, "MSEN fail\n");
|
||||||
|
return PTR_ERR(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
request->op = TO_MSEN;
|
||||||
|
tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
|
||||||
|
rc = tape_do_io_interruptible(device, request);
|
||||||
|
__tape_34xx_medium_sense(request);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tape_34xx_medium_sense_async(struct tape_device *device)
|
||||||
|
{
|
||||||
|
struct tape_request *request;
|
||||||
|
|
||||||
|
request = tape_alloc_request(1, 32);
|
||||||
|
if (IS_ERR(request)) {
|
||||||
|
DBF_EXCEPTION(6, "MSEN fail\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request->op = TO_MSEN;
|
||||||
|
tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
|
||||||
|
request->callback = (void *) __tape_34xx_medium_sense;
|
||||||
|
request->callback_data = NULL;
|
||||||
|
tape_do_io_async(device, request);
|
||||||
|
}
|
||||||
|
|
||||||
struct tape_34xx_work {
|
struct tape_34xx_work {
|
||||||
struct tape_device *device;
|
struct tape_device *device;
|
||||||
enum tape_op op;
|
enum tape_op op;
|
||||||
@@ -109,6 +129,9 @@ struct tape_34xx_work {
|
|||||||
* is inserted but cannot call tape_do_io* from an interrupt context.
|
* is inserted but cannot call tape_do_io* from an interrupt context.
|
||||||
* Maybe that's useful for other actions we want to start from the
|
* Maybe that's useful for other actions we want to start from the
|
||||||
* interrupt handler.
|
* interrupt handler.
|
||||||
|
* 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).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
tape_34xx_work_handler(struct work_struct *work)
|
tape_34xx_work_handler(struct work_struct *work)
|
||||||
@@ -119,7 +142,7 @@ tape_34xx_work_handler(struct work_struct *work)
|
|||||||
|
|
||||||
switch(p->op) {
|
switch(p->op) {
|
||||||
case TO_MSEN:
|
case TO_MSEN:
|
||||||
tape_34xx_medium_sense(device);
|
tape_34xx_medium_sense_async(device);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBF_EVENT(3, "T34XX: internal error: unknown work\n");
|
DBF_EVENT(3, "T34XX: internal error: unknown work\n");
|
||||||
|
@@ -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
|
static int tape_3590_sense_medium(struct tape_device *device)
|
||||||
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
|
static void tape_3590_read_attmsg_async(struct tape_device *device)
|
||||||
tape_3590_read_attmsg(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 "
|
||||||
|
Reference in New Issue
Block a user