]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
FLR - intermediate checkin 6 3/26 - FLR Intel specific logic, first
authorRoss Philipson <ross.philipson@citrix.com>
Thu, 26 Mar 2009 20:59:32 +0000 (16:59 -0400)
committerRoss Philipson <ross.philipson@citrix.com>
Thu, 26 Mar 2009 20:59:32 +0000 (16:59 -0400)
cut.

 Changes to be committed:
modified:   drivers/xen/pciback/pciback_ops.c
modified:   include/linux/pci_regs.h

drivers/xen/pciback/pciback_ops.c
include/linux/pci_regs.h

index a9ba6c774a270d8b2ddded4d8d787412391e9ea4..94391db699fc57c95e96bbb031d3852c9c12a941 100644 (file)
@@ -9,6 +9,20 @@
 #include <xen/evtchn.h>
 #include "pciback.h"
 
+#define PCIBACK_VENDOR_INTEL     0x8086
+#define PCIBACK_DEVICE_IGFX_GM45 0x2a42
+#define PCIBACK_DEVICE_IGFX_Q45  0x2e12
+#define PCIBACK_CLASS_ID_USB     0x0c03
+#define PCIBACK_CLASS_ID_VGA     0x0c00
+#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_OFFSET 0xc0
+
 int verbose_request = 0;
 module_param(verbose_request, int, 0644);
 
@@ -112,37 +126,66 @@ static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos)
 }
 
 /* Vendor specific resets. These can be set in the vendor specific
- * capabilities structures. Currently only the Intel USB reset
- * is supported.
+ * capabilities structures. Currently only the Intel USB and iGFX
+ * reset is supported.
  */
 static int pciback_do_vendor_specific_reset(struct pci_dev *dev)
 {
-#define PCIBACK_VENDOR_INTEL 0x8086
-#define PCIBACK_CLASS_ID_USB 0x0c03
-#define PCIBACK_USB_FLRCTRL  0x4
-       int vendor_pos;
+       int vendor_pos, i;
        u16 vendor_id;
+       u16 device_id;
        u16 class_id;
+       u32 reg32;
+       u8  reg8;
        
-       vendor_pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
-       if (vendor_pos == 0)
-               return -ENXIO;
-
        pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
        if (vendor_id != PCIBACK_VENDOR_INTEL)
                return -ENXIO;
 
        pci_read_config_word(dev, PCI_CLASS_DEVICE, &class_id);
-       if (class_id != PCIBACK_CLASS_ID_USB)
+       if (class_id == PCIBACK_CLASS_ID_VGA) {
+               pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
+               if (device_id == PCIBACK_DEVICE_IGFX_GM45) /* TODO sufficient test ?*/
+                       return -ENXIO;
+
+               pci_read_config_dword(dev, PCIBACK_IGFX_CAP09_OFFSET, &reg32);
+               if ((reg32 & 0x000000F0) != 0x20 ||
+                       ((reg32 >> 16) & 0x000000FF) != 0x06 ||
+                       ((reg32 >> 24) & 0x000000FF) != PCI_CAP_ID_VNDR)
+                       return -ENXIO;
+
+               vendor_pos = PCIBACK_IGFX_CAP09_OFFSET;
+       } else if (class_id == PCIBACK_CLASS_ID_USB) {
+               vendor_pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
+               if (vendor_pos == 0)
+                       return -ENXIO;
+       }
+       else
                return -ENXIO;
 
        pci_block_user_cfg_access(dev);
 
-       pci_write_config_byte(dev, vendor_pos + PCIBACK_USB_FLRCTRL, 1);
-       mdelay(100);
+       if (class_id == PCIBACK_CLASS_ID_VGA) {
+               pci_write_config_byte(dev, PCIBACK_IGFX_MEDIARST_OFFSET, PCIBACK_IGFX_MEDIARST);
+               for (i = 0; i <= 10; i++) {
+                       msleep(100);
+                       pci_read_config_byte(dev, PCIBACK_IGFX_MEDIARST_OFFSET, &reg8);
+                       if ((reg8 & 0x01) == 0)
+                               break;
+                       if (i == 10) {
+                               dev_warn(&dev->dev, "media not reset after 1s; skipping FLR\n");
+                               goto out;
+                       }
+               }
+               pci_write_config_byte(dev, vendor_pos + PCIBACK_IGFX_FLRCTRL, 1);
+       } else {
+               pci_write_config_byte(dev, vendor_pos + PCIBACK_USB_FLRCTRL, 1);
+       }
+       mdelay(200);
 
        pciback_reload_config_space(dev);
 
+out:
        pci_unblock_user_cfg_access(dev);
 
        return 0;
@@ -343,10 +386,6 @@ static int pciback_find_pcie_flr_caps(struct pci_dev *dev)
                }
        }
 
-       /* Next look for the unchained PCIe capabilities for FLR using specific logic */
-       /* TODO */
-
-       /* Else not found */
        return 0;
 }
 
@@ -359,7 +398,10 @@ static int pciback_find_pcie_flr_caps(struct pci_dev *dev)
 static int pciback_find_pci_flr_caps(struct pci_dev *dev)
 {
        int af_pos;
-       u8 cap;
+       u8  cap;
+       u16 vendor_id;
+       u16 device_id;
+       u8  reg8;
 
        /* First look for the PCI AF capabilities for FLR using the capabilities list. This
         * is only used on the devices on the root/host bus (integrated devices). 
@@ -370,16 +412,29 @@ static int pciback_find_pci_flr_caps(struct pci_dev *dev)
        af_pos = pci_find_capability(dev, PCI_CAP_ID_AF);
        if (af_pos) {
                pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, &cap);
-               if (cap & PCI_EXP_DEVCAP_FLR) {
+               if (cap & PCI_AF_CAP_FLR) {
                        return af_pos;
                }
        }
 
        /* Next look for the unchained AF capabilities for FLR using specific logic */
-       /* TODO */
-
-       /* TODO DEPENDING ON LOGIC - MAYBE MERGE W/ ABOVE */
+       pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
+       if (vendor_id != PCIBACK_VENDOR_INTEL)
+               return -ENXIO;
 
+       pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
+       if (device_id == PCIBACK_DEVICE_IGFX_Q45) /* TODO need more IDs ?*/
+               return -ENXIO;
+       
+       af_pos = PCIBACK_IGFX_CAP13_OFFSET;
+       pci_read_config_byte(dev, af_pos + PCI_AF_LENFLD, &reg8);
+       if (reg8 == PCI_AF_LENGTH) {
+               pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, &cap);
+               if (cap & PCI_AF_CAP_FLR) {
+                       return af_pos;
+               }
+       }
+       
        /* Else not found */
        return 0;
 }
index fbe835b764dd55490f117110d23322fb538f6cba..8282c2fc017ab1f451108603a1a159693a641608 100644 (file)
 #define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
 
 /* Advanced Features Capability */
+#define PCI_AF_LENFLD   0x02 /* Device length offset */
 #define PCI_AF_LENGTH   0x06
 #define PCI_AF_DEVCAP   0x03 /* Device capabilities offset */
 #define PCI_AF_CAP_TP   0x01