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