On Fri, Feb 05, 2021 at 05:08:20PM -0800, James Bottomley wrote: > Effectively all of this shuffles the tpmrm device allocation from > chip_alloc to chip_add ... I'm not averse to this but it does mean we > can suffer allocation failures now in the add routine and it makes > error handling a bit more complex. We already have to handle failures here, so this doesn't seem any worse (and the existing error handling looked wrong, I fixed it) > > rc = cdev_device_add(&chip->cdevs, &chip->devs); > > if (rc) { > > dev_err(&chip->devs, > > "unable to cdev_device_add() %s, major > > %d, minor %d, err=%d\n", > > dev_name(&chip->devs), MAJOR(chip- > > >devs.devt), > > MINOR(chip->devs.devt), rc); > > - return rc; > > + goto out_put_devs; > > } > > } > > > > @@ -460,6 +459,10 @@ static int tpm_add_char_device(struct tpm_chip > > *chip) > > idr_replace(&dev_nums_idr, chip, chip->dev_num); > > mutex_unlock(&idr_lock); > > > > +out_put_devs: > > + put_device(&chip->devs); > > I think there should be a if (chip->flags & TPM_CHIP_FLAG_TPM2) here. > > I realise you got everything semantically correct and you only ever go > to this label from somewhere that already has the check, but guess what > will happen when the bot rewriters get hold of this ... Makes sense > > +out_del_dev: > > + cdev_device_del(&chip->cdev); > > return rc; > > } > > > > @@ -640,8 +643,10 @@ void tpm_chip_unregister(struct tpm_chip *chip) > > if (IS_ENABLED(CONFIG_HW_RANDOM_TPM)) > > hwrng_unregister(&chip->hwrng); > > tpm_bios_log_teardown(chip); > > - if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) { > > cdev_device_del(&chip->cdevs, &chip->devs); > > + put_device(&chip->devs); > > + } > > tpm_del_char_device(chip); > > Actually, I think you want to go further here. If there's a > > put_device(&chips->dev) > > as the last statement (or moved into tpm_del_char_device) we should > now The proper TPM driver remove sequence is: remove() { /* Upon return the core guarentees no driver callback is running or * will ever run again */ tpm_chip_unregister() // Safe to do this because nothing will now use the HW resources free_irq(chip->XXX) unmap_memory(chip->YYY) // Now we are done with the memory put_device(&chip-dev); } ie the general driver design should expect the chip memory to continue to exist after unregister because it will need to refer to it to destroy any driver resources. > have no active reference on the devices from the kernel and we can > eliminate the > > rc = devm_add_action_or_reset(pdev, > (void (*)(void *)) put_device, > &chip->dev); This devm exists because adding the put_device to the error unwinds of every driver probe function was too daunting. It can be removed only if someone goes and updates every driver to correctly error-unwind tpm_chip_alloc() with put_device() in the driver probe function. Jason