lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 19 Apr 2019 15:07:45 -0500
From:   Bjorn Helgaas <helgaas@...nel.org>
To:     Alexandru Gagniuc <mr.nuke.me@...il.com>
Cc:     austin_bolen@...l.com, alex_gagniuc@...lteam.com,
        keith.busch@...el.com, Shyam_Iyer@...l.com, lukas@...ner.de,
        okaya@...nel.org, "Rafael J. Wysocki" <rjw@...ysocki.net>,
        Len Brown <lenb@...nel.org>, linux-acpi@...r.kernel.org,
        linux-pci@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v1 2/3] PCI / ACPI: Remove the need for 'struct
 hotplug_params'

On Fri, Feb 08, 2019 at 10:24:12AM -0600, Alexandru Gagniuc wrote:
> We used to first parse all the _HPP and _HPX tables before using the
> information to program registers of PCIe devices. Up until HPX type 2,
> there was only one structure of each type, so we could cheat and store
> it on the stack.
> 
> With HPX type 3 we get an arbitrary number of entries, so the above
> model doesn't scale that well. Instead of parsing all tables at once,
> parse and program each entry separately. For _HPP and _HPX 0 thru 2,
> this is functionally equivalent. The change enables the upcoming _HPX3
> to integrate more easily.

I think this is tremendous!  It's going to simplify this code
dramatically.  Two comments below.

