aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2010-04-30 12:09:33 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-02 15:42:29 -0400
commit683229845f1780b10041ee7a1043fc8f10061455 (patch)
tree88f58f214666762a71d1458a72646dd65372a1a6 /drivers/s390/scsi
parent883c98feaab708d0fc976225b146aa9307023c85 (diff)
[SCSI] zfcp: Report scatter-gather limits to SCSI and block layer
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>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c4
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c45
-rw-r--r--drivers/s390/scsi/zfcp_qdio.h2
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c1
5 files changed, 19 insertions, 34 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 1e6183a86ce5..abf33db647ff 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -545,6 +545,10 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
545 &zfcp_sysfs_adapter_attrs)) 545 &zfcp_sysfs_adapter_attrs))
546 goto failed; 546 goto failed;
547 547
548 /* report size limit per scatter-gather segment */
549 adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
550 adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
551
548 if (!zfcp_adapter_scsi_register(adapter)) 552 if (!zfcp_adapter_scsi_register(adapter))
549 return adapter; 553 return adapter;
550 554
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 7131c7db1f04..72132c13f45b 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -205,6 +205,7 @@ struct zfcp_adapter {
205 struct work_struct scan_work; 205 struct work_struct scan_work;
206 struct service_level service_level; 206 struct service_level service_level;
207 struct workqueue_struct *work_queue; 207 struct workqueue_struct *work_queue;
208 struct device_dma_parameters dma_parms;
208}; 209};
209 210
210struct zfcp_port { 211struct zfcp_port {
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index dbfa312a7f50..aa68515abe21 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -206,35 +206,6 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
206 zfcp_qdio_zero_sbals(sbal, first, count); 206 zfcp_qdio_zero_sbals(sbal, first, count);
207} 207}
208 208
209static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
210 struct zfcp_qdio_req *q_req,
211 unsigned int sbtype, void *start_addr,
212 unsigned int total_length)
213{
214 struct qdio_buffer_element *sbale;
215 unsigned long remaining, length;
216 void *addr;
217
218 /* split segment up */
219 for (addr = start_addr, remaining = total_length; remaining > 0;
220 addr += length, remaining -= length) {
221 sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
222 if (!sbale) {
223 atomic_inc(&qdio->req_q_full);
224 zfcp_qdio_undo_sbals(qdio, q_req);
225 return -EINVAL;
226 }
227
228 /* new piece must not exceed next page boundary */
229 length = min(remaining,
230 (PAGE_SIZE - ((unsigned long)addr &
231 (PAGE_SIZE - 1))));
232 sbale->addr = addr;
233 sbale->length = length;
234 }
235 return 0;
236}
237
238/** 209/**
239 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list 210 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
240 * @fsf_req: request to be processed 211 * @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,
248 int max_sbals) 219 int max_sbals)
249{ 220{
250 struct qdio_buffer_element *sbale; 221 struct qdio_buffer_element *sbale;
251 int retval, bytes = 0; 222 int bytes = 0;
252 223
253 /* figure out last allowed SBAL */ 224 /* figure out last allowed SBAL */
254 zfcp_qdio_sbal_limit(qdio, q_req, max_sbals); 225 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,
258 sbale->flags |= sbtype; 229 sbale->flags |= sbtype;
259 230
260 for (; sg; sg = sg_next(sg)) { 231 for (; sg; sg = sg_next(sg)) {
261 retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype, 232 sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
262 sg_virt(sg), sg->length); 233 if (!sbale) {
263 if (retval < 0) 234 atomic_inc(&qdio->req_q_full);
264 return retval; 235 zfcp_qdio_undo_sbals(qdio, q_req);
236 return -EINVAL;
237 }
238
239 sbale->addr = sg_virt(sg);
240 sbale->length = sg->length;
241
265 bytes += sg->length; 242 bytes += sg->length;
266 } 243 }
267 244
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h
index 8cca54631e1e..f2b5a363bb84 100644
--- a/drivers/s390/scsi/zfcp_qdio.h
+++ b/drivers/s390/scsi/zfcp_qdio.h
@@ -11,6 +11,8 @@
11 11
12#include <asm/qdio.h> 12#include <asm/qdio.h>
13 13
14#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE
15
14/** 16/**
15 * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count 17 * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
16 * @sbal: qdio buffers 18 * @sbal: qdio buffers
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index d13eb9a6408a..066b0507a639 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -682,6 +682,7 @@ struct zfcp_data zfcp_data = {
682 .use_clustering = 1, 682 .use_clustering = 1,
683 .sdev_attrs = zfcp_sysfs_sdev_attrs, 683 .sdev_attrs = zfcp_sysfs_sdev_attrs,
684 .max_sectors = (ZFCP_MAX_SBALES_PER_REQ * 8), 684 .max_sectors = (ZFCP_MAX_SBALES_PER_REQ * 8),
685 .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
685 .shost_attrs = zfcp_sysfs_shost_attrs, 686 .shost_attrs = zfcp_sysfs_shost_attrs,
686 }, 687 },
687}; 688};