static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) { struct xen_pcibk_dev_data *dev_data; int err; dev_data = pci_get_drvdata(dev); if (!pci_is_enabled(dev) && is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: enable\n", pci_name(dev)); err = pci_enable_device(dev); if (err) return err; if (dev_data) dev_data->enable_intx = 1; } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: disable\n", pci_name(dev)); pci_disable_device(dev); if (dev_data) dev_data->enable_intx = 0; } if (!dev->is_busmaster && is_master_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n", pci_name(dev)); pci_set_master(dev); } if (value & PCI_COMMAND_INVALIDATE) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: enable memory-write-invalidate\n", pci_name(dev)); err = pci_set_mwi(dev); if (err) { printk(KERN_WARNING DRV_NAME ": %s: cannot enable " "memory-write-invalidate (%d)\n", pci_name(dev), err); value &= ~PCI_COMMAND_INVALIDATE; } } return pci_write_config_word(dev, offset, value); }
/* Ensure a device is "turned off" and ready to be exported. * (Also see xen_pcibk_config_reset to ensure virtual configuration space is * ready to be re-exported) */ void xen_pcibk_reset_device(struct pci_dev *dev) { u16 cmd; xen_pcibk_control_isr(dev, 1 /* reset device */); /* Disable devices (but not bridges) */ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { #ifdef CONFIG_PCI_MSI /* The guest could have been abruptly killed without * disabling MSI/MSI-X interrupts.*/ if (dev->msix_enabled) pci_disable_msix(dev); if (dev->msi_enabled) pci_disable_msi(dev); #endif if (pci_is_enabled(dev)) pci_disable_device(dev); pci_write_config_word(dev, PCI_COMMAND, 0); dev->is_busmaster = 0; } else { pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & (PCI_COMMAND_INVALIDATE)) { cmd &= ~(PCI_COMMAND_INVALIDATE); pci_write_config_word(dev, PCI_COMMAND, cmd); dev->is_busmaster = 0; } } }
struct usnic_vnic *usnic_vnic_alloc(struct pci_dev *pdev) { struct usnic_vnic *vnic; int err = 0; if (!pci_is_enabled(pdev)) { usnic_err("PCI dev %s is disabled\n", pci_name(pdev)); return ERR_PTR(-EINVAL); } vnic = kzalloc(sizeof(*vnic), GFP_KERNEL); if (!vnic) { usnic_err("Failed to alloc vnic for %s - out of memory\n", pci_name(pdev)); return ERR_PTR(-ENOMEM); } spin_lock_init(&vnic->res_lock); err = usnic_vnic_discover_resources(pdev, vnic); if (err) { usnic_err("Failed to discover %s resources with err %d\n", pci_name(pdev), err); goto out_free_vnic; } usnic_dbg("Allocated vnic for %s\n", usnic_vnic_pci_name(vnic)); return vnic; out_free_vnic: kfree(vnic); return ERR_PTR(err); }
static int pci_disable(void) { struct pci_dev *dev = ltp_pci.dev; prk_info("disable pci device"); /* check if device pointer exists */ if (!dev) { prk_err("dev is NULL"); return TFAIL; } prk_info("is pci enabled '%d', is managed '%d'", pci_is_enabled(dev), pci_is_managed(dev)); pci_release_regions(dev); pci_disable_device(dev); if (dev->current_state == PCI_D3hot || dev->current_state == PCI_D3cold) { prk_info("disabled pci device, state '%s'", pci_power_name(dev->current_state)); return TPASS; } prk_err("failed to disable pci device, state '%s'", pci_power_name(dev->current_state)); return TFAIL; }
static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) { int i; int ret; ret = xen_pcibk_read_config_word(dev, offset, value, data); if (!pci_is_enabled(dev)) return ret; for (i = 0; i < PCI_ROM_RESOURCE; i++) { if (dev->resource[i].flags & IORESOURCE_IO) *value |= PCI_COMMAND_IO; if (dev->resource[i].flags & IORESOURCE_MEM) *value |= PCI_COMMAND_MEMORY; } return ret; }
/* Ensure a device is has the fake IRQ handler "turned on/off" and is * ready to be exported. This MUST be run after xen_pcibk_reset_device * which does the actual PCI device enable/disable. */ static void xen_pcibk_control_isr(struct pci_dev *dev, int reset) { struct xen_pcibk_dev_data *dev_data; int rc; int enable = 0; dev_data = pci_get_drvdata(dev); if (!dev_data) return; /* We don't deal with bridges */ if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) return; if (reset) { dev_data->enable_intx = 0; dev_data->ack_intr = 0; } enable = dev_data->enable_intx; /* Asked to disable, but ISR isn't runnig */ if (!enable && !dev_data->isr_on) return; /* Squirrel away the IRQs in the dev_data. We need this * b/c when device transitions to MSI, the dev->irq is * overwritten with the MSI vector. */ if (enable) dev_data->irq = dev->irq; /* * SR-IOV devices in all use MSI-X and have no legacy * interrupts, so inhibit creating a fake IRQ handler for them. */ if (dev_data->irq == 0) goto out; dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n", dev_data->irq_name, dev_data->irq, pci_is_enabled(dev) ? "on" : "off", dev->msi_enabled ? "MSI" : "", dev->msix_enabled ? "MSI/X" : "", dev_data->isr_on ? "enable" : "disable", enable ? "enable" : "disable"); if (enable) { /* * The MSI or MSI-X should not have an IRQ handler. Otherwise * if the guest terminates we BUG_ON in free_msi_irqs. */ if (dev->msi_enabled || dev->msix_enabled) goto out; rc = request_irq(dev_data->irq, xen_pcibk_guest_interrupt, IRQF_SHARED, dev_data->irq_name, dev); if (rc) { dev_err(&dev->dev, "%s: failed to install fake IRQ " \ "handler for IRQ %d! (rc:%d)\n", dev_data->irq_name, dev_data->irq, rc); goto out; } } else { free_irq(dev_data->irq, dev); dev_data->irq = 0; } dev_data->isr_on = enable; dev_data->ack_intr = enable; out: dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n", dev_data->irq_name, dev_data->irq, pci_is_enabled(dev) ? "on" : "off", dev->msi_enabled ? "MSI" : "", dev->msix_enabled ? "MSI/X" : "", enable ? (dev_data->isr_on ? "enabled" : "failed to enable") : (dev_data->isr_on ? "failed to disable" : "disabled")); }
static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) { struct xen_pcibk_dev_data *dev_data; int err; u16 val; struct pci_cmd_info *cmd = data; dev_data = pci_get_drvdata(dev); if (!pci_is_enabled(dev) && is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: enable\n", pci_name(dev)); err = pci_enable_device(dev); if (err) return err; if (dev_data) dev_data->enable_intx = 1; } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: disable\n", pci_name(dev)); pci_disable_device(dev); if (dev_data) dev_data->enable_intx = 0; } if (!dev->is_busmaster && is_master_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n", pci_name(dev)); pci_set_master(dev); } else if (dev->is_busmaster && !is_master_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: clear bus master\n", pci_name(dev)); pci_clear_master(dev); } if (!(cmd->val & PCI_COMMAND_INVALIDATE) && (value & PCI_COMMAND_INVALIDATE)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: enable memory-write-invalidate\n", pci_name(dev)); err = pci_set_mwi(dev); if (err) { pr_warn("%s: cannot enable memory-write-invalidate (%d)\n", pci_name(dev), err); value &= ~PCI_COMMAND_INVALIDATE; } } else if ((cmd->val & PCI_COMMAND_INVALIDATE) && !(value & PCI_COMMAND_INVALIDATE)) { if (unlikely(verbose_request)) printk(KERN_DEBUG DRV_NAME ": %s: disable memory-write-invalidate\n", pci_name(dev)); pci_clear_mwi(dev); } cmd->val = value; if (!permissive && (!dev_data || !dev_data->permissive)) return 0; /* Only allow the guest to control certain bits. */ err = pci_read_config_word(dev, offset, &val); if (err || val == value) return err; value &= PCI_COMMAND_GUEST; value |= val & ~PCI_COMMAND_GUEST; return pci_write_config_word(dev, offset, value); }