diff options
| author | Jon Burgess <jburgess777@googlemail.com> | 2007-05-03 11:23:44 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-05-09 09:12:42 -0400 |
| commit | 87c3019d7b1acb7704a257d78c482112e9b0c227 (patch) | |
| tree | 312478a0bed426b3ca89bf4fae1880fed9986bd2 /drivers/media/common | |
| parent | 32a1db42480dc972e8e92be68d9e604f6aff5381 (diff) | |
V4L/DVB (5592): DMA: Correctly free resources on error, sync PCI streamed data
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>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/common')
| -rw-r--r-- | drivers/media/common/saa7146_core.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 86cbdbcf9d..ef3e54cd94 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
| @@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa | |||
| 136 | char *mem = vmalloc_32(length); | 136 | char *mem = vmalloc_32(length); |
| 137 | int slen = 0; | 137 | int slen = 0; |
| 138 | 138 | ||
| 139 | if (NULL == mem) { | 139 | if (NULL == mem) |
| 140 | return NULL; | 140 | goto err_null; |
| 141 | } | ||
| 142 | 141 | ||
| 143 | if (!(pt->slist = vmalloc_to_sg(mem, pages))) { | 142 | if (!(pt->slist = vmalloc_to_sg(mem, pages))) |
| 144 | vfree(mem); | 143 | goto err_free_mem; |
| 145 | return NULL; | ||
| 146 | } | ||
| 147 | 144 | ||
| 148 | if (saa7146_pgtable_alloc(pci, pt)) { | 145 | if (saa7146_pgtable_alloc(pci, pt)) |
| 149 | kfree(pt->slist); | 146 | goto err_free_slist; |
| 150 | pt->slist = NULL; | ||
| 151 | vfree(mem); | ||
| 152 | return NULL; | ||
| 153 | } | ||
| 154 | 147 | ||
| 155 | slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE); | 148 | pt->nents = pages; |
| 156 | if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) { | 149 | slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE); |
| 157 | return NULL; | 150 | if (0 == slen) |
| 158 | } | 151 | goto err_free_pgtable; |
| 152 | |||
| 153 | if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) | ||
| 154 | goto err_unmap_sg; | ||
| 159 | 155 | ||
| 160 | return mem; | 156 | return mem; |
| 157 | |||
| 158 | err_unmap_sg: | ||
| 159 | pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); | ||
| 160 | err_free_pgtable: | ||
| 161 | saa7146_pgtable_free(pci, pt); | ||
| 162 | err_free_slist: | ||
| 163 | kfree(pt->slist); | ||
| 164 | pt->slist = NULL; | ||
| 165 | err_free_mem: | ||
| 166 | vfree(mem); | ||
| 167 | err_null: | ||
| 168 | return NULL; | ||
| 169 | } | ||
| 170 | |||
| 171 | void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt) | ||
| 172 | { | ||
| 173 | pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); | ||
| 174 | saa7146_pgtable_free(pci, pt); | ||
| 175 | kfree(pt->slist); | ||
| 176 | pt->slist = NULL; | ||
| 177 | vfree(mem); | ||
| 161 | } | 178 | } |
| 162 | 179 | ||
| 163 | void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) | 180 | 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) | |||
| 166 | return; | 183 | return; |
| 167 | pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); | 184 | pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); |
| 168 | pt->cpu = NULL; | 185 | pt->cpu = NULL; |
| 169 | kfree(pt->slist); | ||
| 170 | pt->slist = NULL; | ||
| 171 | } | 186 | } |
| 172 | 187 | ||
| 173 | int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) | 188 | int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) |
| @@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); | |||
| 528 | EXPORT_SYMBOL_GPL(saa7146_pgtable_free); | 543 | EXPORT_SYMBOL_GPL(saa7146_pgtable_free); |
| 529 | EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); | 544 | EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); |
| 530 | EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); | 545 | EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); |
| 546 | EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable); | ||
| 531 | EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); | 547 | EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); |
| 532 | 548 | ||
| 533 | EXPORT_SYMBOL_GPL(saa7146_setgpio); | 549 | EXPORT_SYMBOL_GPL(saa7146_setgpio); |
