]> www.infradead.org Git - users/willy/xarray.git/commitdiff
tpm: Convert dev_nums to XArray
authorMatthew Wilcox <willy@infradead.org>
Tue, 12 Feb 2019 13:47:51 +0000 (08:47 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 9 Aug 2019 01:38:16 +0000 (21:38 -0400)
Also fix a couple of memory leaks on allocation failure.

Signed-off-by: Matthew Wilcox <willy@infradead.org>
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm.h

index 4838c6a9f0f2c702e932066fba62d7a336a87f36..8d25c932c2aeb6db34f1a3ea0ccbbd7d13007122 100644 (file)
@@ -25,8 +25,7 @@
 #include <linux/hw_random.h>
 #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);
index 1b4f95c13e00a0af0588daf42f75cdd5ace7cd39..4eb672d2d33dbc002d8acc6ad104192ccec4494b 100644 (file)
@@ -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);
index a7fea3e0ca86a992b4c02dc9097eb25b06046230..9e66be9ff1b583cad20950344fb9bafb78bee5de 100644 (file)
@@ -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,