aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Machek <pavel@ucw.cz>2013-06-18 16:34:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-18 18:44:59 -0400
commite3a3c3a205554e564751cd9c0276b2af813d7a92 (patch)
tree34717caa0f8cc89d135ba8f1f319b120a37f69e2
parent05c3e0bb5629b897b0459e4bfb1b93d729033b99 (diff)
UIO: fix uio_pdrv_genirq with device tree but no interrupt
If device is initialized from device tree, but has no interrupt assigned, uio will still try to request and interrupt old way, fails, and fails registration. This is wrong; don't try initializing irq using platform data if device tree is available. Simplified code based on suggestion by Grant Likely. Fixed memory leak in "irq can not be registered" error path. Signed-off-by: Pavel Machek <pavel@denx.de> Reported-by: Detlev Zundel <dzu@denx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/uio/uio_pdrv_genirq.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 960809f010d7..97415492779e 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -103,24 +103,16 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
103 int i; 103 int i;
104 104
105 if (pdev->dev.of_node) { 105 if (pdev->dev.of_node) {
106 int irq;
107
108 /* alloc uioinfo for one device */ 106 /* alloc uioinfo for one device */
109 uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); 107 uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
110 if (!uioinfo) { 108 if (!uioinfo) {
111 ret = -ENOMEM; 109 ret = -ENOMEM;
112 dev_err(&pdev->dev, "unable to kmalloc\n"); 110 dev_err(&pdev->dev, "unable to kmalloc\n");
113 goto bad2; 111 return ret;
114 } 112 }
115 uioinfo->name = pdev->dev.of_node->name; 113 uioinfo->name = pdev->dev.of_node->name;
116 uioinfo->version = "devicetree"; 114 uioinfo->version = "devicetree";
117
118 /* Multiple IRQs are not supported */ 115 /* Multiple IRQs are not supported */
119 irq = platform_get_irq(pdev, 0);
120 if (irq == -ENXIO)
121 uioinfo->irq = UIO_IRQ_NONE;
122 else
123 uioinfo->irq = irq;
124 } 116 }
125 117
126 if (!uioinfo || !uioinfo->name || !uioinfo->version) { 118 if (!uioinfo || !uioinfo->name || !uioinfo->version) {
@@ -148,12 +140,15 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
148 140
149 if (!uioinfo->irq) { 141 if (!uioinfo->irq) {
150 ret = platform_get_irq(pdev, 0); 142 ret = platform_get_irq(pdev, 0);
151 if (ret < 0) { 143 uioinfo->irq = ret;
144 if (ret == -ENXIO && pdev->dev.of_node)
145 uioinfo->irq = UIO_IRQ_NONE;
146 else if (ret < 0) {
152 dev_err(&pdev->dev, "failed to get IRQ\n"); 147 dev_err(&pdev->dev, "failed to get IRQ\n");
153 goto bad0; 148 goto bad1;
154 } 149 }
155 uioinfo->irq = ret;
156 } 150 }
151
157 uiomem = &uioinfo->mem[0]; 152 uiomem = &uioinfo->mem[0];
158 153
159 for (i = 0; i < pdev->num_resources; ++i) { 154 for (i = 0; i < pdev->num_resources; ++i) {
@@ -206,19 +201,19 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
206 ret = uio_register_device(&pdev->dev, priv->uioinfo); 201 ret = uio_register_device(&pdev->dev, priv->uioinfo);
207 if (ret) { 202 if (ret) {
208 dev_err(&pdev->dev, "unable to register uio device\n"); 203 dev_err(&pdev->dev, "unable to register uio device\n");
209 goto bad1; 204 goto bad2;
210 } 205 }
211 206
212 platform_set_drvdata(pdev, priv); 207 platform_set_drvdata(pdev, priv);
213 return 0; 208 return 0;
209 bad2:
210 pm_runtime_disable(&pdev->dev);
214 bad1: 211 bad1:
215 kfree(priv); 212 kfree(priv);
216 pm_runtime_disable(&pdev->dev);
217 bad0: 213 bad0:
218 /* kfree uioinfo for OF */ 214 /* kfree uioinfo for OF */
219 if (pdev->dev.of_node) 215 if (pdev->dev.of_node)
220 kfree(uioinfo); 216 kfree(uioinfo);
221 bad2:
222 return ret; 217 return ret;
223} 218}
224 219