[SCSI] zfcp: Report scatter-gather limits to SCSI and block layer
authorChristof Schmitt <christof.schmitt@de.ibm.com>
Fri, 30 Apr 2010 16:09:33 +0000 (18:09 +0200)
committerJames Bottomley <James.Bottomley@suse.de>
Sun, 2 May 2010 19:42:29 +0000 (15:42 -0400)
Instead of dealing with large segments in the scatter-gather lists in
zfcp_qdio.c, report the limits to the upper layers. With these limits
in place, the code for mapping large data blocks to multiple sbales
can be removed.

Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/s390/scsi/zfcp_scsi.c

index 1e6183a86ce5f4f7ccd91cfdd0566ee85ff70db3..abf33db647ff138d0dd4213a20206fe8aeae621b 100644 (file)
@@ -545,6 +545,10 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                               &zfcp_sysfs_adapter_attrs))
                goto failed;
 
+       /* report size limit per scatter-gather segment */
+       adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
+       adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
+
        if (!zfcp_adapter_scsi_register(adapter))
                return adapter;
 
index 7131c7db1f0478afb91614a23e01d95bcc615c52..72132c13f45b9260caf32eca6562c76e5a0353a2 100644 (file)
@@ -205,6 +205,7 @@ struct zfcp_adapter {
        struct work_struct      scan_work;
        struct service_level    service_level;
        struct workqueue_struct *work_queue;
+       struct device_dma_parameters dma_parms;
 };
 
 struct zfcp_port {
index dbfa312a7f50bb19e66812c310f22cd02fa4439b..aa68515abe21f44b9d5ab11b93fe0bdeac0a1e86 100644 (file)
@@ -206,35 +206,6 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
        zfcp_qdio_zero_sbals(sbal, first, count);
 }
 
-static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
-                               struct zfcp_qdio_req *q_req,
-                               unsigned int sbtype, void *start_addr,
-                               unsigned int total_length)
-{
-       struct qdio_buffer_element *sbale;
-       unsigned long remaining, length;
-       void *addr;
-
-       /* split segment up */
-       for (addr = start_addr, remaining = total_length; remaining > 0;
-            addr += length, remaining -= length) {
-               sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
-               if (!sbale) {
-                       atomic_inc(&qdio->req_q_full);
-                       zfcp_qdio_undo_sbals(qdio, q_req);
-                       return -EINVAL;
-               }
-
-               /* new piece must not exceed next page boundary */
-               length = min(remaining,
-                            (PAGE_SIZE - ((unsigned long)addr &
-                                          (PAGE_SIZE - 1))));
-               sbale->addr = addr;
-               sbale->length = length;
-       }
-       return 0;
-}
-
 /**
  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
  * @fsf_req: request to be processed
@@ -248,7 +219,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                            int max_sbals)
 {
        struct qdio_buffer_element *sbale;
-       int retval, bytes = 0;
+       int bytes = 0;
 
        /* figure out last allowed SBAL */
        zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);
@@ -258,10 +229,16 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
        sbale->flags |= sbtype;
 
        for (; sg; sg = sg_next(sg)) {
-               retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
-                                             sg_virt(sg), sg->length);
-               if (retval < 0)
-                       return retval;
+               sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
+               if (!sbale) {
+                       atomic_inc(&qdio->req_q_full);
+                       zfcp_qdio_undo_sbals(qdio, q_req);
+                       return -EINVAL;
+               }
+
+               sbale->addr = sg_virt(sg);
+               sbale->length = sg->length;
+
                bytes += sg->length;
        }
 
index 8cca54631e1e001d4c83aad80e842c50ff4fcb38..f2b5a363bb844c12aa586370679ee098ebac9ed0 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <asm/qdio.h>
 
+#define ZFCP_QDIO_SBALE_LEN    PAGE_SIZE
+
 /**
  * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
  * @sbal: qdio buffers
index d13eb9a6408a1a55103a14d83929fed0171b8ec2..066b0507a63915dca0b28bacf74903380e1d2644 100644 (file)
@@ -682,6 +682,7 @@ struct zfcp_data zfcp_data = {
                .use_clustering          = 1,
                .sdev_attrs              = zfcp_sysfs_sdev_attrs,
                .max_sectors             = (ZFCP_MAX_SBALES_PER_REQ * 8),
+               .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
                .shost_attrs             = zfcp_sysfs_shost_attrs,
        },
 };