Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-13 Thread Michael Jin
On Mon, Aug 13, 2018 at 12:17 PM, Pu Wen  wrote:
> On 2018/8/12 3:56, Michael Jin wrote:
>>
>> On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:
>>>
>>> diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
>>> -   if (pvt->fam == 0x17) {
>>> +   if (pvt->fam == 0x17 || pvt->vendor == X86_VENDOR_HYGON) {
>>>  __f17h_set_scrubval(pvt, scrubval);
>>
>>
>> Separating the vendor check as an "else if (pvt->vendor ==
>> X86_VENDOR_HYGON)" block would make architectural changes (future
>> hygon models, i.e. 19h, 20h, etc) less confusing.
>
>
> Your suggestion is reasonable, but that might make the branch a little
> complicated.If we explicitly testing Hygon family in condition case,
> will that be ok?
> +if (pvt->fam == 0x17 ||
> +   (pvt->vendor == X86_VENDOR_HYGON && pvt->fam == 0x18))

The condition case for family 18h and vendor Hygon looks better
because it is more clear.

Michael


Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-13 Thread Pu Wen

On 2018/8/12 4:10, Michael Jin wrote:

On Sat, Aug 11, 2018 at 3:56 PM, Michael Jin  wrote:

On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:

@@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt *pvt)
 else
 pvt->dram_type = MEM_DDR4;
 return;
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {


This vendor checking is not necessary as there are no other known
family 18h processors.


Actually, vendor checking works here. Although, AMD has not released a
family 18h yet.


Yes, that's the case.

Thanks,
Pu Wen



Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-13 Thread Pu Wen

On 2018/8/12 3:56, Michael Jin wrote:

On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 18aeabb..fb81354 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -211,7 +211,7 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 
new_bw, u32 min_rate)

 scrubval = scrubrates[i].scrubval;

-   if (pvt->fam == 0x17) {
+   if (pvt->fam == 0x17 || pvt->vendor == X86_VENDOR_HYGON) {
 __f17h_set_scrubval(pvt, scrubval);


Separating the vendor check as an "else if (pvt->vendor ==
X86_VENDOR_HYGON)" block would make architectural changes (future
hygon models, i.e. 19h, 20h, etc) less confusing.


Your suggestion is reasonable, but that might make the branch a little
complicated.If we explicitly testing Hygon family in condition case,
will that be ok?
+if (pvt->fam == 0x17 ||
+   (pvt->vendor == X86_VENDOR_HYGON && pvt->fam == 0x18))




