Message ID | 93ecce28-a158-f02a-d134-8afcaced8efe@gmail.com (mailing list archive) |
---|---|
State | Not Applicable |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | PCI/VPD: Add and use pci_read/write_vpd_any() | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Guessing tree name failed - patch did not apply |
On 9/10/2021 2:22 AM, Heiner Kallweit wrote: > In certain cases we need a variant of pci_read_vpd()/pci_write_vpd() that > does not check against dev->vpd.len. Such cases are: > - reading VPD if dev->vpd.len isn't set yet (in pci_vpd_size()) > - devices that map non-VPD information to arbitrary places in VPD address > space (example: Chelsio T3 EEPROM write-protect flag) > Therefore add function variants that check against PCI_VPD_MAX_SIZE only. > > Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com Reverting this series fixed a hang or stack overflow while reading things like, /sys/devices/pci0000:00/0000:00:00.0/0000:01:00.0/vpd [ 125.797082] Insufficient stack space to handle exception! [ 125.797091] ESR: 0x96000047 -- DABT (current EL) [ 125.797095] FAR: 0xffff80002433ffc0 [ 125.797096] Task stack: [0xffff800024340000..0xffff800024350000] [ 125.797099] IRQ stack: [0xffff8000101c0000..0xffff8000101d0000] [ 125.797102] Overflow stack: [0xffff009b675b02b0..0xffff009b675b12b0] [ 125.797106] CPU: 14 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 [ 125.797110] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 [ 125.797114] pstate: 10000005 (nzcV daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 125.797118] pc : pci_vpd_size+0xc/0x1f8 [ 125.797128] lr : pci_vpd_read+0x2ec/0x420 [ 125.797132] sp : ffff800024340060 [ 125.797133] x29: ffff800024340060 x28: ffff00001a54cbcc x27: 0000000000000000 [ 125.797142] x26: ffff800024340210 x25: 0000000000000004 x24: 1fffe000034a9979 [ 125.797148] x23: ffff00001a54cbc8 x22: ffff00001a54cb38 x21: 0000000000008000 [ 125.797153] x20: 1fffe000034a9979 x19: ffff00001a54c000 x18: 0000000000000000 [ 125.797158] x17: 0000000000000000 x16: 0000000000000000 x15: dfff800000000000 [ 125.797163] x14: ffff800019ab0560 x13: 1fffe00110f9272f x12: ffff60010e945be1 [ 125.797168] x11: 1fffe0010e945be0 x10: 1ffff00004868022 x9 : ffff800010d1a38c [ 125.797174] x8 : ffff700004868022 x7 : dfff800000000000 x6 : 0000000000000000 [ 125.797179] x5 : ffff000887c93540 x4 : 0000000000000000 x3 : ffff800024340210 [ 125.797184] x2 : 0000000000000001 x1 : 0000000000000003 x0 : ffff00001a54c000 [ 125.797190] Kernel panic - not syncing: kernel stack overflow [ 125.797193] CPU: 14 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 [ 125.797197] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 [ 125.797199] Call trace: [ 125.797201] dump_backtrace+0x0/0x3b8 [ 125.797208] show_stack+0x20/0x30 [ 125.797212] dump_stack_lvl+0x8c/0xb8 [ 125.797216] dump_stack+0x1c/0x38 [ 125.797219] panic+0x2b0/0x538 [ 125.797224] add_taint+0x0/0xe8 [ 125.797229] panic_bad_stack+0x1e4/0x230 [ 125.797233] handle_bad_stack+0x38/0x50 [ 125.797237] __bad_stack+0x88/0x8c [ 125.797241] pci_vpd_size+0xc/0x1f8 [ 125.797244] __pci_read_vpd+0x114/0x158 [ 125.797247] pci_vpd_size+0xa0/0x1f8 [ 125.797251] pci_vpd_read+0x2ec/0x420 [ 125.797254] __pci_read_vpd+0x114/0x158 [ 125.797258] pci_vpd_size+0xa0/0x1f8 [ 125.797261] pci_vpd_read+0x2ec/0x420 ... [ 125.798534] __pci_read_vpd+0x114/0x158 [ 125.798538] pci_vpd_size+0xa0/0x1f8 [ 125.798541] pci_vpd_read+0x2ec/0x420 [ 125.798545] __pci_read_vpd+0x114/0x158 __pci_read_vpd at /usr/src/linux-next/drivers/pci/vpd.c:398 [ 125.798548] vpd_read+0x28/0x38 vpd_read at /usr/src/linux-next/drivers/pci/vpd.c:276 [ 125.798551] sysfs_kf_bin_read+0x120/0x218 [ 125.798556] kernfs_fop_read_iter+0x244/0x4a8 [ 125.798559] new_sync_read+0x2bc/0x4e8 [ 125.798564] vfs_read+0x18c/0x390 [ 125.798567] ksys_read+0xf8/0x1e0 [ 125.798570] __arm64_sys_read+0x74/0xa8 [ 125.798574] invoke_syscall.constprop.0+0xdc/0x1d8 [ 125.798578] do_el0_svc+0xe4/0x298 [ 125.798582] el0_svc+0x64/0x130 [ 125.798586] el0t_64_sync_handler+0xb0/0xb8 [ 125.798590] el0t_64_sync+0x180/0x184 [ 125.798598] ------------[ cut here ]------------ [ 125.798600] WARNING: CPU: -32 PID: 1550 at include/linux/cpumask.h:108 smp_send_stop+0x4a4/0x5e8 [ 125.798607] Modules linked in: loop cppc_cpufreq efivarfs ip_tables x_tables ext4 mbcache jbd2 dm_mod igb i2c_algo_bit nvme mlx5_core i2c_core nvme_core firmware_class [ 125.798632] CPU: 791961908 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 [ 125.798637] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 [ 125.798639] pstate: a00003c5 (NzCv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 125.798643] pc : smp_send_stop+0x4a4/0x5e8 [ 125.798647] lr : panic+0x2b8/0x538 [ 125.798650] sp : ffff009b675b0c70 [ 125.798652] x29: ffff009b675b0c70 x28: ffff000887c92ec0 x27: 0000000000000000 [ 125.798658] x26: 0000000000000025 x25: ffff809b55bf0000 x24: ffff800011eeb4d0 [ 125.798663] x23: ffff800011426680 x22: ffff800019393000 x21: ffff800019dfa000 [ 125.798668] x20: 00000000ffffffe0 x19: ffff8000119c0000 x18: 0000000000000000 [ 125.798673] x17: 0000000000000000 x16: 0000000000000002 x15: 0000000000000000 [ 125.798678] x14: 0000000000000000 x13: 000000000000000f x12: ffff7000023ef669 [ 125.798683] x11: 1ffff000023ef668 x10: ffff7000023ef668 x9 : ffff80001133f2cc [ 125.798688] x8 : 0000000000000003 x7 : 0000000000000001 x6 : ffff800011f7b340 [ 125.798693] x5 : 1fffe0136ceb619e x4 : 0000000041b58ab3 x3 : 1fffe0136ceb6000 [ 125.798698] x2 : 1ffff000023dd69a x1 : 0000000000000000 x0 : 0000000000000020 [ 125.798704] Call trace: [ 125.798705] smp_send_stop+0x4a4/0x5e8 [ 125.798709] panic+0x2b8/0x538 [ 125.798713] add_taint+0x0/0xe8 [ 125.798717] panic_bad_stack+0x1e4/0x230 [ 125.798720] handle_bad_stack+0x38/0x50 [ 125.798724] __bad_stack+0x88/0x8c [ 125.798727] pci_vpd_size+0xc/0x1f8 [ 125.798731] __pci_read_vpd+0x114/0x158 [ 125.798734] pci_vpd_size+0xa0/0x1f8 [ 125.798738] pci_vpd_read+0x2ec/0x420 [ 125.798741] __pci_read_vpd+0x114/0x158 [ 125.798744] pci_vpd_size+0xa0/0x1f8 [ 125.798748] pci_vpd_read+0x2ec/0x420
On 12.10.2021 20:59, Qian Cai wrote: > > > On 9/10/2021 2:22 AM, Heiner Kallweit wrote: >> In certain cases we need a variant of pci_read_vpd()/pci_write_vpd() that >> does not check against dev->vpd.len. Such cases are: >> - reading VPD if dev->vpd.len isn't set yet (in pci_vpd_size()) >> - devices that map non-VPD information to arbitrary places in VPD address >> space (example: Chelsio T3 EEPROM write-protect flag) >> Therefore add function variants that check against PCI_VPD_MAX_SIZE only. >> >> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com > Reverting this series fixed a hang or stack overflow while reading things like, > > /sys/devices/pci0000:00/0000:00:00.0/0000:01:00.0/vpd > > [ 125.797082] Insufficient stack space to handle exception! > [ 125.797091] ESR: 0x96000047 -- DABT (current EL) > [ 125.797095] FAR: 0xffff80002433ffc0 > [ 125.797096] Task stack: [0xffff800024340000..0xffff800024350000] > [ 125.797099] IRQ stack: [0xffff8000101c0000..0xffff8000101d0000] > [ 125.797102] Overflow stack: [0xffff009b675b02b0..0xffff009b675b12b0] > [ 125.797106] CPU: 14 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 > [ 125.797110] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 > [ 125.797114] pstate: 10000005 (nzcV daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) > [ 125.797118] pc : pci_vpd_size+0xc/0x1f8 > [ 125.797128] lr : pci_vpd_read+0x2ec/0x420 > [ 125.797132] sp : ffff800024340060 > [ 125.797133] x29: ffff800024340060 x28: ffff00001a54cbcc x27: 0000000000000000 > [ 125.797142] x26: ffff800024340210 x25: 0000000000000004 x24: 1fffe000034a9979 > [ 125.797148] x23: ffff00001a54cbc8 x22: ffff00001a54cb38 x21: 0000000000008000 > [ 125.797153] x20: 1fffe000034a9979 x19: ffff00001a54c000 x18: 0000000000000000 > [ 125.797158] x17: 0000000000000000 x16: 0000000000000000 x15: dfff800000000000 > [ 125.797163] x14: ffff800019ab0560 x13: 1fffe00110f9272f x12: ffff60010e945be1 > [ 125.797168] x11: 1fffe0010e945be0 x10: 1ffff00004868022 x9 : ffff800010d1a38c > [ 125.797174] x8 : ffff700004868022 x7 : dfff800000000000 x6 : 0000000000000000 > [ 125.797179] x5 : ffff000887c93540 x4 : 0000000000000000 x3 : ffff800024340210 > [ 125.797184] x2 : 0000000000000001 x1 : 0000000000000003 x0 : ffff00001a54c000 > [ 125.797190] Kernel panic - not syncing: kernel stack overflow > [ 125.797193] CPU: 14 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 > [ 125.797197] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 > [ 125.797199] Call trace: > [ 125.797201] dump_backtrace+0x0/0x3b8 > [ 125.797208] show_stack+0x20/0x30 > [ 125.797212] dump_stack_lvl+0x8c/0xb8 > [ 125.797216] dump_stack+0x1c/0x38 > [ 125.797219] panic+0x2b0/0x538 > [ 125.797224] add_taint+0x0/0xe8 > [ 125.797229] panic_bad_stack+0x1e4/0x230 > [ 125.797233] handle_bad_stack+0x38/0x50 > [ 125.797237] __bad_stack+0x88/0x8c > [ 125.797241] pci_vpd_size+0xc/0x1f8 > [ 125.797244] __pci_read_vpd+0x114/0x158 > [ 125.797247] pci_vpd_size+0xa0/0x1f8 > [ 125.797251] pci_vpd_read+0x2ec/0x420 > [ 125.797254] __pci_read_vpd+0x114/0x158 > [ 125.797258] pci_vpd_size+0xa0/0x1f8 > [ 125.797261] pci_vpd_read+0x2ec/0x420 > ... > [ 125.798534] __pci_read_vpd+0x114/0x158 > [ 125.798538] pci_vpd_size+0xa0/0x1f8 > [ 125.798541] pci_vpd_read+0x2ec/0x420 > [ 125.798545] __pci_read_vpd+0x114/0x158 > __pci_read_vpd at /usr/src/linux-next/drivers/pci/vpd.c:398 > [ 125.798548] vpd_read+0x28/0x38 > vpd_read at /usr/src/linux-next/drivers/pci/vpd.c:276 > [ 125.798551] sysfs_kf_bin_read+0x120/0x218 > [ 125.798556] kernfs_fop_read_iter+0x244/0x4a8 > [ 125.798559] new_sync_read+0x2bc/0x4e8 > [ 125.798564] vfs_read+0x18c/0x390 > [ 125.798567] ksys_read+0xf8/0x1e0 > [ 125.798570] __arm64_sys_read+0x74/0xa8 > [ 125.798574] invoke_syscall.constprop.0+0xdc/0x1d8 > [ 125.798578] do_el0_svc+0xe4/0x298 > [ 125.798582] el0_svc+0x64/0x130 > [ 125.798586] el0t_64_sync_handler+0xb0/0xb8 > [ 125.798590] el0t_64_sync+0x180/0x184 > [ 125.798598] ------------[ cut here ]------------ > [ 125.798600] WARNING: CPU: -32 PID: 1550 at include/linux/cpumask.h:108 smp_send_stop+0x4a4/0x5e8 > [ 125.798607] Modules linked in: loop cppc_cpufreq efivarfs ip_tables x_tables ext4 mbcache jbd2 dm_mod igb i2c_algo_bit nvme mlx5_core i2c_core nvme_core firmware_class > [ 125.798632] CPU: 791961908 PID: 1550 Comm: lsbug Not tainted 5.15.0-rc5-next-20211012 #143 > [ 125.798637] Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 1.6 06/28/2020 > [ 125.798639] pstate: a00003c5 (NzCv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) > [ 125.798643] pc : smp_send_stop+0x4a4/0x5e8 > [ 125.798647] lr : panic+0x2b8/0x538 > [ 125.798650] sp : ffff009b675b0c70 > [ 125.798652] x29: ffff009b675b0c70 x28: ffff000887c92ec0 x27: 0000000000000000 > [ 125.798658] x26: 0000000000000025 x25: ffff809b55bf0000 x24: ffff800011eeb4d0 > [ 125.798663] x23: ffff800011426680 x22: ffff800019393000 x21: ffff800019dfa000 > [ 125.798668] x20: 00000000ffffffe0 x19: ffff8000119c0000 x18: 0000000000000000 > [ 125.798673] x17: 0000000000000000 x16: 0000000000000002 x15: 0000000000000000 > [ 125.798678] x14: 0000000000000000 x13: 000000000000000f x12: ffff7000023ef669 > [ 125.798683] x11: 1ffff000023ef668 x10: ffff7000023ef668 x9 : ffff80001133f2cc > [ 125.798688] x8 : 0000000000000003 x7 : 0000000000000001 x6 : ffff800011f7b340 > [ 125.798693] x5 : 1fffe0136ceb619e x4 : 0000000041b58ab3 x3 : 1fffe0136ceb6000 > [ 125.798698] x2 : 1ffff000023dd69a x1 : 0000000000000000 x0 : 0000000000000020 > [ 125.798704] Call trace: > [ 125.798705] smp_send_stop+0x4a4/0x5e8 > [ 125.798709] panic+0x2b8/0x538 > [ 125.798713] add_taint+0x0/0xe8 > [ 125.798717] panic_bad_stack+0x1e4/0x230 > [ 125.798720] handle_bad_stack+0x38/0x50 > [ 125.798724] __bad_stack+0x88/0x8c > [ 125.798727] pci_vpd_size+0xc/0x1f8 > [ 125.798731] __pci_read_vpd+0x114/0x158 > [ 125.798734] pci_vpd_size+0xa0/0x1f8 > [ 125.798738] pci_vpd_read+0x2ec/0x420 > [ 125.798741] __pci_read_vpd+0x114/0x158 > [ 125.798744] pci_vpd_size+0xa0/0x1f8 > [ 125.798748] pci_vpd_read+0x2ec/0x420 > Thanks for the report! I could reproduce the issue, the following fixes it for me. Could you please test whether it fixes the issue for you as well? Thank you. diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c index 5108bbd20..a4fc4d069 100644 --- a/drivers/pci/vpd.c +++ b/drivers/pci/vpd.c @@ -96,14 +96,14 @@ static size_t pci_vpd_size(struct pci_dev *dev) return off ?: PCI_VPD_SZ_INVALID; } -static bool pci_vpd_available(struct pci_dev *dev) +static bool pci_vpd_available(struct pci_dev *dev, bool check_size) { struct pci_vpd *vpd = &dev->vpd; if (!vpd->cap) return false; - if (vpd->len == 0) { + if (vpd->len == 0 && check_size) { vpd->len = pci_vpd_size(dev); if (vpd->len == PCI_VPD_SZ_INVALID) { vpd->cap = 0; @@ -156,17 +156,19 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, void *arg, bool check_size) { struct pci_vpd *vpd = &dev->vpd; - unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; + unsigned int max_len; int ret = 0; loff_t end = pos + count; u8 *buf = arg; - if (!pci_vpd_available(dev)) + if (!pci_vpd_available(dev, check_size)) return -ENODEV; if (pos < 0) return -EINVAL; + max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; + if (pos >= max_len) return 0; @@ -218,17 +220,19 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, const void *arg, bool check_size) { struct pci_vpd *vpd = &dev->vpd; - unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; + unsigned int max_len; const u8 *buf = arg; loff_t end = pos + count; int ret = 0; - if (!pci_vpd_available(dev)) + if (!pci_vpd_available(dev, check_size)) return -ENODEV; if (pos < 0 || (pos & 3) || (count & 3)) return -EINVAL; + max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; + if (end > max_len) return -EINVAL; @@ -312,7 +316,7 @@ void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size) void *buf; int cnt; - if (!pci_vpd_available(dev)) + if (!pci_vpd_available(dev, true)) return ERR_PTR(-ENODEV); len = dev->vpd.len;
On 10/12/2021 4:26 PM, Heiner Kallweit wrote: > Thanks for the report! I could reproduce the issue, the following fixes > it for me. Could you please test whether it fixes the issue for you as well? Yes, it works fine. BTW, in the original patch here: --- a/drivers/pci/vpd.c +++ b/drivers/pci/vpd.c @@ -138,9 +138,10 @@ static int pci_vpd_wait(struct pci_dev *dev, bool set) } static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, - void *arg) + void *arg, bool check_size) { struct pci_vpd *vpd = &dev->vpd; + unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; int ret = 0; loff_t end = pos + count; u8 *buf = arg; @@ -151,11 +152,11 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, if (pos < 0) return -EINVAL; - if (pos > vpd->len) + if (pos >= max_len) return 0; I am not sure if "pos >= max_len" is correct there, so just want to give you a chance to double-check.
On 13.10.2021 16:22, Qian Cai wrote: > > > On 10/12/2021 4:26 PM, Heiner Kallweit wrote: >> Thanks for the report! I could reproduce the issue, the following fixes >> it for me. Could you please test whether it fixes the issue for you as well? > > Yes, it works fine. BTW, in the original patch here: > Thanks for testing! > --- a/drivers/pci/vpd.c > +++ b/drivers/pci/vpd.c > @@ -138,9 +138,10 @@ static int pci_vpd_wait(struct pci_dev *dev, bool set) > } > > static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, > - void *arg) > + void *arg, bool check_size) > { > struct pci_vpd *vpd = &dev->vpd; > + unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; > int ret = 0; > loff_t end = pos + count; > u8 *buf = arg; > @@ -151,11 +152,11 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, > if (pos < 0) > return -EINVAL; > > - if (pos > vpd->len) > + if (pos >= max_len) > return 0; > > I am not sure if "pos >= max_len" is correct there, so just want to give you > a chance to double-check. > This is intentional, but good catch.
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c index 25557b272..286cad2a6 100644 --- a/drivers/pci/vpd.c +++ b/drivers/pci/vpd.c @@ -138,9 +138,10 @@ static int pci_vpd_wait(struct pci_dev *dev, bool set) } static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, - void *arg) + void *arg, bool check_size) { struct pci_vpd *vpd = &dev->vpd; + unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; int ret = 0; loff_t end = pos + count; u8 *buf = arg; @@ -151,11 +152,11 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, if (pos < 0) return -EINVAL; - if (pos > vpd->len) + if (pos >= max_len) return 0; - if (end > vpd->len) { - end = vpd->len; + if (end > max_len) { + end = max_len; count = end - pos; } @@ -199,9 +200,10 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, } static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, - const void *arg) + const void *arg, bool check_size) { struct pci_vpd *vpd = &dev->vpd; + unsigned int max_len = check_size ? vpd->len : PCI_VPD_MAX_SIZE; const u8 *buf = arg; loff_t end = pos + count; int ret = 0; @@ -212,7 +214,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, if (pos < 0 || (pos & 3) || (count & 3)) return -EINVAL; - if (end > vpd->len) + if (end > max_len) return -EINVAL; if (mutex_lock_killable(&vpd->lock)) @@ -365,6 +367,24 @@ static int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, return -ENOENT; } +static ssize_t __pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf, + bool check_size) +{ + ssize_t ret; + + if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) { + dev = pci_get_func0_dev(dev); + if (!dev) + return -ENODEV; + + ret = pci_vpd_read(dev, pos, count, buf, check_size); + pci_dev_put(dev); + return ret; + } + + return pci_vpd_read(dev, pos, count, buf, check_size); +} + /** * pci_read_vpd - Read one entry from Vital Product Data * @dev: PCI device struct @@ -373,6 +393,20 @@ static int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, * @buf: pointer to where to store result */ ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf) +{ + return __pci_read_vpd(dev, pos, count, buf, true); +} +EXPORT_SYMBOL(pci_read_vpd); + +/* Same, but allow to access any address */ +ssize_t pci_read_vpd_any(struct pci_dev *dev, loff_t pos, size_t count, void *buf) +{ + return __pci_read_vpd(dev, pos, count, buf, false); +} +EXPORT_SYMBOL(pci_read_vpd_any); + +static ssize_t __pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, + const void *buf, bool check_size) { ssize_t ret; @@ -381,14 +415,13 @@ ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf) if (!dev) return -ENODEV; - ret = pci_vpd_read(dev, pos, count, buf); + ret = pci_vpd_write(dev, pos, count, buf, check_size); pci_dev_put(dev); return ret; } - return pci_vpd_read(dev, pos, count, buf); + return pci_vpd_write(dev, pos, count, buf, check_size); } -EXPORT_SYMBOL(pci_read_vpd); /** * pci_write_vpd - Write entry to Vital Product Data @@ -399,22 +432,17 @@ EXPORT_SYMBOL(pci_read_vpd); */ ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf) { - ssize_t ret; - - if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) { - dev = pci_get_func0_dev(dev); - if (!dev) - return -ENODEV; - - ret = pci_vpd_write(dev, pos, count, buf); - pci_dev_put(dev); - return ret; - } - - return pci_vpd_write(dev, pos, count, buf); + return __pci_write_vpd(dev, pos, count, buf, true); } EXPORT_SYMBOL(pci_write_vpd); +/* Same, but allow to access any address */ +ssize_t pci_write_vpd_any(struct pci_dev *dev, loff_t pos, size_t count, const void *buf) +{ + return __pci_write_vpd(dev, pos, count, buf, false); +} +EXPORT_SYMBOL(pci_write_vpd_any); + int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len, const char *kw, unsigned int *size) { diff --git a/include/linux/pci.h b/include/linux/pci.h index cd8aa6fce..9649bd9e4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1350,6 +1350,8 @@ void pci_unlock_rescan_remove(void); /* Vital Product Data routines */ ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); +ssize_t pci_read_vpd_any(struct pci_dev *dev, loff_t pos, size_t count, void *buf); +ssize_t pci_write_vpd_any(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx);
In certain cases we need a variant of pci_read_vpd()/pci_write_vpd() that does not check against dev->vpd.len. Such cases are: - reading VPD if dev->vpd.len isn't set yet (in pci_vpd_size()) - devices that map non-VPD information to arbitrary places in VPD address space (example: Chelsio T3 EEPROM write-protect flag) Therefore add function variants that check against PCI_VPD_MAX_SIZE only. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> --- drivers/pci/vpd.c | 72 +++++++++++++++++++++++++++++++-------------- include/linux/pci.h | 2 ++ 2 files changed, 52 insertions(+), 22 deletions(-)