mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 09:11:49 +00:00
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>
This commit is contained in:
parent
5edc33480c
commit
ddcc7e347a
@ -2930,7 +2930,22 @@ static void isci_request_io_request_complete(struct isci_host *isci_host,
|
||||
break;
|
||||
}
|
||||
|
||||
isci_request_unmap_sgl(request, isci_host->pdev);
|
||||
switch (task->task_proto) {
|
||||
case SAS_PROTOCOL_SSP:
|
||||
if (task->data_dir == DMA_NONE)
|
||||
break;
|
||||
if (task->num_scatter == 0)
|
||||
/* 0 indicates a single dma address */
|
||||
dma_unmap_single(&isci_host->pdev->dev,
|
||||
request->zero_scatter_daddr,
|
||||
task->total_xfer_len, task->data_dir);
|
||||
else /* unmap the sgl dma addresses */
|
||||
dma_unmap_sg(&isci_host->pdev->dev, task->scatter,
|
||||
request->num_sg_entries, task->data_dir);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Put the completed request on the correct list */
|
||||
isci_task_save_for_upper_layer_completion(isci_host, request, response,
|
||||
|
@ -672,97 +672,10 @@ static inline void isci_request_free(struct isci_host *isci_host,
|
||||
struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost,
|
||||
struct isci_tmf *isci_tmf,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev,
|
||||
struct sas_task *task, gfp_t gfp_flags);
|
||||
|
||||
/**
|
||||
* isci_request_unmap_sgl() - This function unmaps the DMA address of a given
|
||||
* sgl
|
||||
* @request: This parameter points to the isci_request object
|
||||
* @*pdev: This Parameter is the pci_device struct for the controller
|
||||
*
|
||||
*/
|
||||
static inline void
|
||||
isci_request_unmap_sgl(struct isci_request *request, struct pci_dev *pdev)
|
||||
{
|
||||
struct sas_task *task = isci_request_access_task(request);
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: request = %p, task = %p,\n"
|
||||
"task->data_dir = %d, is_sata = %d\n ",
|
||||
__func__,
|
||||
request,
|
||||
task,
|
||||
task->data_dir,
|
||||
sas_protocol_ata(task->task_proto));
|
||||
|
||||
if ((task->data_dir != PCI_DMA_NONE) &&
|
||||
!sas_protocol_ata(task->task_proto)) {
|
||||
if (task->num_scatter == 0)
|
||||
/* 0 indicates a single dma address */
|
||||
dma_unmap_single(
|
||||
&pdev->dev,
|
||||
request->zero_scatter_daddr,
|
||||
task->total_xfer_len,
|
||||
task->data_dir
|
||||
);
|
||||
|
||||
else /* unmap the sgl dma addresses */
|
||||
dma_unmap_sg(
|
||||
&pdev->dev,
|
||||
task->scatter,
|
||||
request->num_sg_entries,
|
||||
task->data_dir
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_request_io_request_get_next_sge() - This function is called by the sci
|
||||
* core to retrieve the next sge for a given request.
|
||||
* @request: This parameter is the isci_request object.
|
||||
* @current_sge_address: This parameter is the last sge retrieved by the sci
|
||||
* core for this request.
|
||||
*
|
||||
* pointer to the next sge for specified request.
|
||||
*/
|
||||
static inline void *
|
||||
isci_request_io_request_get_next_sge(struct isci_request *request,
|
||||
void *current_sge_address)
|
||||
{
|
||||
struct sas_task *task = isci_request_access_task(request);
|
||||
void *ret = NULL;
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: request = %p, "
|
||||
"current_sge_address = %p, "
|
||||
"num_scatter = %d\n",
|
||||
__func__,
|
||||
request,
|
||||
current_sge_address,
|
||||
task->num_scatter);
|
||||
|
||||
if (!current_sge_address) /* First time through.. */
|
||||
ret = task->scatter; /* always task->scatter */
|
||||
else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
|
||||
ret = NULL; /* there is only one element. */
|
||||
else
|
||||
ret = sg_next(current_sge_address); /* sg_next returns NULL
|
||||
* for the last element
|
||||
*/
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: next sge address = %p\n",
|
||||
__func__,
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
isci_terminate_pending_requests(struct isci_host *ihost,
|
||||
struct isci_remote_device *idev);
|
||||
void isci_terminate_pending_requests(struct isci_host *ihost,
|
||||
struct isci_remote_device *idev);
|
||||
enum sci_status
|
||||
scic_task_request_construct(struct scic_sds_controller *scic,
|
||||
struct scic_sds_remote_device *sci_dev,
|
||||
|
Loading…
Reference in New Issue
Block a user