+   amd64_read_pci_cfg(pvt->F6,
+   F17H_SCR_BASE_ADDR, &scrubval);
+   if (scrubval & BIT(0)) {
+   amd64_read_pci_cfg(pvt->F6,


The new lines after "amd64_read_pci_cfg(pvt->F6," can be removed.


To fix the warning "line over 80 characters" reported by running the
checking script checkpatch.pl, I added the new line.
But your sugesstion is reasonable, remove the new line will make the
codes much easier to read.


@@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt *pvt)
 else
 pvt->dram_type = MEM_DDR4;
 return;
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {


This vendor checking is not necessary as there are no other known
family 18h processors.



 switch (pvt->fam) {
@@ -3192,6 +3227,13 @@ static struct amd64_family_type *per_family_init(struct 
amd64_pvt *pvt)
 pvt->ops= &family_types[F17_CPUS].ops;
 break;

+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {
+   fam_type= &family_types[HYGON_F18_CPUS];
+   pvt->ops= &family_types[HYGON_F18_CPUS].ops;
+   break;
+   }


There is a missing second 'break' statement after the "if (pvt->vendor
== X86_VENDOR_HYGON)" block for case 0x18, see case 0x15 and case 0x16
for comparison.


The missed second 'break' is on purpose. Thinking that if BIOS report
a vendor AMD and family 18h processor(which is not in case now),
the code will fall through and print out "Unsupported family".




diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 2ab4d61..f7adc47 100644
+   case 0x18:
+   if (c->x86_vendor == X86_VENDOR_HYGON) {
+   xec_mask = 0x3f;
+   if (!boot_cpu_has(X86_FEATURE_SMCA)) {
+   pr_warn("Decoding supported only on Scalable MCA 
processors.\n");
+   goto err_out;
+   }
+   break;
+   }


The 'break' statement could be moved outside of the "if (c->x86_vendor
== X86_VENDOR_HYGON)" block, this is to allow case 0x18 to reach the
'break' statement if the vendor is not X86_VENDOR_HYGON.


For the same reason as previous, if the vendor is not X86_VENDOR_HYGON,
it's not a valid vendor by now, and should fall through to the default
case and print out error message.

Thanks,
Pu Wen



Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-13 Thread Pu Wen

On 2018/8/12 3:56, Michael Jin wrote:

On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 18aeabb..fb81354 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -211,7 +211,7 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 
new_bw, u32 min_rate)

 scrubval = scrubrates[i].scrubval;

-   if (pvt->fam == 0x17) {
+   if (pvt->fam == 0x17 || pvt->vendor == X86_VENDOR_HYGON) {
 __f17h_set_scrubval(pvt, scrubval);


Separating the vendor check as an "else if (pvt->vendor ==
X86_VENDOR_HYGON)" block would make architectural changes (future
hygon models, i.e. 19h, 20h, etc) less confusing.


Your suggestion is reasonable, but that might make the branch a little
complicated.If we explicitly testing Hygon family in condition case,
will that be ok?
+if (pvt->fam == 0x17 ||
+   (pvt->vendor == X86_VENDOR_HYGON && pvt->fam == 0x18))




+   amd64_read_pci_cfg(pvt->F6,
+   F17H_SCR_BASE_ADDR, &scrubval);
+   if (scrubval & BIT(0)) {
+   amd64_read_pci_cfg(pvt->F6,


The new lines after "amd64_read_pci_cfg(pvt->F6," can be removed.


To fix the warning "line over 80 characters" reported by running the
checking script checkpatch.pl, I added the new line.
But your sugesstion is reasonable, remove the new line will make the
codes much easier to read.


@@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt *pvt)
 else
 pvt->dram_type = MEM_DDR4;
 return;
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {


This vendor checking is not necessary as there are no other known
family 18h processors.



 switch (pvt->fam) {
@@ -3192,6 +3227,13 @@ static struct amd64_family_type *per_family_init(struct 
amd64_pvt *pvt)
 pvt->ops= &family_types[F17_CPUS].ops;
 break;

+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {
+   fam_type= &family_types[HYGON_F18_CPUS];
+   pvt->ops= &family_types[HYGON_F18_CPUS].ops;
+   break;
+   }


There is a missing second 'break' statement after the "if (pvt->vendor
== X86_VENDOR_HYGON)" block for case 0x18, see case 0x15 and case 0x16
for comparison.


The missed second 'break' is on purpose. Thinking that if BIOS report
a vendor AMD and family 18h processor(which is not in case now),
the code will fall through and print out "Unsupported family".




diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 2ab4d61..f7adc47 100644
+   case 0x18:
+   if (c->x86_vendor == X86_VENDOR_HYGON) {
+   xec_mask = 0x3f;
+   if (!boot_cpu_has(X86_FEATURE_SMCA)) {
+   pr_warn("Decoding supported only on Scalable MCA 
processors.\n");
+   goto err_out;
+   }
+   break;
+   }


The 'break' statement could be moved outside of the "if (c->x86_vendor
== X86_VENDOR_HYGON)" block, this is to allow case 0x18 to reach the
'break' statement if the vendor is not X86_VENDOR_HYGON.


For the same reason as previous, if the vendor is not X86_VENDOR_HYGON,
it's not a valid vendor by now, and should fall through to the default
case and print out error message.

Thanks,
Pu Wen



Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-11 Thread Michael Jin
On Sat, Aug 11, 2018 at 3:56 PM, Michael Jin  wrote:
> On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:
>> @@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt 
>> *pvt)
>> else
>> pvt->dram_type = MEM_DDR4;
>> return;
>> +   case 0x18:
>> +   if (pvt->vendor == X86_VENDOR_HYGON) {
>
> This vendor checking is not necessary as there are no other known
> family 18h processors.

Actually, vendor checking works here. Although, AMD has not released a
family 18h yet.


Re: [PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-11 Thread Michael Jin
On Sat, Aug 11, 2018 at 9:30 AM, Pu Wen  wrote:
> diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
> index 18aeabb..fb81354 100644
> --- a/drivers/edac/amd64_edac.c
> +++ b/drivers/edac/amd64_edac.c
> @@ -211,7 +211,7 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 
> new_bw, u32 min_rate)
>
> scrubval = scrubrates[i].scrubval;
>
> -   if (pvt->fam == 0x17) {
> +   if (pvt->fam == 0x17 || pvt->vendor == X86_VENDOR_HYGON) {
> __f17h_set_scrubval(pvt, scrubval);

Separating the vendor check as an "else if (pvt->vendor ==
X86_VENDOR_HYGON)" block would make architectural changes (future
hygon models, i.e. 19h, 20h, etc) less confusing.



> +   amd64_read_pci_cfg(pvt->F6,
> +   F17H_SCR_BASE_ADDR, &scrubval);
> +   if (scrubval & BIT(0)) {
> +   amd64_read_pci_cfg(pvt->F6,

The new lines after "amd64_read_pci_cfg(pvt->F6," can be removed.



> @@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt 
> *pvt)
> else
> pvt->dram_type = MEM_DDR4;
> return;
> +   case 0x18:
> +   if (pvt->vendor == X86_VENDOR_HYGON) {

This vendor checking is not necessary as there are no other known
family 18h processors.


> switch (pvt->fam) {
> @@ -3192,6 +3227,13 @@ static struct amd64_family_type 
> *per_family_init(struct amd64_pvt *pvt)
> pvt->ops= &family_types[F17_CPUS].ops;
> break;
>
> +   case 0x18:
> +   if (pvt->vendor == X86_VENDOR_HYGON) {
> +   fam_type= &family_types[HYGON_F18_CPUS];
> +   pvt->ops= &family_types[HYGON_F18_CPUS].ops;
> +   break;
> +   }

There is a missing second 'break' statement after the "if (pvt->vendor
== X86_VENDOR_HYGON)" block for case 0x18, see case 0x15 and case 0x16
for comparison.



> diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
> index 2ab4d61..f7adc47 100644
> +   case 0x18:
> +   if (c->x86_vendor == X86_VENDOR_HYGON) {
> +   xec_mask = 0x3f;
> +   if (!boot_cpu_has(X86_FEATURE_SMCA)) {
> +   pr_warn("Decoding supported only on Scalable 
> MCA processors.\n");
> +   goto err_out;
> +   }
> +   break;
> +   }

The 'break' statement could be moved outside of the "if (c->x86_vendor
== X86_VENDOR_HYGON)" block, this is to allow case 0x18 to reach the
'break' statement if the vendor is not X86_VENDOR_HYGON.


[PATCH v3 16/17] driver/edac: enable Hygon support to AMD64 EDAC driver

2018-08-11 Thread Pu Wen
To make AMD64 EDAC and MCE drivers working on Hygon platforms, add
vendor checking for Hygon by using the code path of AMD 0x17. Add a
vendor field to struct amd64_pvt and initialize it in per_family_init
for vendor checking.

Also Hygon PCI Device ID DF_F0/DF_F6(0x1460/0x1466) of Host bridges
is needed for edac driver.

Signed-off-by: Pu Wen 
---
 drivers/edac/amd64_edac.c | 45 -
 drivers/edac/amd64_edac.h |  5 +
 drivers/edac/mce_amd.c| 12 +++-
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 18aeabb..fb81354 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -211,7 +211,7 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 
new_bw, u32 min_rate)
 
scrubval = scrubrates[i].scrubval;
 
-   if (pvt->fam == 0x17) {
+   if (pvt->fam == 0x17 || pvt->vendor == X86_VENDOR_HYGON) {
__f17h_set_scrubval(pvt, scrubval);
} else if (pvt->fam == 0x15 && pvt->model == 0x60) {
f15h_select_dct(pvt, 0);
@@ -273,6 +273,20 @@ static int get_scrub_rate(struct mem_ctl_info *mci)
scrubval = 0;
}
break;
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {
+   amd64_read_pci_cfg(pvt->F6,
+   F17H_SCR_BASE_ADDR, &scrubval);
+   if (scrubval & BIT(0)) {
+   amd64_read_pci_cfg(pvt->F6,
+   F17H_SCR_LIMIT_ADDR, &scrubval);
+   scrubval &= 0xF;
+   scrubval += 0x5;
+   } else {
+   scrubval = 0;
+   }
+   break;
+   }
 
default:
amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
@@ -1051,6 +1065,16 @@ static void determine_memory_type(struct amd64_pvt *pvt)
else
pvt->dram_type = MEM_DDR4;
return;
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {
+   if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & 
BIT(5))
+   pvt->dram_type = MEM_LRDDR4;
+   else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) 
& BIT(4))
+   pvt->dram_type = MEM_RDDR4;
+   else
+   pvt->dram_type = MEM_DDR4;
+   return;
+   }
 
default:
WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
@@ -2200,6 +2224,16 @@ static struct amd64_family_type family_types[] = {
.dbam_to_cs = f17_base_addr_to_cs_size,
}
},
+   [HYGON_F18_CPUS] = {
+   /* Hygon F18h uses the same AMD F17h support */
+   .ctl_name = "Hygon_F18h",
+   .f0_id = PCI_DEVICE_ID_HYGON_18H_DF_F0,
+   .f6_id = PCI_DEVICE_ID_HYGON_18H_DF_F6,
+   .ops = {
+   .early_channel_count= f17_early_channel_count,
+   .dbam_to_cs = f17_base_addr_to_cs_size,
+   }
+   },
 };
 
 /*
@@ -3149,6 +3183,7 @@ static struct amd64_family_type *per_family_init(struct 
amd64_pvt *pvt)
pvt->ext_model  = boot_cpu_data.x86_model >> 4;
pvt->stepping   = boot_cpu_data.x86_stepping;
pvt->model  = boot_cpu_data.x86_model;
+   pvt->vendor = boot_cpu_data.x86_vendor;
pvt->fam= boot_cpu_data.x86;
 
switch (pvt->fam) {
@@ -3192,6 +3227,13 @@ static struct amd64_family_type *per_family_init(struct 
amd64_pvt *pvt)
pvt->ops= &family_types[F17_CPUS].ops;
break;
 
+   case 0x18:
+   if (pvt->vendor == X86_VENDOR_HYGON) {
+   fam_type= &family_types[HYGON_F18_CPUS];
+   pvt->ops= &family_types[HYGON_F18_CPUS].ops;
+   break;
+   }
+
default:
amd64_err("Unsupported family!\n");
return NULL;
@@ -3428,6 +3470,7 @@ static const struct x86_cpu_id amd64_cpuids[] = {
{ X86_VENDOR_AMD, 0x15, X86_MODEL_ANY,  X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x16, X86_MODEL_ANY,  X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x17, X86_MODEL_ANY,  X86_FEATURE_ANY, 0 },
+   { X86_VENDOR_HYGON, 0x18, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ }
 };
 MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids);
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 1d4b74e..5176b51 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -116,6 +116,9 @@
 #define PCI_DEVICE_ID_AMD_17H_DF_F00x1460
 #define PCI_D