diff options
author | Johannes Stezenbach <devnull@localhost> | 2004-12-19 17:57:03 +0000 |
---|---|---|
committer | Johannes Stezenbach <devnull@localhost> | 2004-12-19 17:57:03 +0000 |
commit | d9242aaaec257a126af7bfb24cf8d7552c2c9538 (patch) | |
tree | 919bfb0566d1a9c42546b530249994a92c081ff8 /linux/drivers/media/dvb/b2c2 | |
parent | 90019e6129b6d234bd991a89e1f78a6011e4ad55 (diff) | |
download | mediapointer-dvb-s2-d9242aaaec257a126af7bfb24cf8d7552c2c9538.tar.gz mediapointer-dvb-s2-d9242aaaec257a126af7bfb24cf8d7552c2c9538.tar.bz2 |
- release_adapter does not really balance claim_adapter. release_adapter does.
- unneeded tests in free_adapter_object:
+ kfree(NULL) does not hurt (and it will not happen anyway);
+ irq has already been successfully requested;
- propagation of the error status code through driver_initialize;
- check the status code in skystar2_probe;
- skystar2_remove: no need to test adapter->dvb_adapter against NULL.
If such is its value, the driver has oopsen long before due to:
skystar2_probe
-> dvb_dmxdev_init
-> dvb_register_device
-> dvbdev_get_free_id
-> list_for_each (entry, &adap->device_list)
^^^^ -> NULL
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'linux/drivers/media/dvb/b2c2')
-rw-r--r-- | linux/drivers/media/dvb/b2c2/skystar2.c | 147 |
1 files changed, 85 insertions, 62 deletions
diff --git a/linux/drivers/media/dvb/b2c2/skystar2.c b/linux/drivers/media/dvb/b2c2/skystar2.c index 000c84a76..7e54ef5ae 100644 --- a/linux/drivers/media/dvb/b2c2/skystar2.c +++ b/linux/drivers/media/dvb/b2c2/skystar2.c @@ -1746,22 +1746,25 @@ static void free_dma_queue(struct adapter *adapter) free_dma_queue_one(adapter, *p); } +static void release_adapter(struct adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + + iounmap(adapter->io_mem); + pci_disable_device(pdev); + pci_release_region(pdev, 0); + pci_release_region(pdev, 1); +} + static void free_adapter_object(struct adapter *adapter) { dprintk("%s:\n", __FUNCTION__); close_stream(adapter, 0); - - if (adapter->irq != 0) - free_irq(adapter->irq, adapter); - + free_irq(adapter->irq, adapter); free_dma_queue(adapter); - - if (adapter->io_mem) - iounmap(adapter->io_mem); - - if (adapter != 0) - kfree(adapter); + release_adapter(adapter); + kfree(adapter); } static struct pci_driver skystar2_pci_driver; @@ -1871,11 +1874,12 @@ static int driver_initialize(struct pci_dev *pdev) { struct adapter *adapter; u32 tmp; + int ret = -ENOMEM; - if (!(adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL))) { + adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL); + if (!adapter) { dprintk("%s: out of memory!\n", __FUNCTION__); - - return -ENOMEM; + goto out; } memset(adapter, 0, sizeof(struct adapter)); @@ -1885,20 +1889,16 @@ static int driver_initialize(struct pci_dev *pdev) adapter->pdev = pdev; adapter->irq = pdev->irq; - if ((claim_adapter(adapter)) != 1) { - free_adapter_object(adapter); - - return -ENODEV; - } + ret = claim_adapter(adapter); + if (ret < 0) + goto err_kfree; irq_dma_enable_disable_irq(adapter, 0); - if (request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter) != 0) { + ret = request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter); + if (ret < 0) { dprintk("%s: unable to allocate irq=%d !\n", __FUNCTION__, pdev->irq); - - free_adapter_object(adapter); - - return -ENODEV; + goto err_release_adapter; } read_reg_dw(adapter, 0x208); @@ -1906,11 +1906,9 @@ static int driver_initialize(struct pci_dev *pdev) write_reg_dw(adapter, 0x210, 0xb2ff); write_reg_dw(adapter, 0x208, 0x40); - if (init_dma_queue(adapter) < 0) { - free_adapter_object(adapter); - - return -ENODEV; - } + ret = init_dma_queue(adapter); + if (ret < 0) + goto err_free_irq; adapter->b2c2_revision = (read_reg_dw(adapter, 0x204) >> 0x18); @@ -1927,11 +1925,8 @@ static int driver_initialize(struct pci_dev *pdev) default: printk("%s: The revision of the FlexCop chip on your card is %d\n", __FILE__, adapter->b2c2_revision); printk("%s: This driver works only with FlexCopII(rev.130), FlexCopIIB(rev.195) and FlexCopIII(rev.192).\n", __FILE__); - free_adapter_object(adapter); - pci_set_drvdata(pdev, NULL); - pci_release_region(pdev, 1); - pci_release_region(pdev, 0); - return -ENODEV; + ret = -ENODEV; + goto err_free_dma_queue; } decide_how_many_hw_filters(adapter); @@ -1977,7 +1972,19 @@ static int driver_initialize(struct pci_dev *pdev) adapter->lock = SPIN_LOCK_UNLOCKED; - return 0; +out: + return ret; + +err_free_dma_queue: + free_dma_queue(adapter); +err_free_irq: + free_irq(pdev->irq, adapter); +err_release_adapter: + release_adapter(adapter); +err_kfree: + pci_set_drvdata(pdev, NULL); + kfree(adapter); + goto out; } static void driver_halt(struct pci_dev *pdev) @@ -2477,23 +2484,20 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adapter *adapter; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; + int ret = -ENODEV; - int ret; - - if (pdev == NULL) - return -ENODEV; - - if (driver_initialize(pdev) != 0) - return -ENODEV; + if (!pdev) + goto out; - dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name, THIS_MODULE); + ret = driver_initialize(pdev); + if (ret < 0) + goto out; - if (dvb_adapter == NULL) { + ret = dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name, + THIS_MODULE); + if (ret < 0) { printk("%s: Error registering DVB adapter\n", __FUNCTION__); - - driver_halt(pdev); - - return -ENODEV; + goto err_halt; } adapter = (struct adapter *) pci_get_drvdata(pdev); @@ -2519,10 +2523,9 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->i2c_adap.algo_data = NULL; adapter->i2c_adap.id = I2C_ALGO_BIT; - if (i2c_add_adapter(&adapter->i2c_adap) < 0) { - dvb_unregister_adapter (adapter->dvb_adapter); - return -ENOMEM; - } + ret = i2c_add_adapter(&adapter->i2c_adap); + if (ret < 0) + goto err_dvb_unregister; dvbdemux = &adapter->demux; @@ -2534,7 +2537,9 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dvbdemux->write_to_decoder = NULL; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); - dvb_dmx_init(&adapter->demux); + ret = dvb_dmx_init(&adapter->demux); + if (ret < 0) + goto err_i2c_del; adapter->hw_frontend.source = DMX_FRONTEND_0; @@ -2542,27 +2547,45 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->dmxdev.demux = &dvbdemux->dmx; adapter->dmxdev.capabilities = 0; - dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter); + ret = dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter); + if (ret < 0) + goto err_dmx_release; ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->hw_frontend); if (ret < 0) - return ret; + goto err_dmxdev_release; adapter->mem_frontend.source = DMX_MEMORY_FE; ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->mem_frontend); if (ret < 0) - return ret; + goto err_remove_hw_frontend; ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &adapter->hw_frontend); if (ret < 0) - return ret; + goto err_remove_mem_frontend; dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); frontend_init(adapter); +out: + return ret; - return 0; +err_remove_mem_frontend: + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->mem_frontend); +err_remove_hw_frontend: + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->hw_frontend); +err_dmxdev_release: + dvb_dmxdev_release(&adapter->dmxdev); +err_dmx_release: + dvb_dmx_release(&adapter->demux); +err_i2c_del: + i2c_del_adapter(&adapter->i2c_adap); +err_dvb_unregister: + dvb_unregister_adapter(adapter->dvb_adapter); +err_halt: + driver_halt(pdev); + goto out; } static void skystar2_remove(struct pci_dev *pdev) @@ -2586,13 +2609,13 @@ static void skystar2_remove(struct pci_dev *pdev) dvb_dmxdev_release(&adapter->dmxdev); dvb_dmx_release(&adapter->demux); - if (adapter->fe != NULL) dvb_unregister_frontend(adapter->fe); + if (adapter->fe != NULL) + dvb_unregister_frontend(adapter->fe); - if (adapter->dvb_adapter != NULL) { - i2c_del_adapter(&adapter->i2c_adap); + dvb_unregister_adapter(adapter->dvb_adapter); + + i2c_del_adapter(&adapter->i2c_adap); - dvb_unregister_adapter(adapter->dvb_adapter); - } driver_halt(pdev); } } |