PCI / ACPI: Do not export pci_get_hp_params()
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/3 PCI / ACPI: Do not export pci_get_hp_params()
This is only used within drivers/pci, and there is no reason to make it available outside of the PCI core.
--- drivers/pci/pci-acpi.c | 1 - 1 file changed, 1 deletion(-)
drivers/pci/pci-acpi.c +0 -1
@@ -366,7 +366,6 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) }return -ENODEV ; } -EXPORT_SYMBOL_GPL (pci_get_hp_params);/** * pciehp_is_native - Check whether a hotplug port is handled by the OS
Signature · 1 line
2.19.2
Quoted 4 lines · Alexandru Gagniuc
This is only used within
drivers/pci, and there is no reason to make it available outside of the PCI core.Signed-off-by Alexandru Gagniuc <[email protected]>
Applied the whole series to pci/hotplug for v5.2, thanks!
I dropped the "list" member from struct hpx_type3 because it didn't seem to be used.
Quoted 19 lines
--- drivers/pci/pci-acpi.c | 1 - 1 file changed, 1 deletion(-)drivers/pci/pci-acpi.c +0
-1@@ -366,7 +366,6 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) }return -ENODEV ; } -EXPORT_SYMBOL_GPL (pci_get_hp_params);/** * pciehp_is_native - Check whether a hotplug port is handled by the OS Signature · 1 line
2.19.2
Quoted 10 lines · Bjorn Helgaas
Quoted 4 lines · Alexandru Gagniuc
This is only used within
drivers/pci, and there is no reason to make it available outside of the PCI core.Signed-off-by Alexandru Gagniuc <[email protected]>Applied the whole series to pci/hotplug for v5.2, thanks!
I dropped the "list" member from struct
hpx_type3because it didn't seem to be used.
That's a good call. That was a vestigial appendage from when I first intended to store a list of registers in memory. I'm glad we didn't end up needing a list.
Alex
PATCH 2/3 PCI / ACPI: Remove the need for 'struct hotplug_params'
In reply to a message not in the archiveWe 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.
--- drivers/pci/pci-acpi.c | 108 +++++++++++++++++++----------------- drivers/pci/probe.c | 16 ++---- include/linux/pci_hotplug.h | 18 +++--- 3 files changed, 72 insertions(+), 70 deletions(-)
drivers/pci/pci-acpi.c +58 -50
@@ -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))
drivers/pci/probe.c +6 -10
@@ -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, + };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)
include/linux/pci_hotplug.h +8 -10
@@ -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); };#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 ; }
Signature · 1 line
2.19.2
Re: [PATCH v1 2/3] PCI / ACPI: Remove the need for 'struct hotplug_params'
Quoted 10 lines · Alexandru Gagniuc
We used to first parse all the
_HPPand_HPXtables 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
_HPPand_HPX0 thru 2, this is functionally equivalent. The change enables the upcoming_HPX3to integrate more easily.
I think this is tremendous! It's going to simplify this code dramatically. Two comments below.
Quoted 233 lines
Signed-off-by Alexandru Gagniuc <[email protected]>--- drivers/pci/pci-acpi.c | 108 +++++++++++++++++++----------------- drivers/pci/probe.c | 16 ++---- include/linux/pci_hotplug.h | 18 +++--- 3 files changed, 72 insertions(+), 70 deletions(-)drivers/pci/pci-acpi.c +58
-50@@ -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))drivers/pci/probe.c +0
-0
drivers/pci/probe.c static void pci_configure_eetlp_prefix(struct pci_dev *dev) · line 2138
Quoted 10 lines
drivers/pci/probe.c +5
-2@@ -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.
Quoted 28 lines
drivers/pci/probe.c +1
-8pci_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)include/linux/pci_hotplug.h +0
-2@@ -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 */
include/linux/pci_hotplug.h struct hpp_type2 { · line 131
Quoted 10 lines
include/linux/pci_hotplug.h +4
-5-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.
Quoted 21 lines
include/linux/pci_hotplug.h +4
-3#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 ; }Signature · 1 line
2.19.2
Re: [PATCH v1 2/3] PCI / ACPI: Remove the need for 'struct hotplug_params'
Quoted 15 lines · Bjorn Helgaas
Quoted 10 lines · Alexandru Gagniuc
We used to first parse all the
_HPPand_HPXtables 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
_HPPand_HPX0 thru 2, this is functionally equivalent. The change enables the upcoming_HPX3to integrate more easily.I think this is tremendous! It's going to simplify this code dramatically. Two comments below.
Quoted 16 lines
drivers/pci/probe.c static void pci_configure_eetlp_prefix(struct pci_dev *dev) · line 2138
Quoted 9 lines
static void
pci_configure_device(struct pci_dev *dev){drivers/pci/probe.c +5
-2-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 fromprobe.ctopci-acpi.c? The only reason I see to have it inprobe.cis forpci_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 inprobe.cand then potentially having them overwritten by _HPP/_HPX.
Actually, never mind about this. This would be a perfect project for mentoring a Linux newbie.
I'll merge this series as-is and any restructuring/cleanup can happen later, since it's not related to this series anyway.
Bjorn
PATCH 3/3 PCI / ACPI: Implement Type 3 _HPX record
In reply to a message not in the archive_HPX Type 3 is intended to be more generic and allow configuration of settings not possible with Type 2 tables. For example, FW could ensure that the completion timeout value is set accordingly throughout the PCI tree.
Implement support for _HPX3 tables.
--- drivers/pci/pci-acpi.c | 63 ++++++++++++++++++++ drivers/pci/probe.c | 114 ++++++++++++++++++++++++++++++++++++ include/linux/pci_hotplug.h | 56 ++++++++++++++++++ 3 files changed, 233 insertions(+)
drivers/pci/pci-acpi.c +63 -0
@@ -216,6 +216,64 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,return AE_OK ; } +static void parse_hpx3_register (struct hpx_type3 *hpx3_reg, +union acpi_object *reg_fields) +{ + hpx3_reg->device_type = reg_fields[0 ].integer.value; + hpx3_reg->function_type = reg_fields[1 ].integer.value; + hpx3_reg->config_space_location = reg_fields[2 ].integer.value; + hpx3_reg->pci_exp_cap_id = reg_fields[3 ].integer.value; + hpx3_reg->pci_exp_cap_ver = reg_fields[4 ].integer.value; + hpx3_reg->pci_exp_vendor_id = reg_fields[5 ].integer.value; + hpx3_reg->dvsec_id = reg_fields[6 ].integer.value; + hpx3_reg->dvsec_rev = reg_fields[7 ].integer.value; + hpx3_reg->match_offset = reg_fields[8 ].integer.value; + hpx3_reg->match_mask_and = reg_fields[9 ].integer.value; + hpx3_reg->match_value = reg_fields[10 ].integer.value; + hpx3_reg->reg_offset = reg_fields[11 ].integer.value; + hpx3_reg->reg_mask_and = reg_fields[12 ].integer.value; + hpx3_reg->reg_mask_or = reg_fields[13 ].integer.value; +} + +static acpi_status program_type3_hpx_record (struct pci_dev *dev, +union acpi_object *record, +const struct hotplug_program_ops *hp_ops) +{ +union acpi_object *fields = record->package.elements; +u32 desc_count, expected_length, revision; +union acpi_object *reg_fields; +struct hpx_type3 hpx3; +int i; + + revision = fields[1 ].integer.value; +switch (revision) { +case 1 : + desc_count = fields[2 ].integer.value; + expected_length =3 + desc_count *14 ; + +if (record->package.count != expected_length) +return AE_ERROR ; + +for (i =2 ; i < expected_length; i++) +if (fields[i].type !=ACPI_TYPE_INTEGER ) +return AE_ERROR ; + +for (i =0 ; i < desc_count; i++) { + reg_fields = fields +3 + i *14 ; +parse_hpx3_register (&hpx3, reg_fields); + hp_ops->program_type3 (dev, &hpx3); + } + +break ; +default : +printk (KERN_WARNING +"%s: Type 3 Revision %d record not supported\n" , + __func__, revision); +return AE_ERROR ; + } +return AE_OK ; +} +static acpi_status acpi_run_hpx (struct pci_dev *dev,acpi_handle handle,const struct hotplug_program_ops *hp_ops) {
@@ -275,6 +333,11 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle, goto exit; hp_ops->program_type2 (dev, &hpx2);break ; +case 3 : + status =program_type3_hpx_record (dev, record, hp_ops); +if (ACPI_FAILURE (status)) + goto exit; +break ;default :printk (KERN_ERR "%s: Type %d record not supported\n" , __func__, type);
drivers/pci/probe.c +114 -0
126 lines not on this page · raw message
include/linux/pci_hotplug.h +56 -0
66 lines not on this page · raw message
Signature · 1 line
2.19.2