aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2010-11-26 13:22:48 -0500
committerDavid Dillow <dillowda@ornl.gov>2011-01-05 15:24:25 -0500
commitdcb4cb85f4b7caac9769bce464fef16306a4758c (patch)
tree1c21889c8b778415f9a8d46fcf28853eb42ede18 /drivers/infiniband
parent9709f0e05b827049733f439de82a4a1688b37b86 (diff)
IB/srp: allow lockless work posting
Only one CPU at a time will own an RX IU, so using the address of the IU as the work request cookie allows us to avoid taking a lock. We can similarly prepare the TX path for lockless posting by moving the free TX IUs to a list. This also removes the requirement that the queue sizes be a power of 2. Signed-off-by: Bart Van Assche <bvanassche@acm.org> [ broken out, small cleanups, and modified to avoid needing an extra field in the IU by David Dillow] Signed-off-by: David Dillow <dillowda@ornl.gov>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c65
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h7
2 files changed, 28 insertions, 44 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index def9e6b38459..aa78d2615c8d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -568,7 +568,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
568 struct ib_qp_attr qp_attr; 568 struct ib_qp_attr qp_attr;
569 struct srp_request *req, *tmp; 569 struct srp_request *req, *tmp;
570 struct ib_wc wc; 570 struct ib_wc wc;
571 int ret; 571 int i, ret;
572 572
573 if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING)) 573 if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING))
574 return -EAGAIN; 574 return -EAGAIN;
@@ -601,9 +601,9 @@ static int srp_reconnect_target(struct srp_target_port *target)
601 srp_reset_req(target, req); 601 srp_reset_req(target, req);
602 spin_unlock_irq(target->scsi_host->host_lock); 602 spin_unlock_irq(target->scsi_host->host_lock);
603 603
604 target->rx_head = 0; 604 list_del_init(&target->free_tx);
605 target->tx_head = 0; 605 for (i = 0; i < SRP_SQ_SIZE; ++i)
606 target->tx_tail = 0; 606 list_move(&target->tx_ring[i]->list, &target->free_tx);
607 607
608 target->qp_in_error = 0; 608 target->qp_in_error = 0;
609 ret = srp_connect_target(target); 609 ret = srp_connect_target(target);
@@ -817,7 +817,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
817 817
818/* 818/*
819 * Must be called with target->scsi_host->host_lock held to protect 819 * Must be called with target->scsi_host->host_lock held to protect
820 * req_lim and tx_head. Lock cannot be dropped between call here and 820 * req_lim and free_tx. Lock cannot be dropped between call here and
821 * call to __srp_post_send(). 821 * call to __srp_post_send().
822 * 822 *
823 * Note: 823 * Note:
@@ -837,7 +837,7 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
837 837
838 srp_send_completion(target->send_cq, target); 838 srp_send_completion(target->send_cq, target);
839 839
840 if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) 840 if (list_empty(&target->free_tx))
841 return NULL; 841 return NULL;
842 842
843 /* Initiator responses to target requests do not consume credits */ 843 /* Initiator responses to target requests do not consume credits */
@@ -846,14 +846,14 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
846 return NULL; 846 return NULL;
847 } 847 }
848 848
849 iu = target->tx_ring[target->tx_head & SRP_SQ_MASK]; 849 iu = list_first_entry(&target->free_tx, struct srp_iu, list);
850 iu->type = iu_type; 850 iu->type = iu_type;
851 return iu; 851 return iu;
852} 852}
853 853
854/* 854/*
855 * Must be called with target->scsi_host->host_lock held to protect 855 * Must be called with target->scsi_host->host_lock held to protect
856 * req_lim and tx_head. 856 * req_lim and free_tx.
857 */ 857 */
858static int __srp_post_send(struct srp_target_port *target, 858static int __srp_post_send(struct srp_target_port *target,
859 struct srp_iu *iu, int len) 859 struct srp_iu *iu, int len)
@@ -867,7 +867,7 @@ static int __srp_post_send(struct srp_target_port *target,
867 list.lkey = target->srp_host->srp_dev->mr->lkey; 867 list.lkey = target->srp_host->srp_dev->mr->lkey;
868 868
869 wr.next = NULL; 869 wr.next = NULL;
870 wr.wr_id = target->tx_head & SRP_SQ_MASK; 870 wr.wr_id = (uintptr_t) iu;
871 wr.sg_list = &list; 871 wr.sg_list = &list;
872 wr.num_sge = 1; 872 wr.num_sge = 1;
873 wr.opcode = IB_WR_SEND; 873 wr.opcode = IB_WR_SEND;
@@ -876,7 +876,7 @@ static int __srp_post_send(struct srp_target_port *target,
876 ret = ib_post_send(target->qp, &wr, &bad_wr); 876 ret = ib_post_send(target->qp, &wr, &bad_wr);
877 877
878 if (!ret) { 878 if (!ret) {
879 ++target->tx_head; 879 list_del(&iu->list);
880 if (iu->type != SRP_IU_RSP) 880 if (iu->type != SRP_IU_RSP)
881 --target->req_lim; 881 --target->req_lim;
882 } 882 }
@@ -884,36 +884,21 @@ static int __srp_post_send(struct srp_target_port *target,
884 return ret; 884 return ret;
885} 885}
886 886
887static int srp_post_recv(struct srp_target_port *target) 887static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
888{ 888{
889 unsigned long flags;
890 struct srp_iu *iu;
891 struct ib_sge list;
892 struct ib_recv_wr wr, *bad_wr; 889 struct ib_recv_wr wr, *bad_wr;
893 unsigned int next; 890 struct ib_sge list;
894 int ret;
895
896 spin_lock_irqsave(target->scsi_host->host_lock, flags);
897
898 next = target->rx_head & SRP_RQ_MASK;
899 wr.wr_id = next;
900 iu = target->rx_ring[next];
901 891
902 list.addr = iu->dma; 892 list.addr = iu->dma;
903 list.length = iu->size; 893 list.length = iu->size;
904 list.lkey = target->srp_host->srp_dev->mr->lkey; 894 list.lkey = target->srp_host->srp_dev->mr->lkey;
905 895
906 wr.next = NULL; 896 wr.next = NULL;
897 wr.wr_id = (uintptr_t) iu;
907 wr.sg_list = &list; 898 wr.sg_list = &list;
908 wr.num_sge = 1; 899 wr.num_sge = 1;
909 900
910 ret = ib_post_recv(target->qp, &wr, &bad_wr); 901 return ib_post_recv(target->qp, &wr, &bad_wr);
911 if (!ret)
912 ++target->rx_head;
913
914 spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
915
916 return ret;
917} 902}
918 903
919static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) 904static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -1030,14 +1015,11 @@ static void srp_process_aer_req(struct srp_target_port *target,
1030 1015
1031static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) 1016static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
1032{ 1017{
1033 struct ib_device *dev; 1018 struct ib_device *dev = target->srp_host->srp_dev->dev;
1034 struct srp_iu *iu; 1019 struct srp_iu *iu = (struct srp_iu *) wc->wr_id;
1035 int res; 1020 int res;
1036 u8 opcode; 1021 u8 opcode;
1037 1022
1038 iu = target->rx_ring[wc->wr_id];
1039
1040 dev = target->srp_host->srp_dev->dev;
1041 ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len, 1023 ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
1042 DMA_FROM_DEVICE); 1024 DMA_FROM_DEVICE);
1043 1025
@@ -1078,7 +1060,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
1078 ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len, 1060 ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
1079 DMA_FROM_DEVICE); 1061 DMA_FROM_DEVICE);
1080 1062
1081 res = srp_post_recv(target); 1063 res = srp_post_recv(target, iu);
1082 if (res != 0) 1064 if (res != 0)
1083 shost_printk(KERN_ERR, target->scsi_host, 1065 shost_printk(KERN_ERR, target->scsi_host,
1084 PFX "Recv failed with error code %d\n", res); 1066 PFX "Recv failed with error code %d\n", res);
@@ -1107,6 +1089,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
1107{ 1089{
1108 struct srp_target_port *target = target_ptr; 1090 struct srp_target_port *target = target_ptr;
1109 struct ib_wc wc; 1091 struct ib_wc wc;
1092 struct srp_iu *iu;
1110 1093
1111 while (ib_poll_cq(cq, 1, &wc) > 0) { 1094 while (ib_poll_cq(cq, 1, &wc) > 0) {
1112 if (wc.status) { 1095 if (wc.status) {
@@ -1117,7 +1100,8 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
1117 break; 1100 break;
1118 } 1101 }
1119 1102
1120 ++target->tx_tail; 1103 iu = (struct srp_iu *) wc.wr_id;
1104 list_add(&iu->list, &target->free_tx);
1121 } 1105 }
1122} 1106}
1123 1107
@@ -1212,6 +1196,8 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
1212 GFP_KERNEL, DMA_TO_DEVICE); 1196 GFP_KERNEL, DMA_TO_DEVICE);
1213 if (!target->tx_ring[i]) 1197 if (!target->tx_ring[i])
1214 goto err; 1198 goto err;
1199
1200 list_add(&target->tx_ring[i]->list, &target->free_tx);
1215 } 1201 }
1216 1202
1217 return 0; 1203 return 0;
@@ -1373,7 +1359,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
1373 break; 1359 break;
1374 1360
1375 for (i = 0; i < SRP_RQ_SIZE; i++) { 1361 for (i = 0; i < SRP_RQ_SIZE; i++) {
1376 target->status = srp_post_recv(target); 1362 struct srp_iu *iu = target->rx_ring[i];
1363 target->status = srp_post_recv(target, iu);
1377 if (target->status) 1364 if (target->status)
1378 break; 1365 break;
1379 } 1366 }
@@ -1965,6 +1952,7 @@ static ssize_t srp_create_target(struct device *dev,
1965 target->scsi_host = target_host; 1952 target->scsi_host = target_host;
1966 target->srp_host = host; 1953 target->srp_host = host;
1967 1954
1955 INIT_LIST_HEAD(&target->free_tx);
1968 INIT_LIST_HEAD(&target->free_reqs); 1956 INIT_LIST_HEAD(&target->free_reqs);
1969 INIT_LIST_HEAD(&target->req_queue); 1957 INIT_LIST_HEAD(&target->req_queue);
1970 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { 1958 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
@@ -2235,8 +2223,7 @@ static int __init srp_init_module(void)
2235{ 2223{
2236 int ret; 2224 int ret;
2237 2225
2238 BUILD_BUG_ON_NOT_POWER_OF_2(SRP_SQ_SIZE); 2226 BUILD_BUG_ON(FIELD_SIZEOF(struct ib_wc, wr_id) < sizeof(void *));
2239 BUILD_BUG_ON_NOT_POWER_OF_2(SRP_RQ_SIZE);
2240 2227
2241 if (srp_sg_tablesize > 255) { 2228 if (srp_sg_tablesize > 255) {
2242 printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n"); 2229 printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index f8b689a644b7..41ecb46adf15 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -59,10 +59,8 @@ enum {
59 59
60 SRP_RQ_SHIFT = 6, 60 SRP_RQ_SHIFT = 6,
61 SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT, 61 SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT,
62 SRP_RQ_MASK = SRP_RQ_SIZE - 1,
63 62
64 SRP_SQ_SIZE = SRP_RQ_SIZE, 63 SRP_SQ_SIZE = SRP_RQ_SIZE,
65 SRP_SQ_MASK = SRP_SQ_SIZE - 1,
66 SRP_RSP_SQ_SIZE = 1, 64 SRP_RSP_SQ_SIZE = 1,
67 SRP_REQ_SQ_SIZE = SRP_SQ_SIZE - SRP_RSP_SQ_SIZE, 65 SRP_REQ_SQ_SIZE = SRP_SQ_SIZE - SRP_RSP_SQ_SIZE,
68 SRP_TSK_MGMT_SQ_SIZE = 1, 66 SRP_TSK_MGMT_SQ_SIZE = 1,
@@ -144,11 +142,9 @@ struct srp_target_port {
144 142
145 int zero_req_lim; 143 int zero_req_lim;
146 144
147 unsigned rx_head;
148 struct srp_iu *rx_ring[SRP_RQ_SIZE]; 145 struct srp_iu *rx_ring[SRP_RQ_SIZE];
149 146
150 unsigned tx_head; 147 struct list_head free_tx;
151 unsigned tx_tail;
152 struct srp_iu *tx_ring[SRP_SQ_SIZE]; 148 struct srp_iu *tx_ring[SRP_SQ_SIZE];
153 149
154 struct list_head free_reqs; 150 struct list_head free_reqs;
@@ -168,6 +164,7 @@ struct srp_target_port {
168}; 164};
169 165
170struct srp_iu { 166struct srp_iu {
167 struct list_head list;
171 u64 dma; 168 u64 dma;
172 void *buf; 169 void *buf;
173 size_t size; 170 size_t size;