summaryrefslogtreecommitdiff
path: root/linux/drivers/media/common/saa7146_core.c
diff options
context:
space:
mode:
authorOliver Endriss <o.endriss@gmx.de>2007-05-03 17:23:44 +0200
committerOliver Endriss <o.endriss@gmx.de>2007-05-03 17:23:44 +0200
commitce1fef0b7e749c71729bdacaa98708d9b65387a4 (patch)
treef4895d13653aa4b7464f035f5a7d91adfbe4c730 /linux/drivers/media/common/saa7146_core.c
parent43925e774ee9f5e800ee3bf3a762b3667e030e90 (diff)
downloadmediapointer-dvb-s2-ce1fef0b7e749c71729bdacaa98708d9b65387a4.tar.gz
mediapointer-dvb-s2-ce1fef0b7e749c71729bdacaa98708d9b65387a4.tar.bz2
saa7146: DMA: Correctly free resources on error, sync PCI streamed data
From: Jon Burgess <jburgess777@googlemail.com> I added saa7146_vmalloc_destroy_pgtable() which frees the resources allocated by saa7146_vmalloc_build_pgtable() and updated the callers in budget-core.c and av7110.c. I have also been through the updated functions and updated the error paths to ensure they free all allocated resources on error. I also realised that there are other callers to saa7146_pgtable_free() which did not have any sg DMA mapped so it seems wrong to add the pci_unmap_sg() into that function. Instead I created saa7146_vmalloc_destroy_pgtable() to do this. Also included in this patch are the previous fixes for pci_unmap_sg() and syncing the PCI streamed data to work with a SWIOTLB and match the requirements documented in DMA-API.txt. Signed-off-by: Jon Burgess <jburgess777@googlemail.com> Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Diffstat (limited to 'linux/drivers/media/common/saa7146_core.c')
-rw-r--r--linux/drivers/media/common/saa7146_core.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c
index b13f2ade3..06edb5fc1 100644
--- a/linux/drivers/media/common/saa7146_core.c
+++ b/linux/drivers/media/common/saa7146_core.c
@@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
char *mem = vmalloc_32(length);
int slen = 0;
- if (NULL == mem) {
- return NULL;
- }
+ if (NULL == mem)
+ goto err_null;
- if (!(pt->slist = vmalloc_to_sg(mem, pages))) {
- vfree(mem);
- return NULL;
- }
+ if (!(pt->slist = vmalloc_to_sg(mem, pages)))
+ goto err_free_mem;
- if (saa7146_pgtable_alloc(pci, pt)) {
- kfree(pt->slist);
- pt->slist = NULL;
- vfree(mem);
- return NULL;
- }
+ if (saa7146_pgtable_alloc(pci, pt))
+ goto err_free_slist;
- slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
- if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
- return NULL;
- }
+ pt->nents = pages;
+ slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
+ if (0 == slen)
+ goto err_free_pgtable;
+
+ if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
+ goto err_unmap_sg;
return mem;
+
+err_unmap_sg:
+ pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+err_free_pgtable:
+ saa7146_pgtable_free(pci, pt);
+err_free_slist:
+ kfree(pt->slist);
+ pt->slist = NULL;
+err_free_mem:
+ vfree(mem);
+err_null:
+ return NULL;
+}
+
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt)
+{
+ pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+ saa7146_pgtable_free(pci, pt);
+ kfree(pt->slist);
+ pt->slist = NULL;
+ vfree(mem);
}
void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -166,8 +183,6 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
return;
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
pt->cpu = NULL;
- kfree(pt->slist);
- pt->slist = NULL;
}
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -532,6 +547,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
EXPORT_SYMBOL_GPL(saa7146_setgpio);