Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux-dvb] [patch 2.6.10-rc3-mm1 4/5] skystar2: check and propagate more return code
- 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>
diff -puN drivers/media/dvb/b2c2/skystar2.c~dvb-040 drivers/media/dvb/b2c2/skystar2.c
--- linux-2.6.10-rc3/drivers/media/dvb/b2c2/skystar2.c~dvb-040 2004-12-15 01:23:11.663837882 +0100
+++ linux-2.6.10-rc3-romieu/drivers/media/dvb/b2c2/skystar2.c 2004-12-15 01:23:11.668837066 +0100
@@ -1747,21 +1747,28 @@ static void free_dma_queue(struct adapte
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);
+ release_adapter(adapter);
- if (adapter != 0)
kfree(adapter);
}
@@ -1872,11 +1879,12 @@ static int driver_initialize(struct pci_
{
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));
@@ -1886,20 +1894,16 @@ static int driver_initialize(struct pci_
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);
@@ -1907,11 +1911,9 @@ static int driver_initialize(struct pci_
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);
@@ -1928,12 +1930,9 @@ static int driver_initialize(struct pci_
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);
@@ -1978,7 +1977,19 @@ static int driver_initialize(struct pci_
spin_lock_init(&adapter->lock);
- 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)
@@ -2459,23 +2470,20 @@ static int skystar2_probe(struct pci_dev
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);
@@ -2501,10 +2509,9 @@ static int skystar2_probe(struct pci_dev
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;
@@ -2516,7 +2523,9 @@ static int skystar2_probe(struct pci_dev
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;
@@ -2524,27 +2533,45 @@ static int skystar2_probe(struct pci_dev
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)
@@ -2568,13 +2595,13 @@ static void skystar2_remove(struct pci_d
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);
}
}
_
Home |
Main Index |
Thread Index