Date: Wed, 26 May 2010 15:55:52 +0200 From: Giovanni Trematerra <giovanni.trematerra@gmail.com> To: David DEMELIER <demelier.david@gmail.com> Cc: Brandon Gooch <jamesbrandongooch@gmail.com>, freebsd-stable@freebsd.org Subject: Re: Kernel panic when unpluggin AC adaptor Message-ID: <AANLkTinWSNyllR4-H22gEpohbyt2Uoc5EBS3fhgBKb9s@mail.gmail.com> In-Reply-To: <AANLkTilfQjZjJACh1dj7XEHN7uZ36_8N0uh5sX_4eOHk@mail.gmail.com> References: <4DEBDE2C-C0D2-469D-AC42-DD5027926424@FreeBSD.org> <AANLkTilcNzzLt2GUPbL_Vqjspzx5a-oem1oZpKAYqoN8@mail.gmail.com> <AANLkTinYntwwReJDB0blprk1TCy7j1xKca0LzTgUJBDe@mail.gmail.com> <AANLkTikOBiz6XI55pEFlG-SS07r7yyz2o9PifWB9vgHB@mail.gmail.com> <AANLkTinpUCeQpayi-ZjMAyJ6tNhXT5PWM0zLsntgbJ3P@mail.gmail.com> <AANLkTik6oKg1jFWD2zoS7fUZzZl-3Pj-EhgGa2xKer94@mail.gmail.com> <AANLkTimf7wzXoTjvdF07pkrUmU9qYVsxpUtbnmaNX6vv@mail.gmail.com> <AANLkTin7cURd4nS5de7lmtY3igFGGynd1w85Ywj2NCK3@mail.gmail.com> <AANLkTikQygqvB93L8RjGYF2k8ouIjzLFvxUJTuoOPWhc@mail.gmail.com> <AANLkTilfQjZjJACh1dj7XEHN7uZ36_8N0uh5sX_4eOHk@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] On Wed, May 26, 2010 at 3:55 PM, Giovanni Trematerra <giovanni.trematerra@gmail.com> wrote: > On Wed, May 26, 2010 at 12:01 PM, David DEMELIER > <demelier.david@gmail.com> wrote: >> 2010/5/26 Giovanni Trematerra <giovanni.trematerra@gmail.com>: >>> On Wed, May 26, 2010 at 11:14 AM, David DEMELIER >>> <demelier.david@gmail.com> wrote: >>>> 2010/5/25 Giovanni Trematerra <giovanni.trematerra@gmail.com>: >>>>> On Tue, May 25, 2010 at 5:52 PM, David DEMELIER >>>>> <demelier.david@gmail.com> wrote: >>>>>> 2010/5/25 Giovanni Trematerra <giovanni.trematerra@gmail.com>: >>>>>>> On Mon, May 24, 2010 at 9:43 PM, David DEMELIER >>>>>>> <demelier.david@gmail.com> wrote: >>>>>>>> 2010/5/12 Giovanni Trematerra <giovanni.trematerra@gmail.com>: >>>>>>>>> On Fri, May 7, 2010 at 8:33 PM, Demelier David <demelier.david@gmail.com> wrote: >>>>>>>>>> Le Vendredi 07 mai 2010 ŕ 18:22 +0200, Giovanni Trematerra a écrit : >>>>>>>>>>> On Fri, May 7, 2010 at 2:08 PM, Demelier David <demelier.david@gmail.com> wrote: >>>>>>>>>>> > Hi, >>>>>>>>>>> > I noticed that pluggin the AC adaptor when I boot without it does not >>>>>>>>>>> > panic. It only panic when removing it. >>>>>>>>>>> > >>>>>>>>>>> > Maybe that could help ? >>>>>>>>>>> > >>>>>>>>>>> >>>>>>>>>>> Good to know. The problem lies somewhere when performance state change. >>>>>>>>>>> In your case it happens when you remove AC adaptor. Let's hope someone on >>>>>>>>>>> acpi@ ml comes up with a good idea. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Okay so for the moment no change, I'll wait for someone with an idea >>>>>>>>>> that could solve my problem. For me because the panic only happens when >>>>>>>>>> changing profile from ac plugged -> ac unplugged (and not the reverse) I >>>>>>>>>> would think it's a cpu related acpi issue. >>>>>>>>>> >>>>>>>>> >>>>>>>>> I looked deeper and it seems to me that when you unplug the AC >>>>>>>>> adapter, acpi_cpu_notify calls acpi_cpu_cx_cst that try to allocate a >>>>>>>>> new cx_ptr->p_lvlx via acpi_PkgGas. >>>>>>>>> If acpi_PkgGas set cx_ptr->p_lvlx to NULL for any reasons you'll have >>>>>>>>> the panic that you reported. >>>>>>>>> A solution would be to set acpi_cpu_hook to NULL so acpi_cpu_idle won't call it. >>>>>>>>> I need some time to have a patch because of the possible race between >>>>>>>>> acpi_cpu_notify and >>>>>>>>> acpi_cpu_idle during set acpi_cpu_hook to NULL. >>>>>>>>> if you have time and want panic your system you could try the attached >>>>>>>>> patch, just to be >>>>>>>>> sure that we catch it. >>>>>>>>> >>>>>>>> >>>>>>>> Hi, it paniced today ! I don't know why it randomly panic but it did, >>>>>>>> the backtrace didn't change. There is a picture about the panic : >>>>>>>> >>>>>>>> http://img541.imageshack.us/img541/2773/dsc00388xa.jpg >>>>>>> >>>>>>> What was you trying? acpi_idle5.diff.txt patch? >>>>>>> How did it panic? Unplugging AC adapter? >>>>>>> >>>>>> >>>>>> Hi, I tried this one : lvlx.diff.txt. Yes by unplugging the AC adapter. >>>>>> >>>>> >>>>> This is an old one. Could you try acpi_idle5.diff.txt? I kept you in >>>>> Cc when I sent to >>>>> the list. If you have problems, let me know, I'll resend to you the patch. >>>>> >>>>> Thank you. >>>>> >>>> >>>> Hi, it panic'ed with the same backtrace. >>>> >>> >>> Can you please post your dmesg? >>> >> >> Sent ! > > As your PC is in a good mood to make test, :) > could you try this patch? > > Thank you > > -- > Gianni > Here the patch :( [-- Attachment #2 --] diff -r ac95a73d358d sys/dev/acpica/acpi_cpu.c --- a/sys/dev/acpica/acpi_cpu.c Tue May 18 08:13:40 2010 -0400 +++ b/sys/dev/acpica/acpi_cpu.c Wed May 26 09:44:49 2010 -0400 @@ -88,6 +88,7 @@ struct acpi_cpu_softc { int cpu_cx_lowest; char cpu_cx_supported[64]; int cpu_rid; + struct mtx cpu_lock; }; struct acpi_cpu_device { @@ -100,6 +101,10 @@ struct acpi_cpu_device { #define CPU_SET_REG(reg, width, val) \ (bus_space_write_ ## width(rman_get_bustag((reg)), \ rman_get_bushandle((reg)), 0, (val))) +#define ACPI_CPU_LOCK(sc) \ + mtx_lock_spin(&sc->cpu_lock) +#define ACPI_CPU_UNLOCK(sc) \ + mtx_unlock_spin(&sc->cpu_lock) #define PM_USEC(x) ((x) >> 2) /* ~4 clocks per usec (3.57955 Mhz) */ @@ -127,7 +132,7 @@ static int cpu_quirks; /* Indicate any static int cpu_quirks; /* Indicate any hardware bugs. */ /* Runtime state. */ -static int cpu_disable_idle; /* Disable entry to idle function */ +static int cpu_disable_idle; /* Global disable idle function */ static int cpu_cx_count; /* Number of valid Cx states */ /* Values for sysctl. */ @@ -284,6 +289,7 @@ acpi_cpu_attach(device_t dev) ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = device_get_softc(dev); + mtx_init(&sc->cpu_lock, "ntflck", NULL, MTX_SPIN); sc->cpu_dev = dev; sc->cpu_handle = acpi_get_handle(dev); cpu_id = (int)(intptr_t)acpi_get_private(dev); @@ -416,20 +422,25 @@ static int static int acpi_cpu_suspend(device_t dev) { + struct acpi_cpu_softc *sc; int error; + sc = device_get_softc(dev); + ACPI_CPU_LOCK(sc); + cpu_disable_idle = TRUE; + ACPI_CPU_UNLOCK(sc); error = bus_generic_suspend(dev); if (error) return (error); - cpu_disable_idle = TRUE; + return (0); } static int acpi_cpu_resume(device_t dev) { + cpu_disable_idle = FALSE; - cpu_disable_idle = FALSE; return (bus_generic_resume(dev)); } @@ -523,16 +534,15 @@ acpi_cpu_shutdown(device_t dev) { ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + struct acpi_cpu_softc *sc; + + sc = device_get_softc(dev); + ACPI_CPU_LOCK(sc); + cpu_disable_idle = TRUE; + ACPI_CPU_UNLOCK(sc); + /* Allow children to shutdown first. */ bus_generic_shutdown(dev); - - /* - * Disable any entry to the idle function. There is a small race where - * an idle thread have passed this check but not gone to sleep. This - * is ok since device_shutdown() does not free the softc, otherwise - * we'd have to be sure all threads were evicted before returning. - */ - cpu_disable_idle = TRUE; return_VALUE (0); } @@ -609,7 +619,9 @@ acpi_cpu_generic_cx_probe(struct acpi_cp cx_ptr->trans_lat = AcpiGbl_FADT.C2Latency; cx_ptr++; sc->cpu_cx_count++; - } + } else + panic("%s: Cannot allocate resource %d for C3 state", __func__, + cx_ptr->res_type); } if (sc->cpu_p_blk_len < 6) return; @@ -625,7 +637,9 @@ acpi_cpu_generic_cx_probe(struct acpi_cp cx_ptr->trans_lat = AcpiGbl_FADT.C3Latency; cx_ptr++; sc->cpu_cx_count++; - } + } else + panic("%s: Cannot allocate resource %d for C3 state", __func__, + cx_ptr->res_type); } } @@ -637,13 +651,14 @@ static int static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) { + struct resource *lvlx; struct acpi_cx *cx_ptr; ACPI_STATUS status; ACPI_BUFFER buf; ACPI_OBJECT *top; ACPI_OBJECT *pkg; uint32_t count; - int i; + int i, type, rid; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); @@ -722,8 +737,18 @@ acpi_cpu_cx_cst(struct acpi_cpu_softc *s #endif /* Allocate the control register for C2 or C3. */ - acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &sc->cpu_rid, - &cx_ptr->p_lvlx, RF_SHAREABLE); + acpi_PkgGas(sc->cpu_dev, pkg, 0, &type, &rid, + &lvlx, RF_SHAREABLE); + ACPI_CPU_LOCK(sc); + + /* + * if you cannot allocate the control register you need to stop + * the acpi_cpu_idle hook. + */ + cpu_disable_idle = (lvlx == NULL) ? TRUE : FALSE; + sc->cpu_rid = rid; + cx_ptr->p_lvlx = lvlx; + cx_ptr->res_type = type; if (cx_ptr->p_lvlx) { sc->cpu_rid++; ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -732,7 +757,10 @@ acpi_cpu_cx_cst(struct acpi_cpu_softc *s cx_ptr->trans_lat)); cx_ptr++; sc->cpu_cx_count++; - } + } else + device_printf(sc->cpu_dev, "cannot allocate control register" + " for C2 or C3."); + ACPI_CPU_UNLOCK(sc); } AcpiOsFree(buf.Pointer); @@ -883,12 +911,6 @@ acpi_cpu_idle() uint32_t start_time, end_time; int bm_active, cx_next_idx, i; - /* If disabled, return immediately. */ - if (cpu_disable_idle) { - ACPI_ENABLE_IRQS(); - return; - } - /* * Look up our CPU id to get our softc. If it's NULL, we'll use C1 * since there is no ACPI processor object for this CPU. This occurs @@ -896,7 +918,17 @@ acpi_cpu_idle() */ sc = cpu_softc[PCPU_GET(cpuid)]; if (sc == NULL) { - acpi_cpu_c1(); + if (cpu_disable_idle) + ACPI_ENABLE_IRQS(); + else + acpi_cpu_c1(); + return; + } + + ACPI_CPU_LOCK(sc); + if (cpu_disable_idle) { + ACPI_CPU_UNLOCK(sc); + ACPI_ENABLE_IRQS(); return; } @@ -935,6 +967,7 @@ acpi_cpu_idle() */ if (cx_next->type == ACPI_STATE_C1) { sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + 500000 / hz) / 4; + ACPI_CPU_UNLOCK(sc); acpi_cpu_c1(); return; } @@ -975,6 +1008,7 @@ acpi_cpu_idle() AcpiWriteBitRegister(ACPI_BITREG_ARB_DISABLE, 0); AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); } + ACPI_CPU_UNLOCK(sc); ACPI_ENABLE_IRQS(); /* Find the actual time asleep in microseconds. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTinWSNyllR4-H22gEpohbyt2Uoc5EBS3fhgBKb9s>
