]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
Fix for GM45 FLR - command register must have memory space access
authorRoss Philipson <ross.philipson@citrix.com>
Fri, 3 Apr 2009 15:25:00 +0000 (11:25 -0400)
committerRoss Philipson <ross.philipson@citrix.com>
Fri, 3 Apr 2009 15:25:00 +0000 (11:25 -0400)
bit set or FLR hangs.

 Changes to be committed:
modified:   drivers/xen/pciback/pciback_ops.c

drivers/xen/pciback/pciback_ops.c

index e4a96b50bb65732603a75ee3a86a63f00290c4cd..97da39af71eb326eaf82d5cb3608daaf0f165415 100644 (file)
@@ -23,9 +23,6 @@
 int verbose_request = 0;
 module_param(verbose_request, int, 0644);
 
-/* TODO remove once this is fixed */
-static int disable_gm45_igfx_flr = 1;
-
 struct pcistub_sbr_entry {
        struct list_head dev_list;
        struct pci_dev *dev;
@@ -244,7 +241,7 @@ static void pciback_do_pcie_flr(struct pci_dev *dev, int exp_pos)
  * device. This uses the Advanced Features Capability extensions to
  * the PCI spec.
  */
-static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos)
+static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos, int clear_cmd)
 {
        u8 status = 0;
 
@@ -253,7 +250,8 @@ static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos)
        pci_block_user_cfg_access(dev);
 
        /* Clear the command register to prevent new transactions */
-       pci_write_config_word(dev, PCI_COMMAND, 0);
+       if (clear_cmd)
+               pci_write_config_word(dev, PCI_COMMAND, 0);
 
        /* Wait for Transaction Pending bit clean */
        msleep(100);
@@ -283,7 +281,7 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev)
        struct pci_dev *gmch;
        int vendor_pos, i;
        u32 reg32 = 0;
-       u16 device_id;  
+       u16 device_id, cmd;     
        u8 reg8 = 0;
 
        dev_dbg(&dev->dev, "doing vendor specific resets\n");   
@@ -292,9 +290,6 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev)
                return -ENXIO;
 
        if ((dev->class >> 8) == PCIBACK_CLASS_ID_VGA) {
-               if (disable_gm45_igfx_flr)
-                       return -ENXIO;
-
                if (dev->bus->number != 0 || dev->devfn != PCI_DEVFN(2,0))
                        return -ENXIO;
 
@@ -337,9 +332,14 @@ static int pciback_do_vendor_specific_reset(struct pci_dev *dev)
                                goto out;
                        }
                }
-
-               /* The rest is the same as a PCI AF FLR */
-               pciback_do_pci_flr(dev, vendor_pos);
+        
+               /* This specific reset will hang if the command register does not have
+                * memory space access enabled */
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               pci_write_config_word(dev, PCI_COMMAND, (cmd | PCI_COMMAND_MEMORY));
+               /* The rest is the same as a PCI AF FLR - use the same routine */
+               pciback_do_pci_flr(dev, vendor_pos, 0);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
        } else {
                pci_block_user_cfg_access(dev);
 
@@ -469,7 +469,7 @@ void pciback_flr_device(struct pci_dev *dev)
                }
                if (dev_data->dev_type == PCIBACK_TYPE_PCI &&
                        dev_data->af_flr_offset != 0) {
-                       pciback_do_pci_flr(dev, dev_data->af_flr_offset);
+                       pciback_do_pci_flr(dev, dev_data->af_flr_offset, 1);
                        break;
                }