aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/sysfs-pci.txt1
-rw-r--r--arch/x86/kernel/pci-dma.c14
-rw-r--r--arch/x86/pci/common.c8
-rw-r--r--drivers/pci/pci-driver.c2
-rw-r--r--drivers/pci/pci-sysfs.c84
-rw-r--r--include/linux/pci.h1
6 files changed, 79 insertions, 31 deletions
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 5daa2aaec2c5..68ef48839c04 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -36,6 +36,7 @@ files, each with their own function.
36 local_cpus nearby CPU mask (cpumask, ro) 36 local_cpus nearby CPU mask (cpumask, ro)
37 resource PCI resource host addresses (ascii, ro) 37 resource PCI resource host addresses (ascii, ro)
38 resource0..N PCI resource N, if present (binary, mmap) 38 resource0..N PCI resource N, if present (binary, mmap)
39 resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap)
39 rom PCI ROM resource, if present (binary, ro) 40 rom PCI ROM resource, if present (binary, ro)
40 subsystem_device PCI subsystem device (ascii, ro) 41 subsystem_device PCI subsystem device (ascii, ro)
41 subsystem_vendor PCI subsystem vendor (ascii, ro) 42 subsystem_vendor PCI subsystem vendor (ascii, ro)
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index c5ef1af8e79d..dc00a1331ace 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -378,6 +378,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
378 struct page *page; 378 struct page *page;
379 unsigned long dma_mask = 0; 379 unsigned long dma_mask = 0;
380 dma_addr_t bus; 380 dma_addr_t bus;
381 int noretry = 0;
381 382
382 /* ignore region specifiers */ 383 /* ignore region specifiers */
383 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); 384 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
@@ -397,20 +398,25 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
397 if (dev->dma_mask == NULL) 398 if (dev->dma_mask == NULL)
398 return NULL; 399 return NULL;
399 400
400 /* Don't invoke OOM killer */ 401 /* Don't invoke OOM killer or retry in lower 16MB DMA zone */
401 gfp |= __GFP_NORETRY; 402 if (gfp & __GFP_DMA)
403 noretry = 1;
402 404
403#ifdef CONFIG_X86_64 405#ifdef CONFIG_X86_64
404 /* Why <=? Even when the mask is smaller than 4GB it is often 406 /* Why <=? Even when the mask is smaller than 4GB it is often
405 larger than 16MB and in this case we have a chance of 407 larger than 16MB and in this case we have a chance of
406 finding fitting memory in the next higher zone first. If 408 finding fitting memory in the next higher zone first. If
407 not retry with true GFP_DMA. -AK */ 409 not retry with true GFP_DMA. -AK */
408 if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) 410 if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
409 gfp |= GFP_DMA32; 411 gfp |= GFP_DMA32;
412 if (dma_mask < DMA_32BIT_MASK)
413 noretry = 1;
414 }
410#endif 415#endif
411 416
412 again: 417 again:
413 page = dma_alloc_pages(dev, gfp, get_order(size)); 418 page = dma_alloc_pages(dev,
419 noretry ? gfp | __GFP_NORETRY : gfp, get_order(size));
414 if (page == NULL) 420 if (page == NULL)
415 return NULL; 421 return NULL;
416 422
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 6e64aaf00d1d..940185ecaeda 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -328,18 +328,18 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
328#endif 328#endif
329 { 329 {
330 .callback = set_bf_sort, 330 .callback = set_bf_sort,
331 .ident = "HP ProLiant DL385 G2", 331 .ident = "HP ProLiant DL360",
332 .matches = { 332 .matches = {
333 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 333 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
334 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), 334 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"),
335 }, 335 },
336 }, 336 },
337 { 337 {
338 .callback = set_bf_sort, 338 .callback = set_bf_sort,
339 .ident = "HP ProLiant DL585 G2", 339 .ident = "HP ProLiant DL380",
340 .matches = { 340 .matches = {
341 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 341 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
342 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), 342 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"),
343 }, 343 },
344 }, 344 },
345 {} 345 {}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 72cf61ed8f96..e1637bd82b8e 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -181,7 +181,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
181 any need to change it. */ 181 any need to change it. */
182 struct mempolicy *oldpol; 182 struct mempolicy *oldpol;
183 cpumask_t oldmask = current->cpus_allowed; 183 cpumask_t oldmask = current->cpus_allowed;
184 int node = pcibus_to_node(dev->bus); 184 int node = dev_to_node(&dev->dev);
185 185
186 if (node >= 0) { 186 if (node >= 0) {
187 node_to_cpumask_ptr(nodecpumask, node); 187 node_to_cpumask_ptr(nodecpumask, node);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 271d41cc05ab..9ec7d3977a82 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -489,13 +489,14 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
489 * @kobj: kobject for mapping 489 * @kobj: kobject for mapping
490 * @attr: struct bin_attribute for the file being mapped 490 * @attr: struct bin_attribute for the file being mapped
491 * @vma: struct vm_area_struct passed into the mmap 491 * @vma: struct vm_area_struct passed into the mmap
492 * @write_combine: 1 for write_combine mapping
492 * 493 *
493 * Use the regular PCI mapping routines to map a PCI resource into userspace. 494 * Use the regular PCI mapping routines to map a PCI resource into userspace.
494 * FIXME: write combining? maybe automatic for prefetchable regions? 495 * FIXME: write combining? maybe automatic for prefetchable regions?
495 */ 496 */
496static int 497static int
497pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, 498pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
498 struct vm_area_struct *vma) 499 struct vm_area_struct *vma, int write_combine)
499{ 500{
500 struct pci_dev *pdev = to_pci_dev(container_of(kobj, 501 struct pci_dev *pdev = to_pci_dev(container_of(kobj,
501 struct device, kobj)); 502 struct device, kobj));
@@ -518,7 +519,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
518 vma->vm_pgoff += start >> PAGE_SHIFT; 519 vma->vm_pgoff += start >> PAGE_SHIFT;
519 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; 520 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
520 521
521 return pci_mmap_page_range(pdev, vma, mmap_type, 0); 522 return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
523}
524
525static int
526pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr,
527 struct vm_area_struct *vma)
528{
529 return pci_mmap_resource(kobj, attr, vma, 0);
530}
531
532static int
533pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr,
534 struct vm_area_struct *vma)
535{
536 return pci_mmap_resource(kobj, attr, vma, 1);
522} 537}
523 538
524/** 539/**
@@ -541,9 +556,46 @@ pci_remove_resource_files(struct pci_dev *pdev)
541 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); 556 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
542 kfree(res_attr); 557 kfree(res_attr);
543 } 558 }
559
560 res_attr = pdev->res_attr_wc[i];
561 if (res_attr) {
562 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
563 kfree(res_attr);
564 }
544 } 565 }
545} 566}
546 567
568static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
569{
570 /* allocate attribute structure, piggyback attribute name */
571 int name_len = write_combine ? 13 : 10;
572 struct bin_attribute *res_attr;
573 int retval;
574
575 res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
576 if (res_attr) {
577 char *res_attr_name = (char *)(res_attr + 1);
578
579 if (write_combine) {
580 pdev->res_attr_wc[num] = res_attr;
581 sprintf(res_attr_name, "resource%d_wc", num);
582 res_attr->mmap = pci_mmap_resource_wc;
583 } else {
584 pdev->res_attr[num] = res_attr;
585 sprintf(res_attr_name, "resource%d", num);
586 res_attr->mmap = pci_mmap_resource_uc;
587 }
588 res_attr->attr.name = res_attr_name;
589 res_attr->attr.mode = S_IRUSR | S_IWUSR;
590 res_attr->size = pci_resource_len(pdev, num);
591 res_attr->private = &pdev->resource[num];
592 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
593 } else
594 retval = -ENOMEM;
595
596 return retval;
597}
598
547/** 599/**
548 * pci_create_resource_files - create resource files in sysfs for @dev 600 * pci_create_resource_files - create resource files in sysfs for @dev
549 * @dev: dev in question 601 * @dev: dev in question
@@ -557,31 +609,19 @@ static int pci_create_resource_files(struct pci_dev *pdev)
557 609
558 /* Expose the PCI resources from this device as files */ 610 /* Expose the PCI resources from this device as files */
559 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 611 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
560 struct bin_attribute *res_attr;
561 612
562 /* skip empty resources */ 613 /* skip empty resources */
563 if (!pci_resource_len(pdev, i)) 614 if (!pci_resource_len(pdev, i))
564 continue; 615 continue;
565 616
566 /* allocate attribute structure, piggyback attribute name */ 617 retval = pci_create_attr(pdev, i, 0);
567 res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); 618 /* for prefetchable resources, create a WC mappable file */
568 if (res_attr) { 619 if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH)
569 char *res_attr_name = (char *)(res_attr + 1); 620 retval = pci_create_attr(pdev, i, 1);
570 621
571 pdev->res_attr[i] = res_attr; 622 if (retval) {
572 sprintf(res_attr_name, "resource%d", i); 623 pci_remove_resource_files(pdev);
573 res_attr->attr.name = res_attr_name; 624 return retval;
574 res_attr->attr.mode = S_IRUSR | S_IWUSR;
575 res_attr->size = pci_resource_len(pdev, i);
576 res_attr->mmap = pci_mmap_resource;
577 res_attr->private = &pdev->resource[i];
578 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
579 if (retval) {
580 pci_remove_resource_files(pdev);
581 return retval;
582 }
583 } else {
584 return -ENOMEM;
585 } 625 }
586 } 626 }
587 return 0; 627 return 0;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 509159bcd4e7..d18b1dd49fab 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -206,6 +206,7 @@ struct pci_dev {
206 struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ 206 struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
207 int rom_attr_enabled; /* has display of the rom attribute been enabled? */ 207 int rom_attr_enabled; /* has display of the rom attribute been enabled? */
208 struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ 208 struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
209 struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
209#ifdef CONFIG_PCI_MSI 210#ifdef CONFIG_PCI_MSI
210 struct list_head msi_list; 211 struct list_head msi_list;
211#endif 212#endif