Commit ad4a4a82 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 6277d53a 0c2bd9b2
...@@ -62,8 +62,8 @@ static int xpram_devs; ...@@ -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, ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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 @@ static int tape_3592_ioctl_kekl_set(struct tape_device *device, ...@@ -329,17 +329,17 @@ static int tape_3592_ioctl_kekl_set(struct tape_device *device,
/* /*
* 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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment