Commit 608235a3 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/vc' into next

* pci/vc:
  PCI: Rename PCI_VC_PORT_REG1/2 to PCI_VC_PORT_CAP1/2
  PCI: Add Virtual Channel to save/restore support
  PCI: Add support for save/restore of extended capabilities
  PCI: Add pci_wait_for_pending() (refactor pci_wait_for_pending_transaction())
parents a737f76b 274127a1
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o setup-bus.o irq.o vpd.o setup-bus.o vc.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o obj-$(CONFIG_SYSFS) += slot.o
......
...@@ -430,6 +430,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) ...@@ -430,6 +430,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
return best; return best;
} }
/**
* pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
* @dev: the PCI device to operate on
* @pos: config space offset of status word
* @mask: mask of bit(s) to care about in status word
*
* Return 1 when mask bit(s) in status word clear, 0 otherwise.
*/
int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
{
int i;
/* Wait for Transaction Pending bit clean */
for (i = 0; i < 4; i++) {
u16 status;
if (i)
msleep((1 << (i - 1)) * 100);
pci_read_config_word(dev, pos, &status);
if (!(status & mask))
return 1;
}
return 0;
}
/** /**
* pci_restore_bars - restore a devices BAR values (e.g. after wake-up) * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
* @dev: PCI device to have its BARs restored * @dev: PCI device to have its BARs restored
...@@ -835,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state); ...@@ -835,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state);
#define PCI_EXP_SAVE_REGS 7 #define PCI_EXP_SAVE_REGS 7
static struct pci_cap_saved_state *pci_find_saved_cap( static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
struct pci_dev *pci_dev, char cap) u16 cap, bool extended)
{ {
struct pci_cap_saved_state *tmp; struct pci_cap_saved_state *tmp;
hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) {
if (tmp->cap.cap_nr == cap) if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap)
return tmp; return tmp;
} }
return NULL; return NULL;
} }
struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap)
{
return _pci_find_saved_cap(dev, cap, false);
}
struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap)
{
return _pci_find_saved_cap(dev, cap, true);
}
static int pci_save_pcie_state(struct pci_dev *dev) static int pci_save_pcie_state(struct pci_dev *dev)
{ {
int i = 0; int i = 0;
...@@ -948,6 +984,8 @@ pci_save_state(struct pci_dev *dev) ...@@ -948,6 +984,8 @@ pci_save_state(struct pci_dev *dev)
return i; return i;
if ((i = pci_save_pcix_state(dev)) != 0) if ((i = pci_save_pcix_state(dev)) != 0)
return i; return i;
if ((i = pci_save_vc_state(dev)) != 0)
return i;
return 0; return 0;
} }
...@@ -1010,6 +1048,7 @@ void pci_restore_state(struct pci_dev *dev) ...@@ -1010,6 +1048,7 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */ /* PCI Express register must be restored first */
pci_restore_pcie_state(dev); pci_restore_pcie_state(dev);
pci_restore_ats_state(dev); pci_restore_ats_state(dev);
pci_restore_vc_state(dev);
pci_restore_config_space(dev); pci_restore_config_space(dev);
...@@ -1087,7 +1126,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state) ...@@ -1087,7 +1126,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
while (cap->size) { while (cap->size) {
struct pci_cap_saved_state *tmp; struct pci_cap_saved_state *tmp;
tmp = pci_find_saved_cap(dev, cap->cap_nr); tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended);
if (!tmp || tmp->cap.size != cap->size) if (!tmp || tmp->cap.size != cap->size)
return -EINVAL; return -EINVAL;
...@@ -2021,18 +2060,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev, ...@@ -2021,18 +2060,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
} }
/** /**
* pci_add_cap_save_buffer - allocate buffer for saving given capability registers * _pci_add_cap_save_buffer - allocate buffer for saving given
* capability registers
* @dev: the PCI device * @dev: the PCI device
* @cap: the capability to allocate the buffer for * @cap: the capability to allocate the buffer for
* @extended: Standard or Extended capability ID
* @size: requested size of the buffer * @size: requested size of the buffer
*/ */
static int pci_add_cap_save_buffer( static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
struct pci_dev *dev, char cap, unsigned int size) bool extended, unsigned int size)
{ {
int pos; int pos;
struct pci_cap_saved_state *save_state; struct pci_cap_saved_state *save_state;
if (extended)
pos = pci_find_ext_capability(dev, cap);
else
pos = pci_find_capability(dev, cap); pos = pci_find_capability(dev, cap);
if (pos <= 0) if (pos <= 0)
return 0; return 0;
...@@ -2041,12 +2086,23 @@ static int pci_add_cap_save_buffer( ...@@ -2041,12 +2086,23 @@ static int pci_add_cap_save_buffer(
return -ENOMEM; return -ENOMEM;
save_state->cap.cap_nr = cap; save_state->cap.cap_nr = cap;
save_state->cap.cap_extended = extended;
save_state->cap.size = size; save_state->cap.size = size;
pci_add_saved_cap(dev, save_state); pci_add_saved_cap(dev, save_state);
return 0; return 0;
} }
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, false, size);
}
int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, true, size);
}
/** /**
* pci_allocate_cap_save_buffers - allocate buffers for saving capabilities * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
* @dev: the PCI device * @dev: the PCI device
...@@ -2065,6 +2121,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) ...@@ -2065,6 +2121,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
if (error) if (error)
dev_err(&dev->dev, dev_err(&dev->dev,
"unable to preallocate PCI-X save buffer\n"); "unable to preallocate PCI-X save buffer\n");
pci_allocate_vc_save_buffers(dev);
} }
void pci_free_cap_save_buffers(struct pci_dev *dev) void pci_free_cap_save_buffers(struct pci_dev *dev)
...@@ -3204,20 +3262,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary); ...@@ -3204,20 +3262,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
*/ */
int pci_wait_for_pending_transaction(struct pci_dev *dev) int pci_wait_for_pending_transaction(struct pci_dev *dev)
{ {
int i; if (!pci_is_pcie(dev))
u16 status;
/* Wait for Transaction Pending bit clean */
for (i = 0; i < 4; i++) {
if (i)
msleep((1 << (i - 1)) * 100);
pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
if (!(status & PCI_EXP_DEVSTA_TRPND))
return 1; return 1;
}
return 0; return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND);
} }
EXPORT_SYMBOL(pci_wait_for_pending_transaction); EXPORT_SYMBOL(pci_wait_for_pending_transaction);
...@@ -3244,10 +3292,8 @@ static int pcie_flr(struct pci_dev *dev, int probe) ...@@ -3244,10 +3292,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)
static int pci_af_flr(struct pci_dev *dev, int probe) static int pci_af_flr(struct pci_dev *dev, int probe)
{ {
int i;
int pos; int pos;
u8 cap; u8 cap;
u8 status;
pos = pci_find_capability(dev, PCI_CAP_ID_AF); pos = pci_find_capability(dev, PCI_CAP_ID_AF);
if (!pos) if (!pos)
...@@ -3261,14 +3307,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe) ...@@ -3261,14 +3307,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
return 0; return 0;
/* Wait for Transaction Pending bit clean */ /* Wait for Transaction Pending bit clean */
for (i = 0; i < 4; i++) { if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP))
if (i)
msleep((1 << (i - 1)) * 100);
pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
if (!(status & PCI_AF_STATUS_TP))
goto clear; goto clear;
}
dev_err(&dev->dev, "transaction is not cleared; " dev_err(&dev->dev, "transaction is not cleared; "
"proceeding with reset anyway\n"); "proceeding with reset anyway\n");
......
This diff is collapsed.
...@@ -975,20 +975,20 @@ static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos) ...@@ -975,20 +975,20 @@ static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos)
int ret, evcc, phases, vc_arb; int ret, evcc, phases, vc_arb;
int len = PCI_CAP_VC_BASE_SIZEOF; int len = PCI_CAP_VC_BASE_SIZEOF;
ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG1, &tmp); ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_CAP1, &tmp);
if (ret) if (ret)
return pcibios_err_to_errno(ret); return pcibios_err_to_errno(ret);
evcc = tmp & PCI_VC_REG1_EVCC; /* extended vc count */ evcc = tmp & PCI_VC_CAP1_EVCC; /* extended vc count */
ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_REG2, &tmp); ret = pci_read_config_dword(pdev, pos + PCI_VC_PORT_CAP2, &tmp);
if (ret) if (ret)
return pcibios_err_to_errno(ret); return pcibios_err_to_errno(ret);
if (tmp & PCI_VC_REG2_128_PHASE) if (tmp & PCI_VC_CAP2_128_PHASE)
phases = 128; phases = 128;
else if (tmp & PCI_VC_REG2_64_PHASE) else if (tmp & PCI_VC_CAP2_64_PHASE)
phases = 64; phases = 64;
else if (tmp & PCI_VC_REG2_32_PHASE) else if (tmp & PCI_VC_CAP2_32_PHASE)
phases = 32; phases = 32;
else else
phases = 0; phases = 0;
......
...@@ -224,7 +224,8 @@ enum pci_bus_speed { ...@@ -224,7 +224,8 @@ enum pci_bus_speed {
}; };
struct pci_cap_saved_data { struct pci_cap_saved_data {
char cap_nr; u16 cap_nr;
bool cap_extended;
unsigned int size; unsigned int size;
u32 data[0]; u32 data[0];
}; };
...@@ -938,6 +939,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev); ...@@ -938,6 +939,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev);
void pci_msi_off(struct pci_dev *dev); void pci_msi_off(struct pci_dev *dev);
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
int pci_wait_for_pending_transaction(struct pci_dev *dev); int pci_wait_for_pending_transaction(struct pci_dev *dev);
int pcix_get_max_mmrbc(struct pci_dev *dev); int pcix_get_max_mmrbc(struct pci_dev *dev);
int pcix_get_mmrbc(struct pci_dev *dev); int pcix_get_mmrbc(struct pci_dev *dev);
...@@ -976,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev); ...@@ -976,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev);
int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
int pci_load_and_free_saved_state(struct pci_dev *dev, int pci_load_and_free_saved_state(struct pci_dev *dev,
struct pci_saved_state **state); struct pci_saved_state **state);
struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
u16 cap);
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
u16 cap, unsigned int size);
int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
int pci_set_power_state(struct pci_dev *dev, pci_power_t state); int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
...@@ -997,6 +1005,11 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, ...@@ -997,6 +1005,11 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
return __pci_enable_wake(dev, state, false, enable); return __pci_enable_wake(dev, state, false, enable);
} }
/* PCI Virtual Channel */
int pci_save_vc_state(struct pci_dev *dev);
void pci_restore_vc_state(struct pci_dev *dev);
void pci_allocate_vc_save_buffers(struct pci_dev *dev);
#define PCI_EXP_IDO_REQUEST (1<<0) #define PCI_EXP_IDO_REQUEST (1<<0)
#define PCI_EXP_IDO_COMPLETION (1<<1) #define PCI_EXP_IDO_COMPLETION (1<<1)
void pci_enable_ido(struct pci_dev *dev, unsigned long type); void pci_enable_ido(struct pci_dev *dev, unsigned long type);
......
...@@ -685,17 +685,34 @@ ...@@ -685,17 +685,34 @@
#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */ #define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
/* Virtual Channel */ /* Virtual Channel */
#define PCI_VC_PORT_REG1 4 #define PCI_VC_PORT_CAP1 4
#define PCI_VC_REG1_EVCC 0x7 /* extended VC count */ #define PCI_VC_CAP1_EVCC 0x00000007 /* extended VC count */
#define PCI_VC_PORT_REG2 8 #define PCI_VC_CAP1_LPEVCC 0x00000070 /* low prio extended VC count */
#define PCI_VC_REG2_32_PHASE 0x2 #define PCI_VC_CAP1_ARB_SIZE 0x00000c00
#define PCI_VC_REG2_64_PHASE 0x4 #define PCI_VC_PORT_CAP2 8
#define PCI_VC_REG2_128_PHASE 0x8 #define PCI_VC_CAP2_32_PHASE 0x00000002
#define PCI_VC_CAP2_64_PHASE 0x00000004
#define PCI_VC_CAP2_128_PHASE 0x00000008
#define PCI_VC_CAP2_ARB_OFF 0xff000000
#define PCI_VC_PORT_CTRL 12 #define PCI_VC_PORT_CTRL 12
#define PCI_VC_PORT_CTRL_LOAD_TABLE 0x00000001
#define PCI_VC_PORT_STATUS 14 #define PCI_VC_PORT_STATUS 14
#define PCI_VC_PORT_STATUS_TABLE 0x00000001
#define PCI_VC_RES_CAP 16 #define PCI_VC_RES_CAP 16
#define PCI_VC_RES_CAP_32_PHASE 0x00000002
#define PCI_VC_RES_CAP_64_PHASE 0x00000004
#define PCI_VC_RES_CAP_128_PHASE 0x00000008
#define PCI_VC_RES_CAP_128_PHASE_TB 0x00000010
#define PCI_VC_RES_CAP_256_PHASE 0x00000020
#define PCI_VC_RES_CAP_ARB_OFF 0xff000000
#define PCI_VC_RES_CTRL 20 #define PCI_VC_RES_CTRL 20
#define PCI_VC_RES_CTRL_LOAD_TABLE 0x00010000
#define PCI_VC_RES_CTRL_ARB_SELECT 0x000e0000
#define PCI_VC_RES_CTRL_ID 0x07000000
#define PCI_VC_RES_CTRL_ENABLE 0x80000000
#define PCI_VC_RES_STATUS 26 #define PCI_VC_RES_STATUS 26
#define PCI_VC_RES_STATUS_TABLE 0x00000001
#define PCI_VC_RES_STATUS_NEGO 0x00000002
#define PCI_CAP_VC_BASE_SIZEOF 0x10 #define PCI_CAP_VC_BASE_SIZEOF 0x10
#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C #define PCI_CAP_VC_PER_VC_SIZEOF 0x0C
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment