Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+18 -17
+18 -17
drivers/input/serio/xilinx_ps2.c
··· 73 73 spinlock_t lock; 74 74 void __iomem *base_address; /* virt. address of control registers */ 75 75 unsigned int flags; 76 - struct serio serio; /* serio */ 76 + struct serio *serio; /* serio */ 77 + struct device *dev; 77 78 }; 78 79 79 80 /************************************/ ··· 120 119 121 120 /* Check which interrupt is active */ 122 121 if (intr_sr & XPS2_IPIXR_RX_OVF) 123 - dev_warn(drvdata->serio.dev.parent, "receive overrun error\n"); 122 + dev_warn(drvdata->dev, "receive overrun error\n"); 124 123 125 124 if (intr_sr & XPS2_IPIXR_RX_ERR) 126 125 drvdata->flags |= SERIO_PARITY; ··· 133 132 134 133 /* Error, if a byte is not received */ 135 134 if (status) { 136 - dev_err(drvdata->serio.dev.parent, 135 + dev_err(drvdata->dev, 137 136 "wrong rcvd byte count (%d)\n", status); 138 137 } else { 139 - serio_interrupt(&drvdata->serio, c, drvdata->flags); 138 + serio_interrupt(drvdata->serio, c, drvdata->flags); 140 139 drvdata->flags = 0; 141 140 } 142 141 } ··· 194 193 error = request_irq(drvdata->irq, &xps2_interrupt, 0, 195 194 DRIVER_NAME, drvdata); 196 195 if (error) { 197 - dev_err(drvdata->serio.dev.parent, 196 + dev_err(drvdata->dev, 198 197 "Couldn't allocate interrupt %d\n", drvdata->irq); 199 198 return error; 200 199 } ··· 260 259 } 261 260 262 261 drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); 263 - if (!drvdata) { 264 - dev_err(dev, "Couldn't allocate device private record\n"); 265 - return -ENOMEM; 262 + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 263 + if (!drvdata || !serio) { 264 + error = -ENOMEM; 265 + goto failed1; 266 266 } 267 - 268 - dev_set_drvdata(dev, drvdata); 269 267 270 268 spin_lock_init(&drvdata->lock); 271 269 drvdata->irq = r_irq.start; 270 + drvdata->serio = serio; 271 + drvdata->dev = dev; 272 272 273 273 phys_addr = r_mem.start; 274 274 remap_size = resource_size(&r_mem); ··· 300 298 (unsigned long long)phys_addr, drvdata->base_address, 301 299 drvdata->irq); 302 300 303 - serio = &drvdata->serio; 304 301 serio->id.type = SERIO_8042; 305 302 serio->write = sxps2_write; 306 303 serio->open = sxps2_open; ··· 313 312 314 313 serio_register_port(serio); 315 314 315 + platform_set_drvdata(ofdev, drvdata); 316 316 return 0; /* success */ 317 317 318 318 failed2: 319 319 release_mem_region(phys_addr, remap_size); 320 320 failed1: 321 + kfree(serio); 321 322 kfree(drvdata); 322 - dev_set_drvdata(dev, NULL); 323 323 324 324 return error; 325 325 } ··· 335 333 */ 336 334 static int __devexit xps2_of_remove(struct platform_device *of_dev) 337 335 { 338 - struct device *dev = &of_dev->dev; 339 - struct xps2data *drvdata = dev_get_drvdata(dev); 336 + struct xps2data *drvdata = platform_get_drvdata(of_dev); 340 337 struct resource r_mem; /* IO mem resources */ 341 338 342 - serio_unregister_port(&drvdata->serio); 339 + serio_unregister_port(drvdata->serio); 343 340 iounmap(drvdata->base_address); 344 341 345 342 /* Get iospace of the device */ 346 343 if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem)) 347 - dev_err(dev, "invalid address\n"); 344 + dev_err(drvdata->dev, "invalid address\n"); 348 345 else 349 346 release_mem_region(r_mem.start, resource_size(&r_mem)); 350 347 351 348 kfree(drvdata); 352 349 353 - dev_set_drvdata(dev, NULL); 350 + platform_set_drvdata(of_dev, NULL); 354 351 355 352 return 0; 356 353 }