From: Matthew Wilcox Date: Tue, 12 Feb 2019 13:47:51 +0000 (-0500) Subject: tpm: Convert dev_nums to XArray X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7afd80bf8f63e705b57a242867e377be51e1ad27;p=users%2Fwilly%2Fxarray.git tpm: Convert dev_nums to XArray Also fix a couple of memory leaks on allocation failure. Signed-off-by: Matthew Wilcox --- diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 4838c6a9f0f2..8d25c932c2ae 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -25,8 +25,7 @@ #include #include "tpm.h" -DEFINE_IDR(dev_nums_idr); -static DEFINE_MUTEX(idr_lock); +static DEFINE_XARRAY_ALLOC(dev_nums); struct class *tpm_class; struct class *tpmrm_class; @@ -195,25 +194,16 @@ EXPORT_SYMBOL_GPL(tpm_put_ops); */ struct tpm_chip *tpm_default_chip(void) { - struct tpm_chip *chip, *res = NULL; - int chip_num = 0; - int chip_prev; - - mutex_lock(&idr_lock); - - do { - chip_prev = chip_num; - chip = idr_get_next(&dev_nums_idr, &chip_num); - if (chip) { - get_device(&chip->dev); - res = chip; - break; - } - } while (chip_prev != chip_num); + struct tpm_chip *chip; + unsigned long chip_num = 0; - mutex_unlock(&idr_lock); + xa_lock(&dev_nums); + chip = xa_find(&dev_nums, &chip_num, ULONG_MAX, XA_PRESENT); + if (chip) + get_device(&chip->dev); + xa_unlock(&dev_nums); - return res; + return chip; } EXPORT_SYMBOL_GPL(tpm_default_chip); @@ -263,9 +253,7 @@ static void tpm_dev_release(struct device *dev) { struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); - mutex_lock(&idr_lock); - idr_remove(&dev_nums_idr, chip->dev_num); - mutex_unlock(&idr_lock); + xa_erase(&dev_nums, chip->dev_num); kfree(chip->log.bios_event_log); kfree(chip->work_space.context_buf); @@ -336,15 +324,13 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, chip->ops = ops; - mutex_lock(&idr_lock); - rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL); - mutex_unlock(&idr_lock); + rc = xa_alloc(&dev_nums, &chip->dev_num, NULL, + XA_LIMIT(0, TPM_NUM_DEVICES - 1), GFP_KERNEL); if (rc < 0) { dev_err(pdev, "No available tpm device numbers\n"); kfree(chip); return ERR_PTR(rc); } - chip->dev_num = rc; device_initialize(&chip->dev); device_initialize(&chip->devs); @@ -404,8 +390,11 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, return chip; out: + kfree(chip->work_space.context_buf); put_device(&chip->devs); put_device(&chip->dev); + xa_erase(&dev_nums, chip->dev_num); + kfree(chip); return ERR_PTR(rc); } EXPORT_SYMBOL_GPL(tpm_chip_alloc); @@ -464,9 +453,7 @@ static int tpm_add_char_device(struct tpm_chip *chip) } /* Make the chip available. */ - mutex_lock(&idr_lock); - idr_replace(&dev_nums_idr, chip, chip->dev_num); - mutex_unlock(&idr_lock); + xa_store(&dev_nums, chip->dev_num, chip, GFP_KERNEL); return rc; } @@ -476,9 +463,7 @@ static void tpm_del_char_device(struct tpm_chip *chip) cdev_device_del(&chip->cdev, &chip->dev); /* Make the chip unavailable. */ - mutex_lock(&idr_lock); - idr_replace(&dev_nums_idr, NULL, chip->dev_num); - mutex_unlock(&idr_lock); + xa_store(&dev_nums, chip->dev_num, NULL, GFP_KERNEL); /* Make the driver uncallable. */ down_write(&chip->ops_sem); diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1b4f95c13e00..4eb672d2d33d 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -553,7 +553,6 @@ out_destroy_tpm_class: static void __exit tpm_exit(void) { - idr_destroy(&dev_nums_idr); class_destroy(tpm_class); class_destroy(tpmrm_class); unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index a7fea3e0ca86..9e66be9ff1b5 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -375,7 +375,6 @@ extern struct class *tpmrm_class; extern dev_t tpm_devt; extern const struct file_operations tpm_fops; extern const struct file_operations tpmrm_fops; -extern struct idr dev_nums_idr; ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz); ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,