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 86cbdbcf9d7d..ef3e54cd9407 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); |