[SCSI] ibmvscsi: Make max_requests module parameter more accurate
authorBrian King <brking@linux.vnet.ibm.com>
Wed, 17 Dec 2008 23:19:33 +0000 (17:19 -0600)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Fri, 2 Jan 2009 16:59:57 +0000 (10:59 -0600)
In a previous patch to fix an issue with error recovery,
the behavior of the max_requests module paramater was also
changed. If, for some reason, max_requests is set to one by
the user, we will end up with a negative number for can_queue.
Fix this by making max_requests not include the two event structs
needed to do error recovery.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/ibmvscsi/ibmvscsi.c

index 868d35ea01bba1ab0ad33a0ebbde6ed2dfc2c2a9..5c541f7850f931094e5deea7f4ad4c458ff9a285 100644 (file)
@@ -89,6 +89,7 @@ static int max_id = 64;
 static int max_channel = 3;
 static int init_timeout = 5;
 static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
+static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2;
 
 static struct scsi_transport_template *ibmvscsi_transport_template;
 
@@ -1633,7 +1634,7 @@ static struct scsi_host_template driver_template = {
 static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
 {
        /* iu_storage data allocated in initialize_event_pool */
-       unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
+       unsigned long desired_io = max_events * sizeof(union viosrp_iu);
 
        /* add io space for sg data */
        desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 *
@@ -1657,7 +1658,6 @@ 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 - 2;
        host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
        if (!host) {
                dev_err(&vdev->dev, "couldn't allocate host data\n");
@@ -1673,12 +1673,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        atomic_set(&hostdata->request_limit, -1);
        hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
 
-       rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
+       rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events);
        if (rc != 0 && rc != H_RESOURCE) {
                dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
                goto init_crq_failed;
        }
-       if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+       if (initialize_event_pool(&hostdata->pool, max_events, hostdata) != 0) {
                dev_err(&vdev->dev, "couldn't initialize event pool\n");
                goto init_pool_failed;
        }
@@ -1730,7 +1730,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
       add_host_failed:
        release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
-       ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
+       ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events);
       init_crq_failed:
        scsi_host_put(host);
       scsi_host_alloc_failed:
@@ -1742,7 +1742,7 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
        struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
        release_event_pool(&hostdata->pool, hostdata);
        ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
-                                       max_requests);
+                                       max_events);
 
        srp_remove_host(hostdata->host);
        scsi_remove_host(hostdata->host);
@@ -1779,6 +1779,10 @@ int __init ibmvscsi_module_init(void)
 {
        int ret;
 
+       /* Ensure we have two requests to do error recovery */
+       driver_template.can_queue = max_requests;
+       max_events = max_requests + 2;
+
        if (firmware_has_feature(FW_FEATURE_ISERIES))
                ibmvscsi_ops = &iseriesvscsi_ops;
        else if (firmware_has_feature(FW_FEATURE_VIO))