aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-03-25 20:23:19 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-04-03 12:57:11 -0400
commit271002ca7956e5ef140c02af1bd8e93063924ec6 (patch)
tree23672b4bdbdcb3d651f6a7ec9e0c652287fc6d09 /drivers/input
parent131c713fd96e251fcb18f4d2d05f263aa41bb11f (diff)
Input: xilinx_ps2 - allocate serio port separately
'struct serio' is a refcounted data structure with lifetime rules different from 'struct xps2data'. It is quite likely that serio_unregister_port() will try to free memory allocated by the port and that is why it should be allocated separately. Also switch to using platform_get/set_drvdata instead of dev_get/set_drvdata because we are dealing with platform device. Reported-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/serio/xilinx_ps2.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index d96d4c2a76a9..1e983bec7d86 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -73,7 +73,8 @@ struct xps2data {
73 spinlock_t lock; 73 spinlock_t lock;
74 void __iomem *base_address; /* virt. address of control registers */ 74 void __iomem *base_address; /* virt. address of control registers */
75 unsigned int flags; 75 unsigned int flags;
76 struct serio serio; /* serio */ 76 struct serio *serio; /* serio */
77 struct device *dev;
77}; 78};
78 79
79/************************************/ 80/************************************/
@@ -119,7 +120,7 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
119 120
120 /* Check which interrupt is active */ 121 /* Check which interrupt is active */
121 if (intr_sr & XPS2_IPIXR_RX_OVF) 122 if (intr_sr & XPS2_IPIXR_RX_OVF)
122 dev_warn(drvdata->serio.dev.parent, "receive overrun error\n"); 123 dev_warn(drvdata->dev, "receive overrun error\n");
123 124
124 if (intr_sr & XPS2_IPIXR_RX_ERR) 125 if (intr_sr & XPS2_IPIXR_RX_ERR)
125 drvdata->flags |= SERIO_PARITY; 126 drvdata->flags |= SERIO_PARITY;
@@ -132,10 +133,10 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
132 133
133 /* Error, if a byte is not received */ 134 /* Error, if a byte is not received */
134 if (status) { 135 if (status) {
135 dev_err(drvdata->serio.dev.parent, 136 dev_err(drvdata->dev,
136 "wrong rcvd byte count (%d)\n", status); 137 "wrong rcvd byte count (%d)\n", status);
137 } else { 138 } else {
138 serio_interrupt(&drvdata->serio, c, drvdata->flags); 139 serio_interrupt(drvdata->serio, c, drvdata->flags);
139 drvdata->flags = 0; 140 drvdata->flags = 0;
140 } 141 }
141 } 142 }
@@ -193,7 +194,7 @@ static int sxps2_open(struct serio *pserio)
193 error = request_irq(drvdata->irq, &xps2_interrupt, 0, 194 error = request_irq(drvdata->irq, &xps2_interrupt, 0,
194 DRIVER_NAME, drvdata); 195 DRIVER_NAME, drvdata);
195 if (error) { 196 if (error) {
196 dev_err(drvdata->serio.dev.parent, 197 dev_err(drvdata->dev,
197 "Couldn't allocate interrupt %d\n", drvdata->irq); 198 "Couldn't allocate interrupt %d\n", drvdata->irq);
198 return error; 199 return error;
199 } 200 }
@@ -259,15 +260,16 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
259 } 260 }
260 261
261 drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); 262 drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
262 if (!drvdata) { 263 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
263 dev_err(dev, "Couldn't allocate device private record\n"); 264 if (!drvdata || !serio) {
264 return -ENOMEM; 265 error = -ENOMEM;
266 goto failed1;
265 } 267 }
266 268
267 dev_set_drvdata(dev, drvdata);
268
269 spin_lock_init(&drvdata->lock); 269 spin_lock_init(&drvdata->lock);
270 drvdata->irq = r_irq.start; 270 drvdata->irq = r_irq.start;
271 drvdata->serio = serio;
272 drvdata->dev = dev;
271 273
272 phys_addr = r_mem.start; 274 phys_addr = r_mem.start;
273 remap_size = resource_size(&r_mem); 275 remap_size = resource_size(&r_mem);
@@ -298,7 +300,6 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
298 (unsigned long long)phys_addr, drvdata->base_address, 300 (unsigned long long)phys_addr, drvdata->base_address,
299 drvdata->irq); 301 drvdata->irq);
300 302
301 serio = &drvdata->serio;
302 serio->id.type = SERIO_8042; 303 serio->id.type = SERIO_8042;
303 serio->write = sxps2_write; 304 serio->write = sxps2_write;
304 serio->open = sxps2_open; 305 serio->open = sxps2_open;
@@ -312,13 +313,14 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
312 313
313 serio_register_port(serio); 314 serio_register_port(serio);
314 315
316 platform_set_drvdata(ofdev, drvdata);
315 return 0; /* success */ 317 return 0; /* success */
316 318
317failed2: 319failed2:
318 release_mem_region(phys_addr, remap_size); 320 release_mem_region(phys_addr, remap_size);
319failed1: 321failed1:
322 kfree(serio);
320 kfree(drvdata); 323 kfree(drvdata);
321 dev_set_drvdata(dev, NULL);
322 324
323 return error; 325 return error;
324} 326}
@@ -333,22 +335,21 @@ failed1:
333 */ 335 */
334static int __devexit xps2_of_remove(struct platform_device *of_dev) 336static int __devexit xps2_of_remove(struct platform_device *of_dev)
335{ 337{
336 struct device *dev = &of_dev->dev; 338 struct xps2data *drvdata = platform_get_drvdata(of_dev);
337 struct xps2data *drvdata = dev_get_drvdata(dev);
338 struct resource r_mem; /* IO mem resources */ 339 struct resource r_mem; /* IO mem resources */
339 340
340 serio_unregister_port(&drvdata->serio); 341 serio_unregister_port(drvdata->serio);
341 iounmap(drvdata->base_address); 342 iounmap(drvdata->base_address);
342 343
343 /* Get iospace of the device */ 344 /* Get iospace of the device */
344 if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem)) 345 if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem))
345 dev_err(dev, "invalid address\n"); 346 dev_err(drvdata->dev, "invalid address\n");
346 else 347 else
347 release_mem_region(r_mem.start, resource_size(&r_mem)); 348 release_mem_region(r_mem.start, resource_size(&r_mem));
348 349
349 kfree(drvdata); 350 kfree(drvdata);
350 351
351 dev_set_drvdata(dev, NULL); 352 platform_set_drvdata(of_dev, NULL);
352 353
353 return 0; 354 return 0;
354} 355}