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

[PATCH] tpm: Fix lack of driver_unregister in init failcases

driver_unregister is not being properly called when the init function
returns an error case. Restructured the return logic such that this and
the other cleanups all happen in one place. Preformed many of the cleanups
that Andrew Morton's patch on Thursday made in tpm_atmel.c. Fixed
Matthieu's concern about writing before discovery.

(akpm: rmk said:

This driver is buggy. You must not provide your own release function - it
doesn't solve the problem which the warning (which you get when you don't
provide one) is telling you about.

You should convert your device driver over to the replacement dynamic platform
support, once it is merged. IOW, something like:

pdev = platform_device_alloc("mydev", id);
if (pdev) {
err = platform_device_add_resources(pdev, &resources,
ARRAY_SIZE(resources));
if (err == 0)
err = platform_device_add_data(pdev, &platform_data,
sizeof(platform_data));
if (err == 0)
err = platform_device_add(pdev);
} else {
err = -ENOMEM;
}
if (err)
platform_device_put(pdev);
)

Signed-off-by: Kylene Jo Hall <kjhall@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Kylene Jo Hall and committed by
Linus Torvalds
e2a8f7a1 ccb6e363

+23 -25
+23 -25
drivers/char/tpm/tpm_nsc.c
··· 287 287 int lo, hi; 288 288 int nscAddrBase = TPM_ADDR; 289 289 290 - driver_register(&nsc_drv); 291 - 292 - /* select PM channel 1 */ 293 - tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12); 294 290 295 291 /* verify that it is a National part (SID) */ 296 292 if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { ··· 296 300 return -ENODEV; 297 301 } 298 302 303 + driver_register(&nsc_drv); 304 + 299 305 hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); 300 306 lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); 301 307 tpm_nsc.base = (hi<<8) | lo; ··· 305 307 /* enable the DPM module */ 306 308 tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); 307 309 308 - pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL); 309 - if ( !pdev ) 310 - return -ENOMEM; 311 - 312 - memset(pdev, 0, sizeof(struct platform_device)); 310 + pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); 311 + if (!pdev) { 312 + rc = -ENOMEM; 313 + goto err_unreg_drv; 314 + } 313 315 314 316 pdev->name = "tpm_nscl0"; 315 317 pdev->id = -1; ··· 317 319 pdev->dev.release = tpm_nsc_remove; 318 320 pdev->dev.driver = &nsc_drv; 319 321 320 - if ((rc=platform_device_register(pdev)) < 0) { 321 - kfree(pdev); 322 - pdev = NULL; 323 - return rc; 324 - } 322 + if ((rc = platform_device_register(pdev)) < 0) 323 + goto err_free_dev; 325 324 326 325 if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { 327 - platform_device_unregister(pdev); 328 - kfree(pdev); 329 - pdev = NULL; 330 - return -EBUSY; 326 + rc = -EBUSY; 327 + goto err_unreg_dev; 331 328 } 332 329 333 - if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) { 334 - release_region(tpm_nsc.base, 2); 335 - platform_device_unregister(pdev); 336 - kfree(pdev); 337 - pdev = NULL; 338 - return rc; 339 - } 330 + if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) 331 + goto err_rel_reg; 340 332 341 333 dev_dbg(&pdev->dev, "NSC TPM detected\n"); 342 334 dev_dbg(&pdev->dev, ··· 362 374 tpm_read_index(nscAddrBase, 0x27) & 0x1F); 363 375 364 376 return 0; 377 + 378 + err_rel_reg: 379 + release_region(tpm_nsc.base, 2); 380 + err_unreg_dev: 381 + platform_device_unregister(pdev); 382 + err_free_dev: 383 + kfree(pdev); 384 + err_unreg_drv: 385 + driver_unregister(&nsc_drv); 386 + return rc; 365 387 } 366 388 367 389 static void __exit cleanup_nsc(void)