> Signed-off-by: Alexandru Gagniuc <mr.nuke.me@...il.com>
> ---
>  drivers/pci/pci-acpi.c      | 108 +++++++++++++++++++-----------------
>  drivers/pci/probe.c         |  16 ++----
>  include/linux/pci_hotplug.h |  18 +++---
>  3 files changed, 72 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index b25e5fa9d1c9..95f4f86d2f34 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -119,7 +119,7 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
>  }
>  
>  static acpi_status decode_type0_hpx_record(union acpi_object *record,
> -					   struct hotplug_params *hpx)
> +					   struct hpp_type0 *hpx0)
>  {
>  	int i;
>  	union acpi_object *fields = record->package.elements;
> @@ -132,12 +132,11 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
>  		for (i = 2; i < 6; i++)
>  			if (fields[i].type != ACPI_TYPE_INTEGER)
>  				return AE_ERROR;
> -		hpx->t0 = &hpx->type0_data;
> -		hpx->t0->revision        = revision;
> -		hpx->t0->cache_line_size = fields[2].integer.value;
> -		hpx->t0->latency_timer   = fields[3].integer.value;
> -		hpx->t0->enable_serr     = fields[4].integer.value;
> -		hpx->t0->enable_perr     = fields[5].integer.value;
> +		hpx0->revision        = revision;
> +		hpx0->cache_line_size = fields[2].integer.value;
> +		hpx0->latency_timer   = fields[3].integer.value;
> +		hpx0->enable_serr     = fields[4].integer.value;
> +		hpx0->enable_perr     = fields[5].integer.value;
>  		break;
>  	default:
>  		printk(KERN_WARNING
> @@ -149,7 +148,7 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
>  }
>  
>  static acpi_status decode_type1_hpx_record(union acpi_object *record,
> -					   struct hotplug_params *hpx)
> +					   struct hpp_type1 *hpx1)
>  {
>  	int i;
>  	union acpi_object *fields = record->package.elements;
> @@ -162,11 +161,10 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
>  		for (i = 2; i < 5; i++)
>  			if (fields[i].type != ACPI_TYPE_INTEGER)
>  				return AE_ERROR;
> -		hpx->t1 = &hpx->type1_data;
> -		hpx->t1->revision      = revision;
> -		hpx->t1->max_mem_read  = fields[2].integer.value;
> -		hpx->t1->avg_max_split = fields[3].integer.value;
> -		hpx->t1->tot_max_split = fields[4].integer.value;
> +		hpx1->revision      = revision;
> +		hpx1->max_mem_read  = fields[2].integer.value;
> +		hpx1->avg_max_split = fields[3].integer.value;
> +		hpx1->tot_max_split = fields[4].integer.value;
>  		break;
>  	default:
>  		printk(KERN_WARNING
> @@ -178,7 +176,7 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
>  }
>  
>  static acpi_status decode_type2_hpx_record(union acpi_object *record,
> -					   struct hotplug_params *hpx)
> +					   struct hpp_type2 *hpx2)
>  {
>  	int i;
>  	union acpi_object *fields = record->package.elements;
> @@ -191,24 +189,23 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
>  		for (i = 2; i < 18; i++)
>  			if (fields[i].type != ACPI_TYPE_INTEGER)
>  				return AE_ERROR;
> -		hpx->t2 = &hpx->type2_data;
> -		hpx->t2->revision      = revision;
> -		hpx->t2->unc_err_mask_and      = fields[2].integer.value;
> -		hpx->t2->unc_err_mask_or       = fields[3].integer.value;
> -		hpx->t2->unc_err_sever_and     = fields[4].integer.value;
> -		hpx->t2->unc_err_sever_or      = fields[5].integer.value;
> -		hpx->t2->cor_err_mask_and      = fields[6].integer.value;
> -		hpx->t2->cor_err_mask_or       = fields[7].integer.value;
> -		hpx->t2->adv_err_cap_and       = fields[8].integer.value;
> -		hpx->t2->adv_err_cap_or        = fields[9].integer.value;
> -		hpx->t2->pci_exp_devctl_and    = fields[10].integer.value;
> -		hpx->t2->pci_exp_devctl_or     = fields[11].integer.value;
> -		hpx->t2->pci_exp_lnkctl_and    = fields[12].integer.value;
> -		hpx->t2->pci_exp_lnkctl_or     = fields[13].integer.value;
> -		hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
> -		hpx->t2->sec_unc_err_sever_or  = fields[15].integer.value;
> -		hpx->t2->sec_unc_err_mask_and  = fields[16].integer.value;
> -		hpx->t2->sec_unc_err_mask_or   = fields[17].integer.value;
> +		hpx2->revision      = revision;
> +		hpx2->unc_err_mask_and      = fields[2].integer.value;
> +		hpx2->unc_err_mask_or       = fields[3].integer.value;
> +		hpx2->unc_err_sever_and     = fields[4].integer.value;
> +		hpx2->unc_err_sever_or      = fields[5].integer.value;
> +		hpx2->cor_err_mask_and      = fields[6].integer.value;
> +		hpx2->cor_err_mask_or       = fields[7].integer.value;
> +		hpx2->adv_err_cap_and       = fields[8].integer.value;
> +		hpx2->adv_err_cap_or        = fields[9].integer.value;
> +		hpx2->pci_exp_devctl_and    = fields[10].integer.value;
> +		hpx2->pci_exp_devctl_or     = fields[11].integer.value;
> +		hpx2->pci_exp_lnkctl_and    = fields[12].integer.value;
> +		hpx2->pci_exp_lnkctl_or     = fields[13].integer.value;
> +		hpx2->sec_unc_err_sever_and = fields[14].integer.value;
> +		hpx2->sec_unc_err_sever_or  = fields[15].integer.value;
> +		hpx2->sec_unc_err_mask_and  = fields[16].integer.value;
> +		hpx2->sec_unc_err_mask_or   = fields[17].integer.value;
>  		break;
>  	default:
>  		printk(KERN_WARNING
> @@ -219,17 +216,18 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
>  	return AE_OK;
>  }
>  
> -static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
> +static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
> +				const struct hotplug_program_ops *hp_ops)
>  {
>  	acpi_status status;
>  	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
>  	union acpi_object *package, *record, *fields;
> +	struct hpp_type0 hpx0;
> +	struct hpp_type1 hpx1;
> +	struct hpp_type2 hpx2;
>  	u32 type;
>  	int i;
>  
> -	/* Clear the return buffer with zeros */
> -	memset(hpx, 0, sizeof(struct hotplug_params));
> -
>  	status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
>  	if (ACPI_FAILURE(status))
>  		return status;
> @@ -257,19 +255,25 @@ static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
>  		type = fields[0].integer.value;
>  		switch (type) {
>  		case 0:
> -			status = decode_type0_hpx_record(record, hpx);
> +			memset(&hpx0, 0, sizeof(hpx0));
> +			status = decode_type0_hpx_record(record, &hpx0);
>  			if (ACPI_FAILURE(status))
>  				goto exit;
> +			hp_ops->program_type0(dev, &hpx0);
>  			break;
>  		case 1:
> -			status = decode_type1_hpx_record(record, hpx);
> +			memset(&hpx1, 0, sizeof(hpx1));
> +			status = decode_type1_hpx_record(record, &hpx1);
>  			if (ACPI_FAILURE(status))
>  				goto exit;
> +			hp_ops->program_type1(dev, &hpx1);
>  			break;
>  		case 2:
> -			status = decode_type2_hpx_record(record, hpx);
> +			memset(&hpx2, 0, sizeof(hpx2));
> +			status = decode_type2_hpx_record(record, &hpx2);
>  			if (ACPI_FAILURE(status))
>  				goto exit;
> +			hp_ops->program_type2(dev, &hpx2);
>  			break;
>  		default:
>  			printk(KERN_ERR "%s: Type %d record not supported\n",
> @@ -283,14 +287,16 @@ static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
>  	return status;
>  }
>  
> -static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> +static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
> +				const struct hotplug_program_ops *hp_ops)
>  {
>  	acpi_status status;
>  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>  	union acpi_object *package, *fields;
> +	struct hpp_type0 hpp0;
>  	int i;
>  
> -	memset(hpp, 0, sizeof(struct hotplug_params));
> +	memset(&hpp0, 0, sizeof(hpp0));
>  
>  	status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer);
>  	if (ACPI_FAILURE(status))
> @@ -311,12 +317,13 @@ static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
>  		}
>  	}
>  
> -	hpp->t0 = &hpp->type0_data;
> -	hpp->t0->revision        = 1;
> -	hpp->t0->cache_line_size = fields[0].integer.value;
> -	hpp->t0->latency_timer   = fields[1].integer.value;
> -	hpp->t0->enable_serr     = fields[2].integer.value;
> -	hpp->t0->enable_perr     = fields[3].integer.value;
> +	hpp0.revision        = 1;
> +	hpp0.cache_line_size = fields[0].integer.value;
> +	hpp0.latency_timer   = fields[1].integer.value;
> +	hpp0.enable_serr     = fields[2].integer.value;
> +	hpp0.enable_perr     = fields[3].integer.value;
> +
> +	hp_ops->program_type0(dev, &hpp0);
>  
>  exit:
>  	kfree(buffer.pointer);
> @@ -328,7 +335,8 @@ static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
>   * @dev - the pci_dev for which we want parameters
>   * @hpp - allocated by the caller
>   */
> -int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
> +int pci_acpi_program_hp_params(struct pci_dev *dev,
> +			       const struct hotplug_program_ops *hp_ops)
>  {
>  	acpi_status status;
>  	acpi_handle handle, phandle;
> @@ -351,10 +359,10 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
>  	 * this pci dev.
>  	 */
>  	while (handle) {
> -		status = acpi_run_hpx(handle, hpp);
> +		status = acpi_run_hpx(dev, handle, hp_ops);
>  		if (ACPI_SUCCESS(status))
>  			return 0;
> -		status = acpi_run_hpp(handle, hpp);
> +		status = acpi_run_hpp(dev, handle, hp_ops);
>  		if (ACPI_SUCCESS(status))
>  			return 0;
>  		if (acpi_is_root_bridge(handle))
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 257b9f6f2ebb..527c209f0c94 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -2131,8 +2131,11 @@ static void pci_configure_eetlp_prefix(struct pci_dev *dev)
>  
>  static void pci_configure_device(struct pci_dev *dev)
>  {
> -	struct hotplug_params hpp;
> -	int ret;
> +	static const struct hotplug_program_ops hp_ops = {
> +		.program_type0 = program_hpp_type0,
> +		.program_type1 = program_hpp_type1,
> +		.program_type2 = program_hpp_type2,
> +	};

What if we just moved program_hpp_type0(), etc from probe.c to
pci-acpi.c?  The only reason I see to have it in probe.c is for
pci_default_type0, and I think that is a pretty obtuse way of doing
default configuration.  I would have no problem at all just hardcoding
those defaults in probe.c and then potentially having them overwritten
by _HPP/_HPX.

If we moved program_hpp_type0(), etc to pci-acpi.c, we could get rid
of the function pointers and all the ACPI-related code would be in one
place.

>  	pci_configure_mps(dev);
>  	pci_configure_extended_tags(dev, NULL);
> @@ -2140,14 +2143,7 @@ static void pci_configure_device(struct pci_dev *dev)
>  	pci_configure_ltr(dev);
>  	pci_configure_eetlp_prefix(dev);
>  
> -	memset(&hpp, 0, sizeof(hpp));
> -	ret = pci_get_hp_params(dev, &hpp);
> -	if (ret)
> -		return;
> -
> -	program_hpp_type2(dev, hpp.t2);
> -	program_hpp_type1(dev, hpp.t1);
> -	program_hpp_type0(dev, hpp.t0);
> +	pci_acpi_program_hp_params(dev, &hp_ops);
>  }
>  
>  static void pci_release_capabilities(struct pci_dev *dev)
> diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
> index 7acc9f91e72b..c85378edf235 100644
> --- a/include/linux/pci_hotplug.h
> +++ b/include/linux/pci_hotplug.h
> @@ -124,26 +124,24 @@ struct hpp_type2 {
>  	u32 sec_unc_err_mask_or;
>  };
>  
> -struct hotplug_params {
> -	struct hpp_type0 *t0;		/* Type0: NULL if not available */
> -	struct hpp_type1 *t1;		/* Type1: NULL if not available */
> -	struct hpp_type2 *t2;		/* Type2: NULL if not available */
> -	struct hpp_type0 type0_data;
> -	struct hpp_type1 type1_data;
> -	struct hpp_type2 type2_data;
> +struct hotplug_program_ops {
> +	void (*program_type0)(struct pci_dev *dev, struct hpp_type0 *hpp);
> +	void (*program_type1)(struct pci_dev *dev, struct hpp_type1 *hpp);
> +	void (*program_type2)(struct pci_dev *dev, struct hpp_type2 *hpp);
>  };

I think a lot of this stuff is only used in drivers/pci, so it could
be moved from include/linux/pci_hotplug.h to drivers/pci/pci.h.

>  #ifdef CONFIG_ACPI
>  #include <linux/acpi.h>
> -int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
> +int pci_acpi_program_hp_params(struct pci_dev *dev,
> +			       const struct hotplug_program_ops *hp_ops);
>  bool pciehp_is_native(struct pci_dev *bridge);
>  int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
>  bool shpchp_is_native(struct pci_dev *bridge);
>  int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
>  int acpi_pci_detect_ejectable(acpi_handle handle);
>  #else
> -static inline int pci_get_hp_params(struct pci_dev *dev,
> -				    struct hotplug_params *hpp)
> +int pci_acpi_program_hp_params(struct pci_dev *dev,
> +			       const struct hotplug_program_ops *hp_ops);
>  {
>  	return -ENODEV;
>  }
> -- 
> 2.19.2
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