i2c-eg20t: fix race between i2c init and interrupt enable
[pandora-kernel.git] / drivers / i2c / busses / i2c-eg20t.c
index 8cebef4..46f7bea 100644 (file)
@@ -243,7 +243,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
        if (pch_clk > PCH_MAX_CLK)
                pch_clk = 62500;
 
-       pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+       pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
        /* Set transfer speed in I2CBC */
        iowrite32(pch_i2cbc, p + PCH_I2CBC);
 
@@ -315,7 +315,7 @@ static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
        long ret;
        ret = wait_event_timeout(pch_event,
-                       (adap->pch_event_flag != 0), msecs_to_jiffies(50));
+                       (adap->pch_event_flag != 0), msecs_to_jiffies(1000));
 
        if (ret == 0) {
                pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
@@ -909,29 +909,35 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
                adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
 
                pch_adap->dev.parent = &pdev->dev;
-
-               ret = i2c_add_adapter(pch_adap);
-               if (ret) {
-                       pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
-                       goto err_i2c_add_adapter;
-               }
-
-               pch_i2c_init(&adap_info->pch_data[i]);
        }
+
        ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
                  KBUILD_MODNAME, adap_info);
        if (ret) {
                pch_pci_err(pdev, "request_irq FAILED\n");
-               goto err_i2c_add_adapter;
+               goto err_request_irq;
+       }
+
+       for (i = 0; i < adap_info->ch_num; i++) {
+               pch_adap = &adap_info->pch_data[i].pch_adapter;
+
+               pch_i2c_init(&adap_info->pch_data[i]);
+               ret = i2c_add_adapter(pch_adap);
+               if (ret) {
+                       pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
+                       goto err_add_adapter;
+               }
        }
 
        pci_set_drvdata(pdev, adap_info);
        pch_pci_dbg(pdev, "returns %d.\n", ret);
        return 0;
 
-err_i2c_add_adapter:
+err_add_adapter:
        for (j = 0; j < i; j++)
                i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
+       free_irq(pdev->irq, adap_info);
+err_request_irq:
        pci_iounmap(pdev, base_addr);
 err_pci_iomap:
        pci_release_regions(pdev);