diff options
-rw-r--r-- | drivers/target/target_core_pscsi.c | 265 | ||||
-rw-r--r-- | drivers/target/target_core_pscsi.h | 1 |
2 files changed, 92 insertions, 174 deletions
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 77d725886410..b6d609362d62 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
@@ -776,95 +776,6 @@ pscsi_alloc_task(unsigned char *cdb) | |||
776 | return &pt->pscsi_task; | 776 | return &pt->pscsi_task; |
777 | } | 777 | } |
778 | 778 | ||
779 | static inline void pscsi_blk_init_request( | ||
780 | struct se_task *task, | ||
781 | struct pscsi_plugin_task *pt, | ||
782 | struct request *req, | ||
783 | int bidi_read) | ||
784 | { | ||
785 | /* | ||
786 | * Defined as "scsi command" in include/linux/blkdev.h. | ||
787 | */ | ||
788 | req->cmd_type = REQ_TYPE_BLOCK_PC; | ||
789 | /* | ||
790 | * For the extra BIDI-COMMAND READ struct request we do not | ||
791 | * need to setup the remaining structure members | ||
792 | */ | ||
793 | if (bidi_read) | ||
794 | return; | ||
795 | /* | ||
796 | * Setup the done function pointer for struct request, | ||
797 | * also set the end_io_data pointer.to struct se_task. | ||
798 | */ | ||
799 | req->end_io = pscsi_req_done; | ||
800 | req->end_io_data = task; | ||
801 | /* | ||
802 | * Load the referenced struct se_task's SCSI CDB into | ||
803 | * include/linux/blkdev.h:struct request->cmd | ||
804 | */ | ||
805 | req->cmd_len = scsi_command_size(pt->pscsi_cdb); | ||
806 | req->cmd = &pt->pscsi_cdb[0]; | ||
807 | /* | ||
808 | * Setup pointer for outgoing sense data. | ||
809 | */ | ||
810 | req->sense = &pt->pscsi_sense[0]; | ||
811 | req->sense_len = 0; | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * Used for pSCSI data payloads for all *NON* SCF_SCSI_DATA_SG_IO_CDB | ||
816 | */ | ||
817 | static int pscsi_blk_get_request(struct se_task *task) | ||
818 | { | ||
819 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); | ||
820 | struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr; | ||
821 | |||
822 | pt->pscsi_req = blk_get_request(pdv->pdv_sd->request_queue, | ||
823 | (task->task_data_direction == DMA_TO_DEVICE), | ||
824 | GFP_KERNEL); | ||
825 | if (!pt->pscsi_req || IS_ERR(pt->pscsi_req)) { | ||
826 | pr_err("PSCSI: blk_get_request() failed: %ld\n", | ||
827 | IS_ERR(pt->pscsi_req)); | ||
828 | return PYX_TRANSPORT_LU_COMM_FAILURE; | ||
829 | } | ||
830 | /* | ||
831 | * Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC, | ||
832 | * and setup rq callback, CDB and sense. | ||
833 | */ | ||
834 | pscsi_blk_init_request(task, pt, pt->pscsi_req, 0); | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | /* pscsi_do_task(): (Part of se_subsystem_api_t template) | ||
839 | * | ||
840 | * | ||
841 | */ | ||
842 | static int pscsi_do_task(struct se_task *task) | ||
843 | { | ||
844 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); | ||
845 | struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr; | ||
846 | /* | ||
847 | * Set the struct request->timeout value based on peripheral | ||
848 | * device type from SCSI. | ||
849 | */ | ||
850 | if (pdv->pdv_sd->type == TYPE_DISK) | ||
851 | pt->pscsi_req->timeout = PS_TIMEOUT_DISK; | ||
852 | else | ||
853 | pt->pscsi_req->timeout = PS_TIMEOUT_OTHER; | ||
854 | |||
855 | pt->pscsi_req->retries = PS_RETRY; | ||
856 | /* | ||
857 | * Queue the struct request into the struct scsi_device->request_queue. | ||
858 | * Also check for HEAD_OF_QUEUE SAM TASK attr from received se_cmd | ||
859 | * descriptor | ||
860 | */ | ||
861 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, | ||
862 | (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), | ||
863 | pscsi_req_done); | ||
864 | |||
865 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | ||
866 | } | ||
867 | |||
868 | static void pscsi_free_task(struct se_task *task) | 779 | static void pscsi_free_task(struct se_task *task) |
869 | { | 780 | { |
870 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); | 781 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); |
@@ -1048,15 +959,12 @@ static inline struct bio *pscsi_get_bio(int sg_num) | |||
1048 | return bio; | 959 | return bio; |
1049 | } | 960 | } |
1050 | 961 | ||
1051 | static int __pscsi_map_SG( | 962 | static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg, |
1052 | struct se_task *task, | 963 | struct bio **hbio) |
1053 | struct scatterlist *task_sg, | ||
1054 | u32 task_sg_num, | ||
1055 | int bidi_read) | ||
1056 | { | 964 | { |
1057 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); | ||
1058 | struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr; | 965 | struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr; |
1059 | struct bio *bio = NULL, *hbio = NULL, *tbio = NULL; | 966 | u32 task_sg_num = task->task_sg_nents; |
967 | struct bio *bio = NULL, *tbio = NULL; | ||
1060 | struct page *page; | 968 | struct page *page; |
1061 | struct scatterlist *sg; | 969 | struct scatterlist *sg; |
1062 | u32 data_len = task->task_size, i, len, bytes, off; | 970 | u32 data_len = task->task_size, i, len, bytes, off; |
@@ -1065,19 +973,8 @@ static int __pscsi_map_SG( | |||
1065 | int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; | 973 | int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; |
1066 | int rw = (task->task_data_direction == DMA_TO_DEVICE); | 974 | int rw = (task->task_data_direction == DMA_TO_DEVICE); |
1067 | 975 | ||
1068 | if (!task->task_size) | 976 | *hbio = NULL; |
1069 | return 0; | 977 | |
1070 | /* | ||
1071 | * For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup | ||
1072 | * the bio_vec maplist from task->task_sg -> | ||
1073 | * struct scatterlist memory. The struct se_task->task_sg[] currently needs | ||
1074 | * to be attached to struct bios for submission to Linux/SCSI using | ||
1075 | * struct request to struct scsi_device->request_queue. | ||
1076 | * | ||
1077 | * Note that this will be changing post v2.6.28 as Target_Core_Mod/pSCSI | ||
1078 | * is ported to upstream SCSI passthrough functionality that accepts | ||
1079 | * struct scatterlist->page_link or struct page as a paraemeter. | ||
1080 | */ | ||
1081 | pr_debug("PSCSI: nr_pages: %d\n", nr_pages); | 978 | pr_debug("PSCSI: nr_pages: %d\n", nr_pages); |
1082 | 979 | ||
1083 | for_each_sg(task_sg, sg, task_sg_num, i) { | 980 | for_each_sg(task_sg, sg, task_sg_num, i) { |
@@ -1114,8 +1011,8 @@ static int __pscsi_map_SG( | |||
1114 | * bios need to be added to complete a given | 1011 | * bios need to be added to complete a given |
1115 | * struct se_task | 1012 | * struct se_task |
1116 | */ | 1013 | */ |
1117 | if (!hbio) | 1014 | if (!*hbio) |
1118 | hbio = tbio = bio; | 1015 | *hbio = tbio = bio; |
1119 | else | 1016 | else |
1120 | tbio = tbio->bi_next = bio; | 1017 | tbio = tbio->bi_next = bio; |
1121 | } | 1018 | } |
@@ -1151,83 +1048,109 @@ static int __pscsi_map_SG( | |||
1151 | off = 0; | 1048 | off = 0; |
1152 | } | 1049 | } |
1153 | } | 1050 | } |
1154 | /* | ||
1155 | * Setup the primary pt->pscsi_req used for non BIDI and BIDI-COMMAND | ||
1156 | * primary SCSI WRITE poayload mapped for struct se_task->task_sg[] | ||
1157 | */ | ||
1158 | if (!bidi_read) { | ||
1159 | /* | ||
1160 | * Starting with v2.6.31, call blk_make_request() passing in *hbio to | ||
1161 | * allocate the pSCSI task a struct request. | ||
1162 | */ | ||
1163 | pt->pscsi_req = blk_make_request(pdv->pdv_sd->request_queue, | ||
1164 | hbio, GFP_KERNEL); | ||
1165 | if (!pt->pscsi_req) { | ||
1166 | pr_err("pSCSI: blk_make_request() failed\n"); | ||
1167 | goto fail; | ||
1168 | } | ||
1169 | /* | ||
1170 | * Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC, | ||
1171 | * and setup rq callback, CDB and sense. | ||
1172 | */ | ||
1173 | pscsi_blk_init_request(task, pt, pt->pscsi_req, 0); | ||
1174 | |||
1175 | return task->task_sg_nents; | ||
1176 | } | ||
1177 | /* | ||
1178 | * Setup the secondary pt->pscsi_req->next_rq used for the extra BIDI-COMMAND | ||
1179 | * SCSI READ paylaod mapped for struct se_task->task_sg_bidi[] | ||
1180 | */ | ||
1181 | pt->pscsi_req->next_rq = blk_make_request(pdv->pdv_sd->request_queue, | ||
1182 | hbio, GFP_KERNEL); | ||
1183 | if (!pt->pscsi_req->next_rq) { | ||
1184 | pr_err("pSCSI: blk_make_request() failed for BIDI\n"); | ||
1185 | goto fail; | ||
1186 | } | ||
1187 | pscsi_blk_init_request(task, pt, pt->pscsi_req->next_rq, 1); | ||
1188 | 1051 | ||
1189 | return task->task_sg_nents; | 1052 | return task->task_sg_nents; |
1190 | fail: | 1053 | fail: |
1191 | while (hbio) { | 1054 | while (*hbio) { |
1192 | bio = hbio; | 1055 | bio = *hbio; |
1193 | hbio = hbio->bi_next; | 1056 | *hbio = (*hbio)->bi_next; |
1194 | bio->bi_next = NULL; | 1057 | bio->bi_next = NULL; |
1195 | bio_endio(bio, 0); | 1058 | bio_endio(bio, 0); /* XXX: should be error */ |
1196 | } | 1059 | } |
1197 | return ret; | 1060 | return ret; |
1198 | } | 1061 | } |
1199 | 1062 | ||
1200 | /* | 1063 | static int pscsi_do_task(struct se_task *task) |
1201 | * pSCSI maps both ->map_control_SG() and ->map_data_SG() to a single call. | ||
1202 | */ | ||
1203 | static int pscsi_map_SG(struct se_task *task) | ||
1204 | { | 1064 | { |
1065 | struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr; | ||
1066 | struct pscsi_plugin_task *pt = PSCSI_TASK(task); | ||
1067 | struct request *req; | ||
1068 | struct bio *hbio; | ||
1205 | int ret; | 1069 | int ret; |
1206 | 1070 | ||
1207 | /* | 1071 | if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) { |
1208 | * Setup the main struct request for the task->task_sg[] payload | 1072 | req = blk_get_request(pdv->pdv_sd->request_queue, |
1209 | */ | 1073 | (task->task_data_direction == DMA_TO_DEVICE), |
1074 | GFP_KERNEL); | ||
1075 | if (!req || IS_ERR(req)) { | ||
1076 | pr_err("PSCSI: blk_get_request() failed: %ld\n", | ||
1077 | req ? IS_ERR(req) : -ENOMEM); | ||
1078 | return PYX_TRANSPORT_LU_COMM_FAILURE; | ||
1079 | } | ||
1080 | } else { | ||
1081 | BUG_ON(!task->task_size); | ||
1210 | 1082 | ||
1211 | ret = __pscsi_map_SG(task, task->task_sg, task->task_sg_nents, 0); | ||
1212 | if (ret >= 0 && task->task_sg_bidi) { | ||
1213 | /* | 1083 | /* |
1214 | * If present, set up the extra BIDI-COMMAND SCSI READ | 1084 | * Setup the main struct request for the task->task_sg[] payload |
1215 | * struct request and payload. | ||
1216 | */ | 1085 | */ |
1217 | ret = __pscsi_map_SG(task, task->task_sg_bidi, | 1086 | ret = pscsi_map_sg(task, task->task_sg, &hbio); |
1218 | task->task_sg_nents, 1); | 1087 | if (ret < 0) |
1088 | return PYX_TRANSPORT_LU_COMM_FAILURE; | ||
1089 | |||
1090 | req = blk_make_request(pdv->pdv_sd->request_queue, hbio, | ||
1091 | GFP_KERNEL); | ||
1092 | if (!req) { | ||
1093 | pr_err("pSCSI: blk_make_request() failed\n"); | ||
1094 | goto fail; | ||
1095 | } | ||
1096 | |||
1097 | if (task->task_sg_bidi) { | ||
1098 | /* | ||
1099 | * If present, set up the extra BIDI-COMMAND SCSI READ | ||
1100 | * struct request and payload. | ||
1101 | */ | ||
1102 | ret = pscsi_map_sg(task, task->task_sg_bidi, &hbio); | ||
1103 | if (ret < 0) { | ||
1104 | /* XXX: free the main request? */ | ||
1105 | return PYX_TRANSPORT_LU_COMM_FAILURE; | ||
1106 | } | ||
1107 | |||
1108 | /* | ||
1109 | * Setup the secondary pt->pscsi_req->next_rq used for the extra | ||
1110 | * BIDI READ payload. | ||
1111 | */ | ||
1112 | req->next_rq = blk_make_request(pdv->pdv_sd->request_queue, | ||
1113 | hbio, GFP_KERNEL); | ||
1114 | if (!req) { | ||
1115 | pr_err("pSCSI: blk_make_request() failed for BIDI\n"); | ||
1116 | /* XXX: free the main request? */ | ||
1117 | goto fail; | ||
1118 | } | ||
1119 | |||
1120 | req->next_rq->cmd_type = REQ_TYPE_BLOCK_PC; | ||
1121 | } | ||
1219 | } | 1122 | } |
1220 | 1123 | ||
1221 | if (ret < 0) | 1124 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
1222 | return PYX_TRANSPORT_LU_COMM_FAILURE; | 1125 | req->end_io = pscsi_req_done; |
1223 | return 0; | 1126 | req->end_io_data = task; |
1224 | } | 1127 | req->cmd_len = scsi_command_size(pt->pscsi_cdb); |
1128 | req->cmd = &pt->pscsi_cdb[0]; | ||
1129 | req->sense = &pt->pscsi_sense[0]; | ||
1130 | req->sense_len = 0; | ||
1131 | if (pdv->pdv_sd->type == TYPE_DISK) | ||
1132 | req->timeout = PS_TIMEOUT_DISK; | ||
1133 | else | ||
1134 | req->timeout = PS_TIMEOUT_OTHER; | ||
1135 | req->retries = PS_RETRY; | ||
1225 | 1136 | ||
1226 | static int pscsi_CDB_none(struct se_task *task) | 1137 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req, |
1227 | { | 1138 | (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), |
1228 | return pscsi_blk_get_request(task); | 1139 | pscsi_req_done); |
1140 | |||
1141 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | ||
1142 | |||
1143 | fail: | ||
1144 | while (hbio) { | ||
1145 | struct bio *bio = hbio; | ||
1146 | hbio = hbio->bi_next; | ||
1147 | bio->bi_next = NULL; | ||
1148 | bio_endio(bio, 0); /* XXX: should be error */ | ||
1149 | } | ||
1150 | return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; | ||
1229 | } | 1151 | } |
1230 | 1152 | ||
1153 | |||
1231 | /* pscsi_get_cdb(): | 1154 | /* pscsi_get_cdb(): |
1232 | * | 1155 | * |
1233 | * | 1156 | * |
@@ -1334,16 +1257,12 @@ static void pscsi_req_done(struct request *req, int uptodate) | |||
1334 | __blk_put_request(req->q, req->next_rq); | 1257 | __blk_put_request(req->q, req->next_rq); |
1335 | 1258 | ||
1336 | __blk_put_request(req->q, req); | 1259 | __blk_put_request(req->q, req); |
1337 | pt->pscsi_req = NULL; | ||
1338 | } | 1260 | } |
1339 | 1261 | ||
1340 | static struct se_subsystem_api pscsi_template = { | 1262 | static struct se_subsystem_api pscsi_template = { |
1341 | .name = "pscsi", | 1263 | .name = "pscsi", |
1342 | .owner = THIS_MODULE, | 1264 | .owner = THIS_MODULE, |
1343 | .transport_type = TRANSPORT_PLUGIN_PHBA_PDEV, | 1265 | .transport_type = TRANSPORT_PLUGIN_PHBA_PDEV, |
1344 | .cdb_none = pscsi_CDB_none, | ||
1345 | .map_control_SG = pscsi_map_SG, | ||
1346 | .map_data_SG = pscsi_map_SG, | ||
1347 | .attach_hba = pscsi_attach_hba, | 1266 | .attach_hba = pscsi_attach_hba, |
1348 | .detach_hba = pscsi_detach_hba, | 1267 | .detach_hba = pscsi_detach_hba, |
1349 | .pmode_enable_hba = pscsi_pmode_enable_hba, | 1268 | .pmode_enable_hba = pscsi_pmode_enable_hba, |
diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h index ebf4f1ae2c83..fdc17b6aefb3 100644 --- a/drivers/target/target_core_pscsi.h +++ b/drivers/target/target_core_pscsi.h | |||
@@ -27,7 +27,6 @@ struct pscsi_plugin_task { | |||
27 | int pscsi_direction; | 27 | int pscsi_direction; |
28 | int pscsi_result; | 28 | int pscsi_result; |
29 | u32 pscsi_resid; | 29 | u32 pscsi_resid; |
30 | struct request *pscsi_req; | ||
31 | unsigned char pscsi_cdb[0]; | 30 | unsigned char pscsi_cdb[0]; |
32 | } ____cacheline_aligned; | 31 | } ____cacheline_aligned; |
33 | 32 | ||