]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
FLR - intermediate checkin 8 3/27 - Fixed AF FLR per the spec testing
authorRoss Philipson <ross.philipson@citrix.com>
Fri, 27 Mar 2009 20:37:47 +0000 (16:37 -0400)
committerRoss Philipson <ross.philipson@citrix.com>
Fri, 27 Mar 2009 20:37:47 +0000 (16:37 -0400)
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

index f016ccdcaa8d44ee8fd76a481954d23fa814bfaf..2d205a20e7eeeb9d192a57e966d764a7df0fd5f1 100644 (file)
 #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, &reg32);
-               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;