[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>
This commit is contained in:
parent
883c98feaa
commit
683229845f
5 changed files with 19 additions and 34 deletions
|
@ -545,6 +545,10 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
||||||
&zfcp_sysfs_adapter_attrs))
|
&zfcp_sysfs_adapter_attrs))
|
||||||
goto failed;
|
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))
|
if (!zfcp_adapter_scsi_register(adapter))
|
||||||
return adapter;
|
return adapter;
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ struct zfcp_adapter {
|
||||||
struct work_struct scan_work;
|
struct work_struct scan_work;
|
||||||
struct service_level service_level;
|
struct service_level service_level;
|
||||||
struct workqueue_struct *work_queue;
|
struct workqueue_struct *work_queue;
|
||||||
|
struct device_dma_parameters dma_parms;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zfcp_port {
|
struct zfcp_port {
|
||||||
|
|
|
@ -206,35 +206,6 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
|
||||||
zfcp_qdio_zero_sbals(sbal, first, count);
|
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
|
* zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
|
||||||
* @fsf_req: request to be processed
|
* @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)
|
int max_sbals)
|
||||||
{
|
{
|
||||||
struct qdio_buffer_element *sbale;
|
struct qdio_buffer_element *sbale;
|
||||||
int retval, bytes = 0;
|
int bytes = 0;
|
||||||
|
|
||||||
/* figure out last allowed SBAL */
|
/* figure out last allowed SBAL */
|
||||||
zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);
|
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;
|
sbale->flags |= sbtype;
|
||||||
|
|
||||||
for (; sg; sg = sg_next(sg)) {
|
for (; sg; sg = sg_next(sg)) {
|
||||||
retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
|
sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
|
||||||
sg_virt(sg), sg->length);
|
if (!sbale) {
|
||||||
if (retval < 0)
|
atomic_inc(&qdio->req_q_full);
|
||||||
return retval;
|
zfcp_qdio_undo_sbals(qdio, q_req);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sbale->addr = sg_virt(sg);
|
||||||
|
sbale->length = sg->length;
|
||||||
|
|
||||||
bytes += sg->length;
|
bytes += sg->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <asm/qdio.h>
|
#include <asm/qdio.h>
|
||||||
|
|
||||||
|
#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
|
* struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
|
||||||
* @sbal: qdio buffers
|
* @sbal: qdio buffers
|
||||||
|
|
|
@ -682,6 +682,7 @@ struct zfcp_data zfcp_data = {
|
||||||
.use_clustering = 1,
|
.use_clustering = 1,
|
||||||
.sdev_attrs = zfcp_sysfs_sdev_attrs,
|
.sdev_attrs = zfcp_sysfs_sdev_attrs,
|
||||||
.max_sectors = (ZFCP_MAX_SBALES_PER_REQ * 8),
|
.max_sectors = (ZFCP_MAX_SBALES_PER_REQ * 8),
|
||||||
|
.dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
|
||||||
.shost_attrs = zfcp_sysfs_shost_attrs,
|
.shost_attrs = zfcp_sysfs_shost_attrs,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue