Merge branch 'next-rebase' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci

* 'next-rebase' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci:
  PCI: Clean-up MPS debug output
  pci: Clamp pcie_set_readrq() when using "performance" settings
  PCI: enable MPS "performance" setting to properly handle bridge MPS
  PCI: Workaround for Intel MPS errata
  PCI: Add support for PASID capability
  PCI: Add implementation for PRI capability
  PCI: Export ATS functions to modules
  PCI: Move ATS implementation into own file
  PCI / PM: Remove unnecessary error variable from acpi_dev_run_wake()
  PCI hotplug: acpiphp: Prevent deadlock on PCI-to-PCI bridge remove
  PCI / PM: Extend PME polling to all PCI devices
  PCI quirk: mmc: Always check for lower base frequency quirk for Ricoh 1180:e823
  PCI: Make pci_setup_bridge() non-static for use by arch code
  x86: constify PCI raw ops structures
  PCI: Add quirk for known incorrect MPSS
  PCI: Add Solarflare vendor ID and SFC4000 device IDs
This commit is contained in:
Linus Torvalds
2011-10-28 14:20:44 -07:00
30 changed files with 868 additions and 260 deletions
+3 -3
View File
@@ -99,10 +99,10 @@ struct pci_raw_ops {
int reg, int len, u32 val);
};
extern struct pci_raw_ops *raw_pci_ops;
extern struct pci_raw_ops *raw_pci_ext_ops;
extern const struct pci_raw_ops *raw_pci_ops;
extern const struct pci_raw_ops *raw_pci_ext_ops;
extern struct pci_raw_ops pci_direct_conf1;
extern const struct pci_raw_ops pci_direct_conf1;
extern bool port_cf9_safe;
/* arch_initcall level */
+1 -1
View File
@@ -304,7 +304,7 @@ static int ce4100_conf_write(unsigned int seg, unsigned int bus,
return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
}
struct pci_raw_ops ce4100_pci_conf = {
static const struct pci_raw_ops ce4100_pci_conf = {
.read = ce4100_conf_read,
.write = ce4100_conf_write,
};
+2 -2
View File
@@ -33,8 +33,8 @@ int noioapicreroute = 1;
int pcibios_last_bus = -1;
unsigned long pirq_table_addr;
struct pci_bus *pci_root_bus;
struct pci_raw_ops *raw_pci_ops;
struct pci_raw_ops *raw_pci_ext_ops;
const struct pci_raw_ops *__read_mostly raw_pci_ops;
const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val)
+3 -3
View File
@@ -79,7 +79,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF1_ADDRESS
struct pci_raw_ops pci_direct_conf1 = {
const struct pci_raw_ops pci_direct_conf1 = {
.read = pci_conf1_read,
.write = pci_conf1_write,
};
@@ -175,7 +175,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF2_ADDRESS
struct pci_raw_ops pci_direct_conf2 = {
static const struct pci_raw_ops pci_direct_conf2 = {
.read = pci_conf2_read,
.write = pci_conf2_write,
};
@@ -191,7 +191,7 @@ struct pci_raw_ops pci_direct_conf2 = {
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
static int __init pci_sanity_check(struct pci_raw_ops *o)
static int __init pci_sanity_check(const struct pci_raw_ops *o)
{
u32 x = 0;
int year, devfn;
+1 -1
View File
@@ -117,7 +117,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
return 0;
}
static struct pci_raw_ops pci_mmcfg = {
static const struct pci_raw_ops pci_mmcfg = {
.read = pci_mmcfg_read,
.write = pci_mmcfg_write,
};
+1 -1
View File
@@ -81,7 +81,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
return 0;
}
static struct pci_raw_ops pci_mmcfg = {
static const struct pci_raw_ops pci_mmcfg = {
.read = pci_mmcfg_read,
.write = pci_mmcfg_write,
};
+1 -1
View File
@@ -110,7 +110,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF1_MQ_ADDRESS
static struct pci_raw_ops pci_direct_conf1_mq = {
static const struct pci_raw_ops pci_direct_conf1_mq = {
.read = pci_conf1_mq_read,
.write = pci_conf1_mq_write
};
+1 -1
View File
@@ -301,7 +301,7 @@ static int pci_olpc_write(unsigned int seg, unsigned int bus,
return 0;
}
static struct pci_raw_ops pci_olpc_conf = {
static const struct pci_raw_ops pci_olpc_conf = {
.read = pci_olpc_read,
.write = pci_olpc_write,
};
+2 -2
View File
@@ -303,7 +303,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
* Function table for BIOS32 access
*/
static struct pci_raw_ops pci_bios_access = {
static const struct pci_raw_ops pci_bios_access = {
.read = pci_bios_read,
.write = pci_bios_write
};
@@ -312,7 +312,7 @@ static struct pci_raw_ops pci_bios_access = {
* Try to find PCI BIOS.
*/
static struct pci_raw_ops * __devinit pci_find_bios(void)
static const struct pci_raw_ops * __devinit pci_find_bios(void)
{
union bios32 *check;
unsigned char sum;
+2 -1
View File
@@ -80,7 +80,8 @@ static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
static struct workqueue_struct *kacpi_hotplug_wq;
struct workqueue_struct *kacpi_hotplug_wq;
EXPORT_SYMBOL(kacpi_hotplug_wq);
struct acpi_res_list {
resource_size_t start;
+6 -4
View File
@@ -2229,13 +2229,15 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
/* PCI device ID table */
static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
{PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID),
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
.driver_data = (unsigned long) &falcon_a1_nic_type},
{PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID),
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
PCI_DEVICE_ID_SOLARFLARE_SFC4000B),
.driver_data = (unsigned long) &falcon_b0_nic_type},
{PCI_DEVICE(EFX_VENDID_SFC, BETHPAGE_A_P_DEVID),
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, BETHPAGE_A_P_DEVID),
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(EFX_VENDID_SFC, SIENA_A_P_DEVID),
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, SIENA_A_P_DEVID),
.driver_data = (unsigned long) &siena_a0_nic_type},
{0} /* end of list */
};
-4
View File
@@ -15,10 +15,6 @@
#include "filter.h"
/* PCI IDs */
#define EFX_VENDID_SFC 0x1924
#define FALCON_A_P_DEVID 0x0703
#define FALCON_A_S_DEVID 0x6703
#define FALCON_B_P_DEVID 0x0710
#define BETHPAGE_A_P_DEVID 0x0803
#define SIENA_A_P_DEVID 0x0813
+2 -1
View File
@@ -1426,7 +1426,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
}
dev = pci_dev_get(efx->pci_dev);
while ((dev = pci_get_device(EFX_VENDID_SFC, FALCON_A_S_DEVID,
while ((dev = pci_get_device(PCI_VENDOR_ID_SOLARFLARE,
PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1,
dev))) {
if (dev->bus == efx->pci_dev->bus &&
dev->devfn == efx->pci_dev->devfn + 1) {
+2 -1
View File
@@ -764,7 +764,8 @@ int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
if (board->type) {
netif_info(efx, probe, efx->net_dev, "board is %s rev %c%d\n",
(efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
(efx->pci_dev->subsystem_vendor ==
PCI_VENDOR_ID_SOLARFLARE)
? board->type->ref_model : board->type->gen_type,
'A' + board->major, board->minor);
return 0;
+26
View File
@@ -71,9 +71,13 @@ config HT_IRQ
If unsure say Y.
config PCI_ATS
bool
config PCI_IOV
bool "PCI IOV support"
depends on PCI
select PCI_ATS
help
I/O Virtualization is a PCI feature supported by some devices
which allows them to create virtual devices which share their
@@ -81,6 +85,28 @@ config PCI_IOV
If unsure, say N.
config PCI_PRI
bool "PCI PRI support"
select PCI_ATS
help
PRI is the PCI Page Request Interface. It allows PCI devices that are
behind an IOMMU to recover from page faults.
If unsure, say N.
config PCI_PASID
bool "PCI PASID support"
depends on PCI
select PCI_ATS
help
Process Address Space Identifiers (PASIDs) can be used by PCI devices
to access more than one IO address space at the same time. To make
use of this feature an IOMMU is required which also supports PASIDs.
Select this option if you have such an IOMMU and want to compile the
driver for it into your kernel.
If unsure, say N.
config PCI_IOAPIC
bool
depends on PCI
+1
View File
@@ -29,6 +29,7 @@ obj-$(CONFIG_PCI_MSI) += msi.o
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o
#
+438
View File
@@ -0,0 +1,438 @@
/*
* drivers/pci/ats.c
*
* Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com>
* Copyright (C) 2011 Advanced Micro Devices,
*
* PCI Express I/O Virtualization (IOV) support.
* Address Translation Service 1.0
* Page Request Interface added by Joerg Roedel <joerg.roedel@amd.com>
* PASID support added by Joerg Roedel <joerg.roedel@amd.com>
*/
#include <linux/pci-ats.h>
#include <linux/pci.h>
#include "pci.h"
static int ats_alloc_one(struct pci_dev *dev, int ps)
{
int pos;
u16 cap;
struct pci_ats *ats;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
return -ENODEV;
ats = kzalloc(sizeof(*ats), GFP_KERNEL);
if (!ats)
return -ENOMEM;
ats->pos = pos;
ats->stu = ps;
pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
PCI_ATS_MAX_QDEP;
dev->ats = ats;
return 0;
}
static void ats_free_one(struct pci_dev *dev)
{
kfree(dev->ats);
dev->ats = NULL;
}
/**
* pci_enable_ats - enable the ATS capability
* @dev: the PCI device
* @ps: the IOMMU page shift
*
* Returns 0 on success, or negative on failure.
*/
int pci_enable_ats(struct pci_dev *dev, int ps)
{
int rc;
u16 ctrl;
BUG_ON(dev->ats && dev->ats->is_enabled);
if (ps < PCI_ATS_MIN_STU)
return -EINVAL;
if (dev->is_physfn || dev->is_virtfn) {
struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
mutex_lock(&pdev->sriov->lock);
if (pdev->ats)
rc = pdev->ats->stu == ps ? 0 : -EINVAL;
else
rc = ats_alloc_one(pdev, ps);
if (!rc)
pdev->ats->ref_cnt++;
mutex_unlock(&pdev->sriov->lock);
if (rc)
return rc;
}
if (!dev->is_physfn) {
rc = ats_alloc_one(dev, ps);
if (rc)
return rc;
}
ctrl = PCI_ATS_CTRL_ENABLE;
if (!dev->is_virtfn)
ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
dev->ats->is_enabled = 1;
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_ats);
/**
* pci_disable_ats - disable the ATS capability
* @dev: the PCI device
*/
void pci_disable_ats(struct pci_dev *dev)
{
u16 ctrl;
BUG_ON(!dev->ats || !dev->ats->is_enabled);
pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
ctrl &= ~PCI_ATS_CTRL_ENABLE;
pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
dev->ats->is_enabled = 0;
if (dev->is_physfn || dev->is_virtfn) {
struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
mutex_lock(&pdev->sriov->lock);
pdev->ats->ref_cnt--;
if (!pdev->ats->ref_cnt)
ats_free_one(pdev);
mutex_unlock(&pdev->sriov->lock);
}
if (!dev->is_physfn)
ats_free_one(dev);
}
EXPORT_SYMBOL_GPL(pci_disable_ats);
/**
* pci_ats_queue_depth - query the ATS Invalidate Queue Depth
* @dev: the PCI device
*
* Returns the queue depth on success, or negative on failure.
*
* The ATS spec uses 0 in the Invalidate Queue Depth field to
* indicate that the function can accept 32 Invalidate Request.
* But here we use the `real' values (i.e. 1~32) for the Queue
* Depth; and 0 indicates the function shares the Queue with
* other functions (doesn't exclusively own a Queue).
*/
int pci_ats_queue_depth(struct pci_dev *dev)
{
int pos;
u16 cap;
if (dev->is_virtfn)
return 0;
if (dev->ats)
return dev->ats->qdep;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
return -ENODEV;
pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
PCI_ATS_MAX_QDEP;
}
EXPORT_SYMBOL_GPL(pci_ats_queue_depth);
#ifdef CONFIG_PCI_PRI
/**
* pci_enable_pri - Enable PRI capability
* @ pdev: PCI device structure
*
* Returns 0 on success, negative value on error
*/
int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
{
u16 control, status;
u32 max_requests;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
if ((control & PCI_PRI_ENABLE) || !(status & PCI_PRI_STATUS_STOPPED))
return -EBUSY;
pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ_OFF, &max_requests);
reqs = min(max_requests, reqs);
pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ_OFF, reqs);
control |= PCI_PRI_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pri);
/**
* pci_disable_pri - Disable PRI capability
* @pdev: PCI device structure
*
* Only clears the enabled-bit, regardless of its former value
*/
void pci_disable_pri(struct pci_dev *pdev)
{
u16 control;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
control &= ~PCI_PRI_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
}
EXPORT_SYMBOL_GPL(pci_disable_pri);
/**
* pci_pri_enabled - Checks if PRI capability is enabled
* @pdev: PCI device structure
*
* Returns true if PRI is enabled on the device, false otherwise
*/
bool pci_pri_enabled(struct pci_dev *pdev)
{
u16 control;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return false;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
return (control & PCI_PRI_ENABLE) ? true : false;
}
EXPORT_SYMBOL_GPL(pci_pri_enabled);
/**
* pci_reset_pri - Resets device's PRI state
* @pdev: PCI device structure
*
* The PRI capability must be disabled before this function is called.
* Returns 0 on success, negative value on error.
*/
int pci_reset_pri(struct pci_dev *pdev)
{
u16 control;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
if (control & PCI_PRI_ENABLE)
return -EBUSY;
control |= PCI_PRI_RESET;
pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
return 0;
}
EXPORT_SYMBOL_GPL(pci_reset_pri);
/**
* pci_pri_stopped - Checks whether the PRI capability is stopped
* @pdev: PCI device structure
*
* Returns true if the PRI capability on the device is disabled and the
* device has no outstanding PRI requests, false otherwise. The device
* indicates this via the STOPPED bit in the status register of the
* capability.
* The device internal state can be cleared by resetting the PRI state
* with pci_reset_pri(). This can force the capability into the STOPPED
* state.
*/
bool pci_pri_stopped(struct pci_dev *pdev)
{
u16 control, status;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return true;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
if (control & PCI_PRI_ENABLE)
return false;
return (status & PCI_PRI_STATUS_STOPPED) ? true : false;
}
EXPORT_SYMBOL_GPL(pci_pri_stopped);
/**
* pci_pri_status - Request PRI status of a device
* @pdev: PCI device structure
*
* Returns negative value on failure, status on success. The status can
* be checked against status-bits. Supported bits are currently:
* PCI_PRI_STATUS_RF: Response failure
* PCI_PRI_STATUS_UPRGI: Unexpected Page Request Group Index
* PCI_PRI_STATUS_STOPPED: PRI has stopped
*/
int pci_pri_status(struct pci_dev *pdev)
{
u16 status, control;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
/* Stopped bit is undefined when enable == 1, so clear it */
if (control & PCI_PRI_ENABLE)
status &= ~PCI_PRI_STATUS_STOPPED;
return status;
}
EXPORT_SYMBOL_GPL(pci_pri_status);
#endif /* CONFIG_PCI_PRI */
#ifdef CONFIG_PCI_PASID
/**
* pci_enable_pasid - Enable the PASID capability
* @pdev: PCI device structure
* @features: Features to enable
*
* Returns 0 on success, negative value on error. This function checks
* whether the features are actually supported by the device and returns
* an error if not.
*/
int pci_enable_pasid(struct pci_dev *pdev, int features)
{
u16 control, supported;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, &control);
pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
if (!(supported & PCI_PASID_ENABLE))
return -EINVAL;
supported &= PCI_PASID_EXEC | PCI_PASID_PRIV;
/* User wants to enable anything unsupported? */
if ((supported & features) != features)
return -EINVAL;
control = PCI_PASID_ENABLE | features;
pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control);
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pasid);
/**
* pci_disable_pasid - Disable the PASID capability
* @pdev: PCI device structure
*
*/
void pci_disable_pasid(struct pci_dev *pdev)
{
u16 control = 0;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
if (!pos)
return;
pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control);
}
EXPORT_SYMBOL_GPL(pci_disable_pasid);
/**
* pci_pasid_features - Check which PASID features are supported
* @pdev: PCI device structure
*
* Returns a negative value when no PASI capability is present.
* Otherwise is returns a bitmask with supported features. Current
* features reported are:
* PCI_PASID_ENABLE - PASID capability can be enabled
* PCI_PASID_EXEC - Execute permission supported
* PCI_PASID_PRIV - Priviledged mode supported
*/
int pci_pasid_features(struct pci_dev *pdev)
{
u16 supported;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
supported &= PCI_PASID_ENABLE | PCI_PASID_EXEC | PCI_PASID_PRIV;
return supported;
}
EXPORT_SYMBOL_GPL(pci_pasid_features);
#define PASID_NUMBER_SHIFT 8
#define PASID_NUMBER_MASK (0x1f << PASID_NUMBER_SHIFT)
/**
* pci_max_pasid - Get maximum number of PASIDs supported by device
* @pdev: PCI device structure
*
* Returns negative value when PASID capability is not present.
* Otherwise it returns the numer of supported PASIDs.
*/
int pci_max_pasids(struct pci_dev *pdev)
{
u16 supported;
int pos;
pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT;
return (1 << supported);
}
EXPORT_SYMBOL_GPL(pci_max_pasids);
#endif /* CONFIG_PCI_PASID */
+94 -15
View File
@@ -48,6 +48,7 @@
#include <linux/pci-acpi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include "../pci.h"
#include "acpiphp.h"
@@ -1149,15 +1150,35 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK ;
}
/**
* handle_hotplug_event_bridge - handle ACPI event on bridges
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_bridge structure
*
* Handles ACPI event notification on {host,p2p} bridges.
*/
static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
struct acpiphp_hp_work {
struct work_struct work;
acpi_handle handle;
u32 type;
void *context;
};
static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
void *context,
void (*func)(struct work_struct *work))
{
struct acpiphp_hp_work *hp_work;
int ret;
hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
if (!hp_work)
return;
hp_work->handle = handle;
hp_work->type = type;
hp_work->context = context;
INIT_WORK(&hp_work->work, func);
ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
if (!ret)
kfree(hp_work);
}
static void _handle_hotplug_event_bridge(struct work_struct *work)
{
struct acpiphp_bridge *bridge;
char objname[64];
@@ -1165,11 +1186,18 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
.pointer = objname };
struct acpi_device *device;
int num_sub_bridges = 0;
struct acpiphp_hp_work *hp_work;
acpi_handle handle;
u32 type;
hp_work = container_of(work, struct acpiphp_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
handle_bridge_insertion(handle, type);
return;
goto out;
}
bridge = acpiphp_handle_to_bridge(handle);
@@ -1180,7 +1208,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
if (!bridge && !num_sub_bridges) {
err("cannot get bridge info\n");
return;
goto out;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1241,22 +1269,49 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
out:
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
}
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
* handle_hotplug_event_bridge - handle ACPI event on bridges
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_func structure
* @context: pointer to acpiphp_bridge structure
*
* Handles ACPI event notification on slots.
* Handles ACPI event notification on {host,p2p} bridges.
*/
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
void *context)
{
/*
* Currently the code adds all hotplug events to the kacpid_wq
* queue when it should add hotplug events to the kacpi_hotplug_wq.
* The proper way to fix this is to reorganize the code so that
* drivers (dock, etc.) do not call acpi_os_execute(), etc.
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
alloc_acpiphp_hp_work(handle, type, context,
_handle_hotplug_event_bridge);
}
static void _handle_hotplug_event_func(struct work_struct *work)
{
struct acpiphp_func *func;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
struct acpiphp_hp_work *hp_work;
acpi_handle handle;
u32 type;
void *context;
hp_work = container_of(work, struct acpiphp_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
context = hp_work->context;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1291,8 +1346,32 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
kfree(hp_work); /* allocated in handle_hotplug_event_func */
}
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_func structure
*
* Handles ACPI event notification on slots.
*/
static void handle_hotplug_event_func(acpi_handle handle, u32 type,
void *context)
{
/*
* Currently the code adds all hotplug events to the kacpid_wq
* queue when it should add hotplug events to the kacpi_hotplug_wq.
* The proper way to fix this is to reorganize the code so that
* drivers (dock, etc.) do not call acpi_os_execute(), etc.
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
alloc_acpiphp_hp_work(handle, type, context,
_handle_hotplug_event_func);
}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-142
View File
@@ -722,145 +722,3 @@ int pci_num_vf(struct pci_dev *dev)
return dev->sriov->nr_virtfn;
}
EXPORT_SYMBOL_GPL(pci_num_vf);
static int ats_alloc_one(struct pci_dev *dev, int ps)
{
int pos;
u16 cap;
struct pci_ats *ats;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
return -ENODEV;
ats = kzalloc(sizeof(*ats), GFP_KERNEL);
if (!ats)
return -ENOMEM;
ats->pos = pos;
ats->stu = ps;
pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
PCI_ATS_MAX_QDEP;
dev->ats = ats;
return 0;
}
static void ats_free_one(struct pci_dev *dev)
{
kfree(dev->ats);
dev->ats = NULL;
}
/**
* pci_enable_ats - enable the ATS capability
* @dev: the PCI device
* @ps: the IOMMU page shift
*
* Returns 0 on success, or negative on failure.
*/
int pci_enable_ats(struct pci_dev *dev, int ps)
{
int rc;
u16 ctrl;
BUG_ON(dev->ats && dev->ats->is_enabled);
if (ps < PCI_ATS_MIN_STU)
return -EINVAL;
if (dev->is_physfn || dev->is_virtfn) {
struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
mutex_lock(&pdev->sriov->lock);
if (pdev->ats)
rc = pdev->ats->stu == ps ? 0 : -EINVAL;
else
rc = ats_alloc_one(pdev, ps);
if (!rc)
pdev->ats->ref_cnt++;
mutex_unlock(&pdev->sriov->lock);
if (rc)
return rc;
}
if (!dev->is_physfn) {
rc = ats_alloc_one(dev, ps);
if (rc)
return rc;
}
ctrl = PCI_ATS_CTRL_ENABLE;
if (!dev->is_virtfn)
ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
dev->ats->is_enabled = 1;
return 0;
}
/**
* pci_disable_ats - disable the ATS capability
* @dev: the PCI device
*/
void pci_disable_ats(struct pci_dev *dev)
{
u16 ctrl;
BUG_ON(!dev->ats || !dev->ats->is_enabled);
pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
ctrl &= ~PCI_ATS_CTRL_ENABLE;
pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
dev->ats->is_enabled = 0;
if (dev->is_physfn || dev->is_virtfn) {
struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
mutex_lock(&pdev->sriov->lock);
pdev->ats->ref_cnt--;
if (!pdev->ats->ref_cnt)
ats_free_one(pdev);
mutex_unlock(&pdev->sriov->lock);
}
if (!dev->is_physfn)
ats_free_one(dev);
}
/**
* pci_ats_queue_depth - query the ATS Invalidate Queue Depth
* @dev: the PCI device
*
* Returns the queue depth on success, or negative on failure.
*
* The ATS spec uses 0 in the Invalidate Queue Depth field to
* indicate that the function can accept 32 Invalidate Request.
* But here we use the `real' values (i.e. 1~32) for the Queue
* Depth; and 0 indicates the function shares the Queue with
* other functions (doesn't exclusively own a Queue).
*/
int pci_ats_queue_depth(struct pci_dev *dev)
{
int pos;
u16 cap;
if (dev->is_virtfn)
return 0;
if (dev->ats)
return dev->ats->qdep;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
return -ENODEV;
pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
PCI_ATS_MAX_QDEP;
}
+4 -2
View File
@@ -46,6 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
struct pci_dev *pci_dev = context;
if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) {
if (pci_dev->pme_poll)
pci_dev->pme_poll = false;
pci_wakeup_event(pci_dev);
pci_check_pme_status(pci_dev);
pm_runtime_resume(&pci_dev->dev);
@@ -282,7 +285,6 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
{
struct acpi_device *dev;
acpi_handle handle;
int error = -ENODEV;
if (!device_run_wake(phys_dev))
return -EINVAL;
@@ -302,7 +304,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
acpi_disable_wakeup_device_power(dev);
}
return error;
return 0;
}
static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)

Some files were not shown because too many files have changed in this diff Show More