Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68322984 authored by Christof Schmitt's avatar Christof Schmitt Committed by James Bottomley
Browse files

[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: default avatarSwen Schillig <swen@vnet.ibm.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 883c98fe
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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 {
+11 −34
Original line number Diff line number Diff line
@@ -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;
	}

+2 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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,
	},
};