diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-05-10 05:28:48 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:47 -0400 |
commit | c72086e3c2897eaca5b99c005dd9844fdc784981 (patch) | |
tree | f15c4895fd0b761b360961bce15b9f07c7099548 | |
parent | f139303d17c47eff4c5b5407dee0a6d43e8fd146 (diff) |
isci: merge smp request substates into primary state machine
Remove usage of the request substate machine for smp requests identified by:
task->task_proto == SAS_PROTOCOL_SMP
While merging over the smp_request infrastructure noticed that all the
assign buffer implementations are now equal, so moved it to
scic_sds_general_request_construct.
Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/scsi/isci/Makefile | 1 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 462 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 42 | ||||
-rw-r--r-- | drivers/scsi/isci/smp_request.c | 518 | ||||
-rw-r--r-- | drivers/scsi/isci/stp_request.c | 6 |
5 files changed, 436 insertions, 593 deletions
diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 43d2c050bd49..be2b67d0df89 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile | |||
@@ -7,5 +7,4 @@ isci-objs := init.o phy.o request.o sata.o \ | |||
7 | remote_node_table.o \ | 7 | remote_node_table.o \ |
8 | unsolicited_frame_control.o \ | 8 | unsolicited_frame_control.o \ |
9 | stp_request.o \ | 9 | stp_request.o \ |
10 | smp_request.o \ | ||
11 | port_config.o \ | 10 | port_config.o \ |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 5f5168110556..5201dc58a191 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -158,12 +158,6 @@ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) | |||
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_req) | ||
162 | { | ||
163 | if (sci_req->was_tag_assigned_by_user == false) | ||
164 | sci_req->task_context_buffer = &sci_req->tc; | ||
165 | } | ||
166 | |||
167 | static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) | 161 | static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) |
168 | { | 162 | { |
169 | struct ssp_cmd_iu *cmd_iu; | 163 | struct ssp_cmd_iu *cmd_iu; |
@@ -341,12 +335,6 @@ static void scu_ssp_io_request_construct_task_context( | |||
341 | scic_sds_request_build_sgl(sci_req); | 335 | scic_sds_request_build_sgl(sci_req); |
342 | } | 336 | } |
343 | 337 | ||
344 | static void scic_sds_ssp_task_request_assign_buffers(struct scic_sds_request *sci_req) | ||
345 | { | ||
346 | if (sci_req->was_tag_assigned_by_user == false) | ||
347 | sci_req->task_context_buffer = &sci_req->tc; | ||
348 | } | ||
349 | |||
350 | /** | 338 | /** |
351 | * This method will fill in the SCU Task Context for a SSP Task request. The | 339 | * This method will fill in the SCU Task Context for a SSP Task request. The |
352 | * following important settings are utilized: -# priority == | 340 | * following important settings are utilized: -# priority == |
@@ -1261,6 +1249,196 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler | |||
1261 | return SCI_SUCCESS; | 1249 | return SCI_SUCCESS; |
1262 | } | 1250 | } |
1263 | 1251 | ||
1252 | /** | ||
1253 | * This method processes an abnormal TC completion while the SMP request is | ||
1254 | * waiting for a response frame. It decides what happened to the IO based | ||
1255 | * on TC completion status. | ||
1256 | * @sci_req: This parameter specifies the request for which the TC | ||
1257 | * completion was received. | ||
1258 | * @completion_code: This parameter indicates the completion status information | ||
1259 | * for the TC. | ||
1260 | * | ||
1261 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
1262 | * this method always returns success. | ||
1263 | */ | ||
1264 | static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( | ||
1265 | struct scic_sds_request *sci_req, | ||
1266 | u32 completion_code) | ||
1267 | { | ||
1268 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1269 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1270 | /* | ||
1271 | * In the AWAIT RESPONSE state, any TC completion is unexpected. | ||
1272 | * but if the TC has success status, we complete the IO anyway. */ | ||
1273 | scic_sds_request_set_status( | ||
1274 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1275 | ); | ||
1276 | |||
1277 | sci_base_state_machine_change_state( | ||
1278 | &sci_req->state_machine, | ||
1279 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1280 | break; | ||
1281 | |||
1282 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): | ||
1283 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): | ||
1284 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): | ||
1285 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): | ||
1286 | /* | ||
1287 | * These status has been seen in a specific LSI expander, which sometimes | ||
1288 | * is not able to send smp response within 2 ms. This causes our hardware | ||
1289 | * break the connection and set TC completion with one of these SMP_XXX_XX_ERR | ||
1290 | * status. For these type of error, we ask scic user to retry the request. */ | ||
1291 | scic_sds_request_set_status( | ||
1292 | sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED | ||
1293 | ); | ||
1294 | |||
1295 | sci_base_state_machine_change_state( | ||
1296 | &sci_req->state_machine, | ||
1297 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1298 | break; | ||
1299 | |||
1300 | default: | ||
1301 | /* | ||
1302 | * All other completion status cause the IO to be complete. If a NAK | ||
1303 | * was received, then it is up to the user to retry the request. */ | ||
1304 | scic_sds_request_set_status( | ||
1305 | sci_req, | ||
1306 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1307 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1308 | ); | ||
1309 | |||
1310 | sci_base_state_machine_change_state( | ||
1311 | &sci_req->state_machine, | ||
1312 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1313 | break; | ||
1314 | } | ||
1315 | |||
1316 | return SCI_SUCCESS; | ||
1317 | } | ||
1318 | |||
1319 | /* | ||
1320 | * This function processes an unsolicited frame while the SMP request is waiting | ||
1321 | * for a response frame. It will copy the response data, release the | ||
1322 | * unsolicited frame, and transition the request to the | ||
1323 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
1324 | * @sci_req: This parameter specifies the request for which the | ||
1325 | * unsolicited frame was received. | ||
1326 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
1327 | * should contain the response. | ||
1328 | * | ||
1329 | * This function returns an indication of whether the response frame was handled | ||
1330 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
1331 | * indicates successful processing of the TC response. | ||
1332 | */ | ||
1333 | static enum sci_status | ||
1334 | scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, | ||
1335 | u32 frame_index) | ||
1336 | { | ||
1337 | enum sci_status status; | ||
1338 | void *frame_header; | ||
1339 | struct smp_resp *rsp_hdr = &sci_req->smp.rsp; | ||
1340 | ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); | ||
1341 | |||
1342 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1343 | &(scic_sds_request_get_controller(sci_req)->uf_control), | ||
1344 | frame_index, | ||
1345 | &frame_header); | ||
1346 | |||
1347 | /* byte swap the header. */ | ||
1348 | sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); | ||
1349 | |||
1350 | if (rsp_hdr->frame_type == SMP_RESPONSE) { | ||
1351 | void *smp_resp; | ||
1352 | |||
1353 | status = scic_sds_unsolicited_frame_control_get_buffer( | ||
1354 | &(scic_sds_request_get_controller(sci_req)->uf_control), | ||
1355 | frame_index, | ||
1356 | &smp_resp); | ||
1357 | |||
1358 | word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / | ||
1359 | sizeof(u32); | ||
1360 | |||
1361 | sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, | ||
1362 | smp_resp, word_cnt); | ||
1363 | |||
1364 | scic_sds_request_set_status( | ||
1365 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); | ||
1366 | |||
1367 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
1368 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); | ||
1369 | } else { | ||
1370 | /* This was not a response frame why did it get forwarded? */ | ||
1371 | dev_err(scic_to_dev(sci_req->owning_controller), | ||
1372 | "%s: SCIC SMP Request 0x%p received unexpected frame " | ||
1373 | "%d type 0x%02x\n", | ||
1374 | __func__, | ||
1375 | sci_req, | ||
1376 | frame_index, | ||
1377 | rsp_hdr->frame_type); | ||
1378 | |||
1379 | scic_sds_request_set_status( | ||
1380 | sci_req, | ||
1381 | SCU_TASK_DONE_SMP_FRM_TYPE_ERR, | ||
1382 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); | ||
1383 | |||
1384 | sci_base_state_machine_change_state( | ||
1385 | &sci_req->state_machine, | ||
1386 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1387 | } | ||
1388 | |||
1389 | scic_sds_controller_release_frame(sci_req->owning_controller, | ||
1390 | frame_index); | ||
1391 | |||
1392 | return SCI_SUCCESS; | ||
1393 | } | ||
1394 | |||
1395 | /** | ||
1396 | * This method processes the completions transport layer (TL) status to | ||
1397 | * determine if the SMP request was sent successfully. If the SMP request | ||
1398 | * was sent successfully, then the state for the SMP request transits to | ||
1399 | * waiting for a response frame. | ||
1400 | * @sci_req: This parameter specifies the request for which the TC | ||
1401 | * completion was received. | ||
1402 | * @completion_code: This parameter indicates the completion status information | ||
1403 | * for the TC. | ||
1404 | * | ||
1405 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
1406 | * this method always returns success. | ||
1407 | */ | ||
1408 | static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( | ||
1409 | struct scic_sds_request *sci_req, | ||
1410 | u32 completion_code) | ||
1411 | { | ||
1412 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1413 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1414 | scic_sds_request_set_status( | ||
1415 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1416 | ); | ||
1417 | |||
1418 | sci_base_state_machine_change_state( | ||
1419 | &sci_req->state_machine, | ||
1420 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1421 | break; | ||
1422 | |||
1423 | default: | ||
1424 | /* | ||
1425 | * All other completion status cause the IO to be complete. If a NAK | ||
1426 | * was received, then it is up to the user to retry the request. */ | ||
1427 | scic_sds_request_set_status( | ||
1428 | sci_req, | ||
1429 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1430 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1431 | ); | ||
1432 | |||
1433 | sci_base_state_machine_change_state( | ||
1434 | &sci_req->state_machine, | ||
1435 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1436 | break; | ||
1437 | } | ||
1438 | |||
1439 | return SCI_SUCCESS; | ||
1440 | } | ||
1441 | |||
1264 | static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { | 1442 | static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { |
1265 | [SCI_BASE_REQUEST_STATE_INITIAL] = { }, | 1443 | [SCI_BASE_REQUEST_STATE_INITIAL] = { }, |
1266 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { | 1444 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { |
@@ -1280,6 +1458,15 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han | |||
1280 | .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, | 1458 | .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, |
1281 | .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, | 1459 | .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, |
1282 | }, | 1460 | }, |
1461 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
1462 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
1463 | .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, | ||
1464 | .frame_handler = scic_sds_smp_request_await_response_frame_handler, | ||
1465 | }, | ||
1466 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
1467 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
1468 | .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, | ||
1469 | }, | ||
1283 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | 1470 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { |
1284 | .complete_handler = scic_sds_request_completed_state_complete_handler, | 1471 | .complete_handler = scic_sds_request_completed_state_complete_handler, |
1285 | }, | 1472 | }, |
@@ -2038,6 +2225,12 @@ static void scic_sds_request_started_state_enter(void *object) | |||
2038 | struct sci_base_state_machine *sm = &sci_req->state_machine; | 2225 | struct sci_base_state_machine *sm = &sci_req->state_machine; |
2039 | struct isci_request *ireq = sci_req_to_ireq(sci_req); | 2226 | struct isci_request *ireq = sci_req_to_ireq(sci_req); |
2040 | struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); | 2227 | struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); |
2228 | struct sas_task *task; | ||
2229 | |||
2230 | /* XXX as hch said always creating an internal sas_task for tmf | ||
2231 | * requests would simplify the driver | ||
2232 | */ | ||
2233 | task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL; | ||
2041 | 2234 | ||
2042 | SET_STATE_HANDLER( | 2235 | SET_STATE_HANDLER( |
2043 | sci_req, | 2236 | sci_req, |
@@ -2045,15 +2238,19 @@ static void scic_sds_request_started_state_enter(void *object) | |||
2045 | SCI_BASE_REQUEST_STATE_STARTED | 2238 | SCI_BASE_REQUEST_STATE_STARTED |
2046 | ); | 2239 | ); |
2047 | 2240 | ||
2048 | if (ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV) | ||
2049 | sci_base_state_machine_change_state(sm, | ||
2050 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); | ||
2051 | |||
2052 | /* Most of the request state machines have a started substate machine so | 2241 | /* Most of the request state machines have a started substate machine so |
2053 | * start its execution on the entry to the started state. | 2242 | * start its execution on the entry to the started state. |
2054 | */ | 2243 | */ |
2055 | if (sci_req->has_started_substate_machine == true) | 2244 | if (sci_req->has_started_substate_machine == true) |
2056 | sci_base_state_machine_start(&sci_req->started_substate_machine); | 2245 | sci_base_state_machine_start(&sci_req->started_substate_machine); |
2246 | |||
2247 | if (!task && dev->dev_type == SAS_END_DEV) { | ||
2248 | sci_base_state_machine_change_state(sm, | ||
2249 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); | ||
2250 | } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { | ||
2251 | sci_base_state_machine_change_state(sm, | ||
2252 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE); | ||
2253 | } | ||
2057 | } | 2254 | } |
2058 | 2255 | ||
2059 | /** | 2256 | /** |
@@ -2173,6 +2370,28 @@ static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_e | |||
2173 | ); | 2370 | ); |
2174 | } | 2371 | } |
2175 | 2372 | ||
2373 | static void scic_sds_smp_request_started_await_response_substate_enter(void *object) | ||
2374 | { | ||
2375 | struct scic_sds_request *sci_req = object; | ||
2376 | |||
2377 | SET_STATE_HANDLER( | ||
2378 | sci_req, | ||
2379 | scic_sds_request_state_handler_table, | ||
2380 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE | ||
2381 | ); | ||
2382 | } | ||
2383 | |||
2384 | static void scic_sds_smp_request_started_await_tc_completion_substate_enter(void *object) | ||
2385 | { | ||
2386 | struct scic_sds_request *sci_req = object; | ||
2387 | |||
2388 | SET_STATE_HANDLER( | ||
2389 | sci_req, | ||
2390 | scic_sds_request_state_handler_table, | ||
2391 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION | ||
2392 | ); | ||
2393 | } | ||
2394 | |||
2176 | static const struct sci_base_state scic_sds_request_state_table[] = { | 2395 | static const struct sci_base_state scic_sds_request_state_table[] = { |
2177 | [SCI_BASE_REQUEST_STATE_INITIAL] = { | 2396 | [SCI_BASE_REQUEST_STATE_INITIAL] = { |
2178 | .enter_state = scic_sds_request_initial_state_enter, | 2397 | .enter_state = scic_sds_request_initial_state_enter, |
@@ -2190,6 +2409,12 @@ static const struct sci_base_state scic_sds_request_state_table[] = { | |||
2190 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | 2409 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { |
2191 | .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, | 2410 | .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, |
2192 | }, | 2411 | }, |
2412 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
2413 | .enter_state = scic_sds_smp_request_started_await_response_substate_enter, | ||
2414 | }, | ||
2415 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
2416 | .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, | ||
2417 | }, | ||
2193 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | 2418 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { |
2194 | .enter_state = scic_sds_request_completed_state_enter, | 2419 | .enter_state = scic_sds_request_completed_state_enter, |
2195 | }, | 2420 | }, |
@@ -2225,7 +2450,7 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, | |||
2225 | 2450 | ||
2226 | if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { | 2451 | if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { |
2227 | sci_req->was_tag_assigned_by_user = false; | 2452 | sci_req->was_tag_assigned_by_user = false; |
2228 | sci_req->task_context_buffer = NULL; | 2453 | sci_req->task_context_buffer = &sci_req->tc; |
2229 | } else { | 2454 | } else { |
2230 | sci_req->was_tag_assigned_by_user = true; | 2455 | sci_req->was_tag_assigned_by_user = true; |
2231 | 2456 | ||
@@ -2245,26 +2470,20 @@ scic_io_request_construct(struct scic_sds_controller *scic, | |||
2245 | /* Build the common part of the request */ | 2470 | /* Build the common part of the request */ |
2246 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); | 2471 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); |
2247 | 2472 | ||
2248 | if (sci_dev->rnc.remote_node_index == | 2473 | if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) |
2249 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) | ||
2250 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; | 2474 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; |
2251 | 2475 | ||
2252 | if (dev->dev_type == SAS_END_DEV) | 2476 | if (dev->dev_type == SAS_END_DEV) |
2253 | scic_sds_ssp_io_request_assign_buffers(sci_req); | 2477 | /* pass */; |
2254 | else if ((dev->dev_type == SATA_DEV) || | 2478 | else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) |
2255 | (dev->tproto & SAS_PROTOCOL_STP)) { | ||
2256 | scic_sds_stp_request_assign_buffers(sci_req); | ||
2257 | memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); | 2479 | memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); |
2258 | } else if (dev_is_expander(dev)) { | 2480 | else if (dev_is_expander(dev)) |
2259 | scic_sds_smp_request_assign_buffers(sci_req); | ||
2260 | memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); | 2481 | memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); |
2261 | } else | 2482 | else |
2262 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | 2483 | return SCI_FAILURE_UNSUPPORTED_PROTOCOL; |
2263 | 2484 | ||
2264 | if (status == SCI_SUCCESS) { | 2485 | memset(sci_req->task_context_buffer, 0, |
2265 | memset(sci_req->task_context_buffer, 0, | 2486 | offsetof(struct scu_task_context, sgl_pair_ab)); |
2266 | offsetof(struct scu_task_context, sgl_pair_ab)); | ||
2267 | } | ||
2268 | 2487 | ||
2269 | return status; | 2488 | return status; |
2270 | } | 2489 | } |
@@ -2279,17 +2498,12 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, | |||
2279 | /* Build the common part of the request */ | 2498 | /* Build the common part of the request */ |
2280 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); | 2499 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); |
2281 | 2500 | ||
2282 | if (dev->dev_type == SAS_END_DEV) | 2501 | if (dev->dev_type == SAS_END_DEV || |
2283 | scic_sds_ssp_task_request_assign_buffers(sci_req); | 2502 | dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { |
2284 | else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) | ||
2285 | scic_sds_stp_request_assign_buffers(sci_req); | ||
2286 | else | ||
2287 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | ||
2288 | |||
2289 | if (status == SCI_SUCCESS) { | ||
2290 | sci_req->is_task_management_request = true; | 2503 | sci_req->is_task_management_request = true; |
2291 | memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); | 2504 | memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); |
2292 | } | 2505 | } else |
2506 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | ||
2293 | 2507 | ||
2294 | return status; | 2508 | return status; |
2295 | } | 2509 | } |
@@ -2341,6 +2555,174 @@ static enum sci_status isci_request_stp_request_construct( | |||
2341 | } | 2555 | } |
2342 | 2556 | ||
2343 | /* | 2557 | /* |
2558 | * This function will fill in the SCU Task Context for a SMP request. The | ||
2559 | * following important settings are utilized: -# task_type == | ||
2560 | * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type | ||
2561 | * (i.e. non-raw frame) is being utilized to perform task management. -# | ||
2562 | * control_frame == 1. This ensures that the proper endianess is set so | ||
2563 | * that the bytes are transmitted in the right order for a smp request frame. | ||
2564 | * @sci_req: This parameter specifies the smp request object being | ||
2565 | * constructed. | ||
2566 | * | ||
2567 | */ | ||
2568 | static void | ||
2569 | scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, | ||
2570 | struct smp_req *smp_req) | ||
2571 | { | ||
2572 | dma_addr_t dma_addr; | ||
2573 | struct scic_sds_controller *scic; | ||
2574 | struct scic_sds_remote_device *sci_dev; | ||
2575 | struct scic_sds_port *sci_port; | ||
2576 | struct scu_task_context *task_context; | ||
2577 | ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); | ||
2578 | |||
2579 | /* byte swap the smp request. */ | ||
2580 | sci_swab32_cpy(&sci_req->smp.cmd, smp_req, | ||
2581 | word_cnt); | ||
2582 | |||
2583 | task_context = scic_sds_request_get_task_context(sci_req); | ||
2584 | |||
2585 | scic = scic_sds_request_get_controller(sci_req); | ||
2586 | sci_dev = scic_sds_request_get_device(sci_req); | ||
2587 | sci_port = scic_sds_request_get_port(sci_req); | ||
2588 | |||
2589 | /* | ||
2590 | * Fill in the TC with the its required data | ||
2591 | * 00h | ||
2592 | */ | ||
2593 | task_context->priority = 0; | ||
2594 | task_context->initiator_request = 1; | ||
2595 | task_context->connection_rate = sci_dev->connection_rate; | ||
2596 | task_context->protocol_engine_index = | ||
2597 | scic_sds_controller_get_protocol_engine_group(scic); | ||
2598 | task_context->logical_port_index = scic_sds_port_get_index(sci_port); | ||
2599 | task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; | ||
2600 | task_context->abort = 0; | ||
2601 | task_context->valid = SCU_TASK_CONTEXT_VALID; | ||
2602 | task_context->context_type = SCU_TASK_CONTEXT_TYPE; | ||
2603 | |||
2604 | /* 04h */ | ||
2605 | task_context->remote_node_index = sci_dev->rnc.remote_node_index; | ||
2606 | task_context->command_code = 0; | ||
2607 | task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; | ||
2608 | |||
2609 | /* 08h */ | ||
2610 | task_context->link_layer_control = 0; | ||
2611 | task_context->do_not_dma_ssp_good_response = 1; | ||
2612 | task_context->strict_ordering = 0; | ||
2613 | task_context->control_frame = 1; | ||
2614 | task_context->timeout_enable = 0; | ||
2615 | task_context->block_guard_enable = 0; | ||
2616 | |||
2617 | /* 0ch */ | ||
2618 | task_context->address_modifier = 0; | ||
2619 | |||
2620 | /* 10h */ | ||
2621 | task_context->ssp_command_iu_length = smp_req->req_len; | ||
2622 | |||
2623 | /* 14h */ | ||
2624 | task_context->transfer_length_bytes = 0; | ||
2625 | |||
2626 | /* | ||
2627 | * 18h ~ 30h, protocol specific | ||
2628 | * since commandIU has been build by framework at this point, we just | ||
2629 | * copy the frist DWord from command IU to this location. */ | ||
2630 | memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); | ||
2631 | |||
2632 | /* | ||
2633 | * 40h | ||
2634 | * "For SMP you could program it to zero. We would prefer that way | ||
2635 | * so that done code will be consistent." - Venki | ||
2636 | */ | ||
2637 | task_context->task_phase = 0; | ||
2638 | |||
2639 | if (sci_req->was_tag_assigned_by_user) { | ||
2640 | /* | ||
2641 | * Build the task context now since we have already read | ||
2642 | * the data | ||
2643 | */ | ||
2644 | sci_req->post_context = | ||
2645 | (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | | ||
2646 | (scic_sds_controller_get_protocol_engine_group(scic) << | ||
2647 | SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | | ||
2648 | (scic_sds_port_get_index(sci_port) << | ||
2649 | SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | | ||
2650 | scic_sds_io_tag_get_index(sci_req->io_tag)); | ||
2651 | } else { | ||
2652 | /* | ||
2653 | * Build the task context now since we have already read | ||
2654 | * the data. | ||
2655 | * I/O tag index is not assigned because we have to wait | ||
2656 | * until we get a TCi. | ||
2657 | */ | ||
2658 | sci_req->post_context = | ||
2659 | (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | | ||
2660 | (scic_sds_controller_get_protocol_engine_group(scic) << | ||
2661 | SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | | ||
2662 | (scic_sds_port_get_index(sci_port) << | ||
2663 | SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); | ||
2664 | } | ||
2665 | |||
2666 | /* | ||
2667 | * Copy the physical address for the command buffer to the SCU Task | ||
2668 | * Context command buffer should not contain command header. | ||
2669 | */ | ||
2670 | dma_addr = scic_io_request_get_dma_addr(sci_req, | ||
2671 | ((char *) &sci_req->smp.cmd) + | ||
2672 | sizeof(u32)); | ||
2673 | |||
2674 | task_context->command_iu_upper = upper_32_bits(dma_addr); | ||
2675 | task_context->command_iu_lower = lower_32_bits(dma_addr); | ||
2676 | |||
2677 | /* SMP response comes as UF, so no need to set response IU address. */ | ||
2678 | task_context->response_iu_upper = 0; | ||
2679 | task_context->response_iu_lower = 0; | ||
2680 | } | ||
2681 | |||
2682 | static enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) | ||
2683 | { | ||
2684 | struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); | ||
2685 | |||
2686 | if (!smp_req) | ||
2687 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
2688 | |||
2689 | sci_req->protocol = SCIC_SMP_PROTOCOL; | ||
2690 | |||
2691 | /* Construct the SMP SCU Task Context */ | ||
2692 | memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); | ||
2693 | |||
2694 | /* | ||
2695 | * Look at the SMP requests' header fields; for certain SAS 1.x SMP | ||
2696 | * functions under SAS 2.0, a zero request length really indicates | ||
2697 | * a non-zero default length. */ | ||
2698 | if (smp_req->req_len == 0) { | ||
2699 | switch (smp_req->func) { | ||
2700 | case SMP_DISCOVER: | ||
2701 | case SMP_REPORT_PHY_ERR_LOG: | ||
2702 | case SMP_REPORT_PHY_SATA: | ||
2703 | case SMP_REPORT_ROUTE_INFO: | ||
2704 | smp_req->req_len = 2; | ||
2705 | break; | ||
2706 | case SMP_CONF_ROUTE_INFO: | ||
2707 | case SMP_PHY_CONTROL: | ||
2708 | case SMP_PHY_TEST_FUNCTION: | ||
2709 | smp_req->req_len = 9; | ||
2710 | break; | ||
2711 | /* Default - zero is a valid default for 2.0. */ | ||
2712 | } | ||
2713 | } | ||
2714 | |||
2715 | scu_smp_request_construct_task_context(sci_req, smp_req); | ||
2716 | |||
2717 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
2718 | SCI_BASE_REQUEST_STATE_CONSTRUCTED); | ||
2719 | |||
2720 | kfree(smp_req); | ||
2721 | |||
2722 | return SCI_SUCCESS; | ||
2723 | } | ||
2724 | |||
2725 | /* | ||
2344 | * isci_smp_request_build() - This function builds the smp request. | 2726 | * isci_smp_request_build() - This function builds the smp request. |
2345 | * @ireq: This parameter points to the isci_request allocated in the | 2727 | * @ireq: This parameter points to the isci_request allocated in the |
2346 | * request construct function. | 2728 | * request construct function. |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index b5c5b063a369..d090cb1a14d6 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
@@ -88,7 +88,7 @@ enum sci_request_protocol { | |||
88 | SCIC_SMP_PROTOCOL, | 88 | SCIC_SMP_PROTOCOL, |
89 | SCIC_SSP_PROTOCOL, | 89 | SCIC_SSP_PROTOCOL, |
90 | SCIC_STP_PROTOCOL | 90 | SCIC_STP_PROTOCOL |
91 | }; /* XXX remove me, use sas_task.dev instead */; | 91 | }; /* XXX remove me, use sas_task.{dev|task_proto} instead */; |
92 | 92 | ||
93 | struct scic_sds_request { | 93 | struct scic_sds_request { |
94 | /** | 94 | /** |
@@ -310,6 +310,19 @@ enum sci_base_request_states { | |||
310 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, | 310 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, |
311 | 311 | ||
312 | /** | 312 | /** |
313 | * This sub-state indicates that the started task management request | ||
314 | * is waiting for the reception of an unsolicited frame | ||
315 | * (i.e. response IU). | ||
316 | */ | ||
317 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, | ||
318 | |||
319 | /** | ||
320 | * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is | ||
321 | * waiting for the transmission of the initial frame (i.e. command, task, etc.). | ||
322 | */ | ||
323 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, | ||
324 | |||
325 | /** | ||
313 | * This state indicates that the request has completed. | 326 | * This state indicates that the request has completed. |
314 | * This state is entered from the STARTED state. This state is entered from | 327 | * This state is entered from the STARTED state. This state is entered from |
315 | * the ABORTING state. | 328 | * the ABORTING state. |
@@ -461,8 +474,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi | |||
461 | } | 474 | } |
462 | 475 | ||
463 | void scic_sds_request_build_sgl(struct scic_sds_request *sci_req); | 476 | void scic_sds_request_build_sgl(struct scic_sds_request *sci_req); |
464 | void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req); | ||
465 | void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); | ||
466 | enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); | 477 | enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); |
467 | enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); | 478 | enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); |
468 | enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, | 479 | enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, |
@@ -473,30 +484,6 @@ enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req | |||
473 | enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); | 484 | enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); |
474 | 485 | ||
475 | 486 | ||
476 | /** | ||
477 | * enum _scic_sds_smp_request_started_substates - This enumeration depicts all | ||
478 | * of the substates for a SMP request to be performed in the STARTED | ||
479 | * super-state. | ||
480 | * | ||
481 | * | ||
482 | */ | ||
483 | enum scic_sds_smp_request_started_substates { | ||
484 | /** | ||
485 | * This sub-state indicates that the started task management request | ||
486 | * is waiting for the reception of an unsolicited frame | ||
487 | * (i.e. response IU). | ||
488 | */ | ||
489 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, | ||
490 | |||
491 | /** | ||
492 | * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is | ||
493 | * waiting for the transmission of the initial frame (i.e. command, task, etc.). | ||
494 | */ | ||
495 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, | ||
496 | }; | ||
497 | |||
498 | |||
499 | |||
500 | /* XXX open code in caller */ | 487 | /* XXX open code in caller */ |
501 | static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, | 488 | static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, |
502 | dma_addr_t phys_addr) | 489 | dma_addr_t phys_addr) |
@@ -791,7 +778,6 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, | |||
791 | struct scic_sds_request *sci_req); | 778 | struct scic_sds_request *sci_req); |
792 | enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); | 779 | enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); |
793 | enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); | 780 | enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); |
794 | enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req); | ||
795 | void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); | 781 | void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); |
796 | void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); | 782 | void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); |
797 | #endif /* !defined(_ISCI_REQUEST_H_) */ | 783 | #endif /* !defined(_ISCI_REQUEST_H_) */ |
diff --git a/drivers/scsi/isci/smp_request.c b/drivers/scsi/isci/smp_request.c deleted file mode 100644 index d4750a761c58..000000000000 --- a/drivers/scsi/isci/smp_request.c +++ /dev/null | |||
@@ -1,518 +0,0 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include <scsi/sas.h> | ||
57 | #include "state_machine.h" | ||
58 | #include "remote_device.h" | ||
59 | #include "request.h" | ||
60 | #include "scu_completion_codes.h" | ||
61 | #include "scu_task_context.h" | ||
62 | #include "host.h" | ||
63 | |||
64 | static void scu_smp_request_construct_task_context( | ||
65 | struct scic_sds_request *sci_req, | ||
66 | struct smp_req *smp_req); | ||
67 | |||
68 | void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) | ||
69 | { | ||
70 | if (sci_req->was_tag_assigned_by_user == false) | ||
71 | sci_req->task_context_buffer = &sci_req->tc; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * This function will fill in the SCU Task Context for a SMP request. The | ||
76 | * following important settings are utilized: -# task_type == | ||
77 | * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type | ||
78 | * (i.e. non-raw frame) is being utilized to perform task management. -# | ||
79 | * control_frame == 1. This ensures that the proper endianess is set so | ||
80 | * that the bytes are transmitted in the right order for a smp request frame. | ||
81 | * @sci_req: This parameter specifies the smp request object being | ||
82 | * constructed. | ||
83 | * | ||
84 | */ | ||
85 | static void | ||
86 | scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, | ||
87 | struct smp_req *smp_req) | ||
88 | { | ||
89 | dma_addr_t dma_addr; | ||
90 | struct scic_sds_controller *scic; | ||
91 | struct scic_sds_remote_device *sci_dev; | ||
92 | struct scic_sds_port *sci_port; | ||
93 | struct scu_task_context *task_context; | ||
94 | ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); | ||
95 | |||
96 | /* byte swap the smp request. */ | ||
97 | sci_swab32_cpy(&sci_req->smp.cmd, smp_req, | ||
98 | word_cnt); | ||
99 | |||
100 | task_context = scic_sds_request_get_task_context(sci_req); | ||
101 | |||
102 | scic = scic_sds_request_get_controller(sci_req); | ||
103 | sci_dev = scic_sds_request_get_device(sci_req); | ||
104 | sci_port = scic_sds_request_get_port(sci_req); | ||
105 | |||
106 | /* | ||
107 | * Fill in the TC with the its required data | ||
108 | * 00h | ||
109 | */ | ||
110 | task_context->priority = 0; | ||
111 | task_context->initiator_request = 1; | ||
112 | task_context->connection_rate = sci_dev->connection_rate; | ||
113 | task_context->protocol_engine_index = | ||
114 | scic_sds_controller_get_protocol_engine_group(scic); | ||
115 | task_context->logical_port_index = scic_sds_port_get_index(sci_port); | ||
116 | task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; | ||
117 | task_context->abort = 0; | ||
118 | task_context->valid = SCU_TASK_CONTEXT_VALID; | ||
119 | task_context->context_type = SCU_TASK_CONTEXT_TYPE; | ||
120 | |||
121 | /* 04h */ | ||
122 | task_context->remote_node_index = sci_dev->rnc.remote_node_index; | ||
123 | task_context->command_code = 0; | ||
124 | task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; | ||
125 | |||
126 | /* 08h */ | ||
127 | task_context->link_layer_control = 0; | ||
128 | task_context->do_not_dma_ssp_good_response = 1; | ||
129 | task_context->strict_ordering = 0; | ||
130 | task_context->control_frame = 1; | ||
131 | task_context->timeout_enable = 0; | ||
132 | task_context->block_guard_enable = 0; | ||
133 | |||
134 | /* 0ch */ | ||
135 | task_context->address_modifier = 0; | ||
136 | |||
137 | /* 10h */ | ||
138 | task_context->ssp_command_iu_length = smp_req->req_len; | ||
139 | |||
140 | /* 14h */ | ||
141 | task_context->transfer_length_bytes = 0; | ||
142 | |||
143 | /* | ||
144 | * 18h ~ 30h, protocol specific | ||
145 | * since commandIU has been build by framework at this point, we just | ||
146 | * copy the frist DWord from command IU to this location. */ | ||
147 | memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); | ||
148 | |||
149 | /* | ||
150 | * 40h | ||
151 | * "For SMP you could program it to zero. We would prefer that way | ||
152 | * so that done code will be consistent." - Venki | ||
153 | */ | ||
154 | task_context->task_phase = 0; | ||
155 | |||
156 | if (sci_req->was_tag_assigned_by_user) { | ||
157 | /* | ||
158 | * Build the task context now since we have already read | ||
159 | * the data | ||
160 | */ | ||
161 | sci_req->post_context = | ||
162 | (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | | ||
163 | (scic_sds_controller_get_protocol_engine_group(scic) << | ||
164 | SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | | ||
165 | (scic_sds_port_get_index(sci_port) << | ||
166 | SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | | ||
167 | scic_sds_io_tag_get_index(sci_req->io_tag)); | ||
168 | } else { | ||
169 | /* | ||
170 | * Build the task context now since we have already read | ||
171 | * the data. | ||
172 | * I/O tag index is not assigned because we have to wait | ||
173 | * until we get a TCi. | ||
174 | */ | ||
175 | sci_req->post_context = | ||
176 | (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | | ||
177 | (scic_sds_controller_get_protocol_engine_group(scic) << | ||
178 | SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | | ||
179 | (scic_sds_port_get_index(sci_port) << | ||
180 | SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Copy the physical address for the command buffer to the SCU Task | ||
185 | * Context command buffer should not contain command header. | ||
186 | */ | ||
187 | dma_addr = scic_io_request_get_dma_addr(sci_req, | ||
188 | ((char *) &sci_req->smp.cmd) + | ||
189 | sizeof(u32)); | ||
190 | |||
191 | task_context->command_iu_upper = upper_32_bits(dma_addr); | ||
192 | task_context->command_iu_lower = lower_32_bits(dma_addr); | ||
193 | |||
194 | /* SMP response comes as UF, so no need to set response IU address. */ | ||
195 | task_context->response_iu_upper = 0; | ||
196 | task_context->response_iu_lower = 0; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * This function processes an unsolicited frame while the SMP request is waiting | ||
201 | * for a response frame. It will copy the response data, release the | ||
202 | * unsolicited frame, and transition the request to the | ||
203 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
204 | * @sci_req: This parameter specifies the request for which the | ||
205 | * unsolicited frame was received. | ||
206 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
207 | * should contain the response. | ||
208 | * | ||
209 | * This function returns an indication of whether the response frame was handled | ||
210 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
211 | * indicates successful processing of the TC response. | ||
212 | */ | ||
213 | static enum sci_status | ||
214 | scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, | ||
215 | u32 frame_index) | ||
216 | { | ||
217 | enum sci_status status; | ||
218 | void *frame_header; | ||
219 | struct smp_resp *rsp_hdr = &sci_req->smp.rsp; | ||
220 | ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); | ||
221 | |||
222 | status = scic_sds_unsolicited_frame_control_get_header( | ||
223 | &(scic_sds_request_get_controller(sci_req)->uf_control), | ||
224 | frame_index, | ||
225 | &frame_header); | ||
226 | |||
227 | /* byte swap the header. */ | ||
228 | sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); | ||
229 | |||
230 | if (rsp_hdr->frame_type == SMP_RESPONSE) { | ||
231 | void *smp_resp; | ||
232 | |||
233 | status = scic_sds_unsolicited_frame_control_get_buffer( | ||
234 | &(scic_sds_request_get_controller(sci_req)->uf_control), | ||
235 | frame_index, | ||
236 | &smp_resp); | ||
237 | |||
238 | word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / | ||
239 | sizeof(u32); | ||
240 | |||
241 | sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, | ||
242 | smp_resp, word_cnt); | ||
243 | |||
244 | scic_sds_request_set_status( | ||
245 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); | ||
246 | |||
247 | sci_base_state_machine_change_state( | ||
248 | &sci_req->started_substate_machine, | ||
249 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); | ||
250 | } else { | ||
251 | /* This was not a response frame why did it get forwarded? */ | ||
252 | dev_err(scic_to_dev(sci_req->owning_controller), | ||
253 | "%s: SCIC SMP Request 0x%p received unexpected frame " | ||
254 | "%d type 0x%02x\n", | ||
255 | __func__, | ||
256 | sci_req, | ||
257 | frame_index, | ||
258 | rsp_hdr->frame_type); | ||
259 | |||
260 | scic_sds_request_set_status( | ||
261 | sci_req, | ||
262 | SCU_TASK_DONE_SMP_FRM_TYPE_ERR, | ||
263 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); | ||
264 | |||
265 | sci_base_state_machine_change_state( | ||
266 | &sci_req->state_machine, | ||
267 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
268 | } | ||
269 | |||
270 | scic_sds_controller_release_frame(sci_req->owning_controller, | ||
271 | frame_index); | ||
272 | |||
273 | return SCI_SUCCESS; | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * This method processes an abnormal TC completion while the SMP request is | ||
279 | * waiting for a response frame. It decides what happened to the IO based | ||
280 | * on TC completion status. | ||
281 | * @sci_req: This parameter specifies the request for which the TC | ||
282 | * completion was received. | ||
283 | * @completion_code: This parameter indicates the completion status information | ||
284 | * for the TC. | ||
285 | * | ||
286 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
287 | * this method always returns success. | ||
288 | */ | ||
289 | static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( | ||
290 | struct scic_sds_request *sci_req, | ||
291 | u32 completion_code) | ||
292 | { | ||
293 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
294 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
295 | /* | ||
296 | * In the AWAIT RESPONSE state, any TC completion is unexpected. | ||
297 | * but if the TC has success status, we complete the IO anyway. */ | ||
298 | scic_sds_request_set_status( | ||
299 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
300 | ); | ||
301 | |||
302 | sci_base_state_machine_change_state( | ||
303 | &sci_req->state_machine, | ||
304 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
305 | break; | ||
306 | |||
307 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): | ||
308 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): | ||
309 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): | ||
310 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): | ||
311 | /* | ||
312 | * These status has been seen in a specific LSI expander, which sometimes | ||
313 | * is not able to send smp response within 2 ms. This causes our hardware | ||
314 | * break the connection and set TC completion with one of these SMP_XXX_XX_ERR | ||
315 | * status. For these type of error, we ask scic user to retry the request. */ | ||
316 | scic_sds_request_set_status( | ||
317 | sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED | ||
318 | ); | ||
319 | |||
320 | sci_base_state_machine_change_state( | ||
321 | &sci_req->state_machine, | ||
322 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
323 | break; | ||
324 | |||
325 | default: | ||
326 | /* | ||
327 | * All other completion status cause the IO to be complete. If a NAK | ||
328 | * was received, then it is up to the user to retry the request. */ | ||
329 | scic_sds_request_set_status( | ||
330 | sci_req, | ||
331 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
332 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
333 | ); | ||
334 | |||
335 | sci_base_state_machine_change_state( | ||
336 | &sci_req->state_machine, | ||
337 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
338 | break; | ||
339 | } | ||
340 | |||
341 | return SCI_SUCCESS; | ||
342 | } | ||
343 | |||
344 | |||
345 | /** | ||
346 | * This method processes the completions transport layer (TL) status to | ||
347 | * determine if the SMP request was sent successfully. If the SMP request | ||
348 | * was sent successfully, then the state for the SMP request transits to | ||
349 | * waiting for a response frame. | ||
350 | * @sci_req: This parameter specifies the request for which the TC | ||
351 | * completion was received. | ||
352 | * @completion_code: This parameter indicates the completion status information | ||
353 | * for the TC. | ||
354 | * | ||
355 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
356 | * this method always returns success. | ||
357 | */ | ||
358 | static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( | ||
359 | struct scic_sds_request *sci_req, | ||
360 | u32 completion_code) | ||
361 | { | ||
362 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
363 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
364 | scic_sds_request_set_status( | ||
365 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
366 | ); | ||
367 | |||
368 | sci_base_state_machine_change_state( | ||
369 | &sci_req->state_machine, | ||
370 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
371 | break; | ||
372 | |||
373 | default: | ||
374 | /* | ||
375 | * All other completion status cause the IO to be complete. If a NAK | ||
376 | * was received, then it is up to the user to retry the request. */ | ||
377 | scic_sds_request_set_status( | ||
378 | sci_req, | ||
379 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
380 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
381 | ); | ||
382 | |||
383 | sci_base_state_machine_change_state( | ||
384 | &sci_req->state_machine, | ||
385 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | return SCI_SUCCESS; | ||
390 | } | ||
391 | |||
392 | |||
393 | static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { | ||
394 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
395 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
396 | .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, | ||
397 | .frame_handler = scic_sds_smp_request_await_response_frame_handler, | ||
398 | }, | ||
399 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
400 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
401 | .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, | ||
402 | } | ||
403 | }; | ||
404 | |||
405 | /** | ||
406 | * This method performs the actions required when entering the | ||
407 | * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This | ||
408 | * includes setting the IO request state handlers for this sub-state. | ||
409 | * @object: This parameter specifies the request object for which the sub-state | ||
410 | * change is occurring. | ||
411 | * | ||
412 | * none. | ||
413 | */ | ||
414 | static void scic_sds_smp_request_started_await_response_substate_enter( | ||
415 | void *object) | ||
416 | { | ||
417 | struct scic_sds_request *sci_req = object; | ||
418 | |||
419 | SET_STATE_HANDLER( | ||
420 | sci_req, | ||
421 | scic_sds_smp_request_started_substate_handler_table, | ||
422 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE | ||
423 | ); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * This method performs the actions required when entering the | ||
428 | * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. | ||
429 | * This includes setting the SMP request state handlers for this sub-state. | ||
430 | * @object: This parameter specifies the request object for which the sub-state | ||
431 | * change is occurring. | ||
432 | * | ||
433 | * none. | ||
434 | */ | ||
435 | static void scic_sds_smp_request_started_await_tc_completion_substate_enter( | ||
436 | void *object) | ||
437 | { | ||
438 | struct scic_sds_request *sci_req = object; | ||
439 | |||
440 | SET_STATE_HANDLER( | ||
441 | sci_req, | ||
442 | scic_sds_smp_request_started_substate_handler_table, | ||
443 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION | ||
444 | ); | ||
445 | } | ||
446 | |||
447 | static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { | ||
448 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
449 | .enter_state = scic_sds_smp_request_started_await_response_substate_enter, | ||
450 | }, | ||
451 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
452 | .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, | ||
453 | }, | ||
454 | }; | ||
455 | |||
456 | /** | ||
457 | * This method is called by the SCI user to build an SMP IO request. | ||
458 | * | ||
459 | * - The user must have previously called scic_io_request_construct() on the | ||
460 | * supplied IO request. Indicate if the controller successfully built the IO | ||
461 | * request. SCI_SUCCESS This value is returned if the IO request was | ||
462 | * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned | ||
463 | * if the remote_device does not support the SMP protocol. | ||
464 | * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not | ||
465 | * properly set the association between the SCIC IO request and the user's IO | ||
466 | * request. | ||
467 | */ | ||
468 | enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) | ||
469 | { | ||
470 | struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); | ||
471 | |||
472 | if (!smp_req) | ||
473 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
474 | |||
475 | sci_req->protocol = SCIC_SMP_PROTOCOL; | ||
476 | sci_req->has_started_substate_machine = true; | ||
477 | |||
478 | /* Construct the started sub-state machine. */ | ||
479 | sci_base_state_machine_construct( | ||
480 | &sci_req->started_substate_machine, | ||
481 | sci_req, | ||
482 | scic_sds_smp_request_started_substate_table, | ||
483 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE | ||
484 | ); | ||
485 | |||
486 | /* Construct the SMP SCU Task Context */ | ||
487 | memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); | ||
488 | |||
489 | /* | ||
490 | * Look at the SMP requests' header fields; for certain SAS 1.x SMP | ||
491 | * functions under SAS 2.0, a zero request length really indicates | ||
492 | * a non-zero default length. */ | ||
493 | if (smp_req->req_len == 0) { | ||
494 | switch (smp_req->func) { | ||
495 | case SMP_DISCOVER: | ||
496 | case SMP_REPORT_PHY_ERR_LOG: | ||
497 | case SMP_REPORT_PHY_SATA: | ||
498 | case SMP_REPORT_ROUTE_INFO: | ||
499 | smp_req->req_len = 2; | ||
500 | break; | ||
501 | case SMP_CONF_ROUTE_INFO: | ||
502 | case SMP_PHY_CONTROL: | ||
503 | case SMP_PHY_TEST_FUNCTION: | ||
504 | smp_req->req_len = 9; | ||
505 | break; | ||
506 | /* Default - zero is a valid default for 2.0. */ | ||
507 | } | ||
508 | } | ||
509 | |||
510 | scu_smp_request_construct_task_context(sci_req, smp_req); | ||
511 | |||
512 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
513 | SCI_BASE_REQUEST_STATE_CONSTRUCTED); | ||
514 | |||
515 | kfree(smp_req); | ||
516 | |||
517 | return SCI_SUCCESS; | ||
518 | } | ||
diff --git a/drivers/scsi/isci/stp_request.c b/drivers/scsi/isci/stp_request.c index 298086afa5aa..e94ece81ed9d 100644 --- a/drivers/scsi/isci/stp_request.c +++ b/drivers/scsi/isci/stp_request.c | |||
@@ -64,12 +64,6 @@ | |||
64 | #include "scu_task_context.h" | 64 | #include "scu_task_context.h" |
65 | #include "request.h" | 65 | #include "request.h" |
66 | 66 | ||
67 | void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) | ||
68 | { | ||
69 | if (sci_req->was_tag_assigned_by_user == false) | ||
70 | sci_req->task_context_buffer = &sci_req->tc; | ||
71 | } | ||
72 | |||
73 | /** | 67 | /** |
74 | * This method is will fill in the SCU Task Context for any type of SATA | 68 | * This method is will fill in the SCU Task Context for any type of SATA |
75 | * request. This is called from the various SATA constructors. | 69 | * request. This is called from the various SATA constructors. |