aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8310dc2f943b..a35a8b2ba631 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -20,6 +20,8 @@
20#include <linux/pm_wakeup.h> 20#include <linux/pm_wakeup.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <asm/dma.h> /* isa_dma_bridge_buggy */ 22#include <asm/dma.h> /* isa_dma_bridge_buggy */
23#include <linux/device.h>
24#include <asm/setup.h>
23#include "pci.h" 25#include "pci.h"
24 26
25unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; 27unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT;
@@ -2370,6 +2372,121 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
2370 return 0; 2372 return 0;
2371} 2373}
2372 2374
2375#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
2376static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
2377spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED;
2378
2379/**
2380 * pci_specified_resource_alignment - get resource alignment specified by user.
2381 * @dev: the PCI device to get
2382 *
2383 * RETURNS: Resource alignment if it is specified.
2384 * Zero if it is not specified.
2385 */
2386resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
2387{
2388 int seg, bus, slot, func, align_order, count;
2389 resource_size_t align = 0;
2390 char *p;
2391
2392 spin_lock(&resource_alignment_lock);
2393 p = resource_alignment_param;
2394 while (*p) {
2395 count = 0;
2396 if (sscanf(p, "%d%n", &align_order, &count) == 1 &&
2397 p[count] == '@') {
2398 p += count + 1;
2399 } else {
2400 align_order = -1;
2401 }
2402 if (sscanf(p, "%x:%x:%x.%x%n",
2403 &seg, &bus, &slot, &func, &count) != 4) {
2404 seg = 0;
2405 if (sscanf(p, "%x:%x.%x%n",
2406 &bus, &slot, &func, &count) != 3) {
2407 /* Invalid format */
2408 printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n",
2409 p);
2410 break;
2411 }
2412 }
2413 p += count;
2414 if (seg == pci_domain_nr(dev->bus) &&
2415 bus == dev->bus->number &&
2416 slot == PCI_SLOT(dev->devfn) &&
2417 func == PCI_FUNC(dev->devfn)) {
2418 if (align_order == -1) {
2419 align = PAGE_SIZE;
2420 } else {
2421 align = 1 << align_order;
2422 }
2423 /* Found */
2424 break;
2425 }
2426 if (*p != ';' && *p != ',') {
2427 /* End of param or invalid format */
2428 break;
2429 }
2430 p++;
2431 }
2432 spin_unlock(&resource_alignment_lock);
2433 return align;
2434}
2435
2436/**
2437 * pci_is_reassigndev - check if specified PCI is target device to reassign
2438 * @dev: the PCI device to check
2439 *
2440 * RETURNS: non-zero for PCI device is a target device to reassign,
2441 * or zero is not.
2442 */
2443int pci_is_reassigndev(struct pci_dev *dev)
2444{
2445 return (pci_specified_resource_alignment(dev) != 0);
2446}
2447
2448ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
2449{
2450 if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)
2451 count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
2452 spin_lock(&resource_alignment_lock);
2453 strncpy(resource_alignment_param, buf, count);
2454 resource_alignment_param[count] = '\0';
2455 spin_unlock(&resource_alignment_lock);
2456 return count;
2457}
2458
2459ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
2460{
2461 size_t count;
2462 spin_lock(&resource_alignment_lock);
2463 count = snprintf(buf, size, "%s", resource_alignment_param);
2464 spin_unlock(&resource_alignment_lock);
2465 return count;
2466}
2467
2468static ssize_t pci_resource_alignment_show(struct bus_type *bus, char *buf)
2469{
2470 return pci_get_resource_alignment_param(buf, PAGE_SIZE);
2471}
2472
2473static ssize_t pci_resource_alignment_store(struct bus_type *bus,
2474 const char *buf, size_t count)
2475{
2476 return pci_set_resource_alignment_param(buf, count);
2477}
2478
2479BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
2480 pci_resource_alignment_store);
2481
2482static int __init pci_resource_alignment_sysfs_init(void)
2483{
2484 return bus_create_file(&pci_bus_type,
2485 &bus_attr_resource_alignment);
2486}
2487
2488late_initcall(pci_resource_alignment_sysfs_init);
2489
2373static void __devinit pci_no_domains(void) 2490static void __devinit pci_no_domains(void)
2374{ 2491{
2375#ifdef CONFIG_PCI_DOMAINS 2492#ifdef CONFIG_PCI_DOMAINS
@@ -2418,6 +2535,9 @@ static int __init pci_setup(char *str)
2418 pci_cardbus_io_size = memparse(str + 9, &str); 2535 pci_cardbus_io_size = memparse(str + 9, &str);
2419 } else if (!strncmp(str, "cbmemsize=", 10)) { 2536 } else if (!strncmp(str, "cbmemsize=", 10)) {
2420 pci_cardbus_mem_size = memparse(str + 10, &str); 2537 pci_cardbus_mem_size = memparse(str + 10, &str);
2538 } else if (!strncmp(str, "resource_alignment=", 19)) {
2539 pci_set_resource_alignment_param(str + 19,
2540 strlen(str + 19));
2421 } else { 2541 } else {
2422 printk(KERN_ERR "PCI: Unknown option `%s'\n", 2542 printk(KERN_ERR "PCI: Unknown option `%s'\n",
2423 str); 2543 str);