return -EIO;
pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
- if ((pmc & PCI_PM_CAP_VER_MASK) > 2) {
+ if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
printk(KERN_DEBUG
"PCI: %s has unsupported PM cap regs version (%u)\n",
pci_name(dev), pmc & PCI_PM_CAP_VER_MASK);
}
/* check if this device supports the desired state */
- if (state == PCI_D1 || state == PCI_D2) {
- if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
- return -EIO;
- else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
- return -EIO;
- }
+ if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
+ return -EIO;
+ else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
+ return -EIO;
pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
- /* If we're in D3, force entire word to 0.
+ /* If we're (effectively) in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= PCI_D3hot) {
- if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ switch (dev->current_state) {
+ case PCI_UNKNOWN: /* Boot-up */
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
+ && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
need_restore = 1;
+ /* Fall-through: force to D0 */
+ case PCI_D3hot:
+ case PCI_D3cold:
+ case PCI_POWER_ERROR:
pmcsr = 0;
- } else {
+ break;
+ default:
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= state;
+ break;
}
/* enter specified state */
if (platform_pci_choose_state) {
ret = platform_pci_choose_state(dev, state);
if (ret >= 0)
- state = ret;
+ state.event = ret;
}
- switch (state) {
- case 0: return PCI_D0;
- case 3: return PCI_D3hot;
+
+ switch (state.event) {
+ case PM_EVENT_ON:
+ return PCI_D0;
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_SUSPEND:
+ return PCI_D3hot;
default:
- printk("They asked me for state %d\n", state);
+ printk("They asked me for state %d\n", state.event);
BUG();
}
return PCI_D0;
{
int err;
- pci_set_power_state(dev, PCI_D0);
- if ((err = pcibios_enable_device(dev, bars)) < 0)
+ err = pci_set_power_state(dev, PCI_D0);
+ if (err < 0 && err != -EIO)
+ return err;
+ err = pcibios_enable_device(dev, bars);
+ if (err < 0)
return err;
return 0;
}
}
}
+/**
+ * pci_intx - enables/disables PCI INTx for device dev
+ * @dev: the PCI device to operate on
+ * @enable: boolean
+ *
+ * Enables/disables PCI INTx for device dev
+ */
+void
+pci_intx(struct pci_dev *pdev, int enable)
+{
+ u16 pci_command, new;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
+ if (enable) {
+ new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+ } else {
+ new = pci_command | PCI_COMMAND_INTX_DISABLE;
+ }
+
+ if (new != pci_command) {
+ pci_write_config_word(pdev, PCI_COMMAND, new);
+ }
+}
+
#ifndef HAVE_ARCH_PCI_SET_DMA_MASK
/*
* These can be overridden by arch-specific implementations
EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
+EXPORT_SYMBOL_GPL(pci_intx);
EXPORT_SYMBOL(pci_set_dma_mask);
EXPORT_SYMBOL(pci_set_consistent_dma_mask);
EXPORT_SYMBOL(pci_assign_resource);