Commit 91ab5d9d authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Bjorn Helgaas

PCI/VPD: Make pci_vpd_wait() uninterruptible

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.comSigned-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 1285762c
...@@ -24,7 +24,6 @@ struct pci_vpd { ...@@ -24,7 +24,6 @@ struct pci_vpd {
unsigned int len; unsigned int len;
u16 flag; u16 flag;
u8 cap; u8 cap;
unsigned int busy:1;
unsigned int valid:1; unsigned int valid:1;
}; };
...@@ -129,22 +128,14 @@ static int pci_vpd_wait(struct pci_dev *dev) ...@@ -129,22 +128,14 @@ static int pci_vpd_wait(struct pci_dev *dev)
u16 status; u16 status;
int ret; int ret;
if (!vpd->busy)
return 0;
do { do {
ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR, ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
&status); &status);
if (ret < 0) if (ret < 0)
return ret; return ret;
if ((status & PCI_VPD_ADDR_F) == vpd->flag) { if ((status & PCI_VPD_ADDR_F) == vpd->flag)
vpd->busy = 0;
return 0; return 0;
}
if (fatal_signal_pending(current))
return -EINTR;
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout))
break; break;
...@@ -162,7 +153,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -162,7 +153,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
void *arg) void *arg)
{ {
struct pci_vpd *vpd = dev->vpd; struct pci_vpd *vpd = dev->vpd;
int ret; int ret = 0;
loff_t end = pos + count; loff_t end = pos + count;
u8 *buf = arg; u8 *buf = arg;
...@@ -188,19 +179,19 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -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)) if (mutex_lock_killable(&vpd->lock))
return -EINTR; return -EINTR;
ret = pci_vpd_wait(dev);
if (ret < 0)
goto out;
while (pos < end) { while (pos < end) {
u32 val; u32 val;
unsigned int i, skip; unsigned int i, skip;
if (fatal_signal_pending(current)) {
ret = -EINTR;
break;
}
ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR, ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
pos & ~3); pos & ~3);
if (ret < 0) if (ret < 0)
break; break;
vpd->busy = 1;
vpd->flag = PCI_VPD_ADDR_F; vpd->flag = PCI_VPD_ADDR_F;
ret = pci_vpd_wait(dev); ret = pci_vpd_wait(dev);
if (ret < 0) if (ret < 0)
...@@ -220,7 +211,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -220,7 +211,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
val >>= 8; val >>= 8;
} }
} }
out:
mutex_unlock(&vpd->lock); mutex_unlock(&vpd->lock);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -250,10 +241,6 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t 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)) if (mutex_lock_killable(&vpd->lock))
return -EINTR; return -EINTR;
ret = pci_vpd_wait(dev);
if (ret < 0)
goto out;
while (pos < end) { while (pos < end) {
u32 val; u32 val;
...@@ -270,7 +257,6 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -270,7 +257,6 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
if (ret < 0) if (ret < 0)
break; break;
vpd->busy = 1;
vpd->flag = 0; vpd->flag = 0;
ret = pci_vpd_wait(dev); ret = pci_vpd_wait(dev);
if (ret < 0) if (ret < 0)
...@@ -278,7 +264,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -278,7 +264,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
pos += sizeof(u32); pos += sizeof(u32);
} }
out:
mutex_unlock(&vpd->lock); mutex_unlock(&vpd->lock);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -341,7 +327,6 @@ void pci_vpd_init(struct pci_dev *dev) ...@@ -341,7 +327,6 @@ void pci_vpd_init(struct pci_dev *dev)
vpd->ops = &pci_vpd_ops; vpd->ops = &pci_vpd_ops;
mutex_init(&vpd->lock); mutex_init(&vpd->lock);
vpd->cap = cap; vpd->cap = cap;
vpd->busy = 0;
vpd->valid = 0; vpd->valid = 0;
dev->vpd = vpd; dev->vpd = vpd;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment