PCI: Wait for device to become ready after a power management reset
[linux-2.6-block.git] / drivers / pci / pci.c
index 764ca7b8840d412c604ccef81a5db3cbf8d44078..a3042e475901a491f8efb2dbeb07f2d6f35a7cb4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *     PCI Bus Services, see include/linux/pci.h for further explanation.
  *
@@ -125,6 +126,9 @@ static int __init pcie_port_pm_setup(char *str)
 }
 __setup("pcie_port_pm=", pcie_port_pm_setup);
 
+/* Time to wait after a reset for device to become responsive */
+#define PCIE_RESET_READY_POLL_MS 60000
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -156,7 +160,7 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
         * Make sure the BAR is actually a memory resource, not an IO resource
         */
        if (res->flags & IORESOURCE_UNSET || !(res->flags & IORESOURCE_MEM)) {
-               dev_warn(&pdev->dev, "can't ioremap BAR %d: %pR\n", bar, res);
+               pci_warn(pdev, "can't ioremap BAR %d: %pR\n", bar, res);
                return NULL;
        }
        return ioremap_nocache(res->start, resource_size(res));
@@ -648,7 +652,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
         */
        if (state != PCI_D0 && dev->current_state <= PCI_D3cold
            && dev->current_state > state) {
-               dev_err(&dev->dev, "invalid power transition (from state %d to %d)\n",
+               pci_err(dev, "invalid power transition (from state %d to %d)\n",
                        dev->current_state, state);
                return -EINVAL;
        }
@@ -696,7 +700,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
        pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
        dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
        if (dev->current_state != state && printk_ratelimit())
-               dev_info(&dev->dev, "Refused to change power state, currently in D%d\n",
+               pci_info(dev, "Refused to change power state, currently in D%d\n",
                         dev->current_state);
 
        /*
@@ -970,7 +974,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
        case PM_EVENT_HIBERNATE:
                return PCI_D3hot;
        default:
-               dev_info(&dev->dev, "unrecognized suspend event %d\n",
+               pci_info(dev, "unrecognized suspend event %d\n",
                         state.event);
                BUG();
        }
@@ -1013,7 +1017,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state) {
-               dev_err(&dev->dev, "buffer not found in %s\n", __func__);
+               pci_err(dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }
 
@@ -1061,7 +1065,7 @@ static int pci_save_pcix_state(struct pci_dev *dev)
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
        if (!save_state) {
-               dev_err(&dev->dev, "buffer not found in %s\n", __func__);
+               pci_err(dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }
 
@@ -1121,7 +1125,7 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
                return;
 
        for (;;) {
-               dev_dbg(&pdev->dev, "restoring config space at offset %#x (was %#x, writing %#x)\n",
+               pci_dbg(pdev, "restoring config space at offset %#x (was %#x, writing %#x)\n",
                        offset, val, saved_val);
                pci_write_config_dword(pdev, offset, saved_val);
                if (retry-- <= 0)
@@ -1358,7 +1362,7 @@ static void pci_enable_bridge(struct pci_dev *dev)
 
        retval = pci_enable_device(dev);
        if (retval)
-               dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n",
+               pci_err(dev, "Error enabling bridge (%d), continuing\n",
                        retval);
        pci_set_master(dev);
 }
@@ -1867,7 +1871,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
                        pme_dev = kmalloc(sizeof(struct pci_pme_device),
                                          GFP_KERNEL);
                        if (!pme_dev) {
-                               dev_warn(&dev->dev, "can't enable PME#\n");
+                               pci_warn(dev, "can't enable PME#\n");
                                return;
                        }
                        pme_dev->dev = dev;
@@ -1891,7 +1895,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
                }
        }
 
-       dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled");
+       pci_dbg(dev, "PME# %s\n", enable ? "enabled" : "disabled");
 }
 EXPORT_SYMBOL(pci_pme_active);
 
@@ -2428,7 +2432,7 @@ void pci_pm_init(struct pci_dev *dev)
        pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc);
 
        if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
-               dev_err(&dev->dev, "unsupported PM cap regs version (%u)\n",
+               pci_err(dev, "unsupported PM cap regs version (%u)\n",
                        pmc & PCI_PM_CAP_VER_MASK);
                return;
        }
@@ -2448,15 +2452,14 @@ void pci_pm_init(struct pci_dev *dev)
                        dev->d2_support = true;
 
                if (dev->d1_support || dev->d2_support)
-                       dev_printk(KERN_DEBUG, &dev->dev, "supports%s%s\n",
+                       pci_printk(KERN_DEBUG, dev, "supports%s%s\n",
                                   dev->d1_support ? " D1" : "",
                                   dev->d2_support ? " D2" : "");
        }
 
        pmc &= PCI_PM_CAP_PME_MASK;
        if (pmc) {
-               dev_printk(KERN_DEBUG, &dev->dev,
-                        "PME# supported from%s%s%s%s%s\n",
+               pci_printk(KERN_DEBUG, dev, "PME# supported from%s%s%s%s%s\n",
                         (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
                         (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
                         (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
@@ -2548,13 +2551,13 @@ static int pci_ea_read(struct pci_dev *dev, int offset)
 
        res = pci_ea_get_resource(dev, bei, prop);
        if (!res) {
-               dev_err(&dev->dev, "Unsupported EA entry BEI: %u\n", bei);
+               pci_err(dev, "Unsupported EA entry BEI: %u\n", bei);
                goto out;
        }
 
        flags = pci_ea_flags(dev, prop);
        if (!flags) {
-               dev_err(&dev->dev, "Unsupported EA properties: %#x\n", prop);
+               pci_err(dev, "Unsupported EA properties: %#x\n", prop);
                goto out;
        }
 
@@ -2604,13 +2607,12 @@ static int pci_ea_read(struct pci_dev *dev, int offset)
        }
 
        if (end < start) {
-               dev_err(&dev->dev, "EA Entry crosses address boundary\n");
+               pci_err(dev, "EA Entry crosses address boundary\n");
                goto out;
        }
 
        if (ent_size != ent_offset - offset) {
-               dev_err(&dev->dev,
-                       "EA Entry Size (%d) does not match length read (%d)\n",
+               pci_err(dev, "EA Entry Size (%d) does not match length read (%d)\n",
                        ent_size, ent_offset - offset);
                goto out;
        }
@@ -2621,16 +2623,16 @@ static int pci_ea_read(struct pci_dev *dev, int offset)
        res->flags = flags;
 
        if (bei <= PCI_EA_BEI_BAR5)
-               dev_printk(KERN_DEBUG, &dev->dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_printk(KERN_DEBUG, dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei, res, prop);
        else if (bei == PCI_EA_BEI_ROM)
-               dev_printk(KERN_DEBUG, &dev->dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_printk(KERN_DEBUG, dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
                           res, prop);
        else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5)
-               dev_printk(KERN_DEBUG, &dev->dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_printk(KERN_DEBUG, dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei - PCI_EA_BEI_VF_BAR0, res, prop);
        else
-               dev_printk(KERN_DEBUG, &dev->dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_printk(KERN_DEBUG, dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei, res, prop);
 
 out:
@@ -2727,13 +2729,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
        error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP,
                                        PCI_EXP_SAVE_REGS * sizeof(u16));
        if (error)
-               dev_err(&dev->dev,
-                       "unable to preallocate PCI Express save buffer\n");
+               pci_err(dev, "unable to preallocate PCI Express save buffer\n");
 
        error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16));
        if (error)
-               dev_err(&dev->dev,
-                       "unable to preallocate PCI-X save buffer\n");
+               pci_err(dev, "unable to preallocate PCI-X save buffer\n");
 
        pci_allocate_vc_save_buffers(dev);
 }
@@ -3069,6 +3069,81 @@ int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size)
        return 0;
 }
 
+/**
+ * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port
+ * @dev: the PCI device
+ * @cap_mask: mask of desired AtomicOp sizes, including one or more of:
+ *     PCI_EXP_DEVCAP2_ATOMIC_COMP32
+ *     PCI_EXP_DEVCAP2_ATOMIC_COMP64
+ *     PCI_EXP_DEVCAP2_ATOMIC_COMP128
+ *
+ * Return 0 if all upstream bridges support AtomicOp routing, egress
+ * blocking is disabled on all upstream ports, and the root port supports
+ * the requested completion capabilities (32-bit, 64-bit and/or 128-bit
+ * AtomicOp completion), or negative otherwise.
+ */
+int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
+{
+       struct pci_bus *bus = dev->bus;
+       struct pci_dev *bridge;
+       u32 cap, ctl2;
+
+       if (!pci_is_pcie(dev))
+               return -EINVAL;
+
+       /*
+        * Per PCIe r4.0, sec 6.15, endpoints and root ports may be
+        * AtomicOp requesters.  For now, we only support endpoints as
+        * requesters and root ports as completers.  No endpoints as
+        * completers, and no peer-to-peer.
+        */
+
+       switch (pci_pcie_type(dev)) {
+       case PCI_EXP_TYPE_ENDPOINT:
+       case PCI_EXP_TYPE_LEG_END:
+       case PCI_EXP_TYPE_RC_END:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       while (bus->parent) {
+               bridge = bus->self;
+
+               pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap);
+
+               switch (pci_pcie_type(bridge)) {
+               /* Ensure switch ports support AtomicOp routing */
+               case PCI_EXP_TYPE_UPSTREAM:
+               case PCI_EXP_TYPE_DOWNSTREAM:
+                       if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE))
+                               return -EINVAL;
+                       break;
+
+               /* Ensure root port supports all the sizes we care about */
+               case PCI_EXP_TYPE_ROOT_PORT:
+                       if ((cap & cap_mask) != cap_mask)
+                               return -EINVAL;
+                       break;
+               }
+
+               /* Ensure upstream ports don't block AtomicOps on egress */
+               if (!bridge->has_secondary_link) {
+                       pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2,
+                                                  &ctl2);
+                       if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK)
+                               return -EINVAL;
+               }
+
+               bus = bus->parent;
+       }
+
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
+                                PCI_EXP_DEVCTL2_ATOMIC_REQ);
+       return 0;
+}
+EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
+
 /**
  * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
  * @dev: the PCI device
@@ -3202,7 +3277,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar,
        return 0;
 
 err_out:
-       dev_warn(&pdev->dev, "BAR %d: can't reserve %pR\n", bar,
+       pci_warn(pdev, "BAR %d: can't reserve %pR\n", bar,
                 &pdev->resource[bar]);
        return -EBUSY;
 }
@@ -3625,7 +3700,7 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
        else
                cmd = old_cmd & ~PCI_COMMAND_MASTER;
        if (cmd != old_cmd) {
-               dev_dbg(&dev->dev, "%s bus mastering\n",
+               pci_dbg(dev, "%s bus mastering\n",
                        enable ? "enabling" : "disabling");
                pci_write_config_word(dev, PCI_COMMAND, cmd);
        }
@@ -3726,7 +3801,7 @@ int pci_set_cacheline_size(struct pci_dev *dev)
        if (cacheline_size == pci_cache_line_size)
                return 0;
 
-       dev_printk(KERN_DEBUG, &dev->dev, "cache line size of %d is not supported\n",
+       pci_printk(KERN_DEBUG, dev, "cache line size of %d is not supported\n",
                   pci_cache_line_size << 2);
 
        return -EINVAL;
@@ -3755,7 +3830,7 @@ int pci_set_mwi(struct pci_dev *dev)
 
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        if (!(cmd & PCI_COMMAND_INVALIDATE)) {
-               dev_dbg(&dev->dev, "enabling Mem-Wr-Inval\n");
+               pci_dbg(dev, "enabling Mem-Wr-Inval\n");
                cmd |= PCI_COMMAND_INVALIDATE;
                pci_write_config_word(dev, PCI_COMMAND, cmd);
        }
@@ -3945,20 +4020,13 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
-static void pci_flr_wait(struct pci_dev *dev)
+static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
 {
-       int delay = 1, timeout = 60000;
+       int delay = 1;
        u32 id;
 
        /*
-        * Per PCIe r3.1, sec 6.6.2, a device must complete an FLR within
-        * 100ms, but may silently discard requests while the FLR is in
-        * progress.  Wait 100ms before trying to access the device.
-        */
-       msleep(100);
-
-       /*
-        * After 100ms, the device should not silently discard config
+        * After reset, the device should not silently discard config
         * requests, but it may still indicate that it needs more time by
         * responding to them with CRS completions.  The Root Port will
         * generally synthesize ~0 data to complete the read (except when
@@ -3972,14 +4040,14 @@ static void pci_flr_wait(struct pci_dev *dev)
        pci_read_config_dword(dev, PCI_COMMAND, &id);
        while (id == ~0) {
                if (delay > timeout) {
-                       dev_warn(&dev->dev, "not ready %dms after FLR; giving up\n",
-                                100 + delay - 1);
-                       return;
+                       pci_warn(dev, "not ready %dms after %s; giving up\n",
+                                delay - 1, reset_type);
+                       return -ENOTTY;
                }
 
                if (delay > 1000)
-                       dev_info(&dev->dev, "not ready %dms after FLR; waiting\n",
-                                100 + delay - 1);
+                       pci_info(dev, "not ready %dms after %s; waiting\n",
+                                delay - 1, reset_type);
 
                msleep(delay);
                delay *= 2;
@@ -3987,7 +4055,10 @@ static void pci_flr_wait(struct pci_dev *dev)
        }
 
        if (delay > 1000)
-               dev_info(&dev->dev, "ready %dms after FLR\n", 100 + delay - 1);
+               pci_info(dev, "ready %dms after %s\n", delay - 1,
+                        reset_type);
+
+       return 0;
 }
 
 /**
@@ -4016,13 +4087,21 @@ static bool pcie_has_flr(struct pci_dev *dev)
  * device supports FLR before calling this function, e.g. by using the
  * pcie_has_flr() helper.
  */
-void pcie_flr(struct pci_dev *dev)
+int pcie_flr(struct pci_dev *dev)
 {
        if (!pci_wait_for_pending_transaction(dev))
-               dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
+               pci_err(dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
 
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-       pci_flr_wait(dev);
+
+       /*
+        * Per PCIe r4.0, sec 6.6.2, a device must complete an FLR within
+        * 100ms, but may silently discard requests while the FLR is in
+        * progress.  Wait 100ms before trying to access the device.
+        */
+       msleep(100);
+
+       return pci_dev_wait(dev, "FLR", PCIE_RESET_READY_POLL_MS);
 }
 EXPORT_SYMBOL_GPL(pcie_flr);
 
@@ -4052,11 +4131,19 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
         */
        if (!pci_wait_for_pending(dev, pos + PCI_AF_CTRL,
                                 PCI_AF_STATUS_TP << 8))
-               dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
+               pci_err(dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
 
        pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
-       pci_flr_wait(dev);
-       return 0;
+
+       /*
+        * Per Advanced Capabilities for Conventional PCI ECN, 13 April 2006,
+        * updated 27 July 2006; a device must complete an FLR within
+        * 100ms, but may silently discard requests while the FLR is in
+        * progress.  Wait 100ms before trying to access the device.
+        */
+       msleep(100);
+
+       return pci_dev_wait(dev, "AF_FLR", PCIE_RESET_READY_POLL_MS);
 }
 
 /**
@@ -4101,7 +4188,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
        pci_dev_d3_sleep(dev);
 
-       return 0;
+       return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
 }
 
 void pci_reset_secondary_bus(struct pci_dev *dev)
@@ -4307,8 +4394,9 @@ int __pci_reset_function_locked(struct pci_dev *dev)
        if (rc != -ENOTTY)
                return rc;
        if (pcie_has_flr(dev)) {
-               pcie_flr(dev);
-               return 0;
+               rc = pcie_flr(dev);
+               if (rc != -ENOTTY)
+                       return rc;
        }
        rc = pci_af_flr(dev, 0);
        if (rc != -ENOTTY)
@@ -4378,9 +4466,8 @@ int pci_reset_function(struct pci_dev *dev)
 {
        int rc;
 
-       rc = pci_probe_reset_function(dev);
-       if (rc)
-               return rc;
+       if (!dev->reset_fn)
+               return -ENOTTY;
 
        pci_dev_lock(dev);
        pci_dev_save_and_disable(dev);
@@ -4415,9 +4502,8 @@ int pci_reset_function_locked(struct pci_dev *dev)
 {
        int rc;
 
-       rc = pci_probe_reset_function(dev);
-       if (rc)
-               return rc;
+       if (!dev->reset_fn)
+               return -ENOTTY;
 
        pci_dev_save_and_disable(dev);
 
@@ -4439,18 +4525,17 @@ int pci_try_reset_function(struct pci_dev *dev)
 {
        int rc;
 
-       rc = pci_probe_reset_function(dev);
-       if (rc)
-               return rc;
+       if (!dev->reset_fn)
+               return -ENOTTY;
 
        if (!pci_dev_trylock(dev))
                return -EAGAIN;
 
        pci_dev_save_and_disable(dev);
        rc = __pci_reset_function_locked(dev);
+       pci_dev_restore(dev);
        pci_dev_unlock(dev);
 
-       pci_dev_restore(dev);
        return rc;
 }
 EXPORT_SYMBOL_GPL(pci_try_reset_function);
@@ -4658,7 +4743,9 @@ static void pci_slot_restore(struct pci_slot *slot)
        list_for_each_entry(dev, &slot->bus->devices, bus_list) {
                if (!dev->slot || dev->slot != slot)
                        continue;
+               pci_dev_lock(dev);
                pci_dev_restore(dev);
+               pci_dev_unlock(dev);
                if (dev->subordinate)
                        pci_bus_restore(dev->subordinate);
        }
@@ -5175,12 +5262,12 @@ void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
                dev->dma_alias_mask = kcalloc(BITS_TO_LONGS(U8_MAX),
                                              sizeof(long), GFP_KERNEL);
        if (!dev->dma_alias_mask) {
-               dev_warn(&dev->dev, "Unable to allocate DMA alias mask\n");
+               pci_warn(dev, "Unable to allocate DMA alias mask\n");
                return;
        }
 
        set_bit(devfn, dev->dma_alias_mask);
-       dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
+       pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n",
                 PCI_SLOT(devfn), PCI_FUNC(devfn));
 }
 
@@ -5329,7 +5416,7 @@ static void pci_request_resource_alignment(struct pci_dev *dev, int bar,
                return;
 
        if (r->flags & IORESOURCE_PCI_FIXED) {
-               dev_info(&dev->dev, "BAR%d %pR: ignoring requested alignment %#llx\n",
+               pci_info(dev, "BAR%d %pR: ignoring requested alignment %#llx\n",
                         bar, r, (unsigned long long)align);
                return;
        }
@@ -5366,7 +5453,7 @@ static void pci_request_resource_alignment(struct pci_dev *dev, int bar,
         * devices and we use the second.
         */
 
-       dev_info(&dev->dev, "BAR%d %pR: requesting alignment to %#llx\n",
+       pci_info(dev, "BAR%d %pR: requesting alignment to %#llx\n",
                 bar, r, (unsigned long long)align);
 
        if (resize) {
@@ -5412,13 +5499,11 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
 
        if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
            (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
-               dev_warn(&dev->dev,
-                       "Can't reassign resources to host bridge.\n");
+               pci_warn(dev, "Can't reassign resources to host bridge\n");
                return;
        }
 
-       dev_info(&dev->dev,
-               "Disabling memory decoding and releasing memory resources.\n");
+       pci_info(dev, "Disabling memory decoding and releasing memory resources\n");
        pci_read_config_word(dev, PCI_COMMAND, &command);
        command &= ~PCI_COMMAND_MEMORY;
        pci_write_config_word(dev, PCI_COMMAND, command);