aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIshai Rabinovitz <ishai@mellanox.co.il>2006-08-03 13:35:43 -0400
committerRoland Dreier <rolandd@cisco.com>2006-08-03 13:35:43 -0400
commit559ce8f150d7d031c79c4d79173860f1bdfe3ce4 (patch)
treecaaa6a11e5678ef70f5ef86748b3805717edebb1
parentd916a8f1b43b358685b1672390ead11f2d3b74c6 (diff)
IB/srp: Work around data corruption bug on Mellanox targets
Data corruption has been seen with Mellanox SRP targets when FMRs create a memory region with I/O virtual address != 0. Add a workaround that disables FMR merging for Mellanox targets (OUI 0002c9). Signed-off-by: Ishai Rabinovitz <ishai@mellanox.co.il> Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ff94e4e32691..8257d5a2c8f8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -77,6 +77,14 @@ MODULE_PARM_DESC(topspin_workarounds,
77 77
78static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; 78static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
79 79
80static int mellanox_workarounds = 1;
81
82module_param(mellanox_workarounds, int, 0444);
83MODULE_PARM_DESC(mellanox_workarounds,
84 "Enable workarounds for Mellanox SRP target bugs if != 0");
85
86static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 };
87
80static void srp_add_one(struct ib_device *device); 88static void srp_add_one(struct ib_device *device);
81static void srp_remove_one(struct ib_device *device); 89static void srp_remove_one(struct ib_device *device);
82static void srp_completion(struct ib_cq *cq, void *target_ptr); 90static void srp_completion(struct ib_cq *cq, void *target_ptr);
@@ -569,7 +577,7 @@ err:
569 return ret; 577 return ret;
570} 578}
571 579
572static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, 580static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
573 int sg_cnt, struct srp_request *req, 581 int sg_cnt, struct srp_request *req,
574 struct srp_direct_buf *buf) 582 struct srp_direct_buf *buf)
575{ 583{
@@ -579,10 +587,15 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
579 int page_cnt; 587 int page_cnt;
580 int i, j; 588 int i, j;
581 int ret; 589 int ret;
590 struct srp_device *dev = target->srp_host->dev;
582 591
583 if (!dev->fmr_pool) 592 if (!dev->fmr_pool)
584 return -ENODEV; 593 return -ENODEV;
585 594
595 if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) &&
596 mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3))
597 return -EINVAL;
598
586 len = page_cnt = 0; 599 len = page_cnt = 0;
587 for (i = 0; i < sg_cnt; ++i) { 600 for (i = 0; i < sg_cnt; ++i) {
588 if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { 601 if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
@@ -685,7 +698,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
685 buf->va = cpu_to_be64(sg_dma_address(scat)); 698 buf->va = cpu_to_be64(sg_dma_address(scat));
686 buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); 699 buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
687 buf->len = cpu_to_be32(sg_dma_len(scat)); 700 buf->len = cpu_to_be32(sg_dma_len(scat));
688 } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, 701 } else if (srp_map_fmr(target, scat, count, req,
689 (void *) cmd->add_data)) { 702 (void *) cmd->add_data)) {
690 /* 703 /*
691 * FMR mapping failed, and the scatterlist has more 704 * FMR mapping failed, and the scatterlist has more