From aa02fd76cb1e818573f00fe464a28e6635e69f76 Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Fri, 3 Apr 2009 11:25:00 -0400 Subject: [PATCH] Fix for GM45 FLR - command register must have memory space access bit set or FLR hangs. Changes to be committed: modified: drivers/xen/pciback/pciback_ops.c --- drivers/xen/pciback/pciback_ops.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c index e4a96b50..97da39af 100644 --- a/drivers/xen/pciback/pciback_ops.c +++ b/drivers/xen/pciback/pciback_ops.c @@ -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; } -- 2.39.5