aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Burgess <jburgess777@googlemail.com>2007-05-03 11:23:44 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-05-09 09:12:42 -0400
commit87c3019d7b1acb7704a257d78c482112e9b0c227 (patch)
tree312478a0bed426b3ca89bf4fae1880fed9986bd2
parent32a1db42480dc972e8e92be68d9e604f6aff5381 (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>
-rw-r--r--drivers/media/common/saa7146_core.c54
-rw-r--r--drivers/media/dvb/ttpci/av7110.c9
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c37
-rw-r--r--include/media/saa7146.h2
4 files changed, 63 insertions, 39 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
158err_unmap_sg:
159 pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
160err_free_pgtable:
161 saa7146_pgtable_free(pci, pt);
162err_free_slist:
163 kfree(pt->slist);
164 pt->slist = NULL;
165err_free_mem:
166 vfree(mem);
167err_null:
168 return NULL;
169}
170
171void 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
163void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) 180void 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
173int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) 188int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
528EXPORT_SYMBOL_GPL(saa7146_pgtable_free); 543EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
529EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); 544EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
530EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); 545EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
546EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
531EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); 547EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
532 548
533EXPORT_SYMBOL_GPL(saa7146_setgpio); 549EXPORT_SYMBOL_GPL(saa7146_setgpio);
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 67becdd4db60..ef1108c0bf11 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1246,6 +1246,9 @@ static void vpeirq(unsigned long data)
1246 if (!budget->feeding1 || (newdma == olddma)) 1246 if (!budget->feeding1 || (newdma == olddma))
1247 return; 1247 return;
1248 1248
1249 /* Ensure streamed PCI data is synced to CPU */
1250 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
1251
1249#if 0 1252#if 0
1250 /* track rps1 activity */ 1253 /* track rps1 activity */
1251 printk("vpeirq: %02x Event Counter 1 0x%04x\n", 1254 printk("vpeirq: %02x Event Counter 1 0x%04x\n",
@@ -2679,8 +2682,8 @@ err_iobuf_vfree_6:
2679err_pci_free_5: 2682err_pci_free_5:
2680 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus); 2683 pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
2681err_saa71466_vfree_4: 2684err_saa71466_vfree_4:
2682 if (!av7110->grabbing) 2685 if (av7110->grabbing)
2683 saa7146_pgtable_free(pdev, &av7110->pt); 2686 saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
2684err_i2c_del_3: 2687err_i2c_del_3:
2685 i2c_del_adapter(&av7110->i2c_adap); 2688 i2c_del_adapter(&av7110->i2c_adap);
2686err_dvb_unregister_adapter_2: 2689err_dvb_unregister_adapter_2:
@@ -2710,7 +2713,7 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
2710 SAA7146_ISR_CLEAR(saa, MASK_10); 2713 SAA7146_ISR_CLEAR(saa, MASK_10);
2711 msleep(50); 2714 msleep(50);
2712 tasklet_kill(&av7110->vpe_tasklet); 2715 tasklet_kill(&av7110->vpe_tasklet);
2713 saa7146_pgtable_free(saa->pci, &av7110->pt); 2716 saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
2714 } 2717 }
2715 av7110_exit_v4l(av7110); 2718 av7110_exit_v4l(av7110);
2716 2719
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 6b97dc1e6b65..2557ac9620d0 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -195,6 +195,9 @@ static void vpeirq(unsigned long data)
195 u32 newdma = saa7146_read(budget->dev, PCI_VDP3); 195 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
196 u32 count; 196 u32 count;
197 197
198 /* Ensure streamed PCI data is synced to CPU */
199 pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
200
198 /* nearest lower position divisible by 188 */ 201 /* nearest lower position divisible by 188 */
199 newdma -= newdma % 188; 202 newdma -= newdma % 188;
200 203
@@ -504,16 +507,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
504 strcpy(budget->i2c_adap.name, budget->card->name); 507 strcpy(budget->i2c_adap.name, budget->card->name);
505 508
506 if (i2c_add_adapter(&budget->i2c_adap) < 0) { 509 if (i2c_add_adapter(&budget->i2c_adap) < 0) {
507 dvb_unregister_adapter(&budget->dvb_adapter); 510 ret = -ENOMEM;
508 return -ENOMEM; 511 goto err_dvb_unregister;
509 } 512 }
510 513
511 ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac); 514 ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
512 515
513 if (NULL == 516 budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
514 (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) { 517 if (NULL == budget->grabbing) {
515 ret = -ENOMEM; 518 ret = -ENOMEM;
516 goto err; 519 goto err_del_i2c;
517 } 520 }
518 521
519 saa7146_write(dev, PCI_BT_V1, 0x001c0000); 522 saa7146_write(dev, PCI_BT_V1, 0x001c0000);
@@ -526,14 +529,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
526 if (bi->type != BUDGET_FS_ACTIVY) 529 if (bi->type != BUDGET_FS_ACTIVY)
527 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); 530 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
528 531
529 if (budget_register(budget) == 0) { 532 if (budget_register(budget) == 0)
530 return 0; 533 return 0; /* Everything OK */
531 } 534
532err: 535 /* An error occurred, cleanup resources */
533 i2c_del_adapter(&budget->i2c_adap); 536 saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
534 537
535 vfree(budget->grabbing); 538err_del_i2c:
539 i2c_del_adapter(&budget->i2c_adap);
536 540
541err_dvb_unregister:
537 dvb_unregister_adapter(&budget->dvb_adapter); 542 dvb_unregister_adapter(&budget->dvb_adapter);
538 543
539 return ret; 544 return ret;
@@ -555,15 +560,13 @@ int ttpci_budget_deinit(struct budget *budget)
555 560
556 budget_unregister(budget); 561 budget_unregister(budget);
557 562
558 i2c_del_adapter(&budget->i2c_adap);
559
560 dvb_unregister_adapter(&budget->dvb_adapter);
561
562 tasklet_kill(&budget->vpe_tasklet); 563 tasklet_kill(&budget->vpe_tasklet);
563 564
564 saa7146_pgtable_free(dev->pci, &budget->pt); 565 saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
565 566
566 vfree(budget->grabbing); 567 i2c_del_adapter(&budget->i2c_adap);
568
569 dvb_unregister_adapter(&budget->dvb_adapter);
567 570
568 return 0; 571 return 0;
569} 572}
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index 796bcf151a3a..d3f4f5a38214 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -58,6 +58,7 @@ struct saa7146_pgtable {
58 unsigned long offset; 58 unsigned long offset;
59 /* used for custom pagetables (used for example by budget dvb cards) */ 59 /* used for custom pagetables (used for example by budget dvb cards) */
60 struct scatterlist *slist; 60 struct scatterlist *slist;
61 int nents;
61}; 62};
62 63
63struct saa7146_pci_extension_data { 64struct saa7146_pci_extension_data {
@@ -157,6 +158,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
157void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt); 158void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
158int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); 159int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
159char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt); 160char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
161void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt);
160void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data); 162void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
161int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop); 163int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
162 164