diff options
| author | venkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com> | 2008-03-18 17:00:22 -0700 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-06-12 10:12:42 +0200 | 
| commit | 45aec1ae72fc592f231e9e73ed9ed4d10cfbc0b5 (patch) | |
| tree | 758243a7f11d90ac4469144466be6ebb0272a8b4 /drivers/pci/pci-sysfs.c | |
| parent | b7f09ae583c49d28b2796d2fa5893dcf822e3a10 (diff) | |
x86: PAT export resource_wc in pci sysfs
For the ranges with IORESOURCE_PREFETCH, export a new resource_wc interface in
pci /sysfs along with resource (which is uncached).
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
| -rw-r--r-- | drivers/pci/pci-sysfs.c | 84 | 
1 files changed, 62 insertions, 22 deletions
| 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,   * @kobj: kobject for mapping   * @attr: struct bin_attribute for the file being mapped   * @vma: struct vm_area_struct passed into the mmap + * @write_combine: 1 for write_combine mapping   *   * Use the regular PCI mapping routines to map a PCI resource into userspace.   * FIXME: write combining?  maybe automatic for prefetchable regions?   */  static int  pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, -		  struct vm_area_struct *vma) +		  struct vm_area_struct *vma, int write_combine)  {  	struct pci_dev *pdev = to_pci_dev(container_of(kobj,  						       struct device, kobj)); @@ -518,7 +519,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,  	vma->vm_pgoff += start >> PAGE_SHIFT;  	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; -	return pci_mmap_page_range(pdev, vma, mmap_type, 0); +	return pci_mmap_page_range(pdev, vma, mmap_type, write_combine); +} + +static int +pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr, +		     struct vm_area_struct *vma) +{ +	return pci_mmap_resource(kobj, attr, vma, 0); +} + +static int +pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr, +		     struct vm_area_struct *vma) +{ +	return pci_mmap_resource(kobj, attr, vma, 1);  }  /** @@ -541,9 +556,46 @@ pci_remove_resource_files(struct pci_dev *pdev)  			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);  			kfree(res_attr);  		} + +		res_attr = pdev->res_attr_wc[i]; +		if (res_attr) { +			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr); +			kfree(res_attr); +		}  	}  } +static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) +{ +	/* allocate attribute structure, piggyback attribute name */ +	int name_len = write_combine ? 13 : 10; +	struct bin_attribute *res_attr; +	int retval; + +	res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC); +	if (res_attr) { +		char *res_attr_name = (char *)(res_attr + 1); + +		if (write_combine) { +			pdev->res_attr_wc[num] = res_attr; +			sprintf(res_attr_name, "resource%d_wc", num); +			res_attr->mmap = pci_mmap_resource_wc; +		} else { +			pdev->res_attr[num] = res_attr; +			sprintf(res_attr_name, "resource%d", num); +			res_attr->mmap = pci_mmap_resource_uc; +		} +		res_attr->attr.name = res_attr_name; +		res_attr->attr.mode = S_IRUSR | S_IWUSR; +		res_attr->size = pci_resource_len(pdev, num); +		res_attr->private = &pdev->resource[num]; +		retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); +	} else +		retval = -ENOMEM; + +	return retval; +} +  /**   * pci_create_resource_files - create resource files in sysfs for @dev   * @dev: dev in question @@ -557,31 +609,19 @@ static int pci_create_resource_files(struct pci_dev *pdev)  	/* Expose the PCI resources from this device as files */  	for (i = 0; i < PCI_ROM_RESOURCE; i++) { -		struct bin_attribute *res_attr;  		/* skip empty resources */  		if (!pci_resource_len(pdev, i))  			continue; -		/* allocate attribute structure, piggyback attribute name */ -		res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); -		if (res_attr) { -			char *res_attr_name = (char *)(res_attr + 1); - -			pdev->res_attr[i] = res_attr; -			sprintf(res_attr_name, "resource%d", i); -			res_attr->attr.name = res_attr_name; -			res_attr->attr.mode = S_IRUSR | S_IWUSR; -			res_attr->size = pci_resource_len(pdev, i); -			res_attr->mmap = pci_mmap_resource; -			res_attr->private = &pdev->resource[i]; -			retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); -			if (retval) { -				pci_remove_resource_files(pdev); -				return retval; -			} -		} else { -			return -ENOMEM; +		retval = pci_create_attr(pdev, i, 0); +		/* for prefetchable resources, create a WC mappable file */ +		if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH) +			retval = pci_create_attr(pdev, i, 1); + +		if (retval) { +			pci_remove_resource_files(pdev); +			return retval;  		}  	}  	return 0; | 
