diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2011-06-17 13:40:43 -0400 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:51 -0400 |
| commit | ddcc7e347a891937be65358b43f40b7f81185f8f (patch) | |
| tree | 35492d904678bb36560efa05dd1a474e9ee78b36 | |
| parent | 5edc33480c1c363ab361a881f2957b9fba5185cf (diff) | |
isci: fix dma_unmap_sg usage
One bug and a cleanup:
1/ Fix cases where we were unmapping invalid addresses (smp requests were
being unmapped)
[ 604.662770] ------------[ cut here ]------------
[ 604.668026] WARNING: at lib/dma-debug.c:800 check_unmap+0x418/0x740()
[ 604.675315] Hardware name: SandyBridge Platform
[ 604.680465] isci 0000:03:00.0: DMA-API: device driver tries to free an invalid DMA memory address
2/ The unmap routine is too large to be an inline function, and
isci_request_io_request_get_next_sge is unused.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
| -rw-r--r-- | drivers/scsi/isci/request.c | 17 | ||||
| -rw-r--r-- | drivers/scsi/isci/request.h | 91 |
2 files changed, 18 insertions, 90 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f4fbca7b1fa3..395084955150 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
| @@ -2930,7 +2930,22 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, | |||
| 2930 | break; | 2930 | break; |
| 2931 | } | 2931 | } |
| 2932 | 2932 | ||
| 2933 | isci_request_unmap_sgl(request, isci_host->pdev); | 2933 | switch (task->task_proto) { |
| 2934 | case SAS_PROTOCOL_SSP: | ||
| 2935 | if (task->data_dir == DMA_NONE) | ||
| 2936 | break; | ||
| 2937 | if (task->num_scatter == 0) | ||
| 2938 | /* 0 indicates a single dma address */ | ||
| 2939 | dma_unmap_single(&isci_host->pdev->dev, | ||
| 2940 | request->zero_scatter_daddr, | ||
| 2941 | task->total_xfer_len, task->data_dir); | ||
| 2942 | else /* unmap the sgl dma addresses */ | ||
| 2943 | dma_unmap_sg(&isci_host->pdev->dev, task->scatter, | ||
| 2944 | request->num_sg_entries, task->data_dir); | ||
| 2945 | break; | ||
| 2946 | default: | ||
| 2947 | break; | ||
| 2948 | } | ||
| 2934 | 2949 | ||
| 2935 | /* Put the completed request on the correct list */ | 2950 | /* Put the completed request on the correct list */ |
| 2936 | isci_task_save_for_upper_layer_completion(isci_host, request, response, | 2951 | isci_task_save_for_upper_layer_completion(isci_host, request, response, |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index a91d1d6060ce..324fb7b3ab42 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
| @@ -672,97 +672,10 @@ static inline void isci_request_free(struct isci_host *isci_host, | |||
| 672 | struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, | 672 | struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, |
| 673 | struct isci_tmf *isci_tmf, | 673 | struct isci_tmf *isci_tmf, |
| 674 | gfp_t gfp_flags); | 674 | gfp_t gfp_flags); |
| 675 | |||
| 676 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, | 675 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, |
| 677 | struct sas_task *task, gfp_t gfp_flags); | 676 | struct sas_task *task, gfp_t gfp_flags); |
| 678 | 677 | void isci_terminate_pending_requests(struct isci_host *ihost, | |
| 679 | /** | 678 | struct isci_remote_device *idev); |
| 680 | * isci_request_unmap_sgl() - This function unmaps the DMA address of a given | ||
| 681 | * sgl | ||
| 682 | * @request: This parameter points to the isci_request object | ||
| 683 | * @*pdev: This Parameter is the pci_device struct for the controller | ||
| 684 | * | ||
| 685 | */ | ||
| 686 | static inline void | ||
| 687 | isci_request_unmap_sgl(struct isci_request *request, struct pci_dev *pdev) | ||
| 688 | { | ||
| 689 | struct sas_task *task = isci_request_access_task(request); | ||
| 690 | |||
| 691 | dev_dbg(&request->isci_host->pdev->dev, | ||
| 692 | "%s: request = %p, task = %p,\n" | ||
| 693 | "task->data_dir = %d, is_sata = %d\n ", | ||
| 694 | __func__, | ||
| 695 | request, | ||
| 696 | task, | ||
| 697 | task->data_dir, | ||
| 698 | sas_protocol_ata(task->task_proto)); | ||
| 699 | |||
| 700 | if ((task->data_dir != PCI_DMA_NONE) && | ||
| 701 | !sas_protocol_ata(task->task_proto)) { | ||
| 702 | if (task->num_scatter == 0) | ||
| 703 | /* 0 indicates a single dma address */ | ||
| 704 | dma_unmap_single( | ||
| 705 | &pdev->dev, | ||
| 706 | request->zero_scatter_daddr, | ||
| 707 | task->total_xfer_len, | ||
| 708 | task->data_dir | ||
| 709 | ); | ||
| 710 | |||
| 711 | else /* unmap the sgl dma addresses */ | ||
| 712 | dma_unmap_sg( | ||
| 713 | &pdev->dev, | ||
| 714 | task->scatter, | ||
| 715 | request->num_sg_entries, | ||
| 716 | task->data_dir | ||
| 717 | ); | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 721 | /** | ||
| 722 | * isci_request_io_request_get_next_sge() - This function is called by the sci | ||
| 723 | * core to retrieve the next sge for a given request. | ||
| 724 | * @request: This parameter is the isci_request object. | ||
| 725 | * @current_sge_address: This parameter is the last sge retrieved by the sci | ||
| 726 | * core for this request. | ||
| 727 | * | ||
| 728 | * pointer to the next sge for specified request. | ||
| 729 | */ | ||
| 730 | static inline void * | ||
| 731 | isci_request_io_request_get_next_sge(struct isci_request *request, | ||
| 732 | void *current_sge_address) | ||
| 733 | { | ||
| 734 | struct sas_task *task = isci_request_access_task(request); | ||
| 735 | void *ret = NULL; | ||
| 736 | |||
| 737 | dev_dbg(&request->isci_host->pdev->dev, | ||
| 738 | "%s: request = %p, " | ||
| 739 | "current_sge_address = %p, " | ||
| 740 | "num_scatter = %d\n", | ||
| 741 | __func__, | ||
| 742 | request, | ||
| 743 | current_sge_address, | ||
| 744 | task->num_scatter); | ||
| 745 | |||
| 746 | if (!current_sge_address) /* First time through.. */ | ||
| 747 | ret = task->scatter; /* always task->scatter */ | ||
| 748 | else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */ | ||
| 749 | ret = NULL; /* there is only one element. */ | ||
| 750 | else | ||
| 751 | ret = sg_next(current_sge_address); /* sg_next returns NULL | ||
| 752 | * for the last element | ||
| 753 | */ | ||
| 754 | |||
| 755 | dev_dbg(&request->isci_host->pdev->dev, | ||
| 756 | "%s: next sge address = %p\n", | ||
| 757 | __func__, | ||
| 758 | ret); | ||
| 759 | |||
| 760 | return ret; | ||
| 761 | } | ||
| 762 | |||
| 763 | void | ||
| 764 | isci_terminate_pending_requests(struct isci_host *ihost, | ||
| 765 | struct isci_remote_device *idev); | ||
| 766 | enum sci_status | 679 | enum sci_status |
| 767 | scic_task_request_construct(struct scic_sds_controller *scic, | 680 | scic_task_request_construct(struct scic_sds_controller *scic, |
| 768 | struct scic_sds_remote_device *sci_dev, | 681 | struct scic_sds_remote_device *sci_dev, |
