Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1711083 > unrolled thread
| Started by | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| First post | 2017-08-14 18:00 +0200 |
| Last post | 2017-08-15 18:30 +0200 |
| Articles | 20 on this page of 30 — 4 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 18:00 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 18:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 18:50 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 19:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 20:00 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 20:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 20:20 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 20:40 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 21:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 21:40 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-14 22:20 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-14 22:40 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-15 17:40 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Luck, Tony" <tony.luck@intel.com> - 2017-08-15 17:50 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-15 18:00 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 10:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 13:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Steven Rostedt <rostedt@goodmis.org> - 2017-08-16 16:00 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 16:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Steven Rostedt <rostedt@goodmis.org> - 2017-08-16 16:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 19:40 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-16 17:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 18:50 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-16 19:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-16 19:50 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-16 20:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-17 23:10 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-21 11:30 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() Borislav Petkov <bp@alien8.de> - 2017-08-15 18:00 +0200
Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-08-15 18:30 +0200
Page 1 of 2 [1] 2 Next page →
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 18:00 +0200 |
| Subject | Re: [PATCH v2 4/7] ghes_edac: avoid multiple calls to dmi_walk() |
| Message-ID | <uepWy-60G-33@gated-at.bofh.it> |
On Fri, 2017-08-11 at 11:04 +0200, Borislav Petkov wrote: > On Mon, Aug 07, 2017 at 05:59:15PM +0000, Kani, Toshimitsu wrote: > > I think we should keep the current scheme, which registers an mci > > for > > No we shouldn't. > > > each GHES entry. ghes_edac_report_mem_error() expects that error- > > reporting is serialized per a GHES entry. Sharing a single mci > > among all GHES entries / error interfaces might lead to a race > > condition. > > See how I solved it in my patchset and feel free to reuse it. Hmm... Sorry, I failed to see how your patchset solved it. Would you mind to explain how it is done? Thanks! -Toshi
[toc] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 18:30 +0200 |
| Message-ID | <ueqpA-6qC-33@gated-at.bofh.it> |
| In reply to | #1711083 |
On Mon, Aug 14, 2017 at 03:57:35PM +0000, Kani, Toshimitsu wrote:
> Hmm... Sorry, I failed to see how your patchset solved it. Would you
> mind to explain how it is done?
+static int __init ghes_edac_register(void)
{
+ struct ghes_edac_pvt *pvt = ghes_pvt;
Only one local ghes_pvt structure.
And you handle multiple calls into ghes_edac_register() by exiting all
those which are not the first one as the first one already did all the
init.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 18:50 +0200 |
| Message-ID | <ueqIW-6xI-25@gated-at.bofh.it> |
| In reply to | #1711159 |
On Mon, 2017-08-14 at 18:24 +0200, Borislav Petkov wrote:
> On Mon, Aug 14, 2017 at 03:57:35PM +0000, Kani, Toshimitsu wrote:
> > Hmm... Sorry, I failed to see how your patchset solved it. Would
> > you mind to explain how it is done?
>
> +static int __init ghes_edac_register(void)
> {
> + struct ghes_edac_pvt *pvt = ghes_pvt;
>
> Only one local ghes_pvt structure.
>
> And you handle multiple calls into ghes_edac_register() by exiting
> all those which are not the first one as the first one already did
> all the init.
Right, but the issue is how [ghes_edac_]report_mem_error() protects
from possible concurrent calls from multiple GHES sources when there is
only a single mci.
Thanks,
-Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 19:10 +0200 |
| Message-ID | <uer2h-6Tj-7@gated-at.bofh.it> |
| In reply to | #1711220 |
On Mon, Aug 14, 2017 at 04:48:57PM +0000, Kani, Toshimitsu wrote:
> Right, but the issue is how [ghes_edac_]report_mem_error() protects
> from possible concurrent calls from multiple GHES sources when there is
> only a single mci.
Do you know of an actual firmware reporting multiple errors concurrently?
GHES v2 even needs to ACK the current error first before it can read the
next one.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 20:00 +0200 |
| Message-ID | <uerOF-79Q-7@gated-at.bofh.it> |
| In reply to | #1711259 |
On Mon, 2017-08-14 at 19:05 +0200, Borislav Petkov wrote: > On Mon, Aug 14, 2017 at 04:48:57PM +0000, Kani, Toshimitsu wrote: > > Right, but the issue is how [ghes_edac_]report_mem_error() protects > > from possible concurrent calls from multiple GHES sources when > > there is only a single mci. > > Do you know of an actual firmware reporting multiple errors > concurrently? I do not know. We have multiple GHES entries, but they all use SCI. Since ACPICA uses a single threaded workqueue for notify handlers, they are serialized among SCIs. ACPI 6.2 defines multiple notification types in Table 18-383, and ghes_proc() can be called from ghes_poll_func(), ghes_irq_func(), and ghes_notify_sci(). So, I think it is safe to operate per an entry basis. > GHES v2 even needs to ACK the current error first before it can read > the next one. Yes, but this ACK is done per a GHES entry as well. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 20:10 +0200 |
| Message-ID | <uerYl-7s4-1@gated-at.bofh.it> |
| In reply to | #1711301 |
On Mon, Aug 14, 2017 at 05:52:25PM +0000, Kani, Toshimitsu wrote:
> Yes, but this ACK is done per a GHES entry as well.
So is the ghes_edac_report_mem_error() call.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 20:20 +0200 |
| Message-ID | <ues81-7vo-3@gated-at.bofh.it> |
| In reply to | #1711315 |
On Mon, 2017-08-14 at 20:05 +0200, Borislav Petkov wrote: > On Mon, Aug 14, 2017 at 05:52:25PM +0000, Kani, Toshimitsu wrote: > > Yes, but this ACK is done per a GHES entry as well. > > So is the ghes_edac_report_mem_error() call. Right, ghes_edac_report_mem_error() gets serialized per a GHES entry, but not globally. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 20:40 +0200 |
| Message-ID | <uesrn-7E5-3@gated-at.bofh.it> |
| In reply to | #1711323 |
On Mon, Aug 14, 2017 at 06:17:47PM +0000, Kani, Toshimitsu wrote:
> Right, ghes_edac_report_mem_error() gets serialized per a GHES entry,
> but not globally.
Globally what?
What is the actual potential scenario for concurrency issues you see?
Example pls.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 21:10 +0200 |
| Message-ID | <uesUp-83a-7@gated-at.bofh.it> |
| In reply to | #1711336 |
On Mon, 2017-08-14 at 20:35 +0200, Borislav Petkov wrote: > On Mon, Aug 14, 2017 at 06:17:47PM +0000, Kani, Toshimitsu wrote: > > Right, ghes_edac_report_mem_error() gets serialized per a GHES > > entry, but not globally. > > Globally what? GHES v2's ACK is not a global lock. So, it does not guarantee that ghes_edac_report_mem_error() never gets called concurrently. > What is the actual potential scenario for concurrency issues you see? > Example pls. ghes_probe() supports multiple sources defined in acpi_hest_notify_types. Say, there are two entries for memory errors, one with ACPI_HEST_NOTIFY_EXTERNAL and the other with ACPI_HEST_NOTIFY_SCI. They may report errors independently. While ghes_edac_report_mem_error() is being called from the SCI, it can be called from the ext interrupt at a same time. I do not know how likely we see such case, but the code should be written according to the spec. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 21:40 +0200 |
| Message-ID | <uetnr-8cy-9@gated-at.bofh.it> |
| In reply to | #1711356 |
On Mon, Aug 14, 2017 at 07:02:15PM +0000, Kani, Toshimitsu wrote:
> I do not know how likely we see such case, but the code should be
> written according to the spec.
Well, then you'll have to make ghes_edac_report_mem_error() reentrant.
Which doesn't look that hard as the only thing it really needs from
struct ghes_edac_pvt are those string buffers. I guess you can try to do
the simplest thing first and allocate them on the stack.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-14 22:20 +0200 |
| Message-ID | <ueu0a-dy-5@gated-at.bofh.it> |
| In reply to | #1711382 |
On Mon, 2017-08-14 at 21:34 +0200, Borislav Petkov wrote: > On Mon, Aug 14, 2017 at 07:02:15PM +0000, Kani, Toshimitsu wrote: > > I do not know how likely we see such case, but the code should be > > written according to the spec. > > Well, then you'll have to make ghes_edac_report_mem_error() > reentrant. Which doesn't look that hard as the only thing it really > needs from struct ghes_edac_pvt are those string buffers. I guess you > can try to do the simplest thing first and allocate them on the > stack. ghes_edac_report_mem_error() is reentrant as it is now. I think the current code design of allocating mci & ghes_edac_pvt for each GHES source entry makes sense. edac_raw_mc_handle_error() also has the same expectation that the call is serialized per mci. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-14 22:40 +0200 |
| Message-ID | <ueujv-jF-1@gated-at.bofh.it> |
| In reply to | #1711403 |
On Mon, Aug 14, 2017 at 08:17:54PM +0000, Kani, Toshimitsu wrote:
> I think the current code design of allocating mci & ghes_edac_pvt for
> each GHES source entry makes sense.
And I don't.
> edac_raw_mc_handle_error() also has the same expectation that the call
> is serialized per mci.
There's no such thing as "per mci" if the driver scans *all DIMMs* per
register call. If it does it this way, then it is only one mci.
It is actually wrong right now because if you register more than one
mci and you do edac_inc_ce_error()/edac_inc_ue_error(), potentially
different counters get incremented for the same errors. Exactly because
each instance registered is *wrongly* responsible for all DIMMs on the
system.
So you either need to partition the DIMMs per mci (which I can't imagine
how it would work) or introduce locking when incrementing the mci->
counters.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-15 17:40 +0200 |
| Message-ID | <ueM6J-33T-1@gated-at.bofh.it> |
| In reply to | #1711424 |
On Mon, 2017-08-14 at 22:39 +0200, Borislav Petkov wrote: > On Mon, Aug 14, 2017 at 08:17:54PM +0000, Kani, Toshimitsu wrote: > > I think the current code design of allocating mci & ghes_edac_pvt > > for each GHES source entry makes sense. > > And I don't. > > > edac_raw_mc_handle_error() also has the same expectation that the > > call is serialized per mci. > > There's no such thing as "per mci" if the driver scans *all DIMMs* > per register call. If it does it this way, then it is only one mci. ghes_edac instantiates an mci as a pseudo device representing a GHES error source. Each error source associates with all DIMMs, and may report errors independently. As ghes_edac is an GHES error-reporting wrapper to edac, this abstraction makes sense. > It is actually wrong right now because if you register more than one > mci and you do edac_inc_ce_error()/edac_inc_ue_error(), potentially > different counters get incremented for the same errors. Exactly > because each instance registered is *wrongly* responsible for all > DIMMs on the system. I do not see a problem in having counters for each GHES error source. This is just statistics info, and ghes_edac does not expect any OS action from the counters. > So you either need to partition the DIMMs per mci (which I can't > imagine how it would work) or introduce locking when incrementing the > mci->counters. I do not think changing the calling convention to edac library interfaces is a good idea for a special case like ghes_edac. Such changes can be a burden for us going forward. I think ghes_edac just needs to work with the current prerequisite. User apps like ras-mc-ctl works as expected for a given (not-so-great) DIMM info from SMBIOS as well. I do not see a probelm from user perspective, either. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | "Luck, Tony" <tony.luck@intel.com> |
|---|---|
| Date | 2017-08-15 17:50 +0200 |
| Message-ID | <ueMgp-37n-7@gated-at.bofh.it> |
| In reply to | #1712259 |
On Tue, Aug 15, 2017 at 08:35:51AM -0700, Kani, Toshimitsu wrote: > User apps like ras-mc-ctl works as expected for a given (not-so-great) > DIMM info from SMBIOS as well. I do not see a probelm from user > perspective, either. Won't the user see all their DIMMs reported for each memory controller under /sys/devices/system/edac/mc/mc*/dimm* ? That sounds confusing. -Tony
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-08-15 18:00 +0200 |
| Message-ID | <ueMq6-3aI-17@gated-at.bofh.it> |
| In reply to | #1712276 |
On Tue, 2017-08-15 at 08:48 -0700, Luck, Tony wrote: > On Tue, Aug 15, 2017 at 08:35:51AM -0700, Kani, Toshimitsu wrote: > > User apps like ras-mc-ctl works as expected for a given (not-so- > > great) DIMM info from SMBIOS as well. I do not see a probelm from > > user perspective, either. > > Won't the user see all their DIMMs reported for each memory > controller under /sys/devices/system/edac/mc/mc*/dimm* ? > > That sounds confusing. ghes_edac only fills dimm_info to the first mci. So, users do not see duplicated info. Thanks, -Toshi
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-16 10:30 +0200 |
| Message-ID | <uf1S9-4H6-11@gated-at.bofh.it> |
| In reply to | #1712276 |
On Tue, Aug 15, 2017 at 08:48:16AM -0700, Luck, Tony wrote:
> Won't the user see all their DIMMs reported for each memory controller
> under /sys/devices/system/edac/mc/mc*/dimm* ?
>
> That sounds confusing.
Right, and adding the locking was really easy. If only people would
debate less and actually try to do what they're being advised to.
But not really: if you wanna have something done, you have to do it
yourself.
Anyway, I think I have a box to run it to, lemme go find it.
Steve, pls check my locking. It looks straightforward to me but I might
be missing some corner case.
Thx.
---
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index 6f80eb65c26c..a22fabef4791 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -28,10 +28,14 @@ struct ghes_edac_pvt {
char msg[80];
};
-static LIST_HEAD(ghes_reglist);
-static DEFINE_MUTEX(ghes_edac_lock);
-static int ghes_edac_mc_num;
+static struct ghes_edac_pvt *ghes_pvt;
+/*
+ * Sync with other, potentially concurrent callers of
+ * ghes_edac_report_mem_error(). We don't know what the
+ * "inventive" firmware would do.
+ */
+static DEFINE_SPINLOCK(ghes_lock);
/* Memory Device - Type 17 of SMBIOS spec */
struct memdev_dmi_entry {
@@ -169,14 +173,11 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
enum hw_event_mc_err_type type;
struct edac_raw_error_desc *e;
struct mem_ctl_info *mci;
- struct ghes_edac_pvt *pvt = NULL;
+ struct ghes_edac_pvt *pvt = ghes_pvt;
+ unsigned long flags;
char *p;
u8 grain_bits;
- list_for_each_entry(pvt, &ghes_reglist, list) {
- if (ghes == pvt->ghes)
- break;
- }
if (!pvt) {
pr_err("Internal error: Can't find EDAC structure\n");
return;
@@ -398,8 +399,16 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
(e->page_frame_number << PAGE_SHIFT) | e->offset_in_page,
grain_bits, e->syndrome, pvt->detail_location);
- /* Report the error via EDAC API */
+ /*
+ * We can do the locking below because GHES defers error processing
+ * from NMI to IRQ context. Whenever that changes, we'd at least
+ * know.
+ */
+ WARN_ON_ONCE(in_nmi());
+
+ spin_lock_irqsave(&ghes_lock, flags);
edac_raw_mc_handle_error(type, mci, e);
+ spin_unlock_irqrestore(&ghes_lock, flags);
}
EXPORT_SYMBOL_GPL(ghes_edac_report_mem_error);
@@ -409,9 +418,14 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
int rc, num_dimm = 0;
struct mem_ctl_info *mci;
struct edac_mc_layer layers[1];
- struct ghes_edac_pvt *pvt;
struct ghes_edac_dimm_fill dimm_fill;
+ /*
+ * We have only one logical memory controller to which all DIMMs belong.
+ */
+ if (ghes_pvt)
+ return 0;
+
/* Get the number of DIMMs */
dmi_walk(ghes_edac_count_dimms, &num_dimm);
@@ -425,26 +439,17 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
layers[0].size = num_dimm;
layers[0].is_virt_csrow = true;
- /*
- * We need to serialize edac_mc_alloc() and edac_mc_add_mc(),
- * to avoid duplicated memory controller numbers
- */
- mutex_lock(&ghes_edac_lock);
- mci = edac_mc_alloc(ghes_edac_mc_num, ARRAY_SIZE(layers), layers,
- sizeof(*pvt));
+ mci = edac_mc_alloc(1, ARRAY_SIZE(layers), layers, sizeof(struct ghes_edac_pvt));
if (!mci) {
pr_info("Can't allocate memory for EDAC data\n");
- mutex_unlock(&ghes_edac_lock);
return -ENOMEM;
}
- pvt = mci->pvt_info;
- memset(pvt, 0, sizeof(*pvt));
- list_add_tail(&pvt->list, &ghes_reglist);
- pvt->ghes = ghes;
- pvt->mci = mci;
- mci->pdev = dev;
+ ghes_pvt = mci->pvt_info;
+ ghes_pvt->ghes = ghes;
+ ghes_pvt->mci = mci;
+ mci->pdev = dev;
mci->mtype_cap = MEM_FLAG_EMPTY;
mci->edac_ctl_cap = EDAC_FLAG_NONE;
mci->edac_cap = EDAC_FLAG_NONE;
@@ -452,36 +457,23 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
mci->ctl_name = "ghes_edac";
mci->dev_name = "ghes";
- if (!ghes_edac_mc_num) {
- if (!fake) {
- pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n");
- pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n");
- pr_info("So, the end result of using this driver varies from vendor to vendor.\n");
- pr_info("If you find incorrect reports, please contact your hardware vendor\n");
- pr_info("to correct its BIOS.\n");
- pr_info("This system has %d DIMM sockets.\n",
- num_dimm);
- } else {
- pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");
- pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");
- pr_info("work on such system. Use this driver with caution\n");
- }
+ if (!fake) {
+ pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n");
+ pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n");
+ pr_info("So, the end result of using this driver varies from vendor to vendor.\n");
+ pr_info("If you find incorrect reports, please contact your hardware vendor\n");
+ pr_info("to correct its BIOS.\n");
+ pr_info("This system has %d DIMM sockets.\n", num_dimm);
+ } else {
+ pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");
+ pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");
+ pr_info("work on such system. Use this driver with caution\n");
}
if (!fake) {
- /*
- * Fill DIMM info from DMI for the memory controller #0
- *
- * Keep it in blank for the other memory controllers, as
- * there's no reliable way to properly credit each DIMM to
- * the memory controller, as different BIOSes fill the
- * DMI bank location fields on different ways
- */
- if (!ghes_edac_mc_num) {
- dimm_fill.count = 0;
- dimm_fill.mci = mci;
- dmi_walk(ghes_edac_dmidecode, &dimm_fill);
- }
+ dimm_fill.count = 0;
+ dimm_fill.mci = mci;
+ dmi_walk(ghes_edac_dmidecode, &dimm_fill);
} else {
struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
mci->n_layers, 0, 0, 0);
@@ -497,12 +489,8 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
if (rc < 0) {
pr_info("Can't register at EDAC core\n");
edac_mc_free(mci);
- mutex_unlock(&ghes_edac_lock);
return -ENODEV;
}
-
- ghes_edac_mc_num++;
- mutex_unlock(&ghes_edac_lock);
return 0;
}
EXPORT_SYMBOL_GPL(ghes_edac_register);
@@ -510,15 +498,9 @@ EXPORT_SYMBOL_GPL(ghes_edac_register);
void ghes_edac_unregister(struct ghes *ghes)
{
struct mem_ctl_info *mci;
- struct ghes_edac_pvt *pvt, *tmp;
-
- list_for_each_entry_safe(pvt, tmp, &ghes_reglist, list) {
- if (ghes == pvt->ghes) {
- mci = pvt->mci;
- edac_mc_del_mc(mci->pdev);
- edac_mc_free(mci);
- list_del(&pvt->list);
- }
- }
+
+ mci = ghes_pvt->mci;
+ edac_mc_del_mc(mci->pdev);
+ edac_mc_free(mci);
}
EXPORT_SYMBOL_GPL(ghes_edac_unregister);
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-16 13:30 +0200 |
| Message-ID | <uf4Gl-6q1-1@gated-at.bofh.it> |
| In reply to | #1712765 |
On Wed, Aug 16, 2017 at 10:29:31AM +0200, Borislav Petkov wrote:
> Anyway, I think I have a box to run it to, lemme go find it.
Seems to boot.
It's a whole another story whether it actually works. :-)
Need some EINJ capabilities urgently but finding a box where it works
reliably is like finding gold.
[ 7.784960] ERST: Failed to get Error Log Address Range.
[ 7.795905] EDAC DEBUG: edac_mc_alloc: allocating 2444 bytes for mci data (16 dimms, 16 csrows/ch
annels)
[ 7.815266] ghes_edac: This EDAC driver relies on BIOS to enumerate memory and get error reports.
[ 7.833372] ghes_edac: Unfortunately, not all BIOSes reflect the memory layout correctly.
[ 7.850093] ghes_edac: So, the end result of using this driver varies from vendor to vendor.
[ 7.867322] ghes_edac: If you find incorrect reports, please contact your hardware vendor
[ 7.884034] ghes_edac: to correct its BIOS.
[ 7.892599] ghes_edac: This system has 16 DIMM sockets.
[ 7.903274] EDAC DEBUG: ghes_edac_dmidecode: DIMM8: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 7.920337] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 7.936532] EDAC DEBUG: ghes_edac_dmidecode: DIMM9: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 7.953591] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 7.969778] EDAC DEBUG: ghes_edac_dmidecode: DIMM10: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 7.987010] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.003199] EDAC DEBUG: ghes_edac_dmidecode: DIMM11: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 8.020432] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.036618] EDAC DEBUG: ghes_edac_dmidecode: DIMM12: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 8.053848] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.070038] EDAC DEBUG: ghes_edac_dmidecode: DIMM13: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 8.087268] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.103456] EDAC DEBUG: ghes_edac_dmidecode: DIMM14: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 8.120687] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.128053] tsc: Refined TSC clocksource calibration: 2099.999 MHz
[ 8.128173] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x1e452fc488e, max_idle_ns: 44
0795307124 ns
[ 8.169800] EDAC DEBUG: ghes_edac_dmidecode: DIMM15: Unbuffered DDR3 RAM size = 2048 MB(ECC)
[ 8.187043] EDAC DEBUG: ghes_edac_dmidecode: type 24, detail 0x80, width 72(total 64)
[ 8.203230] EDAC DEBUG: edac_mc_add_mc_with_groups:
[ 8.213363] EDAC DEBUG: edac_create_sysfs_mci_device: creating bus mc1
[ 8.226643] EDAC DEBUG: edac_create_sysfs_mci_device: creating device mc1
[ 8.240450] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm8, located at memory 8
[ 8.257362] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm8
[ 8.272506] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm9, located at memory 9
[ 8.289409] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm9
[ 8.304556] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm10, located at memory 10
[ 8.321808] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm10
[ 8.337126] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm11, located at memory 11
[ 8.354377] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm11
[ 8.369697] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm12, located at memory 12
[ 8.386946] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm12
[ 8.402266] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm13, located at memory 13
[ 8.419516] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm13
[ 8.434835] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm14, located at memory 14
[ 8.452094] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm14
[ 8.467423] EDAC DEBUG: edac_create_sysfs_mci_device: creating dimm15, located at memory 15
[ 8.484674] EDAC DEBUG: edac_create_dimm_object: creating rank/dimm device dimm15
[ 8.499994] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow8
[ 8.516215] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow9
[ 8.532433] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow10
[ 8.548824] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow11
[ 8.565203] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow12
[ 8.581585] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow13
[ 8.597964] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow14
[ 8.614347] EDAC DEBUG: edac_create_csrow_object: creating (virtual) csrow node csrow15
[ 8.630744] EDAC MC1: Giving out device to module ghes_edac.c controller ghes_edac: DEV ghes (INTERRUPT)
[ 8.650073] [Firmware Warn]: GHES: Poll interval is 0 for generic hardware error source: 1, disabled.
[ 8.669012] GHES: APEI firmware first mode is enabled by WHEA _OSC.
[ 8.681940] Serial: 8250/16550 driver, 32 ports, IRQ sharing disabled
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-08-16 16:00 +0200 |
| Message-ID | <uf71v-7Lj-3@gated-at.bofh.it> |
| In reply to | #1712765 |
On Wed, 16 Aug 2017 10:29:31 +0200
Borislav Petkov <bp@alien8.de> wrote:
> ---
> diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
> index 6f80eb65c26c..a22fabef4791 100644
> --- a/drivers/edac/ghes_edac.c
> +++ b/drivers/edac/ghes_edac.c
> @@ -28,10 +28,14 @@ struct ghes_edac_pvt {
> char msg[80];
> };
>
> -static LIST_HEAD(ghes_reglist);
> -static DEFINE_MUTEX(ghes_edac_lock);
> -static int ghes_edac_mc_num;
> +static struct ghes_edac_pvt *ghes_pvt;
>
> +/*
> + * Sync with other, potentially concurrent callers of
> + * ghes_edac_report_mem_error(). We don't know what the
> + * "inventive" firmware would do.
> + */
> +static DEFINE_SPINLOCK(ghes_lock);
>
> /* Memory Device - Type 17 of SMBIOS spec */
> struct memdev_dmi_entry {
> @@ -169,14 +173,11 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
> enum hw_event_mc_err_type type;
> struct edac_raw_error_desc *e;
> struct mem_ctl_info *mci;
> - struct ghes_edac_pvt *pvt = NULL;
> + struct ghes_edac_pvt *pvt = ghes_pvt;
> + unsigned long flags;
> char *p;
> u8 grain_bits;
>
> - list_for_each_entry(pvt, &ghes_reglist, list) {
> - if (ghes == pvt->ghes)
> - break;
> - }
> if (!pvt) {
> pr_err("Internal error: Can't find EDAC structure\n");
> return;
> @@ -398,8 +399,16 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
> (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page,
> grain_bits, e->syndrome, pvt->detail_location);
>
> - /* Report the error via EDAC API */
> + /*
> + * We can do the locking below because GHES defers error processing
> + * from NMI to IRQ context. Whenever that changes, we'd at least
> + * know.
> + */
> + WARN_ON_ONCE(in_nmi());
Should the above be:
if (WARN_ON_ONCE(in_nmi()))
return;
To prevent a deadlock? Or do we not care?
> +
> + spin_lock_irqsave(&ghes_lock, flags);
> edac_raw_mc_handle_error(type, mci, e);
> + spin_unlock_irqrestore(&ghes_lock, flags);
The above looks fine, as long as there's nothing before it that needs
synchronization.
> }
> EXPORT_SYMBOL_GPL(ghes_edac_report_mem_error);
>
> @@ -409,9 +418,14 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
> int rc, num_dimm = 0;
> struct mem_ctl_info *mci;
> struct edac_mc_layer layers[1];
> - struct ghes_edac_pvt *pvt;
> struct ghes_edac_dimm_fill dimm_fill;
>
> + /*
> + * We have only one logical memory controller to which all DIMMs belong.
> + */
> + if (ghes_pvt)
> + return 0;
What's the likelihood of two calls to ghes_edac_register being done
simultaneously? Because two calls at the same time will get past this.
-- Steve
> +
> /* Get the number of DIMMs */
> dmi_walk(ghes_edac_count_dimms, &num_dimm);
>
> @@ -425,26 +439,17 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
> layers[0].size = num_dimm;
> layers[0].is_virt_csrow = true;
>
> - /*
> - * We need to serialize edac_mc_alloc() and edac_mc_add_mc(),
> - * to avoid duplicated memory controller numbers
> - */
> - mutex_lock(&ghes_edac_lock);
> - mci = edac_mc_alloc(ghes_edac_mc_num, ARRAY_SIZE(layers), layers,
> - sizeof(*pvt));
> + mci = edac_mc_alloc(1, ARRAY_SIZE(layers), layers, sizeof(struct ghes_edac_pvt));
> if (!mci) {
> pr_info("Can't allocate memory for EDAC data\n");
> - mutex_unlock(&ghes_edac_lock);
> return -ENOMEM;
> }
>
> - pvt = mci->pvt_info;
> - memset(pvt, 0, sizeof(*pvt));
> - list_add_tail(&pvt->list, &ghes_reglist);
> - pvt->ghes = ghes;
> - pvt->mci = mci;
> - mci->pdev = dev;
> + ghes_pvt = mci->pvt_info;
> + ghes_pvt->ghes = ghes;
> + ghes_pvt->mci = mci;
>
> + mci->pdev = dev;
> mci->mtype_cap = MEM_FLAG_EMPTY;
> mci->edac_ctl_cap = EDAC_FLAG_NONE;
> mci->edac_cap = EDAC_FLAG_NONE;
> @@ -452,36 +457,23 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
> mci->ctl_name = "ghes_edac";
> mci->dev_name = "ghes";
>
> - if (!ghes_edac_mc_num) {
> - if (!fake) {
> - pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n");
> - pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n");
> - pr_info("So, the end result of using this driver varies from vendor to vendor.\n");
> - pr_info("If you find incorrect reports, please contact your hardware vendor\n");
> - pr_info("to correct its BIOS.\n");
> - pr_info("This system has %d DIMM sockets.\n",
> - num_dimm);
> - } else {
> - pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");
> - pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");
> - pr_info("work on such system. Use this driver with caution\n");
> - }
> + if (!fake) {
> + pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n");
> + pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n");
> + pr_info("So, the end result of using this driver varies from vendor to vendor.\n");
> + pr_info("If you find incorrect reports, please contact your hardware vendor\n");
> + pr_info("to correct its BIOS.\n");
> + pr_info("This system has %d DIMM sockets.\n", num_dimm);
> + } else {
> + pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");
> + pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");
> + pr_info("work on such system. Use this driver with caution\n");
> }
>
> if (!fake) {
> - /*
> - * Fill DIMM info from DMI for the memory controller #0
> - *
> - * Keep it in blank for the other memory controllers, as
> - * there's no reliable way to properly credit each DIMM to
> - * the memory controller, as different BIOSes fill the
> - * DMI bank location fields on different ways
> - */
> - if (!ghes_edac_mc_num) {
> - dimm_fill.count = 0;
> - dimm_fill.mci = mci;
> - dmi_walk(ghes_edac_dmidecode, &dimm_fill);
> - }
> + dimm_fill.count = 0;
> + dimm_fill.mci = mci;
> + dmi_walk(ghes_edac_dmidecode, &dimm_fill);
> } else {
> struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
> mci->n_layers, 0, 0, 0);
> @@ -497,12 +489,8 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
> if (rc < 0) {
> pr_info("Can't register at EDAC core\n");
> edac_mc_free(mci);
> - mutex_unlock(&ghes_edac_lock);
> return -ENODEV;
> }
> -
> - ghes_edac_mc_num++;
> - mutex_unlock(&ghes_edac_lock);
> return 0;
> }
> EXPORT_SYMBOL_GPL(ghes_edac_register);
> @@ -510,15 +498,9 @@ EXPORT_SYMBOL_GPL(ghes_edac_register);
> void ghes_edac_unregister(struct ghes *ghes)
> {
> struct mem_ctl_info *mci;
> - struct ghes_edac_pvt *pvt, *tmp;
> -
> - list_for_each_entry_safe(pvt, tmp, &ghes_reglist, list) {
> - if (ghes == pvt->ghes) {
> - mci = pvt->mci;
> - edac_mc_del_mc(mci->pdev);
> - edac_mc_free(mci);
> - list_del(&pvt->list);
> - }
> - }
> +
> + mci = ghes_pvt->mci;
> + edac_mc_del_mc(mci->pdev);
> + edac_mc_free(mci);
> }
> EXPORT_SYMBOL_GPL(ghes_edac_unregister);
>
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-08-16 16:10 +0200 |
| Message-ID | <uf7bc-83I-27@gated-at.bofh.it> |
| In reply to | #1712975 |
On Wed, Aug 16, 2017 at 09:59:01AM -0400, Steven Rostedt wrote:
> Should the above be:
>
> if (WARN_ON_ONCE(in_nmi()))
> return;
>
> To prevent a deadlock? Or do we not care?
Yeah, better this way.
> What's the likelihood of two calls to ghes_edac_register being done
> simultaneously? Because two calls at the same time will get past this.
Well, that thing gets called per GHES platform device and last time I
checked they do get probed back-to-back but I'll check that again.
Thanks.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-08-16 16:30 +0200 |
| Message-ID | <uf7uy-8bJ-17@gated-at.bofh.it> |
| In reply to | #1712986 |
On Wed, 16 Aug 2017 16:03:50 +0200 Borislav Petkov <bp@alien8.de> wrote: > > What's the likelihood of two calls to ghes_edac_register being done > > simultaneously? Because two calls at the same time will get past this. > > Well, that thing gets called per GHES platform device and last time I > checked they do get probed back-to-back but I'll check that again. Maybe keep that original mutex just in case. -- Steve
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web