mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
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: PCI: OF: Don't crash when bridge parent is NULL. PCI: export pcie_bus_configure_settings symbol PCI: code and comments cleanup PCI: make cardbus-bridge resources optional PCI: make SRIOV resources optional PCI : ability to relocate assigned pci-resources PCI: honor child buses add_size in hot plug configuration PCI: Set PCI-E Max Payload Size on fabric
This commit is contained in:
commit
0c3bef6128
@ -360,6 +360,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
}
|
||||
}
|
||||
|
||||
/* After the PCI-E bus has been walked and all devices discovered,
|
||||
* configure any settings of the fabric that might be necessary.
|
||||
*/
|
||||
if (bus) {
|
||||
struct pci_bus *child;
|
||||
list_for_each_entry(child, &bus->children, node)
|
||||
pcie_bus_configure_settings(child, child->self->pcie_mpss);
|
||||
}
|
||||
|
||||
if (!bus)
|
||||
kfree(sd);
|
||||
|
||||
|
@ -158,47 +158,6 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
|
||||
*/
|
||||
}
|
||||
|
||||
/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
|
||||
static int pci_set_payload(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ppos;
|
||||
u16 pctl, psz;
|
||||
u16 dctl, dsz, dcap, dmax;
|
||||
struct pci_dev *parent;
|
||||
|
||||
parent = dev->bus->self;
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (!pos)
|
||||
return 0;
|
||||
|
||||
/* Read Device MaxPayload capability and setting */
|
||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
|
||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
|
||||
dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
|
||||
dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
|
||||
|
||||
/* Read Parent MaxPayload setting */
|
||||
ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
|
||||
if (!ppos)
|
||||
return 0;
|
||||
pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
|
||||
psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
|
||||
|
||||
/* If parent payload > device max payload -> error
|
||||
* If parent payload > device payload -> set speed
|
||||
* If parent payload <= device payload -> do nothing
|
||||
*/
|
||||
if (psz > dmax)
|
||||
return -1;
|
||||
else if (psz > dsz) {
|
||||
dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
|
||||
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
|
||||
(dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
|
||||
(psz << 5));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_configure_slot(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *cdev;
|
||||
@ -210,9 +169,7 @@ void pci_configure_slot(struct pci_dev *dev)
|
||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
||||
return;
|
||||
|
||||
ret = pci_set_payload(dev);
|
||||
if (ret)
|
||||
dev_warn(&dev->dev, "could not set device max payload\n");
|
||||
pcie_bus_configure_settings(dev->bus, dev->bus->self->pcie_mpss);
|
||||
|
||||
memset(&hpp, 0, sizeof(hpp));
|
||||
ret = pci_get_hp_params(dev, &hpp);
|
||||
|
@ -55,7 +55,7 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
|
||||
*/
|
||||
if (bus->bridge->of_node)
|
||||
return of_node_get(bus->bridge->of_node);
|
||||
if (bus->bridge->parent->of_node)
|
||||
if (bus->bridge->parent && bus->bridge->parent->of_node)
|
||||
return of_node_get(bus->bridge->parent->of_node);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
|
||||
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
|
||||
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
|
||||
|
||||
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
|
||||
|
||||
/*
|
||||
* The default CLS is used if arch didn't set CLS explicitly and not
|
||||
* all pci devices agree on the same value. Arch can override either
|
||||
@ -3222,6 +3224,67 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_set_readrq);
|
||||
|
||||
/**
|
||||
* pcie_get_mps - get PCI Express maximum payload size
|
||||
* @dev: PCI device to query
|
||||
*
|
||||
* Returns maximum payload size in bytes
|
||||
* or appropriate error value.
|
||||
*/
|
||||
int pcie_get_mps(struct pci_dev *dev)
|
||||
{
|
||||
int ret, cap;
|
||||
u16 ctl;
|
||||
|
||||
cap = pci_pcie_cap(dev);
|
||||
if (!cap)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
|
||||
if (!ret)
|
||||
ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_set_mps - set PCI Express maximum payload size
|
||||
* @dev: PCI device to query
|
||||
* @rq: maximum payload size in bytes
|
||||
* valid values are 128, 256, 512, 1024, 2048, 4096
|
||||
*
|
||||
* If possible sets maximum payload size
|
||||
*/
|
||||
int pcie_set_mps(struct pci_dev *dev, int mps)
|
||||
{
|
||||
int cap, err = -EINVAL;
|
||||
u16 ctl, v;
|
||||
|
||||
if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
|
||||
goto out;
|
||||
|
||||
v = ffs(mps) - 8;
|
||||
if (v > dev->pcie_mpss)
|
||||
goto out;
|
||||
v <<= 5;
|
||||
|
||||
cap = pci_pcie_cap(dev);
|
||||
if (!cap)
|
||||
goto out;
|
||||
|
||||
err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
|
||||
ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
|
||||
ctl |= v;
|
||||
err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
|
||||
}
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_select_bars - Make BAR mask from the type of resource
|
||||
* @dev: the PCI device for which BAR mask is made
|
||||
@ -3505,6 +3568,10 @@ static int __init pci_setup(char *str)
|
||||
pci_hotplug_io_size = memparse(str + 9, &str);
|
||||
} else if (!strncmp(str, "hpmemsize=", 10)) {
|
||||
pci_hotplug_mem_size = memparse(str + 10, &str);
|
||||
} else if (!strncmp(str, "pcie_bus_safe", 13)) {
|
||||
pcie_bus_config = PCIE_BUS_SAFE;
|
||||
} else if (!strncmp(str, "pcie_bus_perf", 13)) {
|
||||
pcie_bus_config = PCIE_BUS_PERFORMANCE;
|
||||
} else {
|
||||
printk(KERN_ERR "PCI: Unknown option `%s'\n",
|
||||
str);
|
||||
|
@ -283,6 +283,8 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
||||
extern unsigned long pci_cardbus_resource_alignment(struct resource *);
|
||||
|
||||
static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
|
||||
struct resource *res)
|
||||
{
|
||||
@ -292,6 +294,8 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
|
||||
if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
|
||||
return pci_sriov_resource_alignment(dev, resno);
|
||||
#endif
|
||||
if (dev->class >> 8 == PCI_CLASS_BRIDGE_CARDBUS)
|
||||
return pci_cardbus_resource_alignment(res);
|
||||
return resource_alignment(res);
|
||||
}
|
||||
|
||||
|
@ -856,6 +856,8 @@ void set_pcie_port_type(struct pci_dev *pdev)
|
||||
pdev->pcie_cap = pos;
|
||||
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16);
|
||||
pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
|
||||
pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16);
|
||||
pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
|
||||
}
|
||||
|
||||
void set_pcie_hotplug_bridge(struct pci_dev *pdev)
|
||||
@ -1326,6 +1328,150 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
|
||||
return nr;
|
||||
}
|
||||
|
||||
static int pcie_find_smpss(struct pci_dev *dev, void *data)
|
||||
{
|
||||
u8 *smpss = data;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return 0;
|
||||
|
||||
/* For PCIE hotplug enabled slots not connected directly to a
|
||||
* PCI-E root port, there can be problems when hotplugging
|
||||
* devices. This is due to the possibility of hotplugging a
|
||||
* device into the fabric with a smaller MPS that the devices
|
||||
* currently running have configured. Modifying the MPS on the
|
||||
* running devices could cause a fatal bus error due to an
|
||||
* incoming frame being larger than the newly configured MPS.
|
||||
* To work around this, the MPS for the entire fabric must be
|
||||
* set to the minimum size. Any devices hotplugged into this
|
||||
* fabric will have the minimum MPS set. If the PCI hotplug
|
||||
* slot is directly connected to the root port and there are not
|
||||
* other devices on the fabric (which seems to be the most
|
||||
* common case), then this is not an issue and MPS discovery
|
||||
* will occur as normal.
|
||||
*/
|
||||
if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
|
||||
dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
|
||||
*smpss = 0;
|
||||
|
||||
if (*smpss > dev->pcie_mpss)
|
||||
*smpss = dev->pcie_mpss;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_write_mps(struct pci_dev *dev, int mps)
|
||||
{
|
||||
int rc, dev_mpss;
|
||||
|
||||
dev_mpss = 128 << dev->pcie_mpss;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
|
||||
if (dev->bus->self) {
|
||||
dev_dbg(&dev->bus->dev, "Bus MPSS %d\n",
|
||||
128 << dev->bus->self->pcie_mpss);
|
||||
|
||||
/* For "MPS Force Max", the assumption is made that
|
||||
* downstream communication will never be larger than
|
||||
* the MRRS. So, the MPS only needs to be configured
|
||||
* for the upstream communication. This being the case,
|
||||
* walk from the top down and set the MPS of the child
|
||||
* to that of the parent bus.
|
||||
*/
|
||||
mps = 128 << dev->bus->self->pcie_mpss;
|
||||
if (mps > dev_mpss)
|
||||
dev_warn(&dev->dev, "MPS configured higher than"
|
||||
" maximum supported by the device. If"
|
||||
" a bus issue occurs, try running with"
|
||||
" pci=pcie_bus_safe.\n");
|
||||
}
|
||||
|
||||
dev->pcie_mpss = ffs(mps) - 8;
|
||||
}
|
||||
|
||||
rc = pcie_set_mps(dev, mps);
|
||||
if (rc)
|
||||
dev_err(&dev->dev, "Failed attempting to set the MPS\n");
|
||||
}
|
||||
|
||||
static void pcie_write_mrrs(struct pci_dev *dev, int mps)
|
||||
{
|
||||
int rc, mrrs;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
|
||||
int dev_mpss = 128 << dev->pcie_mpss;
|
||||
|
||||
/* For Max performance, the MRRS must be set to the largest
|
||||
* supported value. However, it cannot be configured larger
|
||||
* than the MPS the device or the bus can support. This assumes
|
||||
* that the largest MRRS available on the device cannot be
|
||||
* smaller than the device MPSS.
|
||||
*/
|
||||
mrrs = mps < dev_mpss ? mps : dev_mpss;
|
||||
} else
|
||||
/* In the "safe" case, configure the MRRS for fairness on the
|
||||
* bus by making all devices have the same size
|
||||
*/
|
||||
mrrs = mps;
|
||||
|
||||
|
||||
/* MRRS is a R/W register. Invalid values can be written, but a
|
||||
* subsiquent read will verify if the value is acceptable or not.
|
||||
* If the MRRS value provided is not acceptable (e.g., too large),
|
||||
* shrink the value until it is acceptable to the HW.
|
||||
*/
|
||||
while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
|
||||
rc = pcie_set_readrq(dev, mrrs);
|
||||
if (rc)
|
||||
dev_err(&dev->dev, "Failed attempting to set the MRRS\n");
|
||||
|
||||
mrrs /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
||||
{
|
||||
int mps = 128 << *(u8 *)data;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return 0;
|
||||
|
||||
dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
|
||||
pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
|
||||
|
||||
pcie_write_mps(dev, mps);
|
||||
pcie_write_mrrs(dev, mps);
|
||||
|
||||
dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
|
||||
pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down,
|
||||
* parents then children fashion. If this changes, then this code will not
|
||||
* work as designed.
|
||||
*/
|
||||
void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
|
||||
{
|
||||
u8 smpss = mpss;
|
||||
|
||||
if (!bus->self)
|
||||
return;
|
||||
|
||||
if (!pci_is_pcie(bus->self))
|
||||
return;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_SAFE) {
|
||||
pcie_find_smpss(bus->self, &smpss);
|
||||
pci_walk_bus(bus, pcie_find_smpss, &smpss);
|
||||
}
|
||||
|
||||
pcie_bus_configure_set(bus->self, &smpss);
|
||||
pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
|
||||
|
||||
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
|
||||
{
|
||||
unsigned int devfn, pass, max = bus->secondary;
|
||||
|
@ -34,6 +34,7 @@ struct resource_list_x {
|
||||
resource_size_t start;
|
||||
resource_size_t end;
|
||||
resource_size_t add_size;
|
||||
resource_size_t min_align;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
@ -65,7 +66,7 @@ void pci_realloc(void)
|
||||
*/
|
||||
static void add_to_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res,
|
||||
resource_size_t add_size)
|
||||
resource_size_t add_size, resource_size_t min_align)
|
||||
{
|
||||
struct resource_list_x *list = head;
|
||||
struct resource_list_x *ln = list->next;
|
||||
@ -84,13 +85,16 @@ static void add_to_list(struct resource_list_x *head,
|
||||
tmp->end = res->end;
|
||||
tmp->flags = res->flags;
|
||||
tmp->add_size = add_size;
|
||||
tmp->min_align = min_align;
|
||||
list->next = tmp;
|
||||
}
|
||||
|
||||
static void add_to_failed_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res)
|
||||
{
|
||||
add_to_list(head, dev, res, 0);
|
||||
add_to_list(head, dev, res,
|
||||
0 /* dont care */,
|
||||
0 /* dont care */);
|
||||
}
|
||||
|
||||
static void __dev_sort_resources(struct pci_dev *dev,
|
||||
@ -121,18 +125,18 @@ static inline void reset_resource(struct resource *res)
|
||||
}
|
||||
|
||||
/**
|
||||
* adjust_resources_sorted() - satisfy any additional resource requests
|
||||
* reassign_resources_sorted() - satisfy any additional resource requests
|
||||
*
|
||||
* @add_head : head of the list tracking requests requiring additional
|
||||
* @realloc_head : head of the list tracking requests requiring additional
|
||||
* resources
|
||||
* @head : head of the list tracking requests with allocated
|
||||
* resources
|
||||
*
|
||||
* Walk through each element of the add_head and try to procure
|
||||
* Walk through each element of the realloc_head and try to procure
|
||||
* additional resources for the element, provided the element
|
||||
* is in the head list.
|
||||
*/
|
||||
static void adjust_resources_sorted(struct resource_list_x *add_head,
|
||||
static void reassign_resources_sorted(struct resource_list_x *realloc_head,
|
||||
struct resource_list *head)
|
||||
{
|
||||
struct resource *res;
|
||||
@ -141,8 +145,8 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
|
||||
resource_size_t add_size;
|
||||
int idx;
|
||||
|
||||
prev = add_head;
|
||||
for (list = add_head->next; list;) {
|
||||
prev = realloc_head;
|
||||
for (list = realloc_head->next; list;) {
|
||||
res = list->res;
|
||||
/* skip resource that has been reset */
|
||||
if (!res->flags)
|
||||
@ -159,13 +163,17 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
|
||||
|
||||
idx = res - &list->dev->resource[0];
|
||||
add_size=list->add_size;
|
||||
if (!resource_size(res) && add_size) {
|
||||
res->end = res->start + add_size - 1;
|
||||
if(pci_assign_resource(list->dev, idx))
|
||||
if (!resource_size(res)) {
|
||||
res->start = list->start;
|
||||
res->end = res->start + add_size - 1;
|
||||
if(pci_assign_resource(list->dev, idx))
|
||||
reset_resource(res);
|
||||
} else if (add_size) {
|
||||
adjust_resource(res, res->start,
|
||||
resource_size(res) + add_size);
|
||||
} else {
|
||||
resource_size_t align = list->min_align;
|
||||
res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
|
||||
if (pci_reassign_resource(list->dev, idx, add_size, align))
|
||||
dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n",
|
||||
res);
|
||||
}
|
||||
out:
|
||||
tmp = list;
|
||||
@ -210,16 +218,16 @@ static void assign_requested_resources_sorted(struct resource_list *head,
|
||||
}
|
||||
|
||||
static void __assign_resources_sorted(struct resource_list *head,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *realloc_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
/* Satisfy the must-have resource requests */
|
||||
assign_requested_resources_sorted(head, fail_head);
|
||||
|
||||
/* Try to satisfy any additional nice-to-have resource
|
||||
/* Try to satisfy any additional optional resource
|
||||
requests */
|
||||
if (add_head)
|
||||
adjust_resources_sorted(add_head, head);
|
||||
if (realloc_head)
|
||||
reassign_resources_sorted(realloc_head, head);
|
||||
free_list(resource_list, head);
|
||||
}
|
||||
|
||||
@ -235,7 +243,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *realloc_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
@ -245,7 +253,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
__dev_sort_resources(dev, &head);
|
||||
|
||||
__assign_resources_sorted(&head, add_head, fail_head);
|
||||
__assign_resources_sorted(&head, realloc_head, fail_head);
|
||||
}
|
||||
|
||||
void pci_setup_cardbus(struct pci_bus *bus)
|
||||
@ -540,13 +548,27 @@ static resource_size_t calculate_memsize(resource_size_t size,
|
||||
return size;
|
||||
}
|
||||
|
||||
static resource_size_t get_res_add_size(struct resource_list_x *realloc_head,
|
||||
struct resource *res)
|
||||
{
|
||||
struct resource_list_x *list;
|
||||
|
||||
/* check if it is in realloc_head list */
|
||||
for (list = realloc_head->next; list && list->res != res;
|
||||
list = list->next);
|
||||
if (list)
|
||||
return list->add_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pbus_size_io() - size the io window of a given bus
|
||||
*
|
||||
* @bus : the bus
|
||||
* @min_size : the minimum io window that must to be allocated
|
||||
* @add_size : additional optional io window
|
||||
* @add_head : track the additional io window on this list
|
||||
* @realloc_head : track the additional io window on this list
|
||||
*
|
||||
* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
||||
* since these windows have 4K granularity and the IO ranges
|
||||
@ -554,11 +576,12 @@ static resource_size_t calculate_memsize(resource_size_t size,
|
||||
* We must be careful with the ISA aliasing though.
|
||||
*/
|
||||
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
resource_size_t add_size, struct resource_list_x *add_head)
|
||||
resource_size_t add_size, struct resource_list_x *realloc_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
|
||||
unsigned long size = 0, size0 = 0, size1 = 0;
|
||||
resource_size_t children_add_size = 0;
|
||||
|
||||
if (!b_res)
|
||||
return;
|
||||
@ -579,11 +602,16 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
size += r_size;
|
||||
else
|
||||
size1 += r_size;
|
||||
|
||||
if (realloc_head)
|
||||
children_add_size += get_res_add_size(realloc_head, r);
|
||||
}
|
||||
}
|
||||
size0 = calculate_iosize(size, min_size, size1,
|
||||
resource_size(b_res), 4096);
|
||||
size1 = (!add_head || (add_head && !add_size)) ? size0 :
|
||||
if (children_add_size > add_size)
|
||||
add_size = children_add_size;
|
||||
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
|
||||
calculate_iosize(size, min_size+add_size, size1,
|
||||
resource_size(b_res), 4096);
|
||||
if (!size0 && !size1) {
|
||||
@ -598,8 +626,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
b_res->start = 4096;
|
||||
b_res->end = b_res->start + size0 - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
if (size1 > size0 && add_head)
|
||||
add_to_list(add_head, bus->self, b_res, size1-size0);
|
||||
if (size1 > size0 && realloc_head)
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -608,7 +636,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
* @bus : the bus
|
||||
* @min_size : the minimum memory window that must to be allocated
|
||||
* @add_size : additional optional memory window
|
||||
* @add_head : track the additional memory window on this list
|
||||
* @realloc_head : track the additional memory window on this list
|
||||
*
|
||||
* Calculate the size of the bus and minimal alignment which
|
||||
* guarantees that all child resources fit in this size.
|
||||
@ -616,7 +644,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
unsigned long type, resource_size_t min_size,
|
||||
resource_size_t add_size,
|
||||
struct resource_list_x *add_head)
|
||||
struct resource_list_x *realloc_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
resource_size_t min_align, align, size, size0, size1;
|
||||
@ -624,6 +652,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
int order, max_order;
|
||||
struct resource *b_res = find_free_bus_resource(bus, type);
|
||||
unsigned int mem64_mask = 0;
|
||||
resource_size_t children_add_size = 0;
|
||||
|
||||
if (!b_res)
|
||||
return 0;
|
||||
@ -645,6 +674,16 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
if (r->parent || (r->flags & mask) != type)
|
||||
continue;
|
||||
r_size = resource_size(r);
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* put SRIOV requested res to the optional list */
|
||||
if (realloc_head && i >= PCI_IOV_RESOURCES &&
|
||||
i <= PCI_IOV_RESOURCE_END) {
|
||||
r->end = r->start - 1;
|
||||
add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
|
||||
children_add_size += r_size;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* For bridges size != alignment */
|
||||
align = pci_resource_alignment(dev, r);
|
||||
order = __ffs(align) - 20;
|
||||
@ -665,6 +704,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
if (order > max_order)
|
||||
max_order = order;
|
||||
mem64_mask &= r->flags & IORESOURCE_MEM_64;
|
||||
|
||||
if (realloc_head)
|
||||
children_add_size += get_res_add_size(realloc_head, r);
|
||||
}
|
||||
}
|
||||
align = 0;
|
||||
@ -681,7 +723,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
align += aligns[order];
|
||||
}
|
||||
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
|
||||
size1 = (!add_head || (add_head && !add_size)) ? size0 :
|
||||
if (children_add_size > add_size)
|
||||
add_size = children_add_size;
|
||||
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
|
||||
calculate_memsize(size, min_size+add_size, 0,
|
||||
resource_size(b_res), min_align);
|
||||
if (!size0 && !size1) {
|
||||
@ -695,12 +739,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
b_res->start = min_align;
|
||||
b_res->end = size0 + min_align - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
|
||||
if (size1 > size0 && add_head)
|
||||
add_to_list(add_head, bus->self, b_res, size1-size0);
|
||||
if (size1 > size0 && realloc_head)
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pci_bus_size_cardbus(struct pci_bus *bus)
|
||||
unsigned long pci_cardbus_resource_alignment(struct resource *res)
|
||||
{
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
return pci_cardbus_io_size;
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
return pci_cardbus_mem_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_bus_size_cardbus(struct pci_bus *bus,
|
||||
struct resource_list_x *realloc_head)
|
||||
{
|
||||
struct pci_dev *bridge = bus->self;
|
||||
struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
|
||||
@ -711,12 +765,14 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
|
||||
* a fixed amount of bus space for CardBus bridges.
|
||||
*/
|
||||
b_res[0].start = 0;
|
||||
b_res[0].end = pci_cardbus_io_size - 1;
|
||||
b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
|
||||
if (realloc_head)
|
||||
add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */);
|
||||
|
||||
b_res[1].start = 0;
|
||||
b_res[1].end = pci_cardbus_io_size - 1;
|
||||
b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
|
||||
if (realloc_head)
|
||||
add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */);
|
||||
|
||||
/*
|
||||
* Check whether prefetchable memory is supported
|
||||
@ -736,21 +792,31 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
|
||||
*/
|
||||
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
|
||||
b_res[2].start = 0;
|
||||
b_res[2].end = pci_cardbus_mem_size - 1;
|
||||
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
|
||||
if (realloc_head)
|
||||
add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */);
|
||||
|
||||
b_res[3].start = 0;
|
||||
b_res[3].end = pci_cardbus_mem_size - 1;
|
||||
b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
|
||||
if (realloc_head)
|
||||
add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */);
|
||||
} else {
|
||||
b_res[3].start = 0;
|
||||
b_res[3].end = pci_cardbus_mem_size * 2 - 1;
|
||||
b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
|
||||
if (realloc_head)
|
||||
add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */);
|
||||
}
|
||||
|
||||
/* set the size of the resource to zero, so that the resource does not
|
||||
* get assigned during required-resource allocation cycle but gets assigned
|
||||
* during the optional-resource allocation cycle.
|
||||
*/
|
||||
b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1;
|
||||
b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0;
|
||||
}
|
||||
|
||||
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
struct resource_list_x *add_head)
|
||||
struct resource_list_x *realloc_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned long mask, prefmask;
|
||||
@ -763,12 +829,12 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_CARDBUS:
|
||||
pci_bus_size_cardbus(b);
|
||||
pci_bus_size_cardbus(b, realloc_head);
|
||||
break;
|
||||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
default:
|
||||
__pci_bus_size_bridges(b, add_head);
|
||||
__pci_bus_size_bridges(b, realloc_head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -792,7 +858,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
* Follow thru
|
||||
*/
|
||||
default:
|
||||
pbus_size_io(bus, 0, additional_io_size, add_head);
|
||||
pbus_size_io(bus, 0, additional_io_size, realloc_head);
|
||||
/* If the bridge supports prefetchable range, size it
|
||||
separately. If it doesn't, or its prefetchable window
|
||||
has already been allocated by arch code, try
|
||||
@ -800,11 +866,11 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
resources. */
|
||||
mask = IORESOURCE_MEM;
|
||||
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
|
||||
if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, realloc_head))
|
||||
mask = prefmask; /* Success, size non-prefetch only. */
|
||||
else
|
||||
additional_mem_size += additional_mem_size;
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, realloc_head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -816,20 +882,20 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
EXPORT_SYMBOL(pci_bus_size_bridges);
|
||||
|
||||
static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *realloc_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_bus *b;
|
||||
struct pci_dev *dev;
|
||||
|
||||
pbus_assign_resources_sorted(bus, add_head, fail_head);
|
||||
pbus_assign_resources_sorted(bus, realloc_head, fail_head);
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
b = dev->subordinate;
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
__pci_bus_assign_resources(b, add_head, fail_head);
|
||||
__pci_bus_assign_resources(b, realloc_head, fail_head);
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
@ -1039,7 +1105,7 @@ void __init
|
||||
pci_assign_unassigned_resources(void)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
struct resource_list_x add_list; /* list of resources that
|
||||
struct resource_list_x realloc_list; /* list of resources that
|
||||
want additional resources */
|
||||
int tried_times = 0;
|
||||
enum release_type rel_type = leaf_only;
|
||||
@ -1052,7 +1118,7 @@ pci_assign_unassigned_resources(void)
|
||||
|
||||
|
||||
head.next = NULL;
|
||||
add_list.next = NULL;
|
||||
realloc_list.next = NULL;
|
||||
|
||||
pci_try_num = max_depth + 1;
|
||||
printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
|
||||
@ -1062,12 +1128,12 @@ again:
|
||||
/* Depth first, calculate sizes and alignments of all
|
||||
subordinate buses. */
|
||||
list_for_each_entry(bus, &pci_root_buses, node)
|
||||
__pci_bus_size_bridges(bus, &add_list);
|
||||
__pci_bus_size_bridges(bus, &realloc_list);
|
||||
|
||||
/* Depth last, allocate resources and update the hardware. */
|
||||
list_for_each_entry(bus, &pci_root_buses, node)
|
||||
__pci_bus_assign_resources(bus, &add_list, &head);
|
||||
BUG_ON(add_list.next);
|
||||
__pci_bus_assign_resources(bus, &realloc_list, &head);
|
||||
BUG_ON(realloc_list.next);
|
||||
tried_times++;
|
||||
|
||||
/* any device complain? */
|
||||
|
@ -128,16 +128,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
|
||||
}
|
||||
#endif /* CONFIG_PCI_QUIRKS */
|
||||
|
||||
|
||||
|
||||
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
||||
int resno)
|
||||
int resno, resource_size_t size, resource_size_t align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t size, min, align;
|
||||
resource_size_t min;
|
||||
int ret;
|
||||
|
||||
size = resource_size(res);
|
||||
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
|
||||
align = pci_resource_alignment(dev, res);
|
||||
|
||||
/* First, try exact prefetching match.. */
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min,
|
||||
@ -154,73 +154,51 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
|
||||
pcibios_align_resource, dev);
|
||||
}
|
||||
|
||||
if (ret < 0 && dev->fw_addr[resno]) {
|
||||
struct resource *root, *conflict;
|
||||
resource_size_t start, end;
|
||||
|
||||
/*
|
||||
* If we failed to assign anything, let's try the address
|
||||
* where firmware left it. That at least has a chance of
|
||||
* working, which is better than just leaving it disabled.
|
||||
*/
|
||||
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
root = &ioport_resource;
|
||||
else
|
||||
root = &iomem_resource;
|
||||
|
||||
start = res->start;
|
||||
end = res->end;
|
||||
res->start = dev->fw_addr[resno];
|
||||
res->end = res->start + size - 1;
|
||||
dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
|
||||
resno, res);
|
||||
conflict = request_resource_conflict(root, res);
|
||||
if (conflict) {
|
||||
dev_info(&dev->dev,
|
||||
"BAR %d: %pR conflicts with %s %pR\n", resno,
|
||||
res, conflict->name, conflict);
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
} else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||
static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
|
||||
int resno, resource_size_t size)
|
||||
{
|
||||
struct resource *root, *conflict;
|
||||
resource_size_t start, end;
|
||||
int ret = 0;
|
||||
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
root = &ioport_resource;
|
||||
else
|
||||
root = &iomem_resource;
|
||||
|
||||
start = res->start;
|
||||
end = res->end;
|
||||
res->start = dev->fw_addr[resno];
|
||||
res->end = res->start + size - 1;
|
||||
dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
|
||||
resno, res);
|
||||
conflict = request_resource_conflict(root, res);
|
||||
if (conflict) {
|
||||
dev_info(&dev->dev,
|
||||
"BAR %d: %pR conflicts with %s %pR\n", resno,
|
||||
res, conflict->name, conflict);
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t align;
|
||||
struct pci_bus *bus;
|
||||
int ret;
|
||||
char *type;
|
||||
|
||||
align = pci_resource_alignment(dev, res);
|
||||
if (!align) {
|
||||
dev_info(&dev->dev, "BAR %d: can't assign %pR "
|
||||
"(bogus alignment)\n", resno, res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus = dev->bus;
|
||||
while ((ret = __pci_assign_resource(bus, dev, resno))) {
|
||||
if (bus->parent && bus->self->transparent)
|
||||
bus = bus->parent;
|
||||
else
|
||||
bus = NULL;
|
||||
if (bus)
|
||||
continue;
|
||||
break;
|
||||
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
|
||||
if (!bus->parent || !bus->self->transparent)
|
||||
break;
|
||||
bus = bus->parent;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@ -241,6 +219,66 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
|
||||
resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t new_size;
|
||||
int ret;
|
||||
|
||||
if (!res->parent) {
|
||||
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resouce %pR "
|
||||
"\n", resno, res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_size = resource_size(res) + addsize + min_align;
|
||||
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t align, size;
|
||||
struct pci_bus *bus;
|
||||
int ret;
|
||||
|
||||
align = pci_resource_alignment(dev, res);
|
||||
if (!align) {
|
||||
dev_info(&dev->dev, "BAR %d: can't assign %pR "
|
||||
"(bogus alignment)\n", resno, res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus = dev->bus;
|
||||
size = resource_size(res);
|
||||
ret = _pci_assign_resource(dev, resno, size, align);
|
||||
|
||||
/*
|
||||
* If we failed to assign anything, let's try the address
|
||||
* where firmware left it. That at least has a chance of
|
||||
* working, which is better than just leaving it disabled.
|
||||
*/
|
||||
if (ret < 0 && dev->fw_addr[resno])
|
||||
ret = pci_revert_fw_address(res, dev, resno, size);
|
||||
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Sort resources by alignment */
|
||||
void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
|
||||
{
|
||||
|
@ -251,7 +251,8 @@ struct pci_dev {
|
||||
u8 revision; /* PCI revision, low byte of class word */
|
||||
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
|
||||
u8 pcie_cap; /* PCI-E capability offset */
|
||||
u8 pcie_type; /* PCI-E device/port type */
|
||||
u8 pcie_type:4; /* PCI-E device/port type */
|
||||
u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */
|
||||
u8 rom_base_reg; /* which config register controls the ROM */
|
||||
u8 pin; /* which interrupt pin this device uses */
|
||||
|
||||
@ -617,6 +618,16 @@ struct pci_driver {
|
||||
/* these external functions are only available when PCI support is enabled */
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
|
||||
|
||||
enum pcie_bus_config_types {
|
||||
PCIE_BUS_PERFORMANCE,
|
||||
PCIE_BUS_SAFE,
|
||||
PCIE_BUS_PEER2PEER,
|
||||
};
|
||||
|
||||
extern enum pcie_bus_config_types pcie_bus_config;
|
||||
|
||||
extern struct bus_type pci_bus_type;
|
||||
|
||||
/* Do NOT directly access these two variables, unless you are arch specific pci
|
||||
@ -796,10 +807,13 @@ int pcix_get_mmrbc(struct pci_dev *dev);
|
||||
int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
|
||||
int pcie_get_readrq(struct pci_dev *dev);
|
||||
int pcie_set_readrq(struct pci_dev *dev, int rq);
|
||||
int pcie_get_mps(struct pci_dev *dev);
|
||||
int pcie_set_mps(struct pci_dev *dev, int mps);
|
||||
int __pci_reset_function(struct pci_dev *dev);
|
||||
int pci_reset_function(struct pci_dev *dev);
|
||||
void pci_update_resource(struct pci_dev *dev, int resno);
|
||||
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
|
||||
int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
|
||||
int pci_select_bars(struct pci_dev *dev, unsigned long flags);
|
||||
|
||||
/* ROM control related routines */
|
||||
|
Loading…
Reference in New Issue
Block a user