Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270321
b: refs/heads/master
c: c320b97
h: refs/heads/master
i:
  270319: 6e1cbe4
v: v3
  • Loading branch information
Joerg Roedel authored and Jesse Barnes committed Oct 14, 2011
1 parent a546c92 commit 7f0c3e0
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d4c0636c2107010f0ef8c4dfbb1d6368ae3b3ed9
refs/heads/master: c320b976d7837c561ce4aa49dfe0a64f0e527ce4
9 changes: 9 additions & 0 deletions trunk/drivers/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ 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_IOAPIC
bool
depends on PCI
Expand Down
167 changes: 167 additions & 0 deletions trunk/drivers/pci/ats.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
* 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>
*/

#include <linux/pci-ats.h>
Expand Down Expand Up @@ -156,3 +158,168 @@ int pci_ats_queue_depth(struct pci_dev *dev)
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 */
42 changes: 42 additions & 0 deletions trunk/include/linux/pci-ats.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct pci_ats {
extern int pci_enable_ats(struct pci_dev *dev, int ps);
extern void pci_disable_ats(struct pci_dev *dev);
extern int pci_ats_queue_depth(struct pci_dev *dev);

/**
* pci_ats_enabled - query the ATS status
* @dev: the PCI device
Expand Down Expand Up @@ -51,4 +52,45 @@ static inline int pci_ats_enabled(struct pci_dev *dev)

#endif /* CONFIG_PCI_IOV */

#ifdef CONFIG_PCI_PRI

extern int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
extern void pci_disable_pri(struct pci_dev *pdev);
extern bool pci_pri_enabled(struct pci_dev *pdev);
extern int pci_reset_pri(struct pci_dev *pdev);
extern bool pci_pri_stopped(struct pci_dev *pdev);
extern int pci_pri_status(struct pci_dev *pdev);

#else /* CONFIG_PCI_PRI */

static inline int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
{
return -ENODEV;
}

static inline void pci_disable_pri(struct pci_dev *pdev)
{
}

static inline bool pci_pri_enabled(struct pci_dev *pdev)
{
return false;
}

static inline int pci_reset_pri(struct pci_dev *pdev)
{
return -ENODEV;
}

static inline bool pci_pri_stopped(struct pci_dev *pdev)
{
return true;
}

static inline int pci_pri_status(struct pci_dev *pdev)
{
return -ENODEV;
}
#endif /* CONFIG_PCI_PRI */

#endif /* LINUX_PCI_ATS_H*/
12 changes: 12 additions & 0 deletions trunk/include/linux/pci_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,18 @@
#define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */
#define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */

/* Page Request Interface */
#define PCI_PRI_CAP 0x13 /* PRI capability ID */
#define PCI_PRI_CONTROL_OFF 0x04 /* Offset of control register */
#define PCI_PRI_STATUS_OFF 0x06 /* Offset of status register */
#define PCI_PRI_ENABLE 0x0001 /* Enable mask */
#define PCI_PRI_RESET 0x0002 /* Reset bit mask */
#define PCI_PRI_STATUS_RF 0x0001 /* Request Failure */
#define PCI_PRI_STATUS_UPRGI 0x0002 /* Unexpected PRG index */
#define PCI_PRI_STATUS_STOPPED 0x0100 /* PRI Stopped */
#define PCI_PRI_MAX_REQ_OFF 0x08 /* Cap offset for max reqs supported */
#define PCI_PRI_ALLOC_REQ_OFF 0x0c /* Cap offset for max reqs allowed */

/* Single Root I/O Virtualization */
#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */
#define PCI_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */
Expand Down

0 comments on commit 7f0c3e0

Please sign in to comment.