As a step towards cleaning things up, I made the following patch,
which makes up a fake scatterlist for non-SG commands.  Since the SCSI
midlayer is moving towards having no non-SG commands (the only ones I
see now are mode sense -- ie none in the usual data path), eventually
we can delete even more code.


Thanks for cleaning this up

Anyway, I should be able to work on adding FMRs to this cleaner
framework now.

Here is the new fmr patch applied to your current framework

Thanks,
Vu

Signed-off-by: Vu Pham <[EMAIL PROTECTED]>


Index: ib_srp.c
===================================================================
--- ib_srp.c	(revision 5918)
+++ ib_srp.c	(working copy)
@@ -500,13 +500,88 @@ err:
 	return ret;
 }
 
+static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
+		       int sg_cnt, struct srp_request *req)
+		       
+{
+	dma_addr_t dma_addr;
+	u32 dma_len;
+	u32 cur_len;
+	u32 tmp_len;
+	int i;
+	u64 *dma_pages;
+	u32 page_cnt;
+	struct srp_fmr *srp_fmr;
+	int unaligned;
+
+	dma_pages = kmalloc(sizeof(u64) * sg_cnt * SRP_MAX_INDIRECT, GFP_ATOMIC);
+	if (!dma_pages)
+		goto err_dpages;	
+
+	srp_fmr = &req->s_fmr;
+	srp_fmr->len = 0;
+	page_cnt = 0;
+	cur_len = 0;
+	unaligned = 0;
+
+	/*
+	 * Walking the sg_list, group all aligned sg_entry to one fmr
+	 * If there is an unaligned sg_entry, fall back to dma_mr
+	 */
+	for (i = 0; i < sg_cnt; ++i, ++scat) {
+		dma_len = sg_dma_len(scat);
+		dma_addr = sg_dma_address(scat);
+
+		if (dma_addr & (PAGE_SIZE - 1))
+			++unaligned;
+
+		if ((dma_addr + dma_len) & (PAGE_SIZE - 1))
+			++unaligned;
+
+		if (i == 0)
+			srp_fmr->io_addr = dma_addr & PAGE_MASK;
+
+		/* 
+		 * Every FMR segment has atmost 1 unaligned element
+		 */
+		if (!unaligned) {
+			cur_len += dma_len;
+			for (tmp_len = 0; tmp_len < dma_len;
+			     tmp_len += PAGE_SIZE, dma_addr += PAGE_SIZE)
+				dma_pages[page_cnt++] = dma_addr & PAGE_MASK;
+
+		} else
+			goto err_farr;
+
+		if (i == (sg_cnt - 1)) {
+			srp_fmr->mem =
+				ib_fmr_pool_map_phys(target->srp_host->fmr_pool,
+						     dma_pages, page_cnt,
+						     &srp_fmr->io_addr);
+			if (IS_ERR(srp_fmr->mem))
+				goto err_farr;
+
+			srp_fmr->len = cur_len;
+		}
+	}
+
+	kfree(dma_pages);
+
+	return 0;
+
+err_farr:
+	kfree(dma_pages);
+
+err_dpages:
+	return -ENOMEM;
+}
+
 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 			struct srp_request *req)
 {
 	struct scatterlist *scat;
 	struct srp_cmd *cmd = req->cmd->buf;
 	int len, nents, count;
-	int i;
 	u8 fmt;
 
 	if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
@@ -519,21 +594,21 @@ static int srp_map_data(struct scsi_cmnd
 		return -EINVAL;
 	}
 
-	/*
-	 * This handling of non-SG commands can be killed when the
-	 * SCSI midlayer no longer generates non-SG commands.
-	 */
-	if (likely(scmnd->use_sg)) {
-		nents = scmnd->use_sg;
-		scat  = scmnd->request_buffer;
-	} else {
-		nents = 1;
-		scat  = &req->fake_sg;
-		sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
-	}
+        /*
+         * This handling of non-SG commands can be killed when the
+         * SCSI midlayer no longer generates non-SG commands.
+         */
+        if (likely(scmnd->use_sg)) {
+                nents = scmnd->use_sg;
+                scat  = scmnd->request_buffer;
+        } else {
+                nents = 1;
+                scat  = &req->fake_sg;
+                sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
+        }
 
-	count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents,
-			   scmnd->sc_data_direction);
+	count = dma_map_sg(target->srp_host->dev->dma_device,
+			   scat, nents, scmnd->sc_data_direction);
 
 	if (count == 1) {
 		struct srp_direct_buf *buf = (void *) cmd->add_data;
@@ -550,6 +625,30 @@ static int srp_map_data(struct scsi_cmnd
 		struct srp_indirect_buf *buf = (void *) cmd->add_data;
 		u32 datalen = 0;
 
+		if (srp_map_fmr(target, scat, count, req)) {
+			int i;
+
+			/* fail map_fmr - use dma rkey */
+			for (i = 0; i < count; ++i) {
+				buf->desc_list[i].va =
+					cpu_to_be64(sg_dma_address(&scat[i]));
+				buf->desc_list[i].key =
+					cpu_to_be32(target->srp_host->mr->rkey);
+				buf->desc_list[i].len =
+					cpu_to_be32(sg_dma_len(&scat[i]));
+				datalen += sg_dma_len(&scat[i]);
+			}
+		} else {
+			count = 1;
+			buf->desc_list[0].va =
+				cpu_to_be64(req->s_fmr.io_addr);
+			buf->desc_list[0].key =
+				cpu_to_be32(req->s_fmr.mem->fmr->rkey);
+			buf->desc_list[0].len =
+				cpu_to_be32(req->s_fmr.len);
+			datalen += req->s_fmr.len;
+		}
+	
 		fmt = SRP_DATA_DESC_INDIRECT;
 
 		if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -565,20 +664,11 @@ static int srp_map_data(struct scsi_cmnd
 		buf->table_desc.len =
 			cpu_to_be32(count * sizeof (struct srp_direct_buf));
 
-		for (i = 0; i < count; ++i) {
-			buf->desc_list[i].va  = cpu_to_be64(sg_dma_address(&scat[i]));
-			buf->desc_list[i].key =
-				cpu_to_be32(target->srp_host->mr->rkey);
-			buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
-
-			datalen += sg_dma_len(&scat[i]);
-		}
-
 		buf->len = cpu_to_be32(datalen);
 
 		len = sizeof (struct srp_cmd) +
-			sizeof (struct srp_indirect_buf) +
-			count * sizeof (struct srp_direct_buf);
+			      sizeof (struct srp_indirect_buf) +
+			      count * sizeof (struct srp_direct_buf);
 	}
 
 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -586,6 +676,7 @@ static int srp_map_data(struct scsi_cmnd
 	else
 		cmd->buf_fmt = fmt;
 
+
 	return len;
 }
 
@@ -593,28 +684,33 @@ static void srp_unmap_data(struct scsi_c
 			   struct srp_target_port *target,
 			   struct srp_request *req)
 {
-	struct scatterlist *scat;
-	int nents;
-
-	if (!scmnd->request_buffer ||
-	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
-	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
-	    return;
+        struct scatterlist *scat;
+        int nents;
 
-	/*
-	 * This handling of non-SG commands can be killed when the
-	 * SCSI midlayer no longer generates non-SG commands.
-	 */
-	if (likely(scmnd->use_sg)) {
-		nents = scmnd->use_sg;
-		scat  = (struct scatterlist *) scmnd->request_buffer;
-	} else {
-		nents = 1;
-		scat  = (struct scatterlist *) scmnd->request_buffer;
+        if (!scmnd->request_buffer ||
+            (scmnd->sc_data_direction != DMA_TO_DEVICE &&
+             scmnd->sc_data_direction != DMA_FROM_DEVICE))
+            return;
+
+        /*
+         * This handling of non-SG commands can be killed when the
+         * SCSI midlayer no longer generates non-SG commands.
+         */
+        if (likely(scmnd->use_sg)) {
+                nents = scmnd->use_sg;
+                scat  = (struct scatterlist *) scmnd->request_buffer;
+        } else {
+                nents = 1;
+                scat  = (struct scatterlist *) scmnd->request_buffer;
+        }
+
+        dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+                     scmnd->sc_data_direction);
+
+	if (req->s_fmr.len) {
+		ib_fmr_pool_unmap(req->s_fmr.mem);
+		req->s_fmr.len = 0;
 	}
-
-	dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
-		     scmnd->sc_data_direction);
 }
 
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -1322,6 +1418,7 @@ static struct scsi_host_template srp_tem
 	.can_queue			= SRP_SQ_SIZE,
 	.this_id			= -1,
 	.sg_tablesize			= SRP_MAX_INDIRECT,
+	.max_sectors			= SRP_MAX_SECTORS,
 	.cmd_per_lun			= SRP_SQ_SIZE,
 	.use_clustering			= ENABLE_CLUSTERING,
 	.shost_attrs			= srp_host_attrs
@@ -1513,8 +1610,10 @@ static ssize_t srp_create_target(struct 
 
 	INIT_WORK(&target->work, srp_reconnect_work, target);
 
-	for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
+	for (i = 0; i < SRP_SQ_SIZE - 1; ++i) {
+		memset(&target->req_ring[i].s_fmr, 0, sizeof(struct srp_fmr));
 		target->req_ring[i].next = i + 1;
+	}
 	target->req_ring[SRP_SQ_SIZE - 1].next = -1;
 	INIT_LIST_HEAD(&target->req_queue);
 
@@ -1598,7 +1697,8 @@ static ssize_t show_port(struct class_de
 
 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
+static struct srp_host *srp_add_port(struct ib_device *device,
+				     struct srp_dev_data *dev_data, u8 port)
 {
 	struct srp_host *host;
 
@@ -1615,16 +1715,9 @@ static struct srp_host *srp_add_port(str
 	host->initiator_port_id[7] = port;
 	memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
 
-	host->pd   = ib_alloc_pd(device);
-	if (IS_ERR(host->pd))
-		goto err_free;
-
-	host->mr   = ib_get_dma_mr(host->pd,
-				   IB_ACCESS_LOCAL_WRITE |
-				   IB_ACCESS_REMOTE_READ |
-				   IB_ACCESS_REMOTE_WRITE);
-	if (IS_ERR(host->mr))
-		goto err_pd;
+	host->pd = dev_data->pd;
+	host->mr = dev_data->mr;
+	host->fmr_pool = dev_data->fmr_pool;
 
 	host->class_dev.class = &srp_class;
 	host->class_dev.dev   = device->dma_device;
@@ -1632,7 +1725,7 @@ static struct srp_host *srp_add_port(str
 		 device->name, port);
 
 	if (class_device_register(&host->class_dev))
-		goto err_mr;
+		goto free_host;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
 		goto err_class;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
@@ -1645,13 +1738,7 @@ static struct srp_host *srp_add_port(str
 err_class:
 	class_device_unregister(&host->class_dev);
 
-err_mr:
-	ib_dereg_mr(host->mr);
-
-err_pd:
-	ib_dealloc_pd(host->pd);
-
-err_free:
+free_host:
 	kfree(host);
 
 	return NULL;
@@ -1659,18 +1746,55 @@ err_free:
 
 static void srp_add_one(struct ib_device *device)
 {
-	struct list_head *dev_list;
+	struct srp_dev_data *dev_data;
+	struct ib_device_attr *dev_attr;
+	struct ib_fmr_pool_param fmr_param;
 	struct srp_host *host;
 	int s, e, p;
 
 	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
 		return;
 
-	dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
-	if (!dev_list)
+	dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
+	if (!dev_attr)
 		return;
 
-	INIT_LIST_HEAD(dev_list);
+	if (ib_query_device(device, dev_attr)) {
+		printk(KERN_WARNING PFX "Query device failed for %s\n",
+		       device->name);
+		goto free_attr;
+	}
+
+	dev_data = kmalloc(sizeof *dev_data, GFP_KERNEL);
+	if (!dev_data)
+		goto free_attr;
+
+	INIT_LIST_HEAD(&dev_data->dev_list);
+
+	dev_data->pd = ib_alloc_pd(device);
+	if (IS_ERR(dev_data->pd))
+		goto free_dev;
+
+	dev_data->mr = ib_get_dma_mr(dev_data->pd,
+				     IB_ACCESS_LOCAL_WRITE |
+				     IB_ACCESS_REMOTE_READ |
+				     IB_ACCESS_REMOTE_WRITE);
+	if (IS_ERR(dev_data->mr))
+		goto err_pd;
+
+	memset(&fmr_param, 0, sizeof fmr_param);
+	fmr_param.pool_size = SRP_FMR_POOL_SIZE;
+	fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE;
+	fmr_param.cache = 0;
+	fmr_param.max_pages_per_fmr = SRP_MAX_SECTORS * 512 / PAGE_SIZE;
+	fmr_param.page_shift = PAGE_SHIFT;
+	fmr_param.access = (IB_ACCESS_LOCAL_WRITE |
+			     IB_ACCESS_REMOTE_WRITE |
+			     IB_ACCESS_REMOTE_READ);
+
+	dev_data->fmr_pool = ib_create_fmr_pool(dev_data->pd, &fmr_param);
+	if (IS_ERR(dev_data->fmr_pool))
+		goto err_mr;
 
 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
 		s = 0;
@@ -1681,25 +1805,36 @@ static void srp_add_one(struct ib_device
 	}
 
 	for (p = s; p <= e; ++p) {
-		host = srp_add_port(device, p);
+		host = srp_add_port(device, dev_data, p);
 		if (host)
-			list_add_tail(&host->list, dev_list);
+			list_add_tail(&host->list, &dev_data->dev_list);
 	}
 
-	ib_set_client_data(device, &srp_client, dev_list);
+	ib_set_client_data(device, &srp_client, dev_data);
+
+	goto free_attr;
+
+err_mr:
+	ib_dereg_mr(dev_data->mr);
+err_pd:
+	ib_dealloc_pd(dev_data->pd);
+free_dev:
+	kfree(dev_data);
+free_attr:
+	kfree(dev_attr);
 }
 
 static void srp_remove_one(struct ib_device *device)
 {
-	struct list_head *dev_list;
+	struct srp_dev_data *dev_data;
 	struct srp_host *host, *tmp_host;
 	LIST_HEAD(target_list);
 	struct srp_target_port *target, *tmp_target;
 	unsigned long flags;
 
-	dev_list = ib_get_client_data(device, &srp_client);
+	dev_data = ib_get_client_data(device, &srp_client);
 
-	list_for_each_entry_safe(host, tmp_host, dev_list, list) {
+	list_for_each_entry_safe(host, tmp_host, &dev_data->dev_list, list) {
 		class_device_unregister(&host->class_dev);
 		/*
 		 * Wait for the sysfs entry to go away, so that no new
@@ -1737,12 +1872,13 @@ static void srp_remove_one(struct ib_dev
 			scsi_host_put(target->scsi_host);
 		}
 
-		ib_dereg_mr(host->mr);
-		ib_dealloc_pd(host->pd);
 		kfree(host);
 	}
 
-	kfree(dev_list);
+	ib_destroy_fmr_pool(dev_data->fmr_pool);
+	ib_dereg_mr(dev_data->mr);
+	ib_dealloc_pd(dev_data->pd);
+	kfree(dev_data);
 }
 
 static int __init srp_init_module(void)
Index: ib_srp.h
===================================================================
--- ib_srp.h	(revision 5918)
+++ ib_srp.h	(working copy)
@@ -53,6 +53,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_sa.h>
 #include <rdma/ib_cm.h>
+#include <rdma/ib_fmr_pool.h>
 
 enum {
 	SRP_PATH_REC_TIMEOUT_MS	= 1000,
@@ -63,13 +64,17 @@ enum {
 
 	SRP_MAX_LUN		= 512,
 	SRP_MAX_IU_LEN		= 256,
+	SRP_MAX_SECTORS		= 256,
 
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
 	SRP_SQ_SIZE		= SRP_RQ_SIZE - 1,
 	SRP_CQ_SIZE		= SRP_SQ_SIZE + SRP_RQ_SIZE,
 
-	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1)
+	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
+
+	SRP_FMR_POOL_SIZE	= 2048,
+	SRP_FMR_DIRTY_SIZE	= SRP_FMR_POOL_SIZE >> 4
 };
 
 #define SRP_OP_RECV		(1 << 31)
@@ -84,6 +89,13 @@ enum srp_target_state {
 	SRP_TARGET_REMOVED
 };
 
+struct srp_dev_data {
+	struct list_head	dev_list;
+	struct ib_pd		*pd;
+	struct ib_mr		*mr;
+	struct ib_fmr_pool	*fmr_pool;
+};
+
 struct srp_host {
 	u8			initiator_port_id[16];
 	struct ib_device       *dev;
@@ -95,6 +107,13 @@ struct srp_host {
 	struct mutex            target_mutex;
 	struct completion	released;
 	struct list_head	list;
+	struct ib_fmr_pool	*fmr_pool;
+};
+
+struct srp_fmr {
+	u64			io_addr;
+	struct ib_pool_fmr	*mem;
+	u32			len;
 };
 
 struct srp_request {
@@ -103,14 +122,15 @@ struct srp_request {
 	struct srp_iu	       *cmd;
 	struct srp_iu	       *tsk_mgmt;
 	/*
-	 * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
-	 * when the SCSI midlayer no longer generates non-SG commands.
-	 */
-	struct scatterlist	fake_sg;
+         * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
+         * when the SCSI midlayer no longer generates non-SG commands.
+         */
+        struct scatterlist      fake_sg;
 	struct completion	done;
 	short			next;
 	u8			cmd_done;
 	u8			tsk_status;
+	struct srp_fmr		s_fmr;
 };
 
 struct srp_target_port {
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to