Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+18 -90
+16 -1
drivers/scsi/isci/request.c
··· 2930 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 2950 /* Put the completed request on the correct list */ 2936 2951 isci_task_save_for_upper_layer_completion(isci_host, request, response,
+2 -89
drivers/scsi/isci/request.h
··· 672 672 struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, 673 673 struct isci_tmf *isci_tmf, 674 674 gfp_t gfp_flags); 675 - 676 675 int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, 677 676 struct sas_task *task, gfp_t gfp_flags); 678 - 679 - /** 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); 677 + void isci_terminate_pending_requests(struct isci_host *ihost, 678 + struct isci_remote_device *idev); 766 679 enum sci_status 767 680 scic_task_request_construct(struct scic_sds_controller *scic, 768 681 struct scic_sds_remote_device *sci_dev,