Linux-EDAC Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v1 1/1] EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable
@ 2020-05-15 21:01 Tony Luck
  2020-05-18 14:21 ` Aristeu Rozanski
  0 siblings, 1 reply; 2+ messages in thread
From: Tony Luck @ 2020-05-15 21:01 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Qiuxu Zhuo, Matthew Riley, Tony Luck, Aristeu Rozanski,
	Mauro Carvalho Chehab, linux-edac

From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>

The skx_edac driver wrongly uses the mtr register to retrieve two fields
close_pg and bank_xor_enable. Fix it by using the correct mcmtr register
to get the two fields.

Cc: <stable@vger.kernel.org>
Reported-by: Matthew Riley <mattdr@google.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

---
 drivers/edac/i10nm_base.c |  2 +-
 drivers/edac/skx_base.c   | 20 ++++++++------------
 drivers/edac/skx_common.c |  6 +++---
 drivers/edac/skx_common.h |  2 +-
 4 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index ea8f2127e238..c8d11da85bec 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -175,7 +175,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
 				 mtr, mcddrtcfg, imc->mc, i, j);
 
 			if (IS_DIMM_PRESENT(mtr))
-				ndimms += skx_get_dimm_info(mtr, 0, dimm,
+				ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
 							    imc, i, j);
 			else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
 				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
index 1ff22136cf72..2c7db95df326 100644
--- a/drivers/edac/skx_base.c
+++ b/drivers/edac/skx_base.c
@@ -169,27 +169,23 @@ static const struct x86_cpu_id skx_cpuids[] = {
 };
 MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
 
-#define SKX_GET_MTMTR(dev, reg) \
-	pci_read_config_dword((dev), 0x87c, &(reg))
-
-static bool skx_check_ecc(struct pci_dev *pdev)
+static bool skx_check_ecc(u32 mcmtr)
 {
-	u32 mtmtr;
-
-	SKX_GET_MTMTR(pdev, mtmtr);
-
-	return !!GET_BITFIELD(mtmtr, 2, 2);
+	return !!GET_BITFIELD(mcmtr, 2, 2);
 }
 
 static int skx_get_dimm_config(struct mem_ctl_info *mci)
 {
 	struct skx_pvt *pvt = mci->pvt_info;
+	u32 mtr, mcmtr, amap, mcddrtcfg;
 	struct skx_imc *imc = pvt->imc;
-	u32 mtr, amap, mcddrtcfg;
 	struct dimm_info *dimm;
 	int i, j;
 	int ndimms;
 
+	/* Only the mcmtr on the first channel is effective */
+	pci_read_config_dword(imc->chan[0].cdev, 0x87c, &mcmtr);
+
 	for (i = 0; i < SKX_NUM_CHANNELS; i++) {
 		ndimms = 0;
 		pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap);
@@ -199,14 +195,14 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci)
 			pci_read_config_dword(imc->chan[i].cdev,
 					      0x80 + 4 * j, &mtr);
 			if (IS_DIMM_PRESENT(mtr)) {
-				ndimms += skx_get_dimm_info(mtr, amap, dimm, imc, i, j);
+				ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j);
 			} else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) {
 				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
 							      EDAC_MOD_STR);
 				nvdimm_count++;
 			}
 		}
-		if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) {
+		if (ndimms && !skx_check_ecc(mcmtr)) {
 			skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc);
 			return -ENODEV;
 		}
diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
index abc9ddd2b7d1..46be1a77bd1d 100644
--- a/drivers/edac/skx_common.c
+++ b/drivers/edac/skx_common.c
@@ -303,7 +303,7 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
 #define numrow(reg)	skx_get_dimm_attr(reg, 2, 4, 12, 1, 6, "rows")
 #define numcol(reg)	skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols")
 
-int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
+int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
 		      struct skx_imc *imc, int chan, int dimmno)
 {
 	int  banks = 16, ranks, rows, cols, npages;
@@ -323,8 +323,8 @@ int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
 		 imc->mc, chan, dimmno, size, npages,
 		 banks, 1 << ranks, rows, cols);
 
-	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0);
-	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9);
+	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mcmtr, 0, 0);
+	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mcmtr, 9, 9);
 	imc->chan[chan].dimms[dimmno].fine_grain_bank = GET_BITFIELD(amap, 0, 0);
 	imc->chan[chan].dimms[dimmno].rowbits = rows;
 	imc->chan[chan].dimms[dimmno].colbits = cols;
diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
index 19dd8c099520..78f8c1de0b71 100644
--- a/drivers/edac/skx_common.h
+++ b/drivers/edac/skx_common.h
@@ -135,7 +135,7 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list);
 
 int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);
 
-int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
+int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
 		      struct skx_imc *imc, int chan, int dimmno);
 
 int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
-- 
2.17.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v1 1/1] EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable
  2020-05-15 21:01 [PATCH v1 1/1] EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable Tony Luck
@ 2020-05-18 14:21 ` Aristeu Rozanski
  0 siblings, 0 replies; 2+ messages in thread
From: Aristeu Rozanski @ 2020-05-18 14:21 UTC (permalink / raw)
  To: Tony Luck
  Cc: Borislav Petkov, Qiuxu Zhuo, Matthew Riley,
	Mauro Carvalho Chehab, linux-edac

On Fri, May 15, 2020 at 02:01:46PM -0700, Tony Luck wrote:
> From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> 
> The skx_edac driver wrongly uses the mtr register to retrieve two fields
> close_pg and bank_xor_enable. Fix it by using the correct mcmtr register
> to get the two fields.
> 
> Cc: <stable@vger.kernel.org>
> Reported-by: Matthew Riley <mattdr@google.com>
> Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> Signed-off-by: Tony Luck <tony.luck@intel.com>
> 
> ---
>  drivers/edac/i10nm_base.c |  2 +-
>  drivers/edac/skx_base.c   | 20 ++++++++------------
>  drivers/edac/skx_common.c |  6 +++---
>  drivers/edac/skx_common.h |  2 +-
>  4 files changed, 13 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
> index ea8f2127e238..c8d11da85bec 100644
> --- a/drivers/edac/i10nm_base.c
> +++ b/drivers/edac/i10nm_base.c
> @@ -175,7 +175,7 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
>  				 mtr, mcddrtcfg, imc->mc, i, j);
>  
>  			if (IS_DIMM_PRESENT(mtr))
> -				ndimms += skx_get_dimm_info(mtr, 0, dimm,
> +				ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
>  							    imc, i, j);
>  			else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
>  				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
> diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
> index 1ff22136cf72..2c7db95df326 100644
> --- a/drivers/edac/skx_base.c
> +++ b/drivers/edac/skx_base.c
> @@ -169,27 +169,23 @@ static const struct x86_cpu_id skx_cpuids[] = {
>  };
>  MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
>  
> -#define SKX_GET_MTMTR(dev, reg) \
> -	pci_read_config_dword((dev), 0x87c, &(reg))
> -
> -static bool skx_check_ecc(struct pci_dev *pdev)
> +static bool skx_check_ecc(u32 mcmtr)
>  {
> -	u32 mtmtr;
> -
> -	SKX_GET_MTMTR(pdev, mtmtr);
> -
> -	return !!GET_BITFIELD(mtmtr, 2, 2);
> +	return !!GET_BITFIELD(mcmtr, 2, 2);
>  }
>  
>  static int skx_get_dimm_config(struct mem_ctl_info *mci)
>  {
>  	struct skx_pvt *pvt = mci->pvt_info;
> +	u32 mtr, mcmtr, amap, mcddrtcfg;
>  	struct skx_imc *imc = pvt->imc;
> -	u32 mtr, amap, mcddrtcfg;
>  	struct dimm_info *dimm;
>  	int i, j;
>  	int ndimms;
>  
> +	/* Only the mcmtr on the first channel is effective */
> +	pci_read_config_dword(imc->chan[0].cdev, 0x87c, &mcmtr);
> +
>  	for (i = 0; i < SKX_NUM_CHANNELS; i++) {
>  		ndimms = 0;
>  		pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap);
> @@ -199,14 +195,14 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci)
>  			pci_read_config_dword(imc->chan[i].cdev,
>  					      0x80 + 4 * j, &mtr);
>  			if (IS_DIMM_PRESENT(mtr)) {
> -				ndimms += skx_get_dimm_info(mtr, amap, dimm, imc, i, j);
> +				ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j);
>  			} else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) {
>  				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
>  							      EDAC_MOD_STR);
>  				nvdimm_count++;
>  			}
>  		}
> -		if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) {
> +		if (ndimms && !skx_check_ecc(mcmtr)) {
>  			skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc);
>  			return -ENODEV;
>  		}
> diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
> index abc9ddd2b7d1..46be1a77bd1d 100644
> --- a/drivers/edac/skx_common.c
> +++ b/drivers/edac/skx_common.c
> @@ -303,7 +303,7 @@ static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
>  #define numrow(reg)	skx_get_dimm_attr(reg, 2, 4, 12, 1, 6, "rows")
>  #define numcol(reg)	skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols")
>  
> -int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
> +int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
>  		      struct skx_imc *imc, int chan, int dimmno)
>  {
>  	int  banks = 16, ranks, rows, cols, npages;
> @@ -323,8 +323,8 @@ int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
>  		 imc->mc, chan, dimmno, size, npages,
>  		 banks, 1 << ranks, rows, cols);
>  
> -	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0);
> -	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9);
> +	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mcmtr, 0, 0);
> +	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mcmtr, 9, 9);
>  	imc->chan[chan].dimms[dimmno].fine_grain_bank = GET_BITFIELD(amap, 0, 0);
>  	imc->chan[chan].dimms[dimmno].rowbits = rows;
>  	imc->chan[chan].dimms[dimmno].colbits = cols;
> diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
> index 19dd8c099520..78f8c1de0b71 100644
> --- a/drivers/edac/skx_common.h
> +++ b/drivers/edac/skx_common.h
> @@ -135,7 +135,7 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list);
>  
>  int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);
>  
> -int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
> +int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
>  		      struct skx_imc *imc, int chan, int dimmno);
>  
>  int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,

Acked-by: Aristeu Rozanski <aris@redhat.com>

-- 
Aristeu


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, back to index

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-15 21:01 [PATCH v1 1/1] EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable Tony Luck
2020-05-18 14:21 ` Aristeu Rozanski

Linux-EDAC Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-edac/0 linux-edac/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-edac linux-edac/ https://lore.kernel.org/linux-edac \
		linux-edac@vger.kernel.org
	public-inbox-index linux-edac

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-edac


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git