diff options
author | Dean Nelson <dnelson@redhat.com> | 2010-03-09 22:26:48 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-19 15:40:22 -0400 |
commit | bdc2bda7c4dd253026cc1fce45fc939304749029 (patch) | |
tree | 2d77daf16bd33f570ffa83853aec64f2253d564b /drivers/pci/pci.c | |
parent | ded1d8f29b4d315a2093cafc3ee17ac870a87972 (diff) |
PCI: fix access of PCI_X_CMD by pcix get and set mmrbc functions
An e1000 driver on a system with a PCI-X bus was always being returned
a value of 135 from both pcix_get_mmrbc() and pcix_set_mmrbc(). This
value reflects an error return of PCIBIOS_BAD_REGISTER_NUMBER from
pci_bus_read_config_dword(,, cap + PCI_X_CMD,).
This is because for a dword, the following portion of the PCI_OP_READ()
macro:
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;
expands to:
if (pos & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
And is always true for 'cap + PCI_X_CMD', which is 0xe4 + 2 = 0xe6. ('cap' is
the result of calling pci_find_capability(, PCI_CAP_ID_PCIX).)
The same problem exists for pci_bus_write_config_dword(,, cap + PCI_X_CMD,).
In both cases, instead of calling _dword(), _word() should be called.
Cc: stable@kernel.org
Signed-off-by: Dean Nelson <dnelson@redhat.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9af986085d09..5c80b59c5931 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2601,13 +2601,13 @@ EXPORT_SYMBOL(pcix_get_max_mmrbc); | |||
2601 | int pcix_get_mmrbc(struct pci_dev *dev) | 2601 | int pcix_get_mmrbc(struct pci_dev *dev) |
2602 | { | 2602 | { |
2603 | int ret, cap; | 2603 | int ret, cap; |
2604 | u32 cmd; | 2604 | u16 cmd; |
2605 | 2605 | ||
2606 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 2606 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
2607 | if (!cap) | 2607 | if (!cap) |
2608 | return -EINVAL; | 2608 | return -EINVAL; |
2609 | 2609 | ||
2610 | ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | 2610 | ret = pci_read_config_word(dev, cap + PCI_X_CMD, &cmd); |
2611 | if (!ret) | 2611 | if (!ret) |
2612 | ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); | 2612 | ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); |
2613 | 2613 | ||
@@ -2627,7 +2627,8 @@ EXPORT_SYMBOL(pcix_get_mmrbc); | |||
2627 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | 2627 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) |
2628 | { | 2628 | { |
2629 | int cap, err = -EINVAL; | 2629 | int cap, err = -EINVAL; |
2630 | u32 stat, cmd, v, o; | 2630 | u32 stat, v, o; |
2631 | u16 cmd; | ||
2631 | 2632 | ||
2632 | if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) | 2633 | if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) |
2633 | goto out; | 2634 | goto out; |
@@ -2645,7 +2646,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | |||
2645 | if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) | 2646 | if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) |
2646 | return -E2BIG; | 2647 | return -E2BIG; |
2647 | 2648 | ||
2648 | err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | 2649 | err = pci_read_config_word(dev, cap + PCI_X_CMD, &cmd); |
2649 | if (err) | 2650 | if (err) |
2650 | goto out; | 2651 | goto out; |
2651 | 2652 | ||
@@ -2657,7 +2658,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | |||
2657 | 2658 | ||
2658 | cmd &= ~PCI_X_CMD_MAX_READ; | 2659 | cmd &= ~PCI_X_CMD_MAX_READ; |
2659 | cmd |= v << 2; | 2660 | cmd |= v << 2; |
2660 | err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd); | 2661 | err = pci_write_config_word(dev, cap + PCI_X_CMD, cmd); |
2661 | } | 2662 | } |
2662 | out: | 2663 | out: |
2663 | return err; | 2664 | return err; |