summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-05-08 05:37:51 +0200
committerPaul Mackerras <paulus@samba.org>2007-05-08 05:37:51 +0200
commit02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1 (patch)
tree04ef573cd4de095c500c9fc3477f4278c0b36300 /drivers/scsi/ibmvscsi
parent[POWERPC] Holly bootwrapper (diff)
parentMerge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6 (diff)
downloadlinux-02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1.tar.xz
linux-02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1.zip
Merge branch 'linux-2.6'
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c80
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c37
3 files changed, 75 insertions, 44 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fbc1d5c3b0a7..b10eefe735c5 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -85,7 +85,7 @@
static int max_id = 64;
static int max_channel = 3;
static int init_timeout = 5;
-static int max_requests = 50;
+static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
#define IBMVSCSI_VERSION "1.5.8"
@@ -538,7 +538,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
int request_status;
int rc;
- /* If we have exhausted our request limit, just fail this request.
+ /* If we have exhausted our request limit, just fail this request,
+ * unless it is for a reset or abort.
* Note that there are rare cases involving driver generated requests
* (such as task management requests) that the mid layer may think we
* can handle more requests (can_queue) when we actually can't
@@ -551,9 +552,30 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
*/
if (request_status < -1)
goto send_error;
- /* Otherwise, if we have run out of requests */
- else if (request_status < 0)
- goto send_busy;
+ /* Otherwise, we may have run out of requests. */
+ /* Abort and reset calls should make it through.
+ * Nothing except abort and reset should use the last two
+ * slots unless we had two or less to begin with.
+ */
+ else if (request_status < 2 &&
+ evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) {
+ /* In the case that we have less than two requests
+ * available, check the server limit as a combination
+ * of the request limit and the number of requests
+ * in-flight (the size of the send list). If the
+ * server limit is greater than 2, return busy so
+ * that the last two are reserved for reset and abort.
+ */
+ int server_limit = request_status;
+ struct srp_event_struct *tmp_evt;
+
+ list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+ server_limit++;
+ }
+
+ if (server_limit > 2)
+ goto send_busy;
+ }
}
/* Copy the IU into the transfer area */
@@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
printk(KERN_ERR "ibmvscsi: send error %d\n",
rc);
+ atomic_inc(&hostdata->request_limit);
goto send_error;
}
@@ -581,7 +604,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
- return SCSI_MLQUEUE_HOST_BUSY;
+ atomic_inc(&hostdata->request_limit);
+ return SCSI_MLQUEUE_HOST_BUSY;
send_error:
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
@@ -831,23 +855,16 @@ static void login_rsp(struct srp_event_struct *evt_struct)
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
- if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
- (max_requests - 2))
- evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
- max_requests - 2;
+ if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
+ printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
- /* Now we know what the real request-limit is */
+ /* Now we know what the real request-limit is.
+ * This value is set rather than added to request_limit because
+ * request_limit could have been set to -1 by this client.
+ */
atomic_set(&hostdata->request_limit,
evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
- hostdata->host->can_queue =
- evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
-
- if (hostdata->host->can_queue < 1) {
- printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
- return;
- }
-
/* If we had any pending I/Os, kick them */
scsi_unblock_requests(hostdata->host);
@@ -1337,6 +1354,27 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
return rc;
}
+/**
+ * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk.
+ * @sdev: struct scsi_device device to configure
+ *
+ * Enable allow_restart for a device if it is a disk. Adjust the
+ * queue_depth here also as is required by the documentation for
+ * struct scsi_host_template.
+ */
+static int ibmvscsi_slave_configure(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = sdev->host;
+ unsigned long lock_flags = 0;
+
+ spin_lock_irqsave(shost->host_lock, lock_flags);
+ if (sdev->type == TYPE_DISK)
+ sdev->allow_restart = 1;
+ scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
+ spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ return 0;
+}
+
/* ------------------------------------------------------------
* sysfs attributes
*/
@@ -1482,8 +1520,9 @@ static struct scsi_host_template driver_template = {
.queuecommand = ibmvscsi_queuecommand,
.eh_abort_handler = ibmvscsi_eh_abort_handler,
.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+ .slave_configure = ibmvscsi_slave_configure,
.cmd_per_lun = 16,
- .can_queue = 1, /* Updated after SRP_LOGIN */
+ .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
.this_id = -1,
.sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
@@ -1503,6 +1542,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vdev->dev.driver_data = NULL;
+ driver_template.can_queue = max_requests;
host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
if (!host) {
printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5c6d93582929..77cc1d40f5bb 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -44,6 +44,8 @@ struct Scsi_Host;
*/
#define MAX_INDIRECT_BUFS 10
+#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+
/* ------------------------------------------------------------
* Data Structures
*/
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index 140dd9700ff6..8ba7dd09d01d 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -35,7 +35,7 @@
#include "ibmvscsi.h"
#define INITIAL_SRP_LIMIT 16
-#define DEFAULT_MAX_SECTORS 512
+#define DEFAULT_MAX_SECTORS 256
#define TGT_NAME "ibmvstgt"
@@ -248,8 +248,8 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
md[i].va + mdone);
if (err != H_SUCCESS) {
- eprintk("rdma error %d %d\n", dir, slen);
- goto out;
+ eprintk("rdma error %d %d %ld\n", dir, slen, err);
+ return -EIO;
}
mlen -= slen;
@@ -265,45 +265,35 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
if (sidx > nsg) {
eprintk("out of sg %p %d %d\n",
iue, sidx, nsg);
- goto out;
+ return -EIO;
}
}
};
rest -= mlen;
}
-out:
-
return 0;
}
-static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
- void (*done)(struct scsi_cmnd *))
-{
- struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
- int err;
-
- err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
- done(sc);
-
- return err;
-}
-
static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
void (*done)(struct scsi_cmnd *))
{
unsigned long flags;
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
struct srp_target *target = iue->target;
+ int err = 0;
- dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+ dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+ cmd->usg_sg);
+
+ if (sc->use_sg)
+ err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
spin_lock_irqsave(&target->lock, flags);
list_del(&iue->ilist);
spin_unlock_irqrestore(&target->lock, flags);
- if (sc->result != SAM_STAT_GOOD) {
+ if (err|| sc->result != SAM_STAT_GOOD) {
eprintk("operation failed %p %d %x\n",
iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
@@ -503,7 +493,8 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
{
struct vio_port *vport = target_to_port(target);
struct iu_entry *iue;
- long err, done;
+ long err;
+ int done = 1;
iue = srp_iu_get(target);
if (!iue) {
@@ -518,7 +509,6 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
if (err != H_SUCCESS) {
eprintk("%ld transferring data error %p\n", err, iue);
- done = 1;
goto out;
}
@@ -794,7 +784,6 @@ static struct scsi_host_template ibmvstgt_sht = {
.use_clustering = DISABLE_CLUSTERING,
.max_sectors = DEFAULT_MAX_SECTORS,
.transfer_response = ibmvstgt_cmd_done,
- .transfer_data = ibmvstgt_transfer_data,
.eh_abort_handler = ibmvstgt_eh_abort_handler,
.tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
.shost_attrs = ibmvstgt_attrs,