From 01bb3a5458ba8558beeda129069aa31201fc2da9 Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Fri, 27 Mar 2009 16:37:47 -0400 Subject: [PATCH] FLR - intermediate checkin 8 3/27 - Fixed AF FLR per the spec testing the TP status. Fixed vendor register check and media reset values. Changes to be committed: modified: drivers/xen/pciback/pciback_ops.c --- drivers/xen/pciback/pciback_ops.c | 51 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c index f016ccdc..2d205a20 100644 --- a/drivers/xen/pciback/pciback_ops.c +++ b/drivers/xen/pciback/pciback_ops.c @@ -13,12 +13,11 @@ #define PCIBACK_CLASS_ID_USB 0x0c03 #define PCIBACK_CLASS_ID_VGA 0x0300 #define PCIBACK_USB_FLRCTRL 0x4 -#define PCIBACK_IGFX_FLRCTRL 0x4 #define PCIBACK_IGFX_CAP09_OFFSET 0xa4 #define PCIBACK_IGFX_CAP13_OFFSET 0xa4 -#define PCIBACK_IGFX_MEDIARST 0xd0 +#define PCIBACK_IGFX_MEDIARST 0x0d #define PCIBACK_IGFX_MEDIARST_OFFSET 0xc0 int verbose_request = 0; @@ -113,11 +112,27 @@ static void pciback_do_pcie_flr(struct pci_dev *dev, int exp_pos) */ static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos) { + u8 status; + pci_block_user_cfg_access(dev); - + + /* Clear the command register to prevent new transactions */ + pci_write_config_word(dev, PCI_COMMAND, 0); + + /* Wait for Transaction Pending bit clean */ + msleep(100); + pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status); + if (status & PCI_AF_STA_TP) { + dev_dbg(&dev->dev, "Busy after 100ms while trying to reset; sleeping for 1 second\n"); + ssleep(1); + pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status); + if (status & PCI_AF_STA_TP) + dev_warn(&dev->dev, "Still busy after 1s; proceeding with reset anyway\n"); + } + pci_write_config_word(dev, af_pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); mdelay(200); - + pciback_reload_config_space(dev); pci_unblock_user_cfg_access(dev); @@ -157,9 +172,9 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev) /* Correct device and platform, assume vendor specific offset */ pci_read_config_dword(dev, PCIBACK_IGFX_CAP09_OFFSET, ®32); - if ((reg32 & 0x000000F0) != 0x20 || + if ((reg32 & 0x000000FF) != PCI_CAP_ID_VNDR || ((reg32 >> 16) & 0x000000FF) != 0x06 || - ((reg32 >> 24) & 0x000000FF) != PCI_CAP_ID_VNDR) + ((reg32 >> 24) & 0x000000F0) != 0x20) return -ENXIO; vendor_pos = PCIBACK_IGFX_CAP09_OFFSET; @@ -169,9 +184,7 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev) return -ENXIO; } else - return -ENXIO; - - pci_block_user_cfg_access(dev); + return -ENXIO; if (class_id == PCIBACK_CLASS_ID_VGA) { pci_write_config_byte(dev, PCIBACK_IGFX_MEDIARST_OFFSET, PCIBACK_IGFX_MEDIARST); @@ -185,17 +198,21 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev) goto out; } } - pci_write_config_byte(dev, vendor_pos + PCIBACK_IGFX_FLRCTRL, 1); + + /* The rest is the same as a PCI AF FLR */ + pciback_do_pci_flr(dev, vendor_pos); } else { + pci_block_user_cfg_access(dev); + pci_write_config_byte(dev, vendor_pos + PCIBACK_USB_FLRCTRL, 1); - } - mdelay(200); + mdelay(200); - pciback_reload_config_space(dev); + pciback_reload_config_space(dev); -out: - pci_unblock_user_cfg_access(dev); + pci_unblock_user_cfg_access(dev); + } +out: return 0; } @@ -446,8 +463,8 @@ static int pciback_find_pci_flr_caps(struct pci_dev *dev) pci_read_config_word(gmch, PCI_DEVICE_ID, &device_id); pci_dev_put(gmch); - if (device_id != PCI_DEVICE_ID_INTEL_GMCHQ45 || - device_id != PCI_DEVICE_ID_INTEL_GMCHG45 || + if (device_id != PCI_DEVICE_ID_INTEL_GMCHQ45 && + device_id != PCI_DEVICE_ID_INTEL_GMCHG45 && device_id != PCI_DEVICE_ID_INTEL_GMCHG41) break; -- 2.39.5