diff options
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r-- | drivers/scsi/isci/task.c | 136 |
1 files changed, 50 insertions, 86 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 01032dc2c116..ded81cd1a781 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -146,7 +146,6 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, | |||
146 | int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | 146 | int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) |
147 | { | 147 | { |
148 | struct isci_host *ihost = dev_to_ihost(task->dev); | 148 | struct isci_host *ihost = dev_to_ihost(task->dev); |
149 | struct isci_request *request = NULL; | ||
150 | struct isci_remote_device *device; | 149 | struct isci_remote_device *device; |
151 | unsigned long flags; | 150 | unsigned long flags; |
152 | int ret; | 151 | int ret; |
@@ -226,8 +225,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
226 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 225 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
227 | 226 | ||
228 | /* build and send the request. */ | 227 | /* build and send the request. */ |
229 | status = isci_request_execute(ihost, task, &request, | 228 | status = isci_request_execute(ihost, task, gfp_flags); |
230 | gfp_flags); | ||
231 | 229 | ||
232 | if (status != SCI_SUCCESS) { | 230 | if (status != SCI_SUCCESS) { |
233 | 231 | ||
@@ -254,54 +252,34 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
254 | return 0; | 252 | return 0; |
255 | } | 253 | } |
256 | 254 | ||
257 | 255 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |
258 | 256 | struct isci_tmf *isci_tmf) | |
259 | /** | ||
260 | * isci_task_request_build() - This function builds the task request object. | ||
261 | * @isci_host: This parameter specifies the ISCI host object | ||
262 | * @request: This parameter points to the isci_request object allocated in the | ||
263 | * request construct function. | ||
264 | * @tmf: This parameter is the task management struct to be built | ||
265 | * | ||
266 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
267 | */ | ||
268 | static enum sci_status isci_task_request_build( | ||
269 | struct isci_host *isci_host, | ||
270 | struct isci_request **isci_request, | ||
271 | struct isci_tmf *isci_tmf) | ||
272 | { | 257 | { |
273 | struct scic_sds_remote_device *sci_device; | 258 | struct scic_sds_remote_device *sci_dev; |
274 | enum sci_status status = SCI_FAILURE; | 259 | enum sci_status status = SCI_FAILURE; |
275 | struct isci_request *request = NULL; | 260 | struct isci_request *ireq = NULL; |
276 | struct isci_remote_device *isci_device; | 261 | struct isci_remote_device *idev; |
277 | struct domain_device *dev; | 262 | struct domain_device *dev; |
278 | 263 | ||
279 | dev_dbg(&isci_host->pdev->dev, | 264 | dev_dbg(&ihost->pdev->dev, |
280 | "%s: isci_tmf = %p\n", __func__, isci_tmf); | 265 | "%s: isci_tmf = %p\n", __func__, isci_tmf); |
281 | 266 | ||
282 | isci_device = isci_tmf->device; | 267 | idev = isci_tmf->device; |
283 | sci_device = &isci_device->sci; | 268 | sci_dev = &idev->sci; |
284 | dev = isci_device->domain_dev; | 269 | dev = idev->domain_dev; |
285 | 270 | ||
286 | /* do common allocation and init of request object. */ | 271 | /* do common allocation and init of request object. */ |
287 | status = isci_request_alloc_tmf( | 272 | ireq = isci_request_alloc_tmf(ihost, isci_tmf, idev, GFP_ATOMIC); |
288 | isci_host, | 273 | if (!ireq) |
289 | isci_tmf, | 274 | return NULL; |
290 | &request, | ||
291 | isci_device, | ||
292 | GFP_ATOMIC | ||
293 | ); | ||
294 | |||
295 | if (status != SCI_SUCCESS) | ||
296 | goto out; | ||
297 | 275 | ||
298 | /* let the core do it's construct. */ | 276 | /* let the core do it's construct. */ |
299 | status = scic_task_request_construct(&isci_host->sci, sci_device, | 277 | status = scic_task_request_construct(&ihost->sci, sci_dev, |
300 | SCI_CONTROLLER_INVALID_IO_TAG, | 278 | SCI_CONTROLLER_INVALID_IO_TAG, |
301 | &request->sci); | 279 | &ireq->sci); |
302 | 280 | ||
303 | if (status != SCI_SUCCESS) { | 281 | if (status != SCI_SUCCESS) { |
304 | dev_warn(&isci_host->pdev->dev, | 282 | dev_warn(&ihost->pdev->dev, |
305 | "%s: scic_task_request_construct failed - " | 283 | "%s: scic_task_request_construct failed - " |
306 | "status = 0x%x\n", | 284 | "status = 0x%x\n", |
307 | __func__, | 285 | __func__, |
@@ -312,30 +290,23 @@ static enum sci_status isci_task_request_build( | |||
312 | /* XXX convert to get this from task->tproto like other drivers */ | 290 | /* XXX convert to get this from task->tproto like other drivers */ |
313 | if (dev->dev_type == SAS_END_DEV) { | 291 | if (dev->dev_type == SAS_END_DEV) { |
314 | isci_tmf->proto = SAS_PROTOCOL_SSP; | 292 | isci_tmf->proto = SAS_PROTOCOL_SSP; |
315 | status = scic_task_request_construct_ssp(&request->sci); | 293 | status = scic_task_request_construct_ssp(&ireq->sci); |
316 | if (status != SCI_SUCCESS) | 294 | if (status != SCI_SUCCESS) |
317 | goto errout; | 295 | goto errout; |
318 | } | 296 | } |
319 | 297 | ||
320 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { | 298 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { |
321 | isci_tmf->proto = SAS_PROTOCOL_SATA; | 299 | isci_tmf->proto = SAS_PROTOCOL_SATA; |
322 | status = isci_sata_management_task_request_build(request); | 300 | status = isci_sata_management_task_request_build(ireq); |
323 | 301 | ||
324 | if (status != SCI_SUCCESS) | 302 | if (status != SCI_SUCCESS) |
325 | goto errout; | 303 | goto errout; |
326 | } | 304 | } |
327 | 305 | return ireq; | |
328 | goto out; | ||
329 | |||
330 | errout: | 306 | errout: |
331 | 307 | isci_request_free(ihost, ireq); | |
332 | /* release the dma memory if we fail. */ | 308 | ireq = NULL; |
333 | isci_request_free(isci_host, request); | 309 | return ireq; |
334 | request = NULL; | ||
335 | |||
336 | out: | ||
337 | *isci_request = request; | ||
338 | return status; | ||
339 | } | 310 | } |
340 | 311 | ||
341 | /** | 312 | /** |
@@ -350,16 +321,14 @@ static enum sci_status isci_task_request_build( | |||
350 | * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes | 321 | * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes |
351 | * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. | 322 | * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. |
352 | */ | 323 | */ |
353 | int isci_task_execute_tmf( | 324 | int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, |
354 | struct isci_host *isci_host, | 325 | unsigned long timeout_ms) |
355 | struct isci_tmf *tmf, | ||
356 | unsigned long timeout_ms) | ||
357 | { | 326 | { |
358 | DECLARE_COMPLETION_ONSTACK(completion); | 327 | DECLARE_COMPLETION_ONSTACK(completion); |
359 | enum sci_task_status status = SCI_TASK_FAILURE; | 328 | enum sci_task_status status = SCI_TASK_FAILURE; |
360 | struct scic_sds_remote_device *sci_device; | 329 | struct scic_sds_remote_device *sci_device; |
361 | struct isci_remote_device *isci_device = tmf->device; | 330 | struct isci_remote_device *isci_device = tmf->device; |
362 | struct isci_request *request; | 331 | struct isci_request *ireq; |
363 | int ret = TMF_RESP_FUNC_FAILED; | 332 | int ret = TMF_RESP_FUNC_FAILED; |
364 | unsigned long flags; | 333 | unsigned long flags; |
365 | unsigned long timeleft; | 334 | unsigned long timeleft; |
@@ -368,13 +337,13 @@ int isci_task_execute_tmf( | |||
368 | * if the device is not there and ready. | 337 | * if the device is not there and ready. |
369 | */ | 338 | */ |
370 | if (!isci_device || isci_device->status != isci_ready_for_io) { | 339 | if (!isci_device || isci_device->status != isci_ready_for_io) { |
371 | dev_dbg(&isci_host->pdev->dev, | 340 | dev_dbg(&ihost->pdev->dev, |
372 | "%s: isci_device = %p not ready (%d)\n", | 341 | "%s: isci_device = %p not ready (%d)\n", |
373 | __func__, | 342 | __func__, |
374 | isci_device, isci_device->status); | 343 | isci_device, isci_device->status); |
375 | return TMF_RESP_FUNC_FAILED; | 344 | return TMF_RESP_FUNC_FAILED; |
376 | } else | 345 | } else |
377 | dev_dbg(&isci_host->pdev->dev, | 346 | dev_dbg(&ihost->pdev->dev, |
378 | "%s: isci_device = %p\n", | 347 | "%s: isci_device = %p\n", |
379 | __func__, isci_device); | 348 | __func__, isci_device); |
380 | 349 | ||
@@ -383,64 +352,59 @@ int isci_task_execute_tmf( | |||
383 | /* Assign the pointer to the TMF's completion kernel wait structure. */ | 352 | /* Assign the pointer to the TMF's completion kernel wait structure. */ |
384 | tmf->complete = &completion; | 353 | tmf->complete = &completion; |
385 | 354 | ||
386 | isci_task_request_build( | 355 | ireq = isci_task_request_build(ihost, tmf); |
387 | isci_host, | 356 | if (!ireq) { |
388 | &request, | 357 | dev_warn(&ihost->pdev->dev, |
389 | tmf | ||
390 | ); | ||
391 | |||
392 | if (!request) { | ||
393 | dev_warn(&isci_host->pdev->dev, | ||
394 | "%s: isci_task_request_build failed\n", | 358 | "%s: isci_task_request_build failed\n", |
395 | __func__); | 359 | __func__); |
396 | return TMF_RESP_FUNC_FAILED; | 360 | return TMF_RESP_FUNC_FAILED; |
397 | } | 361 | } |
398 | 362 | ||
399 | spin_lock_irqsave(&isci_host->scic_lock, flags); | 363 | spin_lock_irqsave(&ihost->scic_lock, flags); |
400 | 364 | ||
401 | /* start the TMF io. */ | 365 | /* start the TMF io. */ |
402 | status = scic_controller_start_task( | 366 | status = scic_controller_start_task( |
403 | &isci_host->sci, | 367 | &ihost->sci, |
404 | sci_device, | 368 | sci_device, |
405 | &request->sci, | 369 | &ireq->sci, |
406 | SCI_CONTROLLER_INVALID_IO_TAG); | 370 | SCI_CONTROLLER_INVALID_IO_TAG); |
407 | 371 | ||
408 | if (status != SCI_TASK_SUCCESS) { | 372 | if (status != SCI_TASK_SUCCESS) { |
409 | dev_warn(&isci_host->pdev->dev, | 373 | dev_warn(&ihost->pdev->dev, |
410 | "%s: start_io failed - status = 0x%x, request = %p\n", | 374 | "%s: start_io failed - status = 0x%x, request = %p\n", |
411 | __func__, | 375 | __func__, |
412 | status, | 376 | status, |
413 | request); | 377 | ireq); |
414 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 378 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
415 | goto cleanup_request; | 379 | goto cleanup_request; |
416 | } | 380 | } |
417 | 381 | ||
418 | if (tmf->cb_state_func != NULL) | 382 | if (tmf->cb_state_func != NULL) |
419 | tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); | 383 | tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); |
420 | 384 | ||
421 | isci_request_change_state(request, started); | 385 | isci_request_change_state(ireq, started); |
422 | 386 | ||
423 | /* add the request to the remote device request list. */ | 387 | /* add the request to the remote device request list. */ |
424 | list_add(&request->dev_node, &isci_device->reqs_in_process); | 388 | list_add(&ireq->dev_node, &isci_device->reqs_in_process); |
425 | 389 | ||
426 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 390 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
427 | 391 | ||
428 | /* Wait for the TMF to complete, or a timeout. */ | 392 | /* Wait for the TMF to complete, or a timeout. */ |
429 | timeleft = wait_for_completion_timeout(&completion, | 393 | timeleft = wait_for_completion_timeout(&completion, |
430 | jiffies + msecs_to_jiffies(timeout_ms)); | 394 | jiffies + msecs_to_jiffies(timeout_ms)); |
431 | 395 | ||
432 | if (timeleft == 0) { | 396 | if (timeleft == 0) { |
433 | spin_lock_irqsave(&isci_host->scic_lock, flags); | 397 | spin_lock_irqsave(&ihost->scic_lock, flags); |
434 | 398 | ||
435 | if (tmf->cb_state_func != NULL) | 399 | if (tmf->cb_state_func != NULL) |
436 | tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); | 400 | tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); |
437 | 401 | ||
438 | status = scic_controller_terminate_request( | 402 | status = scic_controller_terminate_request( |
439 | &request->isci_host->sci, | 403 | &ireq->isci_host->sci, |
440 | &request->isci_device->sci, | 404 | &ireq->isci_device->sci, |
441 | &request->sci); | 405 | &ireq->sci); |
442 | 406 | ||
443 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 407 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
444 | } | 408 | } |
445 | 409 | ||
446 | isci_print_tmf(tmf); | 410 | isci_print_tmf(tmf); |
@@ -448,7 +412,7 @@ int isci_task_execute_tmf( | |||
448 | if (tmf->status == SCI_SUCCESS) | 412 | if (tmf->status == SCI_SUCCESS) |
449 | ret = TMF_RESP_FUNC_COMPLETE; | 413 | ret = TMF_RESP_FUNC_COMPLETE; |
450 | else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) { | 414 | else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) { |
451 | dev_dbg(&isci_host->pdev->dev, | 415 | dev_dbg(&ihost->pdev->dev, |
452 | "%s: tmf.status == " | 416 | "%s: tmf.status == " |
453 | "SCI_FAILURE_IO_RESPONSE_VALID\n", | 417 | "SCI_FAILURE_IO_RESPONSE_VALID\n", |
454 | __func__); | 418 | __func__); |
@@ -456,18 +420,18 @@ int isci_task_execute_tmf( | |||
456 | } | 420 | } |
457 | /* Else - leave the default "failed" status alone. */ | 421 | /* Else - leave the default "failed" status alone. */ |
458 | 422 | ||
459 | dev_dbg(&isci_host->pdev->dev, | 423 | dev_dbg(&ihost->pdev->dev, |
460 | "%s: completed request = %p\n", | 424 | "%s: completed request = %p\n", |
461 | __func__, | 425 | __func__, |
462 | request); | 426 | ireq); |
463 | 427 | ||
464 | if (request->io_request_completion != NULL) { | 428 | if (ireq->io_request_completion != NULL) { |
465 | /* A thread is waiting for this TMF to finish. */ | 429 | /* A thread is waiting for this TMF to finish. */ |
466 | complete(request->io_request_completion); | 430 | complete(ireq->io_request_completion); |
467 | } | 431 | } |
468 | 432 | ||
469 | cleanup_request: | 433 | cleanup_request: |
470 | isci_request_free(isci_host, request); | 434 | isci_request_free(ihost, ireq); |
471 | return ret; | 435 | return ret; |
472 | } | 436 | } |
473 | 437 | ||