diff options
author | Robert Jennings <rcjenn@us.ibm.com> | 2007-03-28 13:45:46 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-04-01 11:36:39 -0400 |
commit | a897ff2a6386ac4368ba41db18b626afd903f9d8 (patch) | |
tree | b88472fc877f6f85d76fe89d9d92b737e675dc6b /drivers/scsi/ibmvscsi/ibmvscsi.c | |
parent | a45c863f02c808107172b4b2975e1130c7da66d6 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index fbc1d5c3b0a7..383f5948ba06 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -85,7 +85,7 @@ | |||
85 | static int max_id = 64; | 85 | static int max_id = 64; |
86 | static int max_channel = 3; | 86 | static int max_channel = 3; |
87 | static int init_timeout = 5; | 87 | static int init_timeout = 5; |
88 | static int max_requests = 50; | 88 | static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; |
89 | 89 | ||
90 | #define IBMVSCSI_VERSION "1.5.8" | 90 | #define IBMVSCSI_VERSION "1.5.8" |
91 | 91 | ||
@@ -538,7 +538,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
538 | int request_status; | 538 | int request_status; |
539 | int rc; | 539 | int rc; |
540 | 540 | ||
541 | /* If we have exhausted our request limit, just fail this request. | 541 | /* If we have exhausted our request limit, just fail this request, |
542 | * unless it is for a reset or abort. | ||
542 | * Note that there are rare cases involving driver generated requests | 543 | * Note that there are rare cases involving driver generated requests |
543 | * (such as task management requests) that the mid layer may think we | 544 | * (such as task management requests) that the mid layer may think we |
544 | * can handle more requests (can_queue) when we actually can't | 545 | * 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, | |||
551 | */ | 552 | */ |
552 | if (request_status < -1) | 553 | if (request_status < -1) |
553 | goto send_error; | 554 | goto send_error; |
554 | /* Otherwise, if we have run out of requests */ | 555 | /* Otherwise, we may have run out of requests. */ |
555 | else if (request_status < 0) | 556 | /* Abort and reset calls should make it through. |
556 | goto send_busy; | 557 | * Nothing except abort and reset should use the last two |
558 | * slots unless we had two or less to begin with. | ||
559 | */ | ||
560 | else if (request_status < 2 && | ||
561 | evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) { | ||
562 | /* In the case that we have less than two requests | ||
563 | * available, check the server limit as a combination | ||
564 | * of the request limit and the number of requests | ||
565 | * in-flight (the size of the send list). If the | ||
566 | * server limit is greater than 2, return busy so | ||
567 | * that the last two are reserved for reset and abort. | ||
568 | */ | ||
569 | int server_limit = request_status; | ||
570 | struct srp_event_struct *tmp_evt; | ||
571 | |||
572 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | ||
573 | server_limit++; | ||
574 | } | ||
575 | |||
576 | if (server_limit > 2) | ||
577 | goto send_busy; | ||
578 | } | ||
557 | } | 579 | } |
558 | 580 | ||
559 | /* Copy the IU into the transfer area */ | 581 | /* Copy the IU into the transfer area */ |
@@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
572 | 594 | ||
573 | printk(KERN_ERR "ibmvscsi: send error %d\n", | 595 | printk(KERN_ERR "ibmvscsi: send error %d\n", |
574 | rc); | 596 | rc); |
597 | atomic_inc(&hostdata->request_limit); | ||
575 | goto send_error; | 598 | goto send_error; |
576 | } | 599 | } |
577 | 600 | ||
@@ -581,7 +604,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
581 | unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); | 604 | unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); |
582 | 605 | ||
583 | free_event_struct(&hostdata->pool, evt_struct); | 606 | free_event_struct(&hostdata->pool, evt_struct); |
584 | return SCSI_MLQUEUE_HOST_BUSY; | 607 | atomic_inc(&hostdata->request_limit); |
608 | return SCSI_MLQUEUE_HOST_BUSY; | ||
585 | 609 | ||
586 | send_error: | 610 | send_error: |
587 | unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); | 611 | 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) | |||
831 | 855 | ||
832 | printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n"); | 856 | printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n"); |
833 | 857 | ||
834 | if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta > | 858 | if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0) |
835 | (max_requests - 2)) | 859 | printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n"); |
836 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta = | ||
837 | max_requests - 2; | ||
838 | 860 | ||
839 | /* Now we know what the real request-limit is */ | 861 | /* Now we know what the real request-limit is. |
862 | * This value is set rather than added to request_limit because | ||
863 | * request_limit could have been set to -1 by this client. | ||
864 | */ | ||
840 | atomic_set(&hostdata->request_limit, | 865 | atomic_set(&hostdata->request_limit, |
841 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); | 866 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); |
842 | 867 | ||
843 | hostdata->host->can_queue = | ||
844 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2; | ||
845 | |||
846 | if (hostdata->host->can_queue < 1) { | ||
847 | printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n"); | ||
848 | return; | ||
849 | } | ||
850 | |||
851 | /* If we had any pending I/Os, kick them */ | 868 | /* If we had any pending I/Os, kick them */ |
852 | scsi_unblock_requests(hostdata->host); | 869 | scsi_unblock_requests(hostdata->host); |
853 | 870 | ||
@@ -1483,7 +1500,7 @@ static struct scsi_host_template driver_template = { | |||
1483 | .eh_abort_handler = ibmvscsi_eh_abort_handler, | 1500 | .eh_abort_handler = ibmvscsi_eh_abort_handler, |
1484 | .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, | 1501 | .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, |
1485 | .cmd_per_lun = 16, | 1502 | .cmd_per_lun = 16, |
1486 | .can_queue = 1, /* Updated after SRP_LOGIN */ | 1503 | .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, |
1487 | .this_id = -1, | 1504 | .this_id = -1, |
1488 | .sg_tablesize = SG_ALL, | 1505 | .sg_tablesize = SG_ALL, |
1489 | .use_clustering = ENABLE_CLUSTERING, | 1506 | .use_clustering = ENABLE_CLUSTERING, |
@@ -1503,6 +1520,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1503 | 1520 | ||
1504 | vdev->dev.driver_data = NULL; | 1521 | vdev->dev.driver_data = NULL; |
1505 | 1522 | ||
1523 | driver_template.can_queue = max_requests; | ||
1506 | host = scsi_host_alloc(&driver_template, sizeof(*hostdata)); | 1524 | host = scsi_host_alloc(&driver_template, sizeof(*hostdata)); |
1507 | if (!host) { | 1525 | if (!host) { |
1508 | printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n"); | 1526 | printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n"); |