PCI/VPD: Make pci_vpd_wait() uninterruptible
authorHeiner Kallweit <hkallweit1@gmail.com>
Thu, 13 May 2021 20:56:41 +0000 (22:56 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 9 Aug 2021 18:43:50 +0000 (13:43 -0500)
Reading/writing 4 bytes should be fast enough even on a slow bus, therefore
pci_vpd_wait() doesn't have to be interruptible.  Making it uninterruptible
allows to simplify the code.

In addition make VPD writes uninterruptible in general.  It's about vital
data, and allowing writes to be interruptible may leave the VPD in an
inconsistent state.

Link: https://lore.kernel.org/r/258bf994-bc2a-2907-9181-2c7a562986d5@gmail.com
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/vpd.c

index 4f262f8..3d9223f 100644 (file)
@@ -24,7 +24,6 @@ struct pci_vpd {
        unsigned int    len;
        u16             flag;
        u8              cap;
-       unsigned int    busy:1;
        unsigned int    valid:1;
 };
 
@@ -129,22 +128,14 @@ static int pci_vpd_wait(struct pci_dev *dev)
        u16 status;
        int ret;
 
-       if (!vpd->busy)
-               return 0;
-
        do {
                ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
                                                &status);
                if (ret < 0)
                        return ret;
 
-               if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
-                       vpd->busy = 0;
+               if ((status & PCI_VPD_ADDR_F) == vpd->flag)
                        return 0;
-               }
-
-               if (fatal_signal_pending(current))
-                       return -EINTR;
 
                if (time_after(jiffies, timeout))
                        break;
@@ -162,7 +153,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
                            void *arg)
 {
        struct pci_vpd *vpd = dev->vpd;
-       int ret;
+       int ret = 0;
        loff_t end = pos + count;
        u8 *buf = arg;
 
@@ -188,19 +179,19 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_wait(dev);
-       if (ret < 0)
-               goto out;
-
        while (pos < end) {
                u32 val;
                unsigned int i, skip;
 
+               if (fatal_signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
                ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
                                                 pos & ~3);
                if (ret < 0)
                        break;
-               vpd->busy = 1;
                vpd->flag = PCI_VPD_ADDR_F;
                ret = pci_vpd_wait(dev);
                if (ret < 0)
@@ -220,7 +211,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
                        val >>= 8;
                }
        }
-out:
+
        mutex_unlock(&vpd->lock);
        return ret ? ret : count;
 }
@@ -250,10 +241,6 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_wait(dev);
-       if (ret < 0)
-               goto out;
-
        while (pos < end) {
                u32 val;
 
@@ -270,7 +257,6 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
                if (ret < 0)
                        break;
 
-               vpd->busy = 1;
                vpd->flag = 0;
                ret = pci_vpd_wait(dev);
                if (ret < 0)
@@ -278,7 +264,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
 
                pos += sizeof(u32);
        }
-out:
+
        mutex_unlock(&vpd->lock);
        return ret ? ret : count;
 }
@@ -341,7 +327,6 @@ void pci_vpd_init(struct pci_dev *dev)
                vpd->ops = &pci_vpd_ops;
        mutex_init(&vpd->lock);
        vpd->cap = cap;
-       vpd->busy = 0;
        vpd->valid = 0;
        dev->vpd = vpd;
 }