Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: PCIe AER: prevent AER injection if hardware masks error reporting PCI/PM: Use per-device D3 delays PCI: Check the node argument passed to cpumask_of_node PCI: AER: fix aer inject result in kernel oops PCI: pcie portdrv: style cleanup
This commit is contained in:
@@ -4684,6 +4684,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
|
|||||||
INIT_WORK(&hw->restart_work, sky2_restart);
|
INIT_WORK(&hw->restart_work, sky2_restart);
|
||||||
|
|
||||||
pci_set_drvdata(pdev, hw);
|
pci_set_drvdata(pdev, hw);
|
||||||
|
pdev->d3_delay = 150;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@@ -75,7 +75,8 @@ static ssize_t local_cpus_show(struct device *dev,
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
mask = cpumask_of_node(dev_to_node(dev));
|
mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
|
||||||
|
cpumask_of_node(dev_to_node(dev));
|
||||||
#else
|
#else
|
||||||
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
|
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
|
||||||
#endif
|
#endif
|
||||||
@@ -93,7 +94,8 @@ static ssize_t local_cpulist_show(struct device *dev,
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
mask = cpumask_of_node(dev_to_node(dev));
|
mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
|
||||||
|
cpumask_of_node(dev_to_node(dev));
|
||||||
#else
|
#else
|
||||||
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
|
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -29,7 +29,17 @@ const char *pci_power_names[] = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(pci_power_names);
|
EXPORT_SYMBOL_GPL(pci_power_names);
|
||||||
|
|
||||||
unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT;
|
unsigned int pci_pm_d3_delay;
|
||||||
|
|
||||||
|
static void pci_dev_d3_sleep(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
unsigned int delay = dev->d3_delay;
|
||||||
|
|
||||||
|
if (delay < pci_pm_d3_delay)
|
||||||
|
delay = pci_pm_d3_delay;
|
||||||
|
|
||||||
|
msleep(delay);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_DOMAINS
|
#ifdef CONFIG_PCI_DOMAINS
|
||||||
int pci_domains_supported = 1;
|
int pci_domains_supported = 1;
|
||||||
@@ -522,7 +532,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||||||
/* Mandatory power management transition delays */
|
/* Mandatory power management transition delays */
|
||||||
/* see PCI PM 1.1 5.6.1 table 18 */
|
/* see PCI PM 1.1 5.6.1 table 18 */
|
||||||
if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
|
if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
|
||||||
msleep(pci_pm_d3_delay);
|
pci_dev_d3_sleep(dev);
|
||||||
else if (state == PCI_D2 || dev->current_state == PCI_D2)
|
else if (state == PCI_D2 || dev->current_state == PCI_D2)
|
||||||
udelay(PCI_PM_D2_DELAY);
|
udelay(PCI_PM_D2_DELAY);
|
||||||
|
|
||||||
@@ -1409,6 +1419,7 @@ void pci_pm_init(struct pci_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->pm_cap = pm;
|
dev->pm_cap = pm;
|
||||||
|
dev->d3_delay = PCI_PM_D3_WAIT;
|
||||||
|
|
||||||
dev->d1_support = false;
|
dev->d1_support = false;
|
||||||
dev->d2_support = false;
|
dev->d2_support = false;
|
||||||
@@ -2247,12 +2258,12 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
|
|||||||
csr &= ~PCI_PM_CTRL_STATE_MASK;
|
csr &= ~PCI_PM_CTRL_STATE_MASK;
|
||||||
csr |= PCI_D3hot;
|
csr |= PCI_D3hot;
|
||||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
|
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
|
||||||
msleep(pci_pm_d3_delay);
|
pci_dev_d3_sleep(dev);
|
||||||
|
|
||||||
csr &= ~PCI_PM_CTRL_STATE_MASK;
|
csr &= ~PCI_PM_CTRL_STATE_MASK;
|
||||||
csr |= PCI_D0;
|
csr |= PCI_D0;
|
||||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
|
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
|
||||||
msleep(pci_pm_d3_delay);
|
pci_dev_d3_sleep(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -321,7 +321,7 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
|
unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
|
||||||
int pos_cap_err, rp_pos_cap_err;
|
int pos_cap_err, rp_pos_cap_err;
|
||||||
u32 sever;
|
u32 sever, mask;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
|
dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
|
||||||
@@ -374,6 +374,24 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||||||
err->header_log2 = einj->header_log2;
|
err->header_log2 = einj->header_log2;
|
||||||
err->header_log3 = einj->header_log3;
|
err->header_log3 = einj->header_log3;
|
||||||
|
|
||||||
|
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &mask);
|
||||||
|
if (einj->cor_status && !(einj->cor_status & ~mask)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
printk(KERN_WARNING "The correctable error(s) is masked "
|
||||||
|
"by device\n");
|
||||||
|
spin_unlock_irqrestore(&inject_lock, flags);
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, &mask);
|
||||||
|
if (einj->uncor_status && !(einj->uncor_status & ~mask)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
printk(KERN_WARNING "The uncorrectable error(s) is masked "
|
||||||
|
"by device\n");
|
||||||
|
spin_unlock_irqrestore(&inject_lock, flags);
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
|
||||||
rperr = __find_aer_error_by_dev(rpdev);
|
rperr = __find_aer_error_by_dev(rpdev);
|
||||||
if (!rperr) {
|
if (!rperr) {
|
||||||
rperr = rperr_alloc;
|
rperr = rperr_alloc;
|
||||||
@@ -413,8 +431,14 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
if (find_aer_device(rpdev, &edev))
|
if (find_aer_device(rpdev, &edev)) {
|
||||||
|
if (!get_service_data(edev)) {
|
||||||
|
printk(KERN_WARNING "AER service is not initialized\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
aer_irq(-1, edev);
|
aer_irq(-1, edev);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
out_put:
|
out_put:
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
static void release_pcie_device(struct device *dev)
|
static void release_pcie_device(struct device *dev)
|
||||||
{
|
{
|
||||||
kfree(to_pcie_device(dev));
|
kfree(to_pcie_device(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,12 +346,11 @@ static int suspend_iter(struct device *dev, void *data)
|
|||||||
{
|
{
|
||||||
struct pcie_port_service_driver *service_driver;
|
struct pcie_port_service_driver *service_driver;
|
||||||
|
|
||||||
if ((dev->bus == &pcie_port_bus_type) &&
|
if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
|
||||||
(dev->driver)) {
|
service_driver = to_service_driver(dev->driver);
|
||||||
service_driver = to_service_driver(dev->driver);
|
if (service_driver->suspend)
|
||||||
if (service_driver->suspend)
|
service_driver->suspend(to_pcie_device(dev));
|
||||||
service_driver->suspend(to_pcie_device(dev));
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,6 +493,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
|
|||||||
|
|
||||||
return driver_register(&new->driver);
|
return driver_register(&new->driver);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(pcie_port_service_register);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pcie_port_service_unregister - unregister PCI Express port service driver
|
* pcie_port_service_unregister - unregister PCI Express port service driver
|
||||||
@@ -503,6 +503,4 @@ void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
|
|||||||
{
|
{
|
||||||
driver_unregister(&drv->driver);
|
driver_unregister(&drv->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(pcie_port_service_register);
|
|
||||||
EXPORT_SYMBOL(pcie_port_service_unregister);
|
EXPORT_SYMBOL(pcie_port_service_unregister);
|
||||||
|
@@ -63,7 +63,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
|||||||
* pcie_portdrv_probe - Probe PCI-Express port devices
|
* pcie_portdrv_probe - Probe PCI-Express port devices
|
||||||
* @dev: PCI-Express port device being probed
|
* @dev: PCI-Express port device being probed
|
||||||
*
|
*
|
||||||
* If detected invokes the pcie_port_device_register() method for
|
* If detected invokes the pcie_port_device_register() method for
|
||||||
* this port device.
|
* this port device.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -78,7 +78,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
|
|||||||
(dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
|
(dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (!dev->irq && dev->pin) {
|
if (!dev->irq && dev->pin) {
|
||||||
dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
|
dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
|
||||||
"check vendor BIOS\n", dev->vendor, dev->device);
|
"check vendor BIOS\n", dev->vendor, dev->device);
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcie_portdrv_remove (struct pci_dev *dev)
|
static void pcie_portdrv_remove(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
pcie_port_device_remove(dev);
|
pcie_port_device_remove(dev);
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
@@ -129,14 +129,13 @@ static int error_detected_iter(struct device *device, void *data)
|
|||||||
static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
|
static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
|
||||||
enum pci_channel_state error)
|
enum pci_channel_state error)
|
||||||
{
|
{
|
||||||
struct aer_broadcast_data result_data =
|
struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
|
||||||
{error, PCI_ERS_RESULT_CAN_RECOVER};
|
int ret;
|
||||||
int retval;
|
|
||||||
|
|
||||||
/* can not fail */
|
/* can not fail */
|
||||||
retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
|
ret = device_for_each_child(&dev->dev, &data, error_detected_iter);
|
||||||
|
|
||||||
return result_data.result;
|
return data.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmio_enabled_iter(struct device *device, void *data)
|
static int mmio_enabled_iter(struct device *device, void *data)
|
||||||
@@ -290,7 +289,7 @@ static int __init pcie_portdrv_init(void)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit pcie_portdrv_exit(void)
|
static void __exit pcie_portdrv_exit(void)
|
||||||
{
|
{
|
||||||
pci_unregister_driver(&pcie_portdriver);
|
pci_unregister_driver(&pcie_portdriver);
|
||||||
pcie_port_bus_unregister();
|
pcie_port_bus_unregister();
|
||||||
|
@@ -243,6 +243,7 @@ struct pci_dev {
|
|||||||
unsigned int d2_support:1; /* Low power state D2 is supported */
|
unsigned int d2_support:1; /* Low power state D2 is supported */
|
||||||
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
|
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
|
||||||
unsigned int wakeup_prepared:1;
|
unsigned int wakeup_prepared:1;
|
||||||
|
unsigned int d3_delay; /* D3->D0 transition time in ms */
|
||||||
|
|
||||||
#ifdef CONFIG_PCIEASPM
|
#ifdef CONFIG_PCIEASPM
|
||||||
struct pcie_link_state *link_state; /* ASPM link state. */
|
struct pcie_link_state *link_state; /* ASPM link state. */
|
||||||
|
Reference in New Issue
Block a user