All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiang Liu <jiang.liu@linux.intel.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Thomas Gleixner <tglx@linutronix.de>,
	Yinghai Lu <yinghai@kernel.org>, Borislav Petkov <bp@alien8.de>,
	Lv Zheng <lv.zheng@intel.com>, Ingo Molnar <mingo@redhat.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	x86@kernel.org, Tony Luck <tony.luck@intel.com>,
	linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
	linux-acpi@vger.kernel.org
Subject: Re: [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
Date: Thu, 29 Jan 2015 11:00:12 +0800	[thread overview]
Message-ID: <54C9A23C.4080807@linux.intel.com> (raw)
In-Reply-To: <20150128233700.GE17623@google.com>

On 2015/1/29 7:37, Bjorn Helgaas wrote:
> On Wed, Jan 28, 2015 at 06:57:37PM +0800, Jiang Liu wrote:
>> Use common ACPI resource discovery interfaces to simplify PCI host bridge
>> resource enumeration.
>>
>> It also fixes the issue discovered by Thomas that function setup_resource()
>> incorrectly validates IO port resources against iomem_resource.
> 
> Is it possible to split this bug fix into its own separate patch?  Mixing
> things together makes git archaeology harder because it hides tiny bug
> fixes inside big changes.
Hi Bjorn,
	I will split out a patch to fix the issue in next version.
Thanks!
Gerry

> 
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
>>  1 file changed, 94 insertions(+), 202 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index bb98afd0591e..3404ea703ecc 100644
>> --- a/arch/x86/pci/acpi.c
>> +++ b/arch/x86/pci/acpi.c
>> @@ -10,9 +10,6 @@
>>  struct pci_root_info {
>>  	struct acpi_device *bridge;
>>  	char name[16];
>> -	unsigned int res_num;
>> -	struct resource *res;
>> -	resource_size_t *res_offset;
>>  	struct pci_sysdata sd;
>>  #ifdef	CONFIG_PCI_MMCONFIG
>>  	bool mcfg_added;
>> @@ -218,130 +215,44 @@ static void teardown_mcfg_map(struct pci_root_info *info)
>>  }
>>  #endif
>>  
>> -static acpi_status resource_to_addr(struct acpi_resource *resource,
>> -				    struct acpi_resource_address64 *addr)
>> -{
>> -	acpi_status status;
>> -	struct acpi_resource_memory24 *memory24;
>> -	struct acpi_resource_memory32 *memory32;
>> -	struct acpi_resource_fixed_memory32 *fixed_memory32;
>> -
>> -	memset(addr, 0, sizeof(*addr));
>> -	switch (resource->type) {
>> -	case ACPI_RESOURCE_TYPE_MEMORY24:
>> -		memory24 = &resource->data.memory24;
>> -		addr->resource_type = ACPI_MEMORY_RANGE;
>> -		addr->address.minimum = memory24->minimum;
>> -		addr->address.address_length = memory24->address_length;
>> -		addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
>> -		return AE_OK;
>> -	case ACPI_RESOURCE_TYPE_MEMORY32:
>> -		memory32 = &resource->data.memory32;
>> -		addr->resource_type = ACPI_MEMORY_RANGE;
>> -		addr->address.minimum = memory32->minimum;
>> -		addr->address.address_length = memory32->address_length;
>> -		addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
>> -		return AE_OK;
>> -	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
>> -		fixed_memory32 = &resource->data.fixed_memory32;
>> -		addr->resource_type = ACPI_MEMORY_RANGE;
>> -		addr->address.minimum = fixed_memory32->address;
>> -		addr->address.address_length = fixed_memory32->address_length;
>> -		addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
>> -		return AE_OK;
>> -	case ACPI_RESOURCE_TYPE_ADDRESS16:
>> -	case ACPI_RESOURCE_TYPE_ADDRESS32:
>> -	case ACPI_RESOURCE_TYPE_ADDRESS64:
>> -		status = acpi_resource_to_address64(resource, addr);
>> -		if (ACPI_SUCCESS(status) &&
>> -		    (addr->resource_type == ACPI_MEMORY_RANGE ||
>> -		    addr->resource_type == ACPI_IO_RANGE) &&
>> -		    addr->address.address_length > 0) {
>> -			return AE_OK;
>> -		}
>> -		break;
>> -	}
>> -	return AE_ERROR;
>> -}
>> -
>> -static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
>> +static void validate_resources(struct device *dev, struct list_head *crs_res,
>> +			       unsigned long type)
>>  {
>> -	struct pci_root_info *info = data;
>> -	struct acpi_resource_address64 addr;
>> -	acpi_status status;
>> -
>> -	status = resource_to_addr(acpi_res, &addr);
>> -	if (ACPI_SUCCESS(status))
>> -		info->res_num++;
>> -	return AE_OK;
>> -}
>> -
>> -static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
>> -{
>> -	struct pci_root_info *info = data;
>> -	struct resource *res;
>> -	struct acpi_resource_address64 addr;
>> -	acpi_status status;
>> -	unsigned long flags;
>> -	u64 start, orig_end, end;
>> -
>> -	status = resource_to_addr(acpi_res, &addr);
>> -	if (!ACPI_SUCCESS(status))
>> -		return AE_OK;
>> -
>> -	if (addr.resource_type == ACPI_MEMORY_RANGE) {
>> -		flags = IORESOURCE_MEM;
>> -		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
>> -			flags |= IORESOURCE_PREFETCH;
>> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
>> -		flags = IORESOURCE_IO;
>> -	} else
>> -		return AE_OK;
>> -
>> -	start = addr.address.minimum + addr.address.translation_offset;
>> -	orig_end = end = addr.address.maximum + addr.address.translation_offset;
>> -
>> -	/* Exclude non-addressable range or non-addressable portion of range */
>> -	end = min(end, (u64)iomem_resource.end);
>> -	if (end <= start) {
>> -		dev_info(&info->bridge->dev,
>> -			"host bridge window [%#llx-%#llx] "
>> -			"(ignored, not CPU addressable)\n", start, orig_end);
>> -		return AE_OK;
>> -	} else if (orig_end != end) {
>> -		dev_info(&info->bridge->dev,
>> -			"host bridge window [%#llx-%#llx] "
>> -			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
>> -			start, orig_end, end + 1, orig_end);
>> -	}
>> +	LIST_HEAD(list);
>> +	struct resource *res1, *res2, *root = NULL;
>> +	struct resource_list_entry *tmp, *entry, *entry2;
>>  
>> -	res = &info->res[info->res_num];
>> -	res->name = info->name;
>> -	res->flags = flags;
>> -	res->start = start;
>> -	res->end = end;
>> -	info->res_offset[info->res_num] = addr.address.translation_offset;
>> -	info->res_num++;
>> +	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
>> +	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
>>  
>> -	if (!pci_use_crs)
>> -		dev_printk(KERN_DEBUG, &info->bridge->dev,
>> -			   "host bridge window %pR (ignored)\n", res);
>> +	list_splice_init(crs_res, &list);
>> +	resource_list_for_each_entry_safe(entry, tmp, &list) {
>> +		bool free = false;
>> +		resource_size_t end;
>>  
>> -	return AE_OK;
>> -}
>> -
>> -static void coalesce_windows(struct pci_root_info *info, unsigned long type)
>> -{
>> -	int i, j;
>> -	struct resource *res1, *res2;
>> -
>> -	for (i = 0; i < info->res_num; i++) {
>> -		res1 = &info->res[i];
>> +		res1 = entry->res;
>>  		if (!(res1->flags & type))
>> -			continue;
>> +			goto next;
>> +
>> +		/* Exclude non-addressable range or non-addressable portion */
>> +		end = min(res1->end, root->end);
>> +		if (end <= res1->start) {
>> +			dev_info(dev, "host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end);
>> +			free = true;
>> +			goto next;
>> +		} else if (res1->end != end) {
>> +			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end,
>> +				 (unsigned long long)end + 1,
>> +				 (unsigned long long)res1->end);
>> +			res1->end = end;
>> +		}
>>  
>> -		for (j = i + 1; j < info->res_num; j++) {
>> -			res2 = &info->res[j];
>> +		resource_list_for_each_entry(entry2, crs_res) {
>> +			res2 = entry2->res;
>>  			if (!(res2->flags & type))
>>  				continue;
>>  
>> @@ -353,118 +264,92 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
>>  			if (resource_overlaps(res1, res2)) {
>>  				res2->start = min(res1->start, res2->start);
>>  				res2->end = max(res1->end, res2->end);
>> -				dev_info(&info->bridge->dev,
>> -					 "host bridge window expanded to %pR; %pR ignored\n",
>> +				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
>>  					 res2, res1);
>> -				res1->flags = 0;
>> +				free = true;
>> +				goto next;
>>  			}
>>  		}
>> +
>> +next:
>> +		resource_list_del(entry);
>> +		if (free)
>> +			resource_list_free_entry(entry);
>> +		else
>> +			resource_list_add_tail(entry, crs_res);
>>  	}
>>  }
>>  
>>  static void add_resources(struct pci_root_info *info,
>> -			  struct list_head *resources)
>> +			  struct list_head *resources,
>> +			  struct list_head *crs_res)
>>  {
>> -	int i;
>> -	struct resource *res, *root, *conflict;
>> -
>> -	coalesce_windows(info, IORESOURCE_MEM);
>> -	coalesce_windows(info, IORESOURCE_IO);
>> +	struct resource_list_entry *entry, *tmp;
>> +	struct resource *res, *conflict, *root = NULL;
>>  
>> -	for (i = 0; i < info->res_num; i++) {
>> -		res = &info->res[i];
>> +	validate_resources(&info->bridge->dev, crs_res, IORESOURCE_MEM);
>> +	validate_resources(&info->bridge->dev, crs_res, IORESOURCE_IO);
>>  
>> +	resource_list_for_each_entry_safe(entry, tmp, crs_res) {
>> +		res = entry->res;
>>  		if (res->flags & IORESOURCE_MEM)
>>  			root = &iomem_resource;
>>  		else if (res->flags & IORESOURCE_IO)
>>  			root = &ioport_resource;
>>  		else
>> -			continue;
>> +			BUG_ON(res);
>>  
>>  		conflict = insert_resource_conflict(root, res);
>> -		if (conflict)
>> +		if (conflict) {
>>  			dev_info(&info->bridge->dev,
>>  				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
>>  				 res, conflict->name, conflict);
>> -		else
>> -			pci_add_resource_offset(resources, res,
>> -					info->res_offset[i]);
>> +			resource_list_destroy_entry(entry);
>> +		}
>>  	}
>> -}
>>  
>> -static void free_pci_root_info_res(struct pci_root_info *info)
>> -{
>> -	kfree(info->res);
>> -	info->res = NULL;
>> -	kfree(info->res_offset);
>> -	info->res_offset = NULL;
>> -	info->res_num = 0;
>> +	list_splice_tail(crs_res, resources);
>>  }
>>  
>> -static void __release_pci_root_info(struct pci_root_info *info)
>> +static void release_pci_root_info(struct pci_host_bridge *bridge)
>>  {
>> -	int i;
>>  	struct resource *res;
>> +	struct resource_list_entry *entry;
>> +	struct pci_root_info *info = bridge->release_data;
>>  
>> -	for (i = 0; i < info->res_num; i++) {
>> -		res = &info->res[i];
>> -
>> -		if (!res->parent)
>> -			continue;
>> -
>> -		if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
>> -			continue;
>> -
>> -		release_resource(res);
>> +	resource_list_for_each_entry(entry, &bridge->windows) {
>> +		res = entry->res;
>> +		if (res->parent &&
>> +		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
>> +			release_resource(res);
>>  	}
>>  
>> -	free_pci_root_info_res(info);
>> -
>>  	teardown_mcfg_map(info);
>> -
>>  	kfree(info);
>>  }
>>  
>> -static void release_pci_root_info(struct pci_host_bridge *bridge)
>> -{
>> -	struct pci_root_info *info = bridge->release_data;
>> -
>> -	__release_pci_root_info(info);
>> -}
>> -
>>  static void probe_pci_root_info(struct pci_root_info *info,
>>  				struct acpi_device *device,
>> -				int busnum, int domain)
>> +				int busnum, int domain,
>> +				struct list_head *list)
>>  {
>> -	size_t size;
>> +	int ret;
>> +	struct resource_list_entry *entry;
>>  
>>  	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
>>  	info->bridge = device;
>> -
>> -	info->res_num = 0;
>> -	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
>> -				info);
>> -	if (!info->res_num)
>> -		return;
>> -
>> -	size = sizeof(*info->res) * info->res_num;
>> -	info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
>> -	if (!info->res) {
>> -		info->res_num = 0;
>> -		return;
>> -	}
>> -
>> -	size = sizeof(*info->res_offset) * info->res_num;
>> -	info->res_num = 0;
>> -	info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
>> -	if (!info->res_offset) {
>> -		kfree(info->res);
>> -		info->res = NULL;
>> -		return;
>> -	}
>> -
>> -	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
>> -				info);
>> +	ret = acpi_dev_get_resources(device, list,
>> +				     acpi_dev_filter_resource_type_cb,
>> +				     (void *)(IORESOURCE_IO | IORESOURCE_MEM));
>> +	if (ret < 0)
>> +		dev_warn(&device->dev,
>> +			 "failed to parse _CRS method, error code %d.\n", ret);
>> +	else if (ret == 0)
>> +		dev_dbg(&device->dev,
>> +			"no IO and memory resources present in _CRS.\n");
>> +	else
>> +		resource_list_for_each_entry(entry, list)
>> +			entry->res->name = info->name;
>>  }
>>  
>>  struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>> @@ -473,6 +358,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>  	struct pci_root_info *info;
>>  	int domain = root->segment;
>>  	int busnum = root->secondary.start;
>> +	struct resource_list_entry *res_entry;
>> +	LIST_HEAD(crs_res);
>>  	LIST_HEAD(resources);
>>  	struct pci_bus *bus;
>>  	struct pci_sysdata *sd;
>> @@ -520,18 +407,22 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>  		memcpy(bus->sysdata, sd, sizeof(*sd));
>>  		kfree(info);
>>  	} else {
>> -		probe_pci_root_info(info, device, busnum, domain);
>> -
>>  		/* insert busn res at first */
>>  		pci_add_resource(&resources,  &root->secondary);
>> +
>>  		/*
>>  		 * _CRS with no apertures is normal, so only fall back to
>>  		 * defaults or native bridge info if we're ignoring _CRS.
>>  		 */
>> -		if (pci_use_crs)
>> -			add_resources(info, &resources);
>> -		else {
>> -			free_pci_root_info_res(info);
>> +		probe_pci_root_info(info, device, busnum, domain, &crs_res);
>> +		if (pci_use_crs) {
>> +			add_resources(info, &resources, &crs_res);
>> +		} else {
>> +			resource_list_for_each_entry(res_entry, &crs_res)
>> +				dev_printk(KERN_DEBUG, &device->dev,
>> +					   "host bridge window %pR (ignored)\n",
>> +					   res_entry->res);
>> +			resource_list_free(&crs_res);
>>  			x86_pci_root_bus_resources(busnum, &resources);
>>  		}
>>  
>> @@ -546,8 +437,9 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>  				to_pci_host_bridge(bus->bridge),
>>  				release_pci_root_info, info);
>>  		} else {
>> -			pci_free_resource_list(&resources);
>> -			__release_pci_root_info(info);
>> +			resource_list_free(&resources);
>> +			teardown_mcfg_map(info);
>> +			kfree(info);
>>  		}
>>  	}
>>  
>> -- 
>> 1.7.10.4
>>

  reply	other threads:[~2015-01-29  3:00 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
2015-01-28 10:57 ` [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures Jiang Liu
2015-01-28 10:57 ` Jiang Liu
2015-01-28 10:57   ` Jiang Liu
2015-01-28 10:57   ` Jiang Liu
2015-01-28 10:57 ` [Patch v2 02/22] ACPI: Remove redundant check in function acpi_dev_resource_address_space() Jiang Liu
2015-01-28 10:57 ` [Patch v2 03/22] ACPI: Implement proper length checks for mem resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 04/22] ACPI: Use the length check for io resources as well Jiang Liu
2015-01-28 10:57 ` [Patch v2 05/22] ACPI: Let the parser return false for disabled resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 06/22] ACPI: Unify the parsing of address_space and ext_address_space Jiang Liu
2015-01-28 10:57 ` [Patch v2 07/22] ACPI: Move the window flag logic to the combined parser Jiang Liu
2015-01-28 10:57 ` [Patch v2 08/22] ACPI: Add prefetch decoding to the address space parser Jiang Liu
2015-01-28 10:57 ` [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource Jiang Liu
2015-01-28 23:15   ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 10/22] ACPI: Normalize return value of resource parser functions Jiang Liu
2015-01-28 10:57 ` [Patch v2 11/22] ACPI: Set flag IORESOURCE_UNSET for unassigned resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 12/22] ACPI: Enforce stricter checks for address space descriptors Jiang Liu
2015-01-28 10:57 ` [Patch v2 13/22] ACPI: Return translation offset when parsing ACPI address space resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 14/22] ACPI: Translate resource into master side address for bridge window resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 15/22] ACPI: Add field offset to struct resource_list_entry Jiang Liu
2015-01-28 10:57 ` [Patch v2 16/22] ACPI: Introduce helper function acpi_dev_filter_resource_type() Jiang Liu
2015-01-28 10:57 ` [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core Jiang Liu
2015-02-05  1:56   ` Vinod Koul
2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
2015-01-28 10:57   ` Jiang Liu
2015-01-28 10:57   ` Jiang Liu
2015-01-28 13:46   ` Will Deacon
2015-01-28 13:46     ` Will Deacon
2015-01-28 13:46     ` Will Deacon
2015-01-28 23:34   ` Bjorn Helgaas
2015-01-28 23:34     ` Bjorn Helgaas
2015-01-28 23:34     ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
2015-01-28 23:37   ` Bjorn Helgaas
2015-01-29  3:00     ` Jiang Liu [this message]
2015-01-28 23:51   ` Bjorn Helgaas
2015-01-29  3:11     ` Jiang Liu
2015-01-28 10:57 ` [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources Jiang Liu
2015-01-28 23:38   ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 21/22] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug Jiang Liu
2015-01-28 10:57 ` [Patch v2 22/22] x86/irq, ACPI: Implement ACPI driver to support " Jiang Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54C9A23C.4080807@linux.intel.com \
    --to=jiang.liu@linux.intel.com \
    --cc=bhelgaas@google.com \
    --cc=bp@alien8.de \
    --cc=hpa@zytor.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lv.zheng@intel.com \
    --cc=mingo@redhat.com \
    --cc=rjw@rjwysocki.net \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.