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 /drivers/scsi/isci/request.c | |
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>
Diffstat (limited to 'drivers/scsi/isci/request.c')
-rw-r--r-- | drivers/scsi/isci/request.c | 462 |
1 files changed, 422 insertions, 40 deletions
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. |