summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-02-16 00:40:31 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2012-02-24 17:37:26 -0500
commit2069ecfbe14ebd71a6f98e8a00724e9adf4fe4ee (patch)
tree5a0328d6e545a6488e85face05b0a4d78676bedf /drivers/pci/pci.c
parent8474ecd9231434d71a39cd1ba118629e1b036137 (diff)
PCI: Move "pci reassigndev resource alignment" out of quirks.c
This isn't really a quirk; calling it directly from pci_add_device makes more sense. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e9f9dc183cfc..b832f0fece97 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3694,6 +3694,68 @@ int pci_is_reassigndev(struct pci_dev *dev)
3694 return (pci_specified_resource_alignment(dev) != 0); 3694 return (pci_specified_resource_alignment(dev) != 0);
3695} 3695}
3696 3696
3697/*
3698 * This function disables memory decoding and releases memory resources
3699 * of the device specified by kernel's boot parameter 'pci=resource_alignment='.
3700 * It also rounds up size to specified alignment.
3701 * Later on, the kernel will assign page-aligned memory resource back
3702 * to the device.
3703 */
3704void pci_reassigndev_resource_alignment(struct pci_dev *dev)
3705{
3706 int i;
3707 struct resource *r;
3708 resource_size_t align, size;
3709 u16 command;
3710
3711 if (!pci_is_reassigndev(dev))
3712 return;
3713
3714 if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
3715 (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
3716 dev_warn(&dev->dev,
3717 "Can't reassign resources to host bridge.\n");
3718 return;
3719 }
3720
3721 dev_info(&dev->dev,
3722 "Disabling memory decoding and releasing memory resources.\n");
3723 pci_read_config_word(dev, PCI_COMMAND, &command);
3724 command &= ~PCI_COMMAND_MEMORY;
3725 pci_write_config_word(dev, PCI_COMMAND, command);
3726
3727 align = pci_specified_resource_alignment(dev);
3728 for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
3729 r = &dev->resource[i];
3730 if (!(r->flags & IORESOURCE_MEM))
3731 continue;
3732 size = resource_size(r);
3733 if (size < align) {
3734 size = align;
3735 dev_info(&dev->dev,
3736 "Rounding up size of resource #%d to %#llx.\n",
3737 i, (unsigned long long)size);
3738 }
3739 r->end = size - 1;
3740 r->start = 0;
3741 }
3742 /* Need to disable bridge's resource window,
3743 * to enable the kernel to reassign new resource
3744 * window later on.
3745 */
3746 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
3747 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
3748 for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
3749 r = &dev->resource[i];
3750 if (!(r->flags & IORESOURCE_MEM))
3751 continue;
3752 r->end = resource_size(r) - 1;
3753 r->start = 0;
3754 }
3755 pci_disable_bridge_window(dev);
3756 }
3757}
3758
3697ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) 3759ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
3698{ 3760{
3699 if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) 3761 if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)