diff options
| -rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 124 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 1 |
2 files changed, 67 insertions, 58 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 2aff8814f2c5..e5bd181dbce5 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -818,9 +818,24 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, | |||
| 818 | } | 818 | } |
| 819 | 819 | ||
| 820 | /* | 820 | /* |
| 821 | * Return an IU and possible credit to the free pool | ||
| 822 | */ | ||
| 823 | static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu, | ||
| 824 | enum srp_iu_type iu_type) | ||
| 825 | { | ||
| 826 | unsigned long flags; | ||
| 827 | |||
| 828 | spin_lock_irqsave(target->scsi_host->host_lock, flags); | ||
| 829 | list_add(&iu->list, &target->free_tx); | ||
| 830 | if (iu_type != SRP_IU_RSP) | ||
| 831 | ++target->req_lim; | ||
| 832 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); | ||
| 833 | } | ||
| 834 | |||
| 835 | /* | ||
| 821 | * Must be called with target->scsi_host->host_lock held to protect | 836 | * Must be called with target->scsi_host->host_lock held to protect |
| 822 | * req_lim and free_tx. Lock cannot be dropped between call here and | 837 | * req_lim and free_tx. If IU is not sent, it must be returned using |
| 823 | * call to __srp_post_send(). | 838 | * srp_put_tx_iu(). |
| 824 | * | 839 | * |
| 825 | * Note: | 840 | * Note: |
| 826 | * An upper limit for the number of allocated information units for each | 841 | * An upper limit for the number of allocated information units for each |
| @@ -843,26 +858,25 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target, | |||
| 843 | return NULL; | 858 | return NULL; |
| 844 | 859 | ||
| 845 | /* Initiator responses to target requests do not consume credits */ | 860 | /* Initiator responses to target requests do not consume credits */ |
| 846 | if (target->req_lim <= rsv && iu_type != SRP_IU_RSP) { | 861 | if (iu_type != SRP_IU_RSP) { |
| 847 | ++target->zero_req_lim; | 862 | if (target->req_lim <= rsv) { |
| 848 | return NULL; | 863 | ++target->zero_req_lim; |
| 864 | return NULL; | ||
| 865 | } | ||
| 866 | |||
| 867 | --target->req_lim; | ||
| 849 | } | 868 | } |
| 850 | 869 | ||
| 851 | iu = list_first_entry(&target->free_tx, struct srp_iu, list); | 870 | iu = list_first_entry(&target->free_tx, struct srp_iu, list); |
| 852 | iu->type = iu_type; | 871 | list_del(&iu->list); |
| 853 | return iu; | 872 | return iu; |
| 854 | } | 873 | } |
| 855 | 874 | ||
| 856 | /* | 875 | static int srp_post_send(struct srp_target_port *target, |
| 857 | * Must be called with target->scsi_host->host_lock held to protect | 876 | struct srp_iu *iu, int len) |
| 858 | * req_lim and free_tx. | ||
| 859 | */ | ||
| 860 | static int __srp_post_send(struct srp_target_port *target, | ||
| 861 | struct srp_iu *iu, int len) | ||
| 862 | { | 877 | { |
| 863 | struct ib_sge list; | 878 | struct ib_sge list; |
| 864 | struct ib_send_wr wr, *bad_wr; | 879 | struct ib_send_wr wr, *bad_wr; |
| 865 | int ret = 0; | ||
| 866 | 880 | ||
| 867 | list.addr = iu->dma; | 881 | list.addr = iu->dma; |
| 868 | list.length = len; | 882 | list.length = len; |
| @@ -875,15 +889,7 @@ static int __srp_post_send(struct srp_target_port *target, | |||
| 875 | wr.opcode = IB_WR_SEND; | 889 | wr.opcode = IB_WR_SEND; |
| 876 | wr.send_flags = IB_SEND_SIGNALED; | 890 | wr.send_flags = IB_SEND_SIGNALED; |
| 877 | 891 | ||
| 878 | ret = ib_post_send(target->qp, &wr, &bad_wr); | 892 | return ib_post_send(target->qp, &wr, &bad_wr); |
| 879 | |||
| 880 | if (!ret) { | ||
| 881 | list_del(&iu->list); | ||
| 882 | if (iu->type != SRP_IU_RSP) | ||
| 883 | --target->req_lim; | ||
| 884 | } | ||
| 885 | |||
| 886 | return ret; | ||
| 887 | } | 893 | } |
| 888 | 894 | ||
| 889 | static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu) | 895 | static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu) |
| @@ -953,34 +959,33 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) | |||
| 953 | static int srp_response_common(struct srp_target_port *target, s32 req_delta, | 959 | static int srp_response_common(struct srp_target_port *target, s32 req_delta, |
| 954 | void *rsp, int len) | 960 | void *rsp, int len) |
| 955 | { | 961 | { |
| 956 | struct ib_device *dev; | 962 | struct ib_device *dev = target->srp_host->srp_dev->dev; |
| 957 | unsigned long flags; | 963 | unsigned long flags; |
| 958 | struct srp_iu *iu; | 964 | struct srp_iu *iu; |
| 959 | int err = 1; | 965 | int err; |
| 960 | |||
| 961 | dev = target->srp_host->srp_dev->dev; | ||
| 962 | 966 | ||
| 963 | spin_lock_irqsave(target->scsi_host->host_lock, flags); | 967 | spin_lock_irqsave(target->scsi_host->host_lock, flags); |
| 964 | target->req_lim += req_delta; | 968 | target->req_lim += req_delta; |
| 965 | |||
| 966 | iu = __srp_get_tx_iu(target, SRP_IU_RSP); | 969 | iu = __srp_get_tx_iu(target, SRP_IU_RSP); |
| 970 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); | ||
| 971 | |||
| 967 | if (!iu) { | 972 | if (!iu) { |
| 968 | shost_printk(KERN_ERR, target->scsi_host, PFX | 973 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| 969 | "no IU available to send response\n"); | 974 | "no IU available to send response\n"); |
| 970 | goto out; | 975 | return 1; |
| 971 | } | 976 | } |
| 972 | 977 | ||
| 973 | ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE); | 978 | ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE); |
| 974 | memcpy(iu->buf, rsp, len); | 979 | memcpy(iu->buf, rsp, len); |
| 975 | ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE); | 980 | ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE); |
| 976 | 981 | ||
| 977 | err = __srp_post_send(target, iu, len); | 982 | err = srp_post_send(target, iu, len); |
| 978 | if (err) | 983 | if (err) { |
| 979 | shost_printk(KERN_ERR, target->scsi_host, PFX | 984 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| 980 | "unable to post response: %d\n", err); | 985 | "unable to post response: %d\n", err); |
| 986 | srp_put_tx_iu(target, iu, SRP_IU_RSP); | ||
| 987 | } | ||
| 981 | 988 | ||
| 982 | out: | ||
| 983 | spin_unlock_irqrestore(target->scsi_host->host_lock, flags); | ||
| 984 | return err; | 989 | return err; |
| 985 | } | 990 | } |
| 986 | 991 | ||
| @@ -1107,14 +1112,14 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr) | |||
| 1107 | } | 1112 | } |
| 1108 | } | 1113 | } |
| 1109 | 1114 | ||
| 1110 | static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, | 1115 | static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) |
| 1111 | void (*done)(struct scsi_cmnd *)) | ||
| 1112 | { | 1116 | { |
| 1113 | struct srp_target_port *target = host_to_target(scmnd->device->host); | 1117 | struct srp_target_port *target = host_to_target(shost); |
| 1114 | struct srp_request *req; | 1118 | struct srp_request *req; |
| 1115 | struct srp_iu *iu; | 1119 | struct srp_iu *iu; |
| 1116 | struct srp_cmd *cmd; | 1120 | struct srp_cmd *cmd; |
| 1117 | struct ib_device *dev; | 1121 | struct ib_device *dev; |
| 1122 | unsigned long flags; | ||
| 1118 | int len; | 1123 | int len; |
| 1119 | 1124 | ||
| 1120 | if (target->state == SRP_TARGET_CONNECTING) | 1125 | if (target->state == SRP_TARGET_CONNECTING) |
| @@ -1123,11 +1128,19 @@ static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, | |||
| 1123 | if (target->state == SRP_TARGET_DEAD || | 1128 | if (target->state == SRP_TARGET_DEAD || |
| 1124 | target->state == SRP_TARGET_REMOVED) { | 1129 | target->state == SRP_TARGET_REMOVED) { |
| 1125 | scmnd->result = DID_BAD_TARGET << 16; | 1130 | scmnd->result = DID_BAD_TARGET << 16; |
| 1126 | done(scmnd); | 1131 | scmnd->scsi_done(scmnd); |
| 1127 | return 0; | 1132 | return 0; |
| 1128 | } | 1133 | } |
| 1129 | 1134 | ||
| 1135 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 1130 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); | 1136 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); |
| 1137 | if (iu) { | ||
| 1138 | req = list_first_entry(&target->free_reqs, struct srp_request, | ||
| 1139 | list); | ||
| 1140 | list_del(&req->list); | ||
| 1141 | } | ||
| 1142 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 1143 | |||
| 1131 | if (!iu) | 1144 | if (!iu) |
| 1132 | goto err; | 1145 | goto err; |
| 1133 | 1146 | ||
| @@ -1135,9 +1148,6 @@ static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, | |||
| 1135 | ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, | 1148 | ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, |
| 1136 | DMA_TO_DEVICE); | 1149 | DMA_TO_DEVICE); |
| 1137 | 1150 | ||
| 1138 | req = list_first_entry(&target->free_reqs, struct srp_request, list); | ||
| 1139 | |||
| 1140 | scmnd->scsi_done = done; | ||
| 1141 | scmnd->result = 0; | 1151 | scmnd->result = 0; |
| 1142 | scmnd->host_scribble = (void *) req; | 1152 | scmnd->host_scribble = (void *) req; |
| 1143 | 1153 | ||
| @@ -1156,30 +1166,33 @@ static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, | |||
| 1156 | if (len < 0) { | 1166 | if (len < 0) { |
| 1157 | shost_printk(KERN_ERR, target->scsi_host, | 1167 | shost_printk(KERN_ERR, target->scsi_host, |
| 1158 | PFX "Failed to map data\n"); | 1168 | PFX "Failed to map data\n"); |
| 1159 | goto err; | 1169 | goto err_iu; |
| 1160 | } | 1170 | } |
| 1161 | 1171 | ||
| 1162 | ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len, | 1172 | ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len, |
| 1163 | DMA_TO_DEVICE); | 1173 | DMA_TO_DEVICE); |
| 1164 | 1174 | ||
| 1165 | if (__srp_post_send(target, iu, len)) { | 1175 | if (srp_post_send(target, iu, len)) { |
| 1166 | shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n"); | 1176 | shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n"); |
| 1167 | goto err_unmap; | 1177 | goto err_unmap; |
| 1168 | } | 1178 | } |
| 1169 | 1179 | ||
| 1170 | list_del(&req->list); | ||
| 1171 | |||
| 1172 | return 0; | 1180 | return 0; |
| 1173 | 1181 | ||
| 1174 | err_unmap: | 1182 | err_unmap: |
| 1175 | srp_unmap_data(scmnd, target, req); | 1183 | srp_unmap_data(scmnd, target, req); |
| 1176 | 1184 | ||
| 1185 | err_iu: | ||
| 1186 | srp_put_tx_iu(target, iu, SRP_IU_CMD); | ||
| 1187 | |||
| 1188 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 1189 | list_add(&req->list, &target->free_reqs); | ||
| 1190 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 1191 | |||
| 1177 | err: | 1192 | err: |
| 1178 | return SCSI_MLQUEUE_HOST_BUSY; | 1193 | return SCSI_MLQUEUE_HOST_BUSY; |
| 1179 | } | 1194 | } |
| 1180 | 1195 | ||
| 1181 | static DEF_SCSI_QCMD(srp_queuecommand) | ||
| 1182 | |||
| 1183 | static int srp_alloc_iu_bufs(struct srp_target_port *target) | 1196 | static int srp_alloc_iu_bufs(struct srp_target_port *target) |
| 1184 | { | 1197 | { |
| 1185 | int i; | 1198 | int i; |
| @@ -1433,17 +1446,18 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, | |||
| 1433 | struct srp_iu *iu; | 1446 | struct srp_iu *iu; |
| 1434 | struct srp_tsk_mgmt *tsk_mgmt; | 1447 | struct srp_tsk_mgmt *tsk_mgmt; |
| 1435 | 1448 | ||
| 1436 | spin_lock_irq(target->scsi_host->host_lock); | ||
| 1437 | |||
| 1438 | if (target->state == SRP_TARGET_DEAD || | 1449 | if (target->state == SRP_TARGET_DEAD || |
| 1439 | target->state == SRP_TARGET_REMOVED) | 1450 | target->state == SRP_TARGET_REMOVED) |
| 1440 | goto out; | 1451 | return -1; |
| 1441 | 1452 | ||
| 1442 | init_completion(&target->tsk_mgmt_done); | 1453 | init_completion(&target->tsk_mgmt_done); |
| 1443 | 1454 | ||
| 1455 | spin_lock_irq(target->scsi_host->host_lock); | ||
| 1444 | iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT); | 1456 | iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT); |
| 1457 | spin_unlock_irq(target->scsi_host->host_lock); | ||
| 1458 | |||
| 1445 | if (!iu) | 1459 | if (!iu) |
| 1446 | goto out; | 1460 | return -1; |
| 1447 | 1461 | ||
| 1448 | ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt, | 1462 | ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt, |
| 1449 | DMA_TO_DEVICE); | 1463 | DMA_TO_DEVICE); |
| @@ -1458,20 +1472,16 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, | |||
| 1458 | 1472 | ||
| 1459 | ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt, | 1473 | ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt, |
| 1460 | DMA_TO_DEVICE); | 1474 | DMA_TO_DEVICE); |
| 1461 | if (__srp_post_send(target, iu, sizeof *tsk_mgmt)) | 1475 | if (srp_post_send(target, iu, sizeof *tsk_mgmt)) { |
| 1462 | goto out; | 1476 | srp_put_tx_iu(target, iu, SRP_IU_TSK_MGMT); |
| 1463 | 1477 | return -1; | |
| 1464 | spin_unlock_irq(target->scsi_host->host_lock); | 1478 | } |
| 1465 | 1479 | ||
| 1466 | if (!wait_for_completion_timeout(&target->tsk_mgmt_done, | 1480 | if (!wait_for_completion_timeout(&target->tsk_mgmt_done, |
| 1467 | msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) | 1481 | msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) |
| 1468 | return -1; | 1482 | return -1; |
| 1469 | 1483 | ||
| 1470 | return 0; | 1484 | return 0; |
| 1471 | |||
| 1472 | out: | ||
| 1473 | spin_unlock_irq(target->scsi_host->host_lock); | ||
| 1474 | return -1; | ||
| 1475 | } | 1485 | } |
| 1476 | 1486 | ||
| 1477 | static int srp_abort(struct scsi_cmnd *scmnd) | 1487 | static int srp_abort(struct scsi_cmnd *scmnd) |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 924d8e9c6672..81686eee7e62 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
| @@ -168,7 +168,6 @@ struct srp_iu { | |||
| 168 | void *buf; | 168 | void *buf; |
| 169 | size_t size; | 169 | size_t size; |
| 170 | enum dma_data_direction direction; | 170 | enum dma_data_direction direction; |
| 171 | enum srp_iu_type type; | ||
| 172 | }; | 171 | }; |
| 173 | 172 | ||
| 174 | #endif /* IB_SRP_H */ | 173 | #endif /* IB_SRP_H */ |
