Another attempt to implement fmr for srp
+ moving dev_list, pd, dma mr, and fmr resource to srp_device per ib_device
+ implementing fmr - try to build a single fmr per scsi_cmd if fail then
falling back to dma mr
Signed-off-by: Vu Pham <[EMAIL PROTECTED]>
Index: ib_srp.c
===================================================================
--- ib_srp.c (revision 5513)
+++ ib_srp.c (working copy)
@@ -500,6 +500,83 @@ 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, register the previous fmr if any
+ * then create a new fmr and register it for the unaligned sg_entry
+ */
+ 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)
{
@@ -520,7 +597,6 @@ static int srp_map_data(struct scsi_cmnd
if (scmnd->use_sg) {
struct scatterlist *scat = scmnd->request_buffer;
int n;
- int i;
n = dma_map_sg(target->srp_host->dev->dma_device,
scat, scmnd->use_sg, scmnd->sc_data_direction);
@@ -540,6 +616,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, n, req)) {
+ int i;
+
+ /* fail map_fmr - use dma rkey */
+ for (i = 0; i < n; ++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 {
+ n = 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)
@@ -555,15 +655,6 @@ static int srp_map_data(struct scsi_cmnd
buf->table_desc.len =
cpu_to_be32(n * sizeof (struct srp_direct_buf));
- for (i = 0; i < n; ++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) +
@@ -622,6 +713,11 @@ static void srp_unmap_data(struct scsi_c
pci_unmap_addr(req, direct_mapping),
scmnd->request_bufflen,
scmnd->sc_data_direction);
+
+ if (req->s_fmr.len) {
+ ib_fmr_pool_unmap(req->s_fmr.mem);
+ req->s_fmr.len = 0;
+ }
}
static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -1242,6 +1338,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
};
@@ -1431,8 +1528,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);
@@ -1516,7 +1615,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;
@@ -1533,16 +1633,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;
@@ -1550,7 +1643,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))
@@ -1563,13 +1656,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;
@@ -1577,18 +1664,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;
@@ -1599,25 +1723,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
@@ -1655,12 +1790,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 5513)
+++ ib_srp.h (working copy)
@@ -52,6 +52,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,
@@ -62,13 +63,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)
@@ -83,6 +88,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;
@@ -94,6 +106,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 {
@@ -106,6 +125,7 @@ struct srp_request {
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