[SCSI] ibmvscsi: allow for dynamic adjustment of server request_limit
The request limit calculations used previously on the client failed to mirror the state of the server. Additionally, when a value < 3 was provided there could be problems setting can_queue and handling abort and reset commands. Signed-off-by: "Robert Jennings" <rcj@linux.vnet.ibm.com> Signed-off-by: Santiago Leon <santil@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
a45c863f02
commit
a897ff2a63
@ -85,7 +85,7 @@
|
|||||||
static int max_id = 64;
|
static int max_id = 64;
|
||||||
static int max_channel = 3;
|
static int max_channel = 3;
|
||||||
static int init_timeout = 5;
|
static int init_timeout = 5;
|
||||||
static int max_requests = 50;
|
static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
|
||||||
|
|
||||||
#define IBMVSCSI_VERSION "1.5.8"
|
#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 request_status;
|
||||||
int rc;
|
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
|
* Note that there are rare cases involving driver generated requests
|
||||||
* (such as task management requests) that the mid layer may think we
|
* (such as task management requests) that the mid layer may think we
|
||||||
* can handle more requests (can_queue) when we actually can't
|
* can handle more requests (can_queue) when we actually can't
|
||||||
@ -551,10 +552,31 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
|
|||||||
*/
|
*/
|
||||||
if (request_status < -1)
|
if (request_status < -1)
|
||||||
goto send_error;
|
goto send_error;
|
||||||
/* Otherwise, if we have run out of requests */
|
/* Otherwise, we may have run out of requests. */
|
||||||
else if (request_status < 0)
|
/* 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;
|
goto send_busy;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the IU into the transfer area */
|
/* Copy the IU into the transfer area */
|
||||||
*evt_struct->xfer_iu = evt_struct->iu;
|
*evt_struct->xfer_iu = evt_struct->iu;
|
||||||
@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
|
|||||||
|
|
||||||
printk(KERN_ERR "ibmvscsi: send error %d\n",
|
printk(KERN_ERR "ibmvscsi: send error %d\n",
|
||||||
rc);
|
rc);
|
||||||
|
atomic_inc(&hostdata->request_limit);
|
||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,6 +604,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
|
|||||||
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
|
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
|
||||||
|
|
||||||
free_event_struct(&hostdata->pool, evt_struct);
|
free_event_struct(&hostdata->pool, evt_struct);
|
||||||
|
atomic_inc(&hostdata->request_limit);
|
||||||
return SCSI_MLQUEUE_HOST_BUSY;
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
|
||||||
send_error:
|
send_error:
|
||||||
@ -831,23 +855,16 @@ static void login_rsp(struct srp_event_struct *evt_struct)
|
|||||||
|
|
||||||
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
|
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
|
||||||
|
|
||||||
if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
|
if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
|
||||||
(max_requests - 2))
|
printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
|
||||||
evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
|
|
||||||
max_requests - 2;
|
|
||||||
|
|
||||||
/* 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,
|
atomic_set(&hostdata->request_limit,
|
||||||
evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
|
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 */
|
/* If we had any pending I/Os, kick them */
|
||||||
scsi_unblock_requests(hostdata->host);
|
scsi_unblock_requests(hostdata->host);
|
||||||
|
|
||||||
@ -1483,7 +1500,7 @@ static struct scsi_host_template driver_template = {
|
|||||||
.eh_abort_handler = ibmvscsi_eh_abort_handler,
|
.eh_abort_handler = ibmvscsi_eh_abort_handler,
|
||||||
.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
|
.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
|
||||||
.cmd_per_lun = 16,
|
.cmd_per_lun = 16,
|
||||||
.can_queue = 1, /* Updated after SRP_LOGIN */
|
.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
|
||||||
.this_id = -1,
|
.this_id = -1,
|
||||||
.sg_tablesize = SG_ALL,
|
.sg_tablesize = SG_ALL,
|
||||||
.use_clustering = ENABLE_CLUSTERING,
|
.use_clustering = ENABLE_CLUSTERING,
|
||||||
@ -1503,6 +1520,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||||||
|
|
||||||
vdev->dev.driver_data = NULL;
|
vdev->dev.driver_data = NULL;
|
||||||
|
|
||||||
|
driver_template.can_queue = max_requests;
|
||||||
host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
|
host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
|
||||||
if (!host) {
|
if (!host) {
|
||||||
printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
|
printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
|
||||||
|
@ -44,6 +44,8 @@ struct Scsi_Host;
|
|||||||
*/
|
*/
|
||||||
#define MAX_INDIRECT_BUFS 10
|
#define MAX_INDIRECT_BUFS 10
|
||||||
|
|
||||||
|
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
|
||||||
|
|
||||||
/* ------------------------------------------------------------
|
/* ------------------------------------------------------------
|
||||||
* Data Structures
|
* Data Structures
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user