Merge branch 'spi/merge' of git://git.secretlab.ca/git/linux-2.6

* 'spi/merge' of git://git.secretlab.ca/git/linux-2.6:
spi/pxa2xx pci: fix the release - remove race

+21 -40
+21 -40
drivers/spi/pxa2xx_spi_pci.c
··· 7 7 #include <linux/of_device.h> 8 8 #include <linux/spi/pxa2xx_spi.h> 9 9 10 - struct awesome_struct { 10 + struct ce4100_info { 11 11 struct ssp_device ssp; 12 - struct platform_device spi_pdev; 13 - struct pxa2xx_spi_master spi_pdata; 12 + struct platform_device *spi_pdev; 14 13 }; 15 14 16 15 static DEFINE_MUTEX(ssp_lock); ··· 50 51 } 51 52 EXPORT_SYMBOL_GPL(pxa_ssp_free); 52 53 53 - static void plat_dev_release(struct device *dev) 54 - { 55 - struct awesome_struct *as = container_of(dev, 56 - struct awesome_struct, spi_pdev.dev); 57 - 58 - of_device_node_put(&as->spi_pdev.dev); 59 - } 60 - 61 54 static int __devinit ce4100_spi_probe(struct pci_dev *dev, 62 55 const struct pci_device_id *ent) 63 56 { 64 57 int ret; 65 58 resource_size_t phys_beg; 66 59 resource_size_t phys_len; 67 - struct awesome_struct *spi_info; 60 + struct ce4100_info *spi_info; 68 61 struct platform_device *pdev; 69 - struct pxa2xx_spi_master *spi_pdata; 62 + struct pxa2xx_spi_master spi_pdata; 70 63 struct ssp_device *ssp; 71 64 72 65 ret = pci_enable_device(dev); ··· 75 84 return ret; 76 85 } 77 86 87 + pdev = platform_device_alloc("pxa2xx-spi", dev->devfn); 78 88 spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL); 79 - if (!spi_info) { 89 + if (!pdev || !spi_info ) { 80 90 ret = -ENOMEM; 81 - goto err_kz; 91 + goto err_nomem; 82 92 } 83 - ssp = &spi_info->ssp; 84 - pdev = &spi_info->spi_pdev; 85 - spi_pdata = &spi_info->spi_pdata; 93 + memset(&spi_pdata, 0, sizeof(spi_pdata)); 94 + spi_pdata.num_chipselect = dev->devfn; 86 95 87 - pdev->name = "pxa2xx-spi"; 88 - pdev->id = dev->devfn; 96 + ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata)); 97 + if (ret) 98 + goto err_nomem; 99 + 89 100 pdev->dev.parent = &dev->dev; 90 - pdev->dev.platform_data = &spi_info->spi_pdata; 91 - 92 101 #ifdef CONFIG_OF 93 102 pdev->dev.of_node = dev->dev.of_node; 94 103 #endif 95 - pdev->dev.release = plat_dev_release; 96 - 97 - spi_pdata->num_chipselect = dev->devfn; 98 - 104 + ssp = &spi_info->ssp; 99 105 ssp->phys_base = pci_resource_start(dev, 0); 100 106 ssp->mmio_base = ioremap(phys_beg, phys_len); 101 107 if (!ssp->mmio_base) { 102 108 dev_err(&pdev->dev, "failed to ioremap() registers\n"); 103 109 ret = -EIO; 104 - goto err_remap; 110 + goto err_nomem; 105 111 } 106 112 ssp->irq = dev->irq; 107 113 ssp->port_id = pdev->id; ··· 110 122 111 123 pci_set_drvdata(dev, spi_info); 112 124 113 - ret = platform_device_register(pdev); 125 + ret = platform_device_add(pdev); 114 126 if (ret) 115 127 goto err_dev_add; 116 128 ··· 123 135 mutex_unlock(&ssp_lock); 124 136 iounmap(ssp->mmio_base); 125 137 126 - err_remap: 127 - kfree(spi_info); 128 - 129 - err_kz: 138 + err_nomem: 130 139 release_mem_region(phys_beg, phys_len); 131 - 140 + platform_device_put(pdev); 141 + kfree(spi_info); 132 142 return ret; 133 143 } 134 144 135 145 static void __devexit ce4100_spi_remove(struct pci_dev *dev) 136 146 { 137 - struct awesome_struct *spi_info; 138 - struct platform_device *pdev; 147 + struct ce4100_info *spi_info; 139 148 struct ssp_device *ssp; 140 149 141 150 spi_info = pci_get_drvdata(dev); 142 - 143 151 ssp = &spi_info->ssp; 144 - pdev = &spi_info->spi_pdev; 145 - 146 - platform_device_unregister(pdev); 152 + platform_device_unregister(spi_info->spi_pdev); 147 153 148 154 iounmap(ssp->mmio_base); 149 155 release_mem_region(pci_resource_start(dev, 0), ··· 153 171 } 154 172 155 173 static struct pci_device_id ce4100_spi_devices[] __devinitdata = { 156 - 157 174 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) }, 158 175 { }, 159 176 };