Commit 3f7401c6 authored by James Bottomley's avatar James Bottomley

Merge mulgrave.(none):/home/jejb/BK/scsi-misc-2.5

into mulgrave.(none):/home/jejb/BK/scsi-misc-new-2.5
parents efa0596f dabae96e
......@@ -40,6 +40,11 @@ const unsigned char scsi_command_size[8] =
#define BLK_DEFAULT_TIMEOUT (60 * HZ)
/* defined in ../scsi/scsi.h ... should it be included? */
#ifndef SCSI_SENSE_BUFFERSIZE
#define SCSI_SENSE_BUFFERSIZE 64
#endif
int blk_do_rq(request_queue_t *q, struct block_device *bdev, struct request *rq)
{
DECLARE_COMPLETION(wait);
......@@ -126,11 +131,11 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
struct sg_io_hdr *uptr)
{
unsigned long uaddr, start_time;
int err, reading, writing, nr_sectors;
int reading, writing, nr_sectors;
struct sg_io_hdr hdr;
struct request *rq;
struct bio *bio;
char sense[24];
char sense[SCSI_SENSE_BUFFERSIZE];
void *buffer;
if (!access_ok(VERIFY_WRITE, uptr, sizeof(*uptr)))
......@@ -265,26 +270,36 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
start_time = jiffies;
/*
* return -EIO if we didn't transfer all data, caller can look at
* residual count to find out how much did succeed
/* ignore return value. All information is passed back to caller
* (if he doesn't check that is his problem).
* N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
err = blk_do_rq(q, bdev, rq);
if (rq->data_len > 0)
err = -EIO;
blk_do_rq(q, bdev, rq);
if (bio) {
bio_unmap_user(bio, reading);
bio_put(bio);
}
/* write to all output members */
hdr.status = rq->errors;
hdr.masked_status = (hdr.status >> 1) & 0x1f;
hdr.msg_status = 0;
hdr.host_status = 0;
hdr.driver_status = 0;
hdr.info = 0;
if (hdr.masked_status || hdr.host_status || hdr.driver_status)
hdr.info |= SG_INFO_CHECK;
hdr.resid = rq->data_len;
hdr.duration = (jiffies - start_time) * (1000 / HZ);
hdr.sb_len_wr = 0;
if (rq->sense_len && hdr.sbp) {
if (!copy_to_user(hdr.sbp,rq->sense, rq->sense_len))
hdr.sb_len_wr = rq->sense_len;
int len = (hdr.mx_sb_len < rq->sense_len) ?
hdr.mx_sb_len : rq->sense_len;
if (!copy_to_user(hdr.sbp, rq->sense, len))
hdr.sb_len_wr = len;
}
blk_put_request(rq);
......@@ -297,8 +312,9 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
kfree(buffer);
}
return err;
/* may not have succeeded, but output values written to control
* structure (struct sg_io_hdr). */
return 0;
}
#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ)
......
......@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/completion.h>
#define __KERNEL_SYSCALLS__
......@@ -335,10 +336,10 @@ void scsi_unregister(struct Scsi_Host *shost)
* Next, kill the kernel error recovery thread for this host.
*/
if (shost->ehandler) {
DECLARE_MUTEX_LOCKED(sem);
DECLARE_COMPLETION(sem);
shost->eh_notify = &sem;
send_sig(SIGHUP, shost->ehandler, 1);
down(&sem);
up(shost->eh_wait);
wait_for_completion(&sem);
shost->eh_notify = NULL;
}
......@@ -368,7 +369,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
{
struct Scsi_Host *shost, *shost_scr;
int gfp_mask;
DECLARE_MUTEX_LOCKED(sem);
DECLARE_COMPLETION(sem);
/* Check to see if this host has any error handling facilities */
if(shost_tp->eh_strategy_handler == NULL &&
......@@ -464,7 +465,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
* Now wait for the kernel error thread to initialize itself
* as it might be needed when we scan the bus.
*/
down(&sem);
wait_for_completion(&sem);
shost->eh_notify = NULL;
shost->hostt->present++;
......
......@@ -381,11 +381,12 @@ struct Scsi_Host
struct task_struct * ehandler; /* Error recovery thread. */
struct semaphore * eh_wait; /* The error recovery thread waits on
this. */
struct semaphore * eh_notify; /* wait for eh to begin */
struct completion * eh_notify; /* wait for eh to begin or end */
struct semaphore * eh_action; /* Wait for specific actions on the
host. */
unsigned int eh_active:1; /* Indicates the eh thread is awake and active if
this is true. */
unsigned int eh_kill:1; /* set when killing the eh thread */
wait_queue_head_t host_wait;
Scsi_Host_Template * hostt;
atomic_t host_active; /* commands checked out */
......
......@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#define __KERNEL_SYSCALLS__
......@@ -41,20 +42,6 @@
#include <scsi/scsi_ioctl.h> /* grr */
/*
* We must always allow SHUTDOWN_SIGS. Even if we are not a module,
* the host drivers that we are using may be loaded as modules, and
* when we unload these, we need to ensure that the error handler thread
* can be shut down.
*
* Note - when we unload a module, we send a SIGHUP. We mustn't
* enable SIGTERM, as this is how the init shuts things down when you
* go to single-user mode. For that matter, init also sends SIGKILL,
* so we mustn't enable that one either. We use SIGHUP instead. Other
* options would be SIGPWR, I suppose.
*/
#define SHUTDOWN_SIGS (sigmask(SIGHUP))
#ifdef DEBUG
#define SENSE_TIMEOUT SCSI_TIMEOUT
#else
......@@ -1589,12 +1576,10 @@ void scsi_error_handler(void *data)
int rtn;
DECLARE_MUTEX_LOCKED(sem);
/*
* We only listen to signals if the HA was loaded as a module.
* If the HA was compiled into the kernel, then we don't listen
* to any signals.
*/
siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
spin_lock_irq(&current->sig->siglock);
sigfillset(&current->blocked);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
lock_kernel();
......@@ -1618,9 +1603,9 @@ void scsi_error_handler(void *data)
/*
* Wake up the thread that created us.
*/
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent \n"));
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of scsi_eh_%d\n",shost->host_no));
up(shost->eh_notify);
complete(shost->eh_notify);
while (1) {
/*
......@@ -1628,7 +1613,7 @@ void scsi_error_handler(void *data)
* away and die. This typically happens if the user is
* trying to unload a module.
*/
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n"));
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d sleeping\n",shost->host_no));
/*
* Note - we always use down_interruptible with the semaphore
......@@ -1640,10 +1625,10 @@ void scsi_error_handler(void *data)
* semaphores isn't unreasonable.
*/
down_interruptible(&sem);
if (signal_pending(current))
if (shost->eh_kill)
break;
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n"));
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d waking up\n",shost->host_no));
shost->eh_active = 1;
......@@ -1671,7 +1656,7 @@ void scsi_error_handler(void *data)
}
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler exiting\n"));
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d exiting\n",shost->host_no));
/*
* Make sure that nobody tries to wake us up again.
......@@ -1691,13 +1676,9 @@ void scsi_error_handler(void *data)
/*
* If anyone is waiting for us to exit (i.e. someone trying to unload
* a driver), then wake up that process to let them know we are on
* the way out the door. This may be overkill - I *think* that we
* could probably just unload the driver and send the signal, and when
* the error handling thread wakes up that it would just exit without
* needing to touch any memory associated with the driver itself.
* the way out the door.
*/
if (shost->eh_notify != NULL)
up(shost->eh_notify);
complete_and_exit(shost->eh_notify, 0);
}
/**
......
......@@ -495,6 +495,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
int this_count = SCpnt->bufflen >> 9;
request_queue_t *q = SCpnt->device->request_queue;
struct request *req = SCpnt->request;
int clear_errors = 1;
/*
* We must do one of several things here:
......@@ -528,10 +529,22 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
kfree(SCpnt->buffer);
}
if (blk_pc_request(req)) {
req->errors = result & 0xff;
if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
req->errors = (driver_byte(result) & DRIVER_SENSE) ?
(CHECK_CONDITION << 1) : (result & 0xff);
if (!result)
req->data_len -= SCpnt->bufflen;
else {
clear_errors = 0;
if (SCpnt->sense_buffer[0] & 0x70) {
int len = 8 + SCpnt->sense_buffer[7];
if (len > SCSI_SENSE_BUFFERSIZE)
len = SCSI_SENSE_BUFFERSIZE;
memcpy(req->sense, SCpnt->sense_buffer, len);
req->sense_len = len;
}
}
}
/*
......@@ -552,6 +565,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
req->nr_sectors, good_sectors));
SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg));
if (clear_errors)
req->errors = 0;
/*
* If multiple sectors are requested in one buffer, then
......
......@@ -224,6 +224,7 @@ sdev_rd_attr (device_blocked, "%d\n");
sdev_rd_attr (current_queue_depth, "%d\n");
sdev_rd_attr (new_queue_depth, "%d\n");
sdev_rd_attr (type, "%d\n");
sdev_rd_attr (scsi_level, "%d\n");
sdev_rd_attr (access_count, "%d\n");
sdev_rd_attr (vendor, "%.8s\n");
sdev_rd_attr (model, "%.16s\n");
......@@ -235,6 +236,7 @@ static struct device_attribute * const sdev_attrs[] = {
&dev_attr_current_queue_depth,
&dev_attr_new_queue_depth,
&dev_attr_type,
&dev_attr_scsi_level,
&dev_attr_access_count,
&dev_attr_vendor,
&dev_attr_model,
......
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