From 75acfecaa031c0e1bc412cee4fe58ba49ff3406c Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 1 May 2006 10:43:46 -0500 Subject: [PATCH] PCI: Add pci_assign_resource_fixed -- allow fixed address assignments PCI: Add pci_assign_resource_fixed -- allow fixed address assignments On some embedded systems the PCI address for hotplug devices are not only known a priori but are required to be at a given PCI address for other master in the system to be able to access. An example of such a system would be an FPGA which is setup from user space after the system has booted. The FPGA may be access by DSPs in the system and those DSPs expect the FPGA at a fixed PCI address. Added pci_assign_resource_fixed() as a way to allow assignment of the PCI devices's BARs at fixed PCI addresses. Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/pci.h') diff --git a/include/linux/pci.h b/include/linux/pci.h index 6c4bc773f7b..b9eb9b021d6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -496,6 +496,7 @@ int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); int pci_assign_resource(struct pci_dev *dev, int i); +int pci_assign_resource_fixed(struct pci_dev *dev, int i); void pci_restore_bars(struct pci_dev *dev); /* ROM control related routines */ -- cgit v1.2.3-70-g09d2 From bd8481e1646d7649fa101ee57a5139b9da3c2436 Mon Sep 17 00:00:00 2001 From: Doug Thompson Date: Mon, 8 May 2006 17:06:09 -0700 Subject: [PATCH] PCI Bus Parity Status-broken hardware attribute, EDAC foundation Currently, the EDAC (error detection and correction) modules that are in the kernel contain some features that need to be moved. After some good feedback on the PCI Parity detection code and interface (http://www.ussg.iu.edu/hypermail/linux/kernel/0603.1/0897.html) this patch ADDs an new attribute to the pci_dev structure: Namely the 'broken_parity_status' bit. When set this indicates that the respective hardware generates false positives of Parity errors. The EDAC "blacklist" solution was inferior and will be removed in a future patch. Also in this patch is a PCI quirk.c entry for an Infiniband PCI-X card which generates false positive parity errors. I am requesting comments on this AND on the possibility of a exposing this 'broken_parity_status' bit to userland via the PCI device sysfs directory for devices. This access would allow for enabling of this feature on new devices and for old devices that have their drivers updated. (SLES 9 SP3 did this on an ATI motherboard video device). There is a need to update such a PCI attribute between kernel releases. This patch just adds a storage place for the attribute and a quirk entry for a known bad PCI device. PCI Parity reaper/harvestor operations are in EDAC itself and will be refactored to use this PCI attribute instead of its own mechanisms (which are currently disabled) in the future. Signed-off-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 11 +++++++++++ include/linux/pci.h | 1 + include/linux/pci_ids.h | 1 + 3 files changed, 13 insertions(+) (limited to 'include/linux/pci.h') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d378478612f..ea48e969a12 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -24,6 +24,17 @@ #include #include "pci.h" +/* The Mellanox Tavor device gives false positive parity errors + * Mark this device with a broken_parity_status, to allow + * PCI scanning code to "skip" this now blacklisted device. + */ +static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) +{ + dev->broken_parity_status = 1; /* This device gives false positives */ +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); + /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ static void __devinit quirk_passive_release(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index b9eb9b021d6..91c37750cd3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -162,6 +162,7 @@ struct pci_dev { unsigned int is_busmaster:1; /* device is busmaster */ unsigned int no_msi:1; /* device may not use msi */ unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ + unsigned int broken_parity_status:1; /* Device generates false positive parity */ u32 saved_config_space[16]; /* config space saved at suspend time */ struct hlist_head saved_cap_space; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bcfe9d4f56a..3d197cdcfa3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1946,6 +1946,7 @@ #define PCI_VENDOR_ID_MELLANOX 0x15b3 #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 +#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 #define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 #define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c -- cgit v1.2.3-70-g09d2 From 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 26 May 2006 10:58:27 +0800 Subject: [PATCH] PCI: disable msi mode in pci_disable_device Brice said the pci_save_msi_state breaks his driver in his special usage (not in suspend/resume), as pci_save_msi_state will disable msi mode. In his usage, pci_save_state will be called at runtime, and later (after the device operates for some time and has an error) pci_restore_state will be called. In another hand, suspend/resume needs disable msi mode, as device should stop working completely. This patch try to workaround this issue. Drivers are expected call pci_disable_device in suspend time after pci_save_state. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 6 ++++-- drivers/pci/pci.c | 9 ++++++++- include/linux/pci.h | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'include/linux/pci.h') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9c69b6966e7..3ec558dc652 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -453,9 +453,11 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_enable(control, 1); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 1; } else { msix_enable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 1; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -472,9 +474,11 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 0; } else { msix_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 0; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -549,7 +553,6 @@ int pci_save_msi_state(struct pci_dev *dev) pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); if (control & PCI_MSI_FLAGS_MASKBIT) pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); - disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); save_state->cap_nr = PCI_CAP_ID_MSI; pci_add_saved_cap(dev, save_state); return 0; @@ -639,7 +642,6 @@ int pci_save_msix_state(struct pci_dev *dev) } dev->irq = temp; - disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); save_state->cap_nr = PCI_CAP_ID_MSIX; pci_add_saved_cap(dev, save_state); return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index aa480370ef1..d408a3c3042 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -551,7 +551,14 @@ void pci_disable_device(struct pci_dev *dev) { u16 pci_command; - + + if (dev->msi_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSI); + if (dev->msix_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSIX); + pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; diff --git a/include/linux/pci.h b/include/linux/pci.h index 91c37750cd3..62a8c22f5f6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -163,6 +163,8 @@ struct pci_dev { unsigned int no_msi:1; /* device may not use msi */ unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ unsigned int broken_parity_status:1; /* Device generates false positive parity */ + unsigned int msi_enabled:1; + unsigned int msix_enabled:1; u32 saved_config_space[16]; /* config space saved at suspend time */ struct hlist_head saved_cap_space; -- cgit v1.2.3-70-g09d2