* RE: [PATCH] [v2] power/fsl: add MDIO dt binding for FMan
From: Shaohui Xie @ 2014-12-23 8:17 UTC (permalink / raw)
To: Scott Wood
Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
Emilian Medve, Igal.Liberman@freescale.com
In-Reply-To: <1419322085.5581.182.camel@freescale.com>
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBXb29kIFNjb3R0LUIwNzQyMQ0K
PiBTZW50OiBUdWVzZGF5LCBEZWNlbWJlciAyMywgMjAxNCA0OjA4IFBNDQo+IFRvOiBYaWUgU2hh
b2h1aS1CMjE5ODkNCj4gQ2M6IE1lZHZlIEVtaWxpYW4tRU1NRURWRTE7IGxpbnV4cHBjLWRldkBs
aXN0cy5vemxhYnMub3JnOw0KPiBkZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZzsgTGliZXJtYW4g
SWdhbC1CMzE5NTANCj4gU3ViamVjdDogUmU6IFtQQVRDSF0gW3YyXSBwb3dlci9mc2w6IGFkZCBN
RElPIGR0IGJpbmRpbmcgZm9yIEZNYW4NCj4gDQo+IE9uIFR1ZSwgMjAxNC0xMi0yMyBhdCAwMToz
NSAtMDYwMCwgWGllIFNoYW9odWktQjIxOTg5IHdyb3RlOg0KPiA+ICstIGJ1cy1mcmVxdWVuY3kN
Cj4gPiArCQlVc2FnZTogb3B0aW9uYWwNCj4gPiArCQlWYWx1ZSB0eXBlOiA8dTMyPg0KPiA+ICsJ
CURlZmluaXRpb246IFNwZWNpZmllcyBleHRlcm5hbCBNRElPIGJ1cyBjbG9jayBzcGVlZCB3aGlj
aCBpcw0KPiA+ICsJCWRpZmZlcmVudCBmcm9tIE1ESU8gc3RhbmRhcmQgMi41TUh6LiBTaG91bGQg
YmUgZGVmaW5lZCBmb3INCj4gU29Dcw0KPiA+ICsJCW9uIHdoaWNoIHRoZSBzdGFuZGFyZCBvbmUg
Y2Fubm90IHdvcmsuDQo+ID4NCj4gPiBXaGF0IHNob3VsZCBJIHJlcGhyYXNlIGl0PyBSZXBsYWNl
IHRoZSBsYXN0IHNlbnRlbmNlIHdpdGggIlNob3VsZCBiZQ0KPiA+IGRlZmluZWQgRm9yIFNvQ3Mg
b24gd2hpY2ggYSBsb3dlciBmcmVxdWVuY3kgdGhhbiB0aGUgc3RhbmRhcmQgaXMNCj4gcmVxdWly
ZWQuIj8NCj4gDQo+IE5laXRoZXIgb2YgdGhlc2Ugd29yayB3aXRoIEVtaWwncyBzY2VuYXJpbyBv
ZiBhIHN5c3RlbSB0aGF0IGFsbG93cyBhDQo+IGZhc3Rlci10aGFuLXN0YW5kYXJkIHNwZWVkLg0K
PiANCj4gSG93IGFib3V0OiAiRGVmaW5pdGlvbjogU3BlY2lmaWVzIHRoZSBleHRlcm5hbCBNRElP
IGJ1cyBjbG9jayBzcGVlZCB0byBiZQ0KPiB1c2VkLCBpZiBkaWZmZXJlbnQgZnJvbSB0aGUgc3Rh
bmRhcmQgMi41IE1Iei4gIFRoaXMgbWF5IGJlIGR1ZSB0byB0aGUNCj4gc3RhbmRhcmQgc3BlZWQg
YmVpbmcgdW5zdXBwb3J0ZWQgKGUuZy4gZHVlIHRvIGEgaGFyZHdhcmUgcHJvYmxlbSksIG9yIHRv
DQo+IGFkdmVydGlzZSB0aGF0IGFsbCByZWxldmFudCBjb21wb25lbnRzIGluIHRoZSBzeXN0ZW0g
c3VwcG9ydCBhIGZhc3Rlcg0KPiBzcGVlZC4iDQpbUy5IXSBPSy4gSSdsbCB1c2UgdGhpcyBpbiBW
My4NCg0KPiANCj4gPiBIb3cgYWJvdXQgdGhlIHZhbHVlIHVzZWQgaW4gZXhhbXBsZT8NCj4gPiBT
aG91bGQgMi41TUh6IGJlIHVzZWQgb3IgYSBsb3dlciBvbmU/DQo+IA0KPiBJZiB5b3UgZG9uJ3Qg
aGF2ZSBhIHJlYWxpc3RpYyBleGFtcGxlIHRvIHVzZSwgZG9uJ3QgcHV0IGl0IGluIHRoZSBleGFt
cGxlDQo+IGF0IGFsbC4gIDIuNU1IeiBpcyB0aGUgd29yc3QgZXhhbXBsZSB0byB1c2UgYmVjYXVz
ZSB0aGF0J3MgdGhlIGRlZmF1bHQNCj4gYW5kIHRoZXJlJ2QgYmUgbm8gcmVhc29uIHRvIHVzZSB0
aGUgcHJvcGVydHkgYXQgYWxsLg0KW1MuSF0gT0suIFRoZSBWMyB3aWxsIG5vdCBoYXZlIHRoaXMg
aW4gZXhhbXBsZS4NCg0KVGhhbmsgeW91IGFsbCBmb3IgcmV2aWV3aW5nIQ0KU2hhb2h1aQ0K
^ permalink raw reply
* [PATCH] [v3] power/fsl: add MDIO dt binding for FMan
From: shh.xie @ 2014-12-23 7:57 UTC (permalink / raw)
To: linuxppc-dev, devicetree, scottwood; +Cc: Shaohui Xie, Emilian.Medve
From: Shaohui Xie <Shaohui.Xie@freescale.com>
This binding is for FMan MDIO, it covers FMan v2 & FMan v3.
Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
---
changes in v3:
rephrase the 'Definition' of property 'bus-frequency', don't include the
property in example.
changes in v2:
addressed comments from Scott in V1.
.../devicetree/bindings/powerpc/fsl/fman.txt | 69 ++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
index edeea16..737aa4c 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
@@ -7,6 +7,7 @@ CONTENTS
- FMan MURAM Node
- FMan dTSEC/XGEC/mEMAC Node
- FMan IEEE 1588 Node
+ - FMan MDIO Node
- Example
=============================================================================
@@ -357,6 +358,69 @@ ptp-timer@fe000 {
};
=============================================================================
+FMan MDIO Node
+
+DESCRIPTION
+
+The MDIO is a bus to which the PHY devices are connected.
+
+PROPERTIES
+
+- compatible
+ Usage: required
+ Value type: <stringlist>
+ Definition: A standard property.
+ Must include "fsl,fman-mdio" for 1 Gb/s MDIO from FMan v2.
+ Must include "fsl,fman-xmdio" for 10 Gb/s MDIO from FMan v2.
+ Must include "fsl,fman-memac-mdio" for 1/10 Gb/s MDIO from
+ FMan v3.
+
+- reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property.
+
+- bus-frequency
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the external MDIO bus clock speed to
+ be used, if different from the standard 2.5 MHz.
+ This may be due to the standard speed being unsupported (e.g.
+ due to a hardware problem), or to advertise that all relevant
+ components in the system support a faster speed.
+
+- interrupts
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Event interrupt of external MDIO controller.
+ 1 Gb/s MDIO and 10 Gb/s MDIO has one interrupt respectively.
+
+- fsl,fman-internal-mdio
+ Usage: required for internal MDIO
+ Value type: boolean
+ Definition: Fman has internal MDIO for internal PCS(Physical
+ Coding Sublayer) PHYs and external MDIO for external PHYs.
+ The settings and programming routines for internal/external
+ MDIO are different. Must be included for internal MDIO.
+
+EXAMPLE
+
+Example for FMan v2 external MDIO:
+
+mdio@f1000 {
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+};
+
+Example for FMan v3 internal MDIO:
+
+mdio@f1000 {
+ compatible = "fsl,fman-memac-mdio";
+ reg = <0xf1000 0x1000>;
+ fsl,fman-internal-mdio;
+};
+
+=============================================================================
Example
fman@400000 {
@@ -531,4 +595,9 @@ fman@400000 {
compatible = "fsl,fman-ptp-timer";
reg = <0xfe000 0x1000>;
};
+
+ mdio@f1000 {
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+ };
};
--
1.8.4.1
^ permalink raw reply related
* Re: [PATCH v6 3/4] perf Documentation: add event parameters
From: Jiri Olsa @ 2014-12-23 9:51 UTC (permalink / raw)
To: Sukadev Bhattiprolu
Cc: peterz, linux-kernel, Arnaldo Carvalho de Melo, dev,
Paul Mackerras, linuxppc-dev
In-Reply-To: <20141222193436.GB19784@us.ibm.com>
On Mon, Dec 22, 2014 at 11:34:36AM -0800, Sukadev Bhattiprolu wrote:
> Jiri Olsa [jolsa@redhat.com] wrote:
> | On Sun, Dec 21, 2014 at 11:49:26PM -0800, Sukadev Bhattiprolu wrote:
> | > From: Cody P Schafer <cody@linux.vnet.ibm.com>
> | > + In the case of the last example, a value replacing "?" would
> | > + need to be provided by the user selecting the particular event.
> | > + This is referred to as "event parameterization". All
> | > + non-numerical values indicate an event parameter.
> |
> | I see.. here's the glitch ;-) I thought we agreed on forcing '?'
> | as the value for param events, not 'All non-numerical values'
>
> Yes, it is currently more broad than needed, but it is not really
> user input - we are just parsing sysfs entries that developer specified
> in the kernel. If necessary, we can tighten that independently ?
I think it's better to tighten it up from the beginning, so when
we decide later for other string usage, we will not breake the
'current behaviour'.
Like if now we allow users (kernel pmu modules) to put anything
as param event's value, we will brake their expectations/code if
we later decide for another usage of that string value.
As Cody wrong in last version thread:
---
Compared to monopolizing all strings (which is what I did when
initialy writing this), using a '$' prefix would allow less pain when
some events suddenly need non-integer parameters.
---
thanks,
jirka
^ permalink raw reply
* Re: [PATCH v6 1/4] tools/perf: support parsing parameterized events
From: Jiri Olsa @ 2014-12-23 9:55 UTC (permalink / raw)
To: Sukadev Bhattiprolu
Cc: peterz, linux-kernel, Arnaldo Carvalho de Melo, dev,
Paul Mackerras, linuxppc-dev
In-Reply-To: <20141222193045.GA19784@us.ibm.com>
On Mon, Dec 22, 2014 at 11:30:45AM -0800, Sukadev Bhattiprolu wrote:
> Jiri Olsa [jolsa@redhat.com] wrote:
> | On Sun, Dec 21, 2014 at 11:49:24PM -0800, Sukadev Bhattiprolu wrote:
> |
> | SNIP
> |
> | > + }
> | >
> | > switch (format->value) {
> | > case PERF_PMU_FORMAT_VALUE_CONFIG:
> | > @@ -592,11 +629,16 @@ static int pmu_config_term(struct list_head *formats,
> | > }
> | >
> | > /*
> | > - * XXX If we ever decide to go with string values for
> | > - * non-hardcoded terms, here's the place to translate
> | > - * them into value.
> | > + * Either directly use a numeric term, or try to translate string terms
> | > + * using event parameters.
> | > */
> | > - pmu_format_value(format->bits, term->val.num, vp, zero);
> | > + if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
> | > + val = term->val.num;
> | > + else
> | > + if (pmu_resolve_param_term(term, head_terms, &val))
> | > + return -EINVAL;
> | > +
> |
> | I'm ok with the change logic, but I'm missing here check for the 'term'
> | string value to be '?', so we force subst terms to have '?' as value..
> | I believe thats what we decided in the previous set discussion, right?
>
> The =? is not a user input, so I did not think of validating that.
>
> perf tool expects kernel/sysfs to show entries like 'core=?'. Are you
> saying that we should error out if kernel mistakenly displays 'core=$val'
> or 'core=?val' ?
I think the we should at least try to have interface unambiguous
from the beginning
> If a required parameter is missing, we catch that in pmu_resolve_param_term().
> If a bogus parameter is specified we catch that above in pmu_config_term().
but the value of that param is unspecified, and if we later want to
add another type of string values we would be screwed.. as I described
in the previous reply for your other patch.
jirka
^ permalink raw reply
* Re: [PATCH] powerpc/smp: Fix Non-boot cpus cannot be bring up.
From: Benjamin Herrenschmidt @ 2014-12-23 9:55 UTC (permalink / raw)
To: Michael Ellerman; +Cc: scottwood, linuxppc-dev, Dongsheng Wang, anton
In-Reply-To: <1419296441.30550.3.camel@ellerman.id.au>
On Tue, 2014-12-23 at 12:00 +1100, Michael Ellerman wrote:
> On Mon, 2014-12-22 at 14:38 +0800, Dongsheng Wang wrote:
> > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> >
> > Kernel cannot bring up Non-boot cpus always get "Processor xx is stuck".
> > this issue bring by http://patchwork.ozlabs.org/patch/418912/ (powerpc:
> > Secondary CPUs must set cpu_callin_map after setting active and online)
> > We need to take timebase after bootup cpu give the timebase firstly.
> >
> > When start_secondary, non-boot cpus set cpu_callin_map for boot cpu
> > after that boot cpu will give the timebase for non-boot cpu. Otherwise
> > non-boot cpus will fall in dead loop to waiting bootup cpu to give
> > imebase.
>
> Right.
>
> However, doesn't this introduce the possibility that the secondary cpu is up
> and marked online but has an unsynchronised clock?
As long as it doesn't execute anything (and at that point it shouldn't
have interrupts enabled) it should be ok. The TB cannot be observed
outside of that CPU.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 3/3] powerpc/config: Enable MDIO support
From: shh.xie @ 2014-12-23 10:17 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: Andy Fleming, Shaohui Xie
From: Andy Fleming <afleming@gmail.com>
Also, enable Vitesse PHY and fixed PHY support.
Signed-off-by: Andy Fleming <afleming@gmail.com>
Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
---
this patch is based on below patch:
http://patchwork.ozlabs.org/patch/423348/
arch/powerpc/configs/corenet32_smp_defconfig | 1 +
arch/powerpc/configs/corenet64_smp_defconfig | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index 6577c41..14855db 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -98,6 +98,7 @@ CONFIG_SATA_SIL=y
CONFIG_PATA_SIL680=y
CONFIG_NETDEVICES=y
CONFIG_FSL_PQ_MDIO=y
+CONFIG_FSL_XGMAC_MDIO=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_VITESSE_PHY=y
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 4016cf6..e9ccc78 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -79,7 +79,11 @@ CONFIG_SATA_FSL=y
CONFIG_SATA_SIL24=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_FSL_XGMAC_MDIO=y
CONFIG_E1000E=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
CONFIG_MDIO_BUS_MUX=y
CONFIG_MDIO_BUS_MUX_GPIO=y
CONFIG_MDIO_BUS_MUX_MMIOREG=y
--
1.8.4.1
^ permalink raw reply related
* Re: [PATCH] i2c-qoriq: modified compatibility for correct prescaler
From: Valentin Longchamp @ 2014-12-23 13:23 UTC (permalink / raw)
To: Scott Wood, Wolfram Sang
Cc: Linux device trees, danielle.costantino, Boschung, Rainer,
Brunck, Holger, Linux I2C, Linux PowerPC Kernel
In-Reply-To: <54899FB4.9010207@keymile.com>
Wolfgang, Scott,
On 12/11/2014 02:44 PM, Valentin Longchamp wrote:
> Hi all,
>
> Picking up this issue again.
>
> On 11/26/2014 02:41 AM, Scott Wood wrote:
>> On Tue, 2014-11-25 at 19:13 +0100, Wolfram Sang wrote:
>>> On Mon, Nov 17, 2014 at 07:28:03PM -0600, Scott Wood wrote:
>>>> On Fri, 2014-11-14 at 09:28 +0100, Wolfram Sang wrote:
>>>>>>>
>>>>>>> If we're going to change the device tree I'd rather just add a property
>>>>>>> to say what the prescaler is.
>>>>>>
>>>>>> We would however, leave the boards' device trees that use things like
>>>>>> "fsl,mpc8543-i2c" as is and introduce the prescaler for the others requiring it.
>>>>>>
>>>>>>
>>>>>> Now the drawback is that the driver would require a change, to parse this
>>>>>> prescaler new prescaler property. Would this be OK from your point of view
>>>>>> Wolfram ? If yes, I will send the patches for it.
>>>>>
>>>>> I don't think it is OK.
>>>>
>>>> Why?
>>>
>>> Because I thought it could be deduced. Then, a seperate property would
>>> not be OK.
>>>
>>>>> I'd think it can be deduced from the compatible property.
>>>>
>>>> For almost all existing device trees it cannot be.
>>>
>>> Pity :( If we do introduce a new property, it should probably be
>>> "clock-div". Grepping through binding documentation, that seems
>>> accepted. We should ask DT maintainers, too, to be safe.
>>>
>>>> If you want something that will work without changing device trees,
>>>> you'll need to use SVR to identify the SoC.
>>>
>>> The driver is doing that already, see mpc_i2c_get_sec_cfg_8xxx(). Dunno
>>> if it makes sense to add to it for consistency reasons?
>>
>> That's not SVR, but sure. Better to avoid messing with existing device
>> trees.
>>
>
> What is then the agreement here ? Add a clock-div to the device trees ? Or do
> something similar to mpc_i2c_get_sec_cfg_8xxx() ?
>
> I think the clock-div property is better according to Freescale's AN 2919
> section 3.1 Source clock. All the source clocks are fixed (with a clock-div of 2
> in case of mpc8536/43/45/47/48/67/68/72, plus p2020) except for the mpc8533/44
> where it can be 2 or 3, and that's what mpc_i2c_get_sec_cfg_8xxx() determines.
>
> So mpc_i2c_get_sec_cfg_8xxx() should remain the exception and the other
> prescaler values should be derived from an additional clock-div that must be
> added in the respective device trees (at least for the qoriq devices, because
> for instance mpc8543 already has the correct prescaler thanks to
> mpc_i2c_data_8543 from i2c-mpc.c).
>
Do you have an opinion on the above ?
Valentin
^ permalink raw reply
* Re: [PATCH] i2c-qoriq: modified compatibility for correct prescaler
From: Wolfram Sang @ 2014-12-23 13:49 UTC (permalink / raw)
To: Valentin Longchamp
Cc: Linux device trees, danielle.costantino, Boschung, Rainer,
Brunck, Holger, Linux I2C, Scott Wood, Linux PowerPC Kernel
In-Reply-To: <54996CB5.8030808@keymile.com>
[-- Attachment #1: Type: text/plain, Size: 1241 bytes --]
On Tue, Dec 23, 2014 at 02:23:01PM +0100, Valentin Longchamp wrote:
> Wolfgang, Scott,
Wolfram, please.
> > What is then the agreement here ? Add a clock-div to the device trees ? Or do
> > something similar to mpc_i2c_get_sec_cfg_8xxx() ?
> >
> > I think the clock-div property is better according to Freescale's AN 2919
> > section 3.1 Source clock. All the source clocks are fixed (with a clock-div of 2
> > in case of mpc8536/43/45/47/48/67/68/72, plus p2020) except for the mpc8533/44
> > where it can be 2 or 3, and that's what mpc_i2c_get_sec_cfg_8xxx() determines.
> >
> > So mpc_i2c_get_sec_cfg_8xxx() should remain the exception and the other
> > prescaler values should be derived from an additional clock-div that must be
> > added in the respective device trees (at least for the qoriq devices, because
> > for instance mpc8543 already has the correct prescaler thanks to
> > mpc_i2c_data_8543 from i2c-mpc.c).
> >
>
> Do you have an opinion on the above ?
I don't mind. I'll leave it to PowerPC experts to judge if a new binding
is apropriate or reading SVR is the way to go. If it is going to be a
new binding, then please look around before if there is already
something similar around...
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* [PATCH] cleanup on stack DECLARE_COMPLETIONs
From: Nicholas Mc Guire @ 2014-12-23 17:34 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Dimitri Sivanich, linux-scsi, linux-usb, Felipe Balbi,
Nicholas Mc Guire, James E.J. Bottomley, Juergen E. Fischer,
linuxppc-dev
fixups for incorrect use of DECLARE_COMPLETION. see also commit
6e9a4738 ("completions: lockdep annotate on stack completions")
The only somewhat special case being
drivers/misc/sgi-gru/grukservices.c:quicktest2
which had a static qualifier in the original DECLARE_COMPLETION()
but that seems to be wrong (why should the completion persisted between
successive calls ?) so the conversion to DECLARE_COMPLETION_ONSTACK
was also applied and the static qualifier removed.
Not sure if this is suitable in this form or if it should go out as
5 seperate patches ?
This was only code reviewed and compile tested
Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
---
drivers/macintosh/ams/ams-pmu.c | 4 ++--
drivers/misc/sgi-gru/grukservices.c | 2 +-
drivers/scsi/aha152x.c | 2 +-
drivers/usb/gadget/udc/fsl_qe_udc.c | 2 +-
drivers/usb/gadget/udc/fsl_udc_core.c | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/macintosh/ams/ams-pmu.c b/drivers/macintosh/ams/ams-pmu.c
index 4f61b3e..c2b178f 100644
--- a/drivers/macintosh/ams/ams-pmu.c
+++ b/drivers/macintosh/ams/ams-pmu.c
@@ -52,7 +52,7 @@ static void ams_pmu_req_complete(struct adb_request *req)
static void ams_pmu_set_register(u8 reg, u8 value)
{
static struct adb_request req;
- DECLARE_COMPLETION(req_complete);
+ DECLARE_COMPLETION_ONSTACK(req_complete);
req.arg = &req_complete;
if (pmu_request(&req, ams_pmu_req_complete, 4, ams_pmu_cmd, 0x00, reg, value))
@@ -65,7 +65,7 @@ static void ams_pmu_set_register(u8 reg, u8 value)
static u8 ams_pmu_get_register(u8 reg)
{
static struct adb_request req;
- DECLARE_COMPLETION(req_complete);
+ DECLARE_COMPLETION_ONSTACK(req_complete);
req.arg = &req_complete;
if (pmu_request(&req, ams_pmu_req_complete, 3, ams_pmu_cmd, 0x01, reg))
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 913de07..4e412fe 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -1044,7 +1044,7 @@ done:
static int quicktest2(unsigned long arg)
{
- static DECLARE_COMPLETION(cmp);
+ DECLARE_COMPLETION_ONSTACK(cmp);
unsigned long han;
int blade_id = 0;
int numcb = 4;
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 2b960b3..b16afb9 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1055,7 +1055,7 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt)
static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
{
struct Scsi_Host *shpnt = SCpnt->device->host;
- DECLARE_COMPLETION(done);
+ DECLARE_COMPLETION_ONSTACK(done);
int ret, issued, disconnected;
unsigned char old_cmd_len = SCpnt->cmd_len;
unsigned long flags;
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 795c99c..e0822f1 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2630,7 +2630,7 @@ static int qe_udc_remove(struct platform_device *ofdev)
struct qe_udc *udc = platform_get_drvdata(ofdev);
struct qe_ep *ep;
unsigned int size;
- DECLARE_COMPLETION(done);
+ DECLARE_COMPLETION_ONSTACK(done);
usb_del_gadget_udc(&udc->gadget);
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 2df8074..c3830ad 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2529,7 +2529,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
- DECLARE_COMPLETION(done);
+ DECLARE_COMPLETION_ONSTACK(done);
if (!udc_controller)
return -ENODEV;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] cleanup on stack DECLARE_COMPLETIONs
From: Felipe Balbi @ 2014-12-23 18:19 UTC (permalink / raw)
To: Nicholas Mc Guire
Cc: Dimitri Sivanich, linux-scsi, linux-usb, Felipe Balbi,
James E.J. Bottomley, Juergen E. Fischer, linuxppc-dev
In-Reply-To: <1419356048-22405-1-git-send-email-der.herr@hofr.at>
[-- Attachment #1: Type: text/plain, Size: 876 bytes --]
On Tue, Dec 23, 2014 at 06:34:08PM +0100, Nicholas Mc Guire wrote:
> fixups for incorrect use of DECLARE_COMPLETION. see also commit
> 6e9a4738 ("completions: lockdep annotate on stack completions")
> The only somewhat special case being
> drivers/misc/sgi-gru/grukservices.c:quicktest2
> which had a static qualifier in the original DECLARE_COMPLETION()
> but that seems to be wrong (why should the completion persisted between
> successive calls ?) so the conversion to DECLARE_COMPLETION_ONSTACK
> was also applied and the static qualifier removed.
>
> Not sure if this is suitable in this form or if it should go out as
> 5 seperate patches ?
>
> This was only code reviewed and compile tested
>
> Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
please split drivers/usb/gadget out of this patch so I can take it
through my tree.
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* [PATCH] gadget: cleanup on stack DECLARE_COMPLETIONs
From: Nicholas Mc Guire @ 2014-12-23 18:50 UTC (permalink / raw)
To: Felipe Balbi
Cc: Greg Kroah-Hartman, linux-usb, linux-kernel, Rob Herring,
Nicholas Mc Guire, Grant Likely, linuxppc-dev
fixups for incorrect use of DECLARE_COMPLETION. see also commit
6e9a4738 ("completions: lockdep annotate on stack completions")
patch is against 3.18.0 linux-next
This was only code reviewed and compile tested
Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
---
drivers/usb/gadget/udc/fsl_qe_udc.c | 2 +-
drivers/usb/gadget/udc/fsl_udc_core.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 795c99c..e0822f1 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2630,7 +2630,7 @@ static int qe_udc_remove(struct platform_device *ofdev)
struct qe_udc *udc = platform_get_drvdata(ofdev);
struct qe_ep *ep;
unsigned int size;
- DECLARE_COMPLETION(done);
+ DECLARE_COMPLETION_ONSTACK(done);
usb_del_gadget_udc(&udc->gadget);
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 2df8074..c3830ad 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2529,7 +2529,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
- DECLARE_COMPLETION(done);
+ DECLARE_COMPLETION_ONSTACK(done);
if (!udc_controller)
return -ENODEV;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v6 1/4] tools/perf: support parsing parameterized events
From: Sukadev Bhattiprolu @ 2014-12-23 19:58 UTC (permalink / raw)
To: Jiri Olsa
Cc: peterz, linux-kernel, Arnaldo Carvalho de Melo, dev,
Paul Mackerras, linuxppc-dev
In-Reply-To: <20141223095506.GB22265@krava.brq.redhat.com>
>From a24b480ff54381a7e092597864cf615162afdd60 Mon Sep 17 00:00:00 2001
From: Cody P Schafer <cody@linux.vnet.ibm.com>
Date: Wed, 24 Sep 2014 12:27:15 -0700
Subject: [PATCH 1/4] tools/perf: support parsing parameterized events
Enable event specification like:
pmu/event_name,param1=0x1,param2=0x4/
Assuming that
/sys/bus/event_source/devices/pmu/events/event_name
Contains something like
param2=?,bar=1,param1=?
Changelog[v6]:
[Jiri Olsa] Add a check to make sure that sysfs entries with
parameters exactly match '=?'.
Changelog[v4]:
[Jiri Olsa] Merge to recent perf-core and fix a small conflict.
Changelog[v3]:
[Jiri Olsa] If the sysfs event file specifies 'param=val', make the
usage 'hv_24x7/event,param=123/' rather than 'hv_24x7/event,val=123/'.
CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
tools/perf/util/parse-events.h | 1 +
tools/perf/util/pmu.c | 74 +++++++++++++++++++++++++++++++++++-------
2 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index db2cf78..ca226ce 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ struct parse_events_term {
int type_val;
int type_term;
struct list_head list;
+ bool used;
};
struct parse_events_evlist {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 5c9c494..bfbecf7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -551,31 +551,68 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
}
/*
+ * Term is a string term, and might be a param-term. Try to look up it's value
+ * in the remaining terms.
+ * - We have a term like "base-or-format-term=param-term",
+ * - We need to find the value supplied for "param-term" (with param-term named
+ * in a config string) later on in the term list.
+ */
+static int pmu_resolve_param_term(struct parse_events_term *term,
+ struct list_head *head_terms,
+ __u64 *value)
+{
+ struct parse_events_term *t;
+
+ list_for_each_entry(t, head_terms, list) {
+ if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
+ if (!strcmp(t->config, term->config)) {
+ t->used = true;
+ *value = t->val.num;
+ return 0;
+ }
+ }
+ }
+
+ if (verbose)
+ printf("Required parameter '%s' not specified\n", term->config);
+
+ return -1;
+}
+
+/*
* Setup one of config[12] attr members based on the
* user input data - term parameter.
*/
static int pmu_config_term(struct list_head *formats,
struct perf_event_attr *attr,
struct parse_events_term *term,
+ struct list_head *head_terms,
bool zero)
{
struct perf_pmu_format *format;
__u64 *vp;
+ __u64 val;
+
+ /*
+ * If this is a parameter we've already used for parameterized-eval,
+ * skip it in normal eval.
+ */
+ if (term->used)
+ return 0;
/*
- * Support only for hardcoded and numnerial terms.
* Hardcoded terms should be already in, so nothing
* to be done for them.
*/
if (parse_events__is_hardcoded_term(term))
return 0;
- if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
- return -EINVAL;
-
format = pmu_find_format(formats, term->config);
- if (!format)
+ if (!format) {
+ if (verbose)
+ printf("Invalid event/parameter '%s'\n", term->config);
return -EINVAL;
+ }
switch (format->value) {
case PERF_PMU_FORMAT_VALUE_CONFIG:
@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
}
/*
- * XXX If we ever decide to go with string values for
- * non-hardcoded terms, here's the place to translate
- * them into value.
+ * Either directly use a numeric term, or try to translate string terms
+ * using event parameters.
*/
- pmu_format_value(format->bits, term->val.num, vp, zero);
+ if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
+ val = term->val.num;
+ else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
+ if (strcmp(term->val.str, "?")) {
+ if (verbose)
+ pr_info("Invalid sysfs entry %s=%s\n",
+ term->config, term->val.str);
+ return -EINVAL;
+ }
+
+ if (pmu_resolve_param_term(term, head_terms, &val))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ pmu_format_value(format->bits, val, vp, zero);
return 0;
}
@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
{
struct parse_events_term *term;
- list_for_each_entry(term, head_terms, list)
- if (pmu_config_term(formats, attr, term, zero))
+ list_for_each_entry(term, head_terms, list) {
+ if (pmu_config_term(formats, attr, term, head_terms, zero))
return -EINVAL;
+ }
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v6 3/4] perf Documentation: add event parameters
From: Sukadev Bhattiprolu @ 2014-12-23 19:59 UTC (permalink / raw)
To: Jiri Olsa
Cc: peterz, linux-kernel, Arnaldo Carvalho de Melo, dev,
Paul Mackerras, linuxppc-dev
In-Reply-To: <20141223095121.GA22265@krava.brq.redhat.com>
>From bfc20fd2161060cc51f3f24aa91663da39e97750 Mon Sep 17 00:00:00 2001
From: Cody P Schafer <cody@linux.vnet.ibm.com>
Date: Wed, 24 Sep 2014 12:27:22 -0700
Subject: [PATCH 3/4] perf Documentation: add event parameters
Event parameters are a basic way for partial events to be specified in
sysfs with per-event names given to the fields that need to be filled in
when using a particular event.
It is intended for supporting cases where the single 'cpu' parameter is
insufficient. For example, POWER 8 has events for physical
sockets/cores/cpus that are accessible from with virtual machines. To
keep using the single 'cpu' parameter we'd need to perform a mapping
between Linux's cpus and the physical machine's cpus (in this case
Linux is running under a hypervisor). This isn't possible because
bindings between our cpus and physical cpus may not be fixed, and we
probably won't have a "cpu" on each physical cpu.
Changelog[v6]
Update event description to explain how required parameters
are displayed.
CC: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
Documentation/ABI/testing/sysfs-bus-event_source-devices-events | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
index 20979f8..505f080 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
@@ -52,12 +52,18 @@ Description: Per-pmu performance monitoring events specific to the running syste
event=0x2abc
event=0x423,inv,cmask=0x3
domain=0x1,offset=0x8,starting_index=0xffff
+ domain=0x1,offset=0x8,core=?
Each of the assignments indicates a value to be assigned to a
particular set of bits (as defined by the format file
corresponding to the <term>) in the perf_event structure passed
to the perf_open syscall.
+ In the case of the last example, a value replacing "?" would
+ need to be provided by the user selecting the particular event.
+ This is referred to as "event parameterization". Event
+ parameters have the format 'param=?'.
+
What: /sys/bus/event_source/devices/<pmu>/events/<event>.unit
Date: 2014/02/24
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 0/3] powerpc/pstore: Add pstore support for nvram partitions
From: Hari Bathini @ 2014-12-24 11:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Mahesh J Salgaonkar
This patch series adds pstore support on powernv platform to
read different nvram partitions and write compressed data to
oops-log nvram partition. As pseries platform already has
pstore support, this series moves most of the common code
for pseries and powernv platforms to a common file. Tested
the patches successfully on both pseries and powernv
platforms.
Changes from v2:
Added an empty version of clobbering_unread_rtas_event()
routine for !PSERIES, to avoid ifdef at the call sites
---
Hari Bathini (3):
powerpc/nvram: move generic code for nvram and pstore
pstore: Add pstore type id for firmware partition
pstore: add pstore support on powernv
arch/powerpc/include/asm/nvram.h | 50 ++
arch/powerpc/include/asm/rtas.h | 4
arch/powerpc/kernel/nvram_64.c | 677 +++++++++++++++++++++++++++
arch/powerpc/platforms/powernv/opal-nvram.c | 10
arch/powerpc/platforms/pseries/nvram.c | 665 ---------------------------
fs/pstore/inode.c | 3
include/linux/pstore.h | 1
7 files changed, 749 insertions(+), 661 deletions(-)
--
- Hari
^ permalink raw reply
* [PATCH v3 1/3] powerpc/nvram: move generic code for nvram and pstore
From: Hari Bathini @ 2014-12-24 11:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Mahesh J Salgaonkar
In-Reply-To: <20141224115729.25731.20371.stgit@localhost.localdomain>
With minor checks, we can move most of the code for nvram
under pseries to a common place to be re-used by other
powerpc platforms like powernv. This patch moves such
common code to arch/powerpc/kernel/nvram_64.c file.
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/nvram.h | 50 ++
arch/powerpc/include/asm/rtas.h | 4
arch/powerpc/kernel/nvram_64.c | 656 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/nvram.c | 665 --------------------------------
4 files changed, 714 insertions(+), 661 deletions(-)
diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index b0fe0fe..09a518b 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -9,12 +9,43 @@
#ifndef _ASM_POWERPC_NVRAM_H
#define _ASM_POWERPC_NVRAM_H
-
+#include <linux/types.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <uapi/asm/nvram.h>
+/*
+ * Set oops header version to distinguish between old and new format header.
+ * lnx,oops-log partition max size is 4000, header version > 4000 will
+ * help in identifying new header.
+ */
+#define OOPS_HDR_VERSION 5000
+
+struct err_log_info {
+ __be32 error_type;
+ __be32 seq_num;
+};
+
+struct nvram_os_partition {
+ const char *name;
+ int req_size; /* desired size, in bytes */
+ int min_size; /* minimum acceptable size (0 means req_size) */
+ long size; /* size of data portion (excluding err_log_info) */
+ long index; /* offset of data portion of partition */
+ bool os_partition; /* partition initialized by OS, not FW */
+};
+
+struct oops_log_info {
+ __be16 version;
+ __be16 report_length;
+ __be64 timestamp;
+} __attribute__((packed));
+
+extern struct nvram_os_partition oops_log_partition;
+
#ifdef CONFIG_PPC_PSERIES
+extern struct nvram_os_partition rtas_log_partition;
+
extern int nvram_write_error_log(char * buff, int length,
unsigned int err_type, unsigned int err_seq);
extern int nvram_read_error_log(char * buff, int length,
@@ -50,6 +81,23 @@ extern void pmac_xpram_write(int xpaddr, u8 data);
/* Synchronize NVRAM */
extern void nvram_sync(void);
+/* Initialize NVRAM OS partition */
+extern int __init nvram_init_os_partition(struct nvram_os_partition *part);
+
+/* Initialize NVRAM oops partition */
+extern void __init nvram_init_oops_partition(int rtas_partition_exists);
+
+/* Read a NVRAM partition */
+extern int nvram_read_partition(struct nvram_os_partition *part, char *buff,
+ int length, unsigned int *err_type,
+ unsigned int *error_log_cnt);
+
+/* Write to NVRAM OS partition */
+extern int nvram_write_os_partition(struct nvram_os_partition *part,
+ char *buff, int length,
+ unsigned int err_type,
+ unsigned int error_log_cnt);
+
/* Determine NVRAM size */
extern ssize_t nvram_get_size(void);
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index b390f55..bcf6693 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -343,8 +343,12 @@ extern int early_init_dt_scan_rtas(unsigned long node,
extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
#ifdef CONFIG_PPC_PSERIES
+extern unsigned long last_rtas_event;
+extern int clobbering_unread_rtas_event(void);
extern int pseries_devicetree_update(s32 scope);
extern void post_mobility_fixup(void);
+#else
+int clobbering_unread_rtas_event(void) { return 0; }
#endif
#ifdef CONFIG_PPC_RTAS_DAEMON
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 34f7c9b..42e5c6a 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -26,6 +26,9 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/kmsg_dump.h>
+#include <linux/pstore.h>
+#include <linux/zlib.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#include <asm/rtas.h>
@@ -54,6 +57,659 @@ struct nvram_partition {
static LIST_HEAD(nvram_partitions);
+#ifdef CONFIG_PPC_PSERIES
+struct nvram_os_partition rtas_log_partition = {
+ .name = "ibm,rtas-log",
+ .req_size = 2079,
+ .min_size = 1055,
+ .index = -1,
+ .os_partition = true
+};
+#endif
+
+struct nvram_os_partition oops_log_partition = {
+ .name = "lnx,oops-log",
+ .req_size = 4000,
+ .min_size = 2000,
+ .index = -1,
+ .os_partition = true
+};
+
+static const char *nvram_os_partitions[] = {
+#ifdef CONFIG_PPC_PSERIES
+ "ibm,rtas-log",
+#endif
+ "lnx,oops-log",
+ NULL
+};
+
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+ .dump = oops_to_nvram
+};
+
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a oops header.
+ * oops header has u16 holding the version of oops header (to differentiate
+ * between old and new format header) followed by u16 holding the length of
+ * the compressed* text (*Or uncompressed, if compression fails.) and u64
+ * holding the timestamp. oops_buf[] gets written to NVRAM.
+ *
+ * oops_log_info points to the header. oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * | +- oops_data
+ * v v
+ * +-----------+-----------+-----------+------------------------+
+ * | version | length | timestamp | text |
+ * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
+ * +-----------+-----------+-----------+------------------------+
+ * ^
+ * +- oops_log_info
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
+
+#ifdef CONFIG_PSTORE
+#ifdef CONFIG_PPC_PSERIES
+static struct nvram_os_partition of_config_partition = {
+ .name = "of-config",
+ .index = -1,
+ .os_partition = false
+};
+#endif
+
+static struct nvram_os_partition common_partition = {
+ .name = "common",
+ .index = -1,
+ .os_partition = false
+};
+
+static enum pstore_type_id nvram_type_ids[] = {
+ PSTORE_TYPE_DMESG,
+ PSTORE_TYPE_PPC_COMMON,
+ -1,
+ -1,
+ -1
+};
+static int read_type;
+#endif
+
+/* nvram_write_os_partition
+ *
+ * We need to buffer the error logs into nvram to ensure that we have
+ * the failure information to decode. If we have a severe error there
+ * is no way to guarantee that the OS or the machine is in a state to
+ * get back to user land and write the error to disk. For example if
+ * the SCSI device driver causes a Machine Check by writing to a bad
+ * IO address, there is no way of guaranteeing that the device driver
+ * is in any state that is would also be able to write the error data
+ * captured to disk, thus we buffer it in NVRAM for analysis on the
+ * next boot.
+ *
+ * In NVRAM the partition containing the error log buffer will looks like:
+ * Header (in bytes):
+ * +-----------+----------+--------+------------+------------------+
+ * | signature | checksum | length | name | data |
+ * |0 |1 |2 3|4 15|16 length-1|
+ * +-----------+----------+--------+------------+------------------+
+ *
+ * The 'data' section would look like (in bytes):
+ * +--------------+------------+-----------------------------------+
+ * | event_logged | sequence # | error log |
+ * |0 3|4 7|8 error_log_size-1|
+ * +--------------+------------+-----------------------------------+
+ *
+ * event_logged: 0 if event has not been logged to syslog, 1 if it has
+ * sequence #: The unique sequence # for each event. (until it wraps)
+ * error log: The error log from event_scan
+ */
+int nvram_write_os_partition(struct nvram_os_partition *part,
+ char *buff, int length,
+ unsigned int err_type,
+ unsigned int error_log_cnt)
+{
+ int rc;
+ loff_t tmp_index;
+ struct err_log_info info;
+
+ if (part->index == -1)
+ return -ESPIPE;
+
+ if (length > part->size)
+ length = part->size;
+
+ info.error_type = cpu_to_be32(err_type);
+ info.seq_num = cpu_to_be32(error_log_cnt);
+
+ tmp_index = part->index;
+
+ rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info),
+ &tmp_index);
+ if (rc <= 0) {
+ pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
+ return rc;
+ }
+
+ rc = ppc_md.nvram_write(buff, length, &tmp_index);
+ if (rc <= 0) {
+ pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+/* nvram_read_partition
+ *
+ * Reads nvram partition for at most 'length'
+ */
+int nvram_read_partition(struct nvram_os_partition *part, char *buff,
+ int length, unsigned int *err_type,
+ unsigned int *error_log_cnt)
+{
+ int rc;
+ loff_t tmp_index;
+ struct err_log_info info;
+
+ if (part->index == -1)
+ return -1;
+
+ if (length > part->size)
+ length = part->size;
+
+ tmp_index = part->index;
+
+ if (part->os_partition) {
+ rc = ppc_md.nvram_read((char *)&info,
+ sizeof(struct err_log_info),
+ &tmp_index);
+ if (rc <= 0) {
+ pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
+ return rc;
+ }
+ }
+
+ rc = ppc_md.nvram_read(buff, length, &tmp_index);
+ if (rc <= 0) {
+ pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
+ return rc;
+ }
+
+ if (part->os_partition) {
+ *error_log_cnt = be32_to_cpu(info.seq_num);
+ *err_type = be32_to_cpu(info.error_type);
+ }
+
+ return 0;
+}
+
+/* nvram_init_os_partition
+ *
+ * This sets up a partition with an "OS" signature.
+ *
+ * The general strategy is the following:
+ * 1.) If a partition with the indicated name already exists...
+ * - If it's large enough, use it.
+ * - Otherwise, recycle it and keep going.
+ * 2.) Search for a free partition that is large enough.
+ * 3.) If there's not a free partition large enough, recycle any obsolete
+ * OS partitions and try again.
+ * 4.) Will first try getting a chunk that will satisfy the requested size.
+ * 5.) If a chunk of the requested size cannot be allocated, then try finding
+ * a chunk that will satisfy the minum needed.
+ *
+ * Returns 0 on success, else -1.
+ */
+int __init nvram_init_os_partition(struct nvram_os_partition *part)
+{
+ loff_t p;
+ int size;
+
+ /* Look for ours */
+ p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
+
+ /* Found one but too small, remove it */
+ if (p && size < part->min_size) {
+ pr_info("nvram: Found too small %s partition,"
+ " removing it...\n", part->name);
+ nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
+ p = 0;
+ }
+
+ /* Create one if we didn't find */
+ if (!p) {
+ p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+ part->req_size, part->min_size);
+ if (p == -ENOSPC) {
+ pr_info("nvram: No room to create %s partition, "
+ "deleting any obsolete OS partitions...\n",
+ part->name);
+ nvram_remove_partition(NULL, NVRAM_SIG_OS,
+ nvram_os_partitions);
+ p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+ part->req_size, part->min_size);
+ }
+ }
+
+ if (p <= 0) {
+ pr_err("nvram: Failed to find or create %s"
+ " partition, err %d\n", part->name, (int)p);
+ return -1;
+ }
+
+ part->index = p;
+ part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
+
+ return 0;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+ size_t outlen)
+{
+ int err, ret;
+
+ ret = -EIO;
+ err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+ MEM_LEVEL, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK)
+ goto error;
+
+ stream.next_in = in;
+ stream.avail_in = inlen;
+ stream.total_in = 0;
+ stream.next_out = out;
+ stream.avail_out = outlen;
+ stream.total_out = 0;
+
+ err = zlib_deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ goto error;
+
+ err = zlib_deflateEnd(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ if (stream.total_out >= stream.total_in)
+ goto error;
+
+ ret = stream.total_out;
+error:
+ return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+ struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+ int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+ oops_data_sz);
+ if (zipped_len < 0) {
+ pr_err("nvram: compression failed; returned %d\n", zipped_len);
+ pr_err("nvram: logging uncompressed oops/panic report\n");
+ return -1;
+ }
+ oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+ oops_hdr->report_length = cpu_to_be16(zipped_len);
+ oops_hdr->timestamp = cpu_to_be64(get_seconds());
+ return 0;
+}
+
+#ifdef CONFIG_PSTORE
+static int nvram_pstore_open(struct pstore_info *psi)
+{
+ /* Reset the iterator to start reading partitions again */
+ read_type = -1;
+ return 0;
+}
+
+/**
+ * nvram_pstore_write - pstore write callback for nvram
+ * @type: Type of message logged
+ * @reason: reason behind dump (oops/panic)
+ * @id: identifier to indicate the write performed
+ * @part: pstore writes data to registered buffer in parts,
+ * part number will indicate the same.
+ * @count: Indicates oops count
+ * @compressed: Flag to indicate the log is compressed
+ * @size: number of bytes written to the registered buffer
+ * @psi: registered pstore_info structure
+ *
+ * Called by pstore_dump() when an oops or panic report is logged in the
+ * printk buffer.
+ * Returns 0 on successful write.
+ */
+static int nvram_pstore_write(enum pstore_type_id type,
+ enum kmsg_dump_reason reason,
+ u64 *id, unsigned int part, int count,
+ bool compressed, size_t size,
+ struct pstore_info *psi)
+{
+ int rc;
+ unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
+ struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
+
+ /* part 1 has the recent messages from printk buffer */
+ if (part > 1 || (type != PSTORE_TYPE_DMESG))
+ return -1;
+
+ if (clobbering_unread_rtas_event())
+ return -1;
+
+ oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+ oops_hdr->report_length = cpu_to_be16(size);
+ oops_hdr->timestamp = cpu_to_be64(get_seconds());
+
+ if (compressed)
+ err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+
+ rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
+ (int) (sizeof(*oops_hdr) + size), err_type, count);
+
+ if (rc != 0)
+ return rc;
+
+ *id = part;
+ return 0;
+}
+
+/*
+ * Reads the oops/panic report, rtas, of-config and common partition.
+ * Returns the length of the data we read from each partition.
+ * Returns 0 if we've been called before.
+ */
+static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
+ int *count, struct timespec *time, char **buf,
+ bool *compressed, struct pstore_info *psi)
+{
+ struct oops_log_info *oops_hdr;
+ unsigned int err_type, id_no, size = 0;
+ struct nvram_os_partition *part = NULL;
+ char *buff = NULL;
+ int sig = 0;
+ loff_t p;
+
+ read_type++;
+
+ switch (nvram_type_ids[read_type]) {
+ case PSTORE_TYPE_DMESG:
+ part = &oops_log_partition;
+ *type = PSTORE_TYPE_DMESG;
+ break;
+ case PSTORE_TYPE_PPC_COMMON:
+ sig = NVRAM_SIG_SYS;
+ part = &common_partition;
+ *type = PSTORE_TYPE_PPC_COMMON;
+ *id = PSTORE_TYPE_PPC_COMMON;
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+ break;
+#ifdef CONFIG_PPC_PSERIES
+ case PSTORE_TYPE_PPC_RTAS:
+ part = &rtas_log_partition;
+ *type = PSTORE_TYPE_PPC_RTAS;
+ time->tv_sec = last_rtas_event;
+ time->tv_nsec = 0;
+ break;
+ case PSTORE_TYPE_PPC_OF:
+ sig = NVRAM_SIG_OF;
+ part = &of_config_partition;
+ *type = PSTORE_TYPE_PPC_OF;
+ *id = PSTORE_TYPE_PPC_OF;
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ if (!part->os_partition) {
+ p = nvram_find_partition(part->name, sig, &size);
+ if (p <= 0) {
+ pr_err("nvram: Failed to find partition %s, "
+ "err %d\n", part->name, (int)p);
+ return 0;
+ }
+ part->index = p;
+ part->size = size;
+ }
+
+ buff = kmalloc(part->size, GFP_KERNEL);
+
+ if (!buff)
+ return -ENOMEM;
+
+ if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
+ kfree(buff);
+ return 0;
+ }
+
+ *count = 0;
+
+ if (part->os_partition)
+ *id = id_no;
+
+ if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
+ size_t length, hdr_size;
+
+ oops_hdr = (struct oops_log_info *)buff;
+ if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
+ /* Old format oops header had 2-byte record size */
+ hdr_size = sizeof(u16);
+ length = be16_to_cpu(oops_hdr->version);
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+ } else {
+ hdr_size = sizeof(*oops_hdr);
+ length = be16_to_cpu(oops_hdr->report_length);
+ time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
+ time->tv_nsec = 0;
+ }
+ *buf = kmalloc(length, GFP_KERNEL);
+ if (*buf == NULL)
+ return -ENOMEM;
+ memcpy(*buf, buff + hdr_size, length);
+ kfree(buff);
+
+ if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
+ *compressed = true;
+ else
+ *compressed = false;
+ return length;
+ }
+
+ *buf = buff;
+ return part->size;
+}
+
+static struct pstore_info nvram_pstore_info = {
+ .owner = THIS_MODULE,
+ .name = "nvram",
+ .open = nvram_pstore_open,
+ .read = nvram_pstore_read,
+ .write = nvram_pstore_write,
+};
+
+static int nvram_pstore_init(void)
+{
+ int rc = 0;
+
+ nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
+ nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
+
+ nvram_pstore_info.buf = oops_data;
+ nvram_pstore_info.bufsize = oops_data_sz;
+
+ spin_lock_init(&nvram_pstore_info.buf_lock);
+
+ rc = pstore_register(&nvram_pstore_info);
+ if (rc != 0)
+ pr_err("nvram: pstore_register() failed, defaults to "
+ "kmsg_dump; returned %d\n", rc);
+
+ return rc;
+}
+#else
+static int nvram_pstore_init(void)
+{
+ return -1;
+}
+#endif
+
+void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+ int rc;
+
+ rc = nvram_init_os_partition(&oops_log_partition);
+ if (rc != 0) {
+#ifdef CONFIG_PPC_PSERIES
+ if (!rtas_partition_exists) {
+ pr_err("nvram: Failed to initialize oops partition!");
+ return;
+ }
+ pr_notice("nvram: Using %s partition to log both"
+ " RTAS errors and oops/panic reports\n",
+ rtas_log_partition.name);
+ memcpy(&oops_log_partition, &rtas_log_partition,
+ sizeof(rtas_log_partition));
+#else
+ pr_err("nvram: Failed to initialize oops partition!");
+ return;
+#endif
+ }
+ oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+ if (!oops_buf) {
+ pr_err("nvram: No memory for %s partition\n",
+ oops_log_partition.name);
+ return;
+ }
+ oops_data = oops_buf + sizeof(struct oops_log_info);
+ oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
+
+ rc = nvram_pstore_init();
+
+ if (!rc)
+ return;
+
+ /*
+ * Figure compression (preceded by elimination of each line's <n>
+ * severity prefix) will reduce the oops/panic report to at most
+ * 45% of its original size.
+ */
+ big_oops_buf_sz = (oops_data_sz * 100) / 45;
+ big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+ if (big_oops_buf) {
+ stream.workspace = kmalloc(zlib_deflate_workspacesize(
+ WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+ if (!stream.workspace) {
+ pr_err("nvram: No memory for compression workspace; "
+ "skipping compression of %s partition data\n",
+ oops_log_partition.name);
+ kfree(big_oops_buf);
+ big_oops_buf = NULL;
+ }
+ } else {
+ pr_err("No memory for uncompressed %s data; "
+ "skipping compression\n", oops_log_partition.name);
+ stream.workspace = NULL;
+ }
+
+ rc = kmsg_dump_register(&nvram_kmsg_dumper);
+ if (rc != 0) {
+ pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+ kfree(oops_buf);
+ kfree(big_oops_buf);
+ kfree(stream.workspace);
+ }
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer. We want to capture as much
+ * of the printk buffer as possible. First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition. If that's too much, go back and capture uncompressed text.
+ */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+ static unsigned int oops_count = 0;
+ static bool panicking = false;
+ static DEFINE_SPINLOCK(lock);
+ unsigned long flags;
+ size_t text_len;
+ unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+ int rc = -1;
+
+ switch (reason) {
+ case KMSG_DUMP_RESTART:
+ case KMSG_DUMP_HALT:
+ case KMSG_DUMP_POWEROFF:
+ /* These are almost always orderly shutdowns. */
+ return;
+ case KMSG_DUMP_OOPS:
+ break;
+ case KMSG_DUMP_PANIC:
+ panicking = true;
+ break;
+ case KMSG_DUMP_EMERG:
+ if (panicking)
+ /* Panic report already captured. */
+ return;
+ break;
+ default:
+ pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
+ __func__, (int) reason);
+ return;
+ }
+
+ if (clobbering_unread_rtas_event())
+ return;
+
+ if (!spin_trylock_irqsave(&lock, flags))
+ return;
+
+ if (big_oops_buf) {
+ kmsg_dump_get_buffer(dumper, false,
+ big_oops_buf, big_oops_buf_sz, &text_len);
+ rc = zip_oops(text_len);
+ }
+ if (rc != 0) {
+ kmsg_dump_rewind(dumper);
+ kmsg_dump_get_buffer(dumper, false,
+ oops_data, oops_data_sz, &text_len);
+ err_type = ERR_TYPE_KERNEL_PANIC;
+ oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+ oops_hdr->report_length = cpu_to_be16(text_len);
+ oops_hdr->timestamp = cpu_to_be64(get_seconds());
+ }
+
+ (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+ (int) (sizeof(*oops_hdr) + text_len), err_type,
+ ++oops_count);
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
{
int size;
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 054a0ed..97b8fc6 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -30,129 +30,17 @@
/* Max bytes to read/write in one go */
#define NVRW_CNT 0x20
-/*
- * Set oops header version to distinguish between old and new format header.
- * lnx,oops-log partition max size is 4000, header version > 4000 will
- * help in identifying new header.
- */
-#define OOPS_HDR_VERSION 5000
-
static unsigned int nvram_size;
static int nvram_fetch, nvram_store;
static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
static DEFINE_SPINLOCK(nvram_lock);
-struct err_log_info {
- __be32 error_type;
- __be32 seq_num;
-};
-
-struct nvram_os_partition {
- const char *name;
- int req_size; /* desired size, in bytes */
- int min_size; /* minimum acceptable size (0 means req_size) */
- long size; /* size of data portion (excluding err_log_info) */
- long index; /* offset of data portion of partition */
- bool os_partition; /* partition initialized by OS, not FW */
-};
-
-static struct nvram_os_partition rtas_log_partition = {
- .name = "ibm,rtas-log",
- .req_size = 2079,
- .min_size = 1055,
- .index = -1,
- .os_partition = true
-};
-
-static struct nvram_os_partition oops_log_partition = {
- .name = "lnx,oops-log",
- .req_size = 4000,
- .min_size = 2000,
- .index = -1,
- .os_partition = true
-};
-
-static const char *pseries_nvram_os_partitions[] = {
- "ibm,rtas-log",
- "lnx,oops-log",
- NULL
-};
-
-struct oops_log_info {
- __be16 version;
- __be16 report_length;
- __be64 timestamp;
-} __attribute__((packed));
-
-static void oops_to_nvram(struct kmsg_dumper *dumper,
- enum kmsg_dump_reason reason);
-
-static struct kmsg_dumper nvram_kmsg_dumper = {
- .dump = oops_to_nvram
-};
-
/* See clobbering_unread_rtas_event() */
#define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */
static unsigned long last_unread_rtas_event; /* timestamp */
-/*
- * For capturing and compressing an oops or panic report...
-
- * big_oops_buf[] holds the uncompressed text we're capturing.
- *
- * oops_buf[] holds the compressed text, preceded by a oops header.
- * oops header has u16 holding the version of oops header (to differentiate
- * between old and new format header) followed by u16 holding the length of
- * the compressed* text (*Or uncompressed, if compression fails.) and u64
- * holding the timestamp. oops_buf[] gets written to NVRAM.
- *
- * oops_log_info points to the header. oops_data points to the compressed text.
- *
- * +- oops_buf
- * | +- oops_data
- * v v
- * +-----------+-----------+-----------+------------------------+
- * | version | length | timestamp | text |
- * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
- * +-----------+-----------+-----------+------------------------+
- * ^
- * +- oops_log_info
- *
- * We preallocate these buffers during init to avoid kmalloc during oops/panic.
- */
-static size_t big_oops_buf_sz;
-static char *big_oops_buf, *oops_buf;
-static char *oops_data;
-static size_t oops_data_sz;
-
-/* Compression parameters */
-#define COMPR_LEVEL 6
-#define WINDOW_BITS 12
-#define MEM_LEVEL 4
-static struct z_stream_s stream;
-
#ifdef CONFIG_PSTORE
-static struct nvram_os_partition of_config_partition = {
- .name = "of-config",
- .index = -1,
- .os_partition = false
-};
-
-static struct nvram_os_partition common_partition = {
- .name = "common",
- .index = -1,
- .os_partition = false
-};
-
-static enum pstore_type_id nvram_type_ids[] = {
- PSTORE_TYPE_DMESG,
- PSTORE_TYPE_PPC_RTAS,
- PSTORE_TYPE_PPC_OF,
- PSTORE_TYPE_PPC_COMMON,
- -1
-};
-static int read_type;
-static unsigned long last_rtas_event;
+unsigned long last_rtas_event;
#endif
static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
@@ -246,73 +134,11 @@ static ssize_t pSeries_nvram_get_size(void)
return nvram_size ? nvram_size : -ENODEV;
}
-
-/* nvram_write_os_partition, nvram_write_error_log
+/* nvram_write_error_log
*
* We need to buffer the error logs into nvram to ensure that we have
- * the failure information to decode. If we have a severe error there
- * is no way to guarantee that the OS or the machine is in a state to
- * get back to user land and write the error to disk. For example if
- * the SCSI device driver causes a Machine Check by writing to a bad
- * IO address, there is no way of guaranteeing that the device driver
- * is in any state that is would also be able to write the error data
- * captured to disk, thus we buffer it in NVRAM for analysis on the
- * next boot.
- *
- * In NVRAM the partition containing the error log buffer will looks like:
- * Header (in bytes):
- * +-----------+----------+--------+------------+------------------+
- * | signature | checksum | length | name | data |
- * |0 |1 |2 3|4 15|16 length-1|
- * +-----------+----------+--------+------------+------------------+
- *
- * The 'data' section would look like (in bytes):
- * +--------------+------------+-----------------------------------+
- * | event_logged | sequence # | error log |
- * |0 3|4 7|8 error_log_size-1|
- * +--------------+------------+-----------------------------------+
- *
- * event_logged: 0 if event has not been logged to syslog, 1 if it has
- * sequence #: The unique sequence # for each event. (until it wraps)
- * error log: The error log from event_scan
+ * the failure information to decode.
*/
-static int nvram_write_os_partition(struct nvram_os_partition *part,
- char *buff, int length,
- unsigned int err_type,
- unsigned int error_log_cnt)
-{
- int rc;
- loff_t tmp_index;
- struct err_log_info info;
-
- if (part->index == -1) {
- return -ESPIPE;
- }
-
- if (length > part->size) {
- length = part->size;
- }
-
- info.error_type = cpu_to_be32(err_type);
- info.seq_num = cpu_to_be32(error_log_cnt);
-
- tmp_index = part->index;
-
- rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
- if (rc <= 0) {
- pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
- return rc;
- }
-
- rc = ppc_md.nvram_write(buff, length, &tmp_index);
- if (rc <= 0) {
- pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
- return rc;
- }
-
- return 0;
-}
-
int nvram_write_error_log(char * buff, int length,
unsigned int err_type, unsigned int error_log_cnt)
{
@@ -328,50 +154,6 @@ int nvram_write_error_log(char * buff, int length,
return rc;
}
-/* nvram_read_partition
- *
- * Reads nvram partition for at most 'length'
- */
-static int nvram_read_partition(struct nvram_os_partition *part, char *buff,
- int length, unsigned int *err_type,
- unsigned int *error_log_cnt)
-{
- int rc;
- loff_t tmp_index;
- struct err_log_info info;
-
- if (part->index == -1)
- return -1;
-
- if (length > part->size)
- length = part->size;
-
- tmp_index = part->index;
-
- if (part->os_partition) {
- rc = ppc_md.nvram_read((char *)&info,
- sizeof(struct err_log_info),
- &tmp_index);
- if (rc <= 0) {
- pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
- return rc;
- }
- }
-
- rc = ppc_md.nvram_read(buff, length, &tmp_index);
- if (rc <= 0) {
- pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
- return rc;
- }
-
- if (part->os_partition) {
- *error_log_cnt = be32_to_cpu(info.seq_num);
- *err_type = be32_to_cpu(info.error_type);
- }
-
- return 0;
-}
-
/* nvram_read_error_log
*
* Reads nvram for error log for at most 'length'
@@ -407,67 +189,6 @@ int nvram_clear_error_log(void)
return 0;
}
-/* pseries_nvram_init_os_partition
- *
- * This sets up a partition with an "OS" signature.
- *
- * The general strategy is the following:
- * 1.) If a partition with the indicated name already exists...
- * - If it's large enough, use it.
- * - Otherwise, recycle it and keep going.
- * 2.) Search for a free partition that is large enough.
- * 3.) If there's not a free partition large enough, recycle any obsolete
- * OS partitions and try again.
- * 4.) Will first try getting a chunk that will satisfy the requested size.
- * 5.) If a chunk of the requested size cannot be allocated, then try finding
- * a chunk that will satisfy the minum needed.
- *
- * Returns 0 on success, else -1.
- */
-static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
- *part)
-{
- loff_t p;
- int size;
-
- /* Look for ours */
- p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
-
- /* Found one but too small, remove it */
- if (p && size < part->min_size) {
- pr_info("nvram: Found too small %s partition,"
- " removing it...\n", part->name);
- nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
- p = 0;
- }
-
- /* Create one if we didn't find */
- if (!p) {
- p = nvram_create_partition(part->name, NVRAM_SIG_OS,
- part->req_size, part->min_size);
- if (p == -ENOSPC) {
- pr_info("nvram: No room to create %s partition, "
- "deleting any obsolete OS partitions...\n",
- part->name);
- nvram_remove_partition(NULL, NVRAM_SIG_OS,
- pseries_nvram_os_partitions);
- p = nvram_create_partition(part->name, NVRAM_SIG_OS,
- part->req_size, part->min_size);
- }
- }
-
- if (p <= 0) {
- pr_err("nvram: Failed to find or create %s"
- " partition, err %d\n", part->name, (int)p);
- return -1;
- }
-
- part->index = p;
- part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
-
- return 0;
-}
-
/*
* Are we using the ibm,rtas-log for oops/panic reports? And if so,
* would logging this oops/panic overwrite an RTAS event that rtas_errd
@@ -476,7 +197,7 @@ static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
* We assume that if rtas_errd hasn't read the RTAS event in
* NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
*/
-static int clobbering_unread_rtas_event(void)
+int clobbering_unread_rtas_event(void)
{
return (oops_log_partition.index == rtas_log_partition.index
&& last_unread_rtas_event
@@ -484,313 +205,6 @@ static int clobbering_unread_rtas_event(void)
NVRAM_RTAS_READ_TIMEOUT);
}
-/* Derived from logfs_compress() */
-static int nvram_compress(const void *in, void *out, size_t inlen,
- size_t outlen)
-{
- int err, ret;
-
- ret = -EIO;
- err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
- MEM_LEVEL, Z_DEFAULT_STRATEGY);
- if (err != Z_OK)
- goto error;
-
- stream.next_in = in;
- stream.avail_in = inlen;
- stream.total_in = 0;
- stream.next_out = out;
- stream.avail_out = outlen;
- stream.total_out = 0;
-
- err = zlib_deflate(&stream, Z_FINISH);
- if (err != Z_STREAM_END)
- goto error;
-
- err = zlib_deflateEnd(&stream);
- if (err != Z_OK)
- goto error;
-
- if (stream.total_out >= stream.total_in)
- goto error;
-
- ret = stream.total_out;
-error:
- return ret;
-}
-
-/* Compress the text from big_oops_buf into oops_buf. */
-static int zip_oops(size_t text_len)
-{
- struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
- int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
- oops_data_sz);
- if (zipped_len < 0) {
- pr_err("nvram: compression failed; returned %d\n", zipped_len);
- pr_err("nvram: logging uncompressed oops/panic report\n");
- return -1;
- }
- oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
- oops_hdr->report_length = cpu_to_be16(zipped_len);
- oops_hdr->timestamp = cpu_to_be64(get_seconds());
- return 0;
-}
-
-#ifdef CONFIG_PSTORE
-static int nvram_pstore_open(struct pstore_info *psi)
-{
- /* Reset the iterator to start reading partitions again */
- read_type = -1;
- return 0;
-}
-
-/**
- * nvram_pstore_write - pstore write callback for nvram
- * @type: Type of message logged
- * @reason: reason behind dump (oops/panic)
- * @id: identifier to indicate the write performed
- * @part: pstore writes data to registered buffer in parts,
- * part number will indicate the same.
- * @count: Indicates oops count
- * @compressed: Flag to indicate the log is compressed
- * @size: number of bytes written to the registered buffer
- * @psi: registered pstore_info structure
- *
- * Called by pstore_dump() when an oops or panic report is logged in the
- * printk buffer.
- * Returns 0 on successful write.
- */
-static int nvram_pstore_write(enum pstore_type_id type,
- enum kmsg_dump_reason reason,
- u64 *id, unsigned int part, int count,
- bool compressed, size_t size,
- struct pstore_info *psi)
-{
- int rc;
- unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
- struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
-
- /* part 1 has the recent messages from printk buffer */
- if (part > 1 || type != PSTORE_TYPE_DMESG ||
- clobbering_unread_rtas_event())
- return -1;
-
- oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
- oops_hdr->report_length = cpu_to_be16(size);
- oops_hdr->timestamp = cpu_to_be64(get_seconds());
-
- if (compressed)
- err_type = ERR_TYPE_KERNEL_PANIC_GZ;
-
- rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
- (int) (sizeof(*oops_hdr) + size), err_type, count);
-
- if (rc != 0)
- return rc;
-
- *id = part;
- return 0;
-}
-
-/*
- * Reads the oops/panic report, rtas, of-config and common partition.
- * Returns the length of the data we read from each partition.
- * Returns 0 if we've been called before.
- */
-static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
- int *count, struct timespec *time, char **buf,
- bool *compressed, struct pstore_info *psi)
-{
- struct oops_log_info *oops_hdr;
- unsigned int err_type, id_no, size = 0;
- struct nvram_os_partition *part = NULL;
- char *buff = NULL;
- int sig = 0;
- loff_t p;
-
- read_type++;
-
- switch (nvram_type_ids[read_type]) {
- case PSTORE_TYPE_DMESG:
- part = &oops_log_partition;
- *type = PSTORE_TYPE_DMESG;
- break;
- case PSTORE_TYPE_PPC_RTAS:
- part = &rtas_log_partition;
- *type = PSTORE_TYPE_PPC_RTAS;
- time->tv_sec = last_rtas_event;
- time->tv_nsec = 0;
- break;
- case PSTORE_TYPE_PPC_OF:
- sig = NVRAM_SIG_OF;
- part = &of_config_partition;
- *type = PSTORE_TYPE_PPC_OF;
- *id = PSTORE_TYPE_PPC_OF;
- time->tv_sec = 0;
- time->tv_nsec = 0;
- break;
- case PSTORE_TYPE_PPC_COMMON:
- sig = NVRAM_SIG_SYS;
- part = &common_partition;
- *type = PSTORE_TYPE_PPC_COMMON;
- *id = PSTORE_TYPE_PPC_COMMON;
- time->tv_sec = 0;
- time->tv_nsec = 0;
- break;
- default:
- return 0;
- }
-
- if (!part->os_partition) {
- p = nvram_find_partition(part->name, sig, &size);
- if (p <= 0) {
- pr_err("nvram: Failed to find partition %s, "
- "err %d\n", part->name, (int)p);
- return 0;
- }
- part->index = p;
- part->size = size;
- }
-
- buff = kmalloc(part->size, GFP_KERNEL);
-
- if (!buff)
- return -ENOMEM;
-
- if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
- kfree(buff);
- return 0;
- }
-
- *count = 0;
-
- if (part->os_partition)
- *id = id_no;
-
- if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
- size_t length, hdr_size;
-
- oops_hdr = (struct oops_log_info *)buff;
- if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
- /* Old format oops header had 2-byte record size */
- hdr_size = sizeof(u16);
- length = be16_to_cpu(oops_hdr->version);
- time->tv_sec = 0;
- time->tv_nsec = 0;
- } else {
- hdr_size = sizeof(*oops_hdr);
- length = be16_to_cpu(oops_hdr->report_length);
- time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
- time->tv_nsec = 0;
- }
- *buf = kmalloc(length, GFP_KERNEL);
- if (*buf == NULL)
- return -ENOMEM;
- memcpy(*buf, buff + hdr_size, length);
- kfree(buff);
-
- if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
- *compressed = true;
- else
- *compressed = false;
- return length;
- }
-
- *buf = buff;
- return part->size;
-}
-
-static struct pstore_info nvram_pstore_info = {
- .owner = THIS_MODULE,
- .name = "nvram",
- .open = nvram_pstore_open,
- .read = nvram_pstore_read,
- .write = nvram_pstore_write,
-};
-
-static int nvram_pstore_init(void)
-{
- int rc = 0;
-
- nvram_pstore_info.buf = oops_data;
- nvram_pstore_info.bufsize = oops_data_sz;
-
- spin_lock_init(&nvram_pstore_info.buf_lock);
-
- rc = pstore_register(&nvram_pstore_info);
- if (rc != 0)
- pr_err("nvram: pstore_register() failed, defaults to "
- "kmsg_dump; returned %d\n", rc);
-
- return rc;
-}
-#else
-static int nvram_pstore_init(void)
-{
- return -1;
-}
-#endif
-
-static void __init nvram_init_oops_partition(int rtas_partition_exists)
-{
- int rc;
-
- rc = pseries_nvram_init_os_partition(&oops_log_partition);
- if (rc != 0) {
- if (!rtas_partition_exists)
- return;
- pr_notice("nvram: Using %s partition to log both"
- " RTAS errors and oops/panic reports\n",
- rtas_log_partition.name);
- memcpy(&oops_log_partition, &rtas_log_partition,
- sizeof(rtas_log_partition));
- }
- oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
- if (!oops_buf) {
- pr_err("nvram: No memory for %s partition\n",
- oops_log_partition.name);
- return;
- }
- oops_data = oops_buf + sizeof(struct oops_log_info);
- oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
-
- rc = nvram_pstore_init();
-
- if (!rc)
- return;
-
- /*
- * Figure compression (preceded by elimination of each line's <n>
- * severity prefix) will reduce the oops/panic report to at most
- * 45% of its original size.
- */
- big_oops_buf_sz = (oops_data_sz * 100) / 45;
- big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
- if (big_oops_buf) {
- stream.workspace = kmalloc(zlib_deflate_workspacesize(
- WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
- if (!stream.workspace) {
- pr_err("nvram: No memory for compression workspace; "
- "skipping compression of %s partition data\n",
- oops_log_partition.name);
- kfree(big_oops_buf);
- big_oops_buf = NULL;
- }
- } else {
- pr_err("No memory for uncompressed %s data; "
- "skipping compression\n", oops_log_partition.name);
- stream.workspace = NULL;
- }
-
- rc = kmsg_dump_register(&nvram_kmsg_dumper);
- if (rc != 0) {
- pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
- kfree(oops_buf);
- kfree(big_oops_buf);
- kfree(stream.workspace);
- }
-}
-
static int __init pseries_nvram_init_log_partitions(void)
{
int rc;
@@ -798,7 +212,7 @@ static int __init pseries_nvram_init_log_partitions(void)
/* Scan nvram for partitions */
nvram_scan_partitions();
- rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+ rc = nvram_init_os_partition(&rtas_log_partition);
nvram_init_oops_partition(rc == 0);
return 0;
}
@@ -834,72 +248,3 @@ int __init pSeries_nvram_init(void)
return 0;
}
-
-/*
- * This is our kmsg_dump callback, called after an oops or panic report
- * has been written to the printk buffer. We want to capture as much
- * of the printk buffer as possible. First, capture as much as we can
- * that we think will compress sufficiently to fit in the lnx,oops-log
- * partition. If that's too much, go back and capture uncompressed text.
- */
-static void oops_to_nvram(struct kmsg_dumper *dumper,
- enum kmsg_dump_reason reason)
-{
- struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
- static unsigned int oops_count = 0;
- static bool panicking = false;
- static DEFINE_SPINLOCK(lock);
- unsigned long flags;
- size_t text_len;
- unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
- int rc = -1;
-
- switch (reason) {
- case KMSG_DUMP_RESTART:
- case KMSG_DUMP_HALT:
- case KMSG_DUMP_POWEROFF:
- /* These are almost always orderly shutdowns. */
- return;
- case KMSG_DUMP_OOPS:
- break;
- case KMSG_DUMP_PANIC:
- panicking = true;
- break;
- case KMSG_DUMP_EMERG:
- if (panicking)
- /* Panic report already captured. */
- return;
- break;
- default:
- pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
- __func__, (int) reason);
- return;
- }
-
- if (clobbering_unread_rtas_event())
- return;
-
- if (!spin_trylock_irqsave(&lock, flags))
- return;
-
- if (big_oops_buf) {
- kmsg_dump_get_buffer(dumper, false,
- big_oops_buf, big_oops_buf_sz, &text_len);
- rc = zip_oops(text_len);
- }
- if (rc != 0) {
- kmsg_dump_rewind(dumper);
- kmsg_dump_get_buffer(dumper, false,
- oops_data, oops_data_sz, &text_len);
- err_type = ERR_TYPE_KERNEL_PANIC;
- oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
- oops_hdr->report_length = cpu_to_be16(text_len);
- oops_hdr->timestamp = cpu_to_be64(get_seconds());
- }
-
- (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
- (int) (sizeof(*oops_hdr) + text_len), err_type,
- ++oops_count);
-
- spin_unlock_irqrestore(&lock, flags);
-}
^ permalink raw reply related
* [PATCH v3 2/3] pstore: Add pstore type id for firmware partition
From: Hari Bathini @ 2014-12-24 11:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Mahesh J Salgaonkar
In-Reply-To: <20141224115729.25731.20371.stgit@localhost.localdomain>
This patch adds a pstore type id to be used for opal specific
nvram partitions.
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
fs/pstore/inode.c | 3 +++
include/linux/pstore.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 5041660..8e0c009 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -359,6 +359,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
case PSTORE_TYPE_PPC_COMMON:
sprintf(name, "powerpc-common-%s-%lld", psname, id);
break;
+ case PSTORE_TYPE_PPC_OPAL:
+ sprintf(name, "powerpc-opal-%s-%lld", psname, id);
+ break;
case PSTORE_TYPE_UNKNOWN:
sprintf(name, "unknown-%s-%lld", psname, id);
break;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index ece0c6b..af44980 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,6 +39,7 @@ enum pstore_type_id {
PSTORE_TYPE_PPC_RTAS = 4,
PSTORE_TYPE_PPC_OF = 5,
PSTORE_TYPE_PPC_COMMON = 6,
+ PSTORE_TYPE_PPC_OPAL = 7,
PSTORE_TYPE_UNKNOWN = 255
};
^ permalink raw reply related
* [PATCH v3 3/3] pstore: add pstore support on powernv
From: Hari Bathini @ 2014-12-24 11:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Mahesh J Salgaonkar
In-Reply-To: <20141224115729.25731.20371.stgit@localhost.localdomain>
This patch extends pstore, a generic interface to platform dependent
persistent storage, support for powernv platform to capture certain
useful information, during dying moments. Such support is already in
place for pseries platform. This patch re-uses most of that code.
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
arch/powerpc/kernel/nvram_64.c | 25 +++++++++++++++++++++++--
arch/powerpc/platforms/powernv/opal-nvram.c | 10 ++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 42e5c6a..293da88 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -127,6 +127,14 @@ static size_t oops_data_sz;
static struct z_stream_s stream;
#ifdef CONFIG_PSTORE
+#ifdef CONFIG_PPC_POWERNV
+static struct nvram_os_partition skiboot_partition = {
+ .name = "ibm,skiboot",
+ .index = -1,
+ .os_partition = false
+};
+#endif
+
#ifdef CONFIG_PPC_PSERIES
static struct nvram_os_partition of_config_partition = {
.name = "of-config",
@@ -477,6 +485,16 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
time->tv_nsec = 0;
break;
#endif
+#ifdef CONFIG_PPC_POWERNV
+ case PSTORE_TYPE_PPC_OPAL:
+ sig = NVRAM_SIG_FW;
+ part = &skiboot_partition;
+ *type = PSTORE_TYPE_PPC_OPAL;
+ *id = PSTORE_TYPE_PPC_OPAL;
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+ break;
+#endif
default:
return 0;
}
@@ -552,8 +570,11 @@ static int nvram_pstore_init(void)
{
int rc = 0;
- nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
- nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
+ if (machine_is(pseries)) {
+ nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
+ nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
+ } else
+ nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
nvram_pstore_info.buf = oops_data;
nvram_pstore_info.bufsize = oops_data_sz;
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
index f9896fd..9db4398 100644
--- a/arch/powerpc/platforms/powernv/opal-nvram.c
+++ b/arch/powerpc/platforms/powernv/opal-nvram.c
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include <asm/opal.h>
+#include <asm/nvram.h>
#include <asm/machdep.h>
static unsigned int nvram_size;
@@ -62,6 +63,15 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
return count;
}
+static int __init opal_nvram_init_log_partitions(void)
+{
+ /* Scan nvram for partitions */
+ nvram_scan_partitions();
+ nvram_init_oops_partition(0);
+ return 0;
+}
+machine_arch_initcall(powernv, opal_nvram_init_log_partitions);
+
void __init opal_nvram_init(void)
{
struct device_node *np;
^ permalink raw reply related
* unable to boot kernel on power6
From: Anatoly Pugachev @ 2014-12-24 21:41 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 304 bytes --]
Hello!
Can someone from powerpc kernel guys look at
https://bugzilla.redhat.com/show_bug.cgi?id=1093163
It can not load kernel on power6 JS22 (type 7998) blade, starting from 3.11
kernel (but 3.9.x actually bootable).
Thanks.
PS: not sure, is it worth investigating since it's power6 (old hardware).
[-- Attachment #2: Type: text/html, Size: 420 bytes --]
^ permalink raw reply
* [PATCH 0/6] kbuild: refactor Makefiles related with cc-version
From: Masahiro Yamada @ 2014-12-25 5:31 UTC (permalink / raw)
To: linux-kbuild
Cc: Michal Marek, Jonathan Corbet, Andi Kleen, Robert Richter,
linux-parisc, linux-doc, Peter Oberparleiter, Helge Deller, x86,
linux-kernel, James E.J. Bottomley, Masahiro Yamada, Ingo Molnar,
H. Peter Anvin, Paul Mackerras, Thomas Gleixner, H. Peter Anvin,
linuxppc-dev
Masahiro Yamada (6):
kbuild: fix cc-ifversion macro
kbuild: do not add $(call ...) to invoke cc-version or cc-fullversion
kbuild,gcov: remove unnecessary workaround
kbuild,gcov: simplify kernel/gcov/Makefile
kbuild: allow cc-ifversion to have the argument for false condition
kbuild,gcov: simplify kernel/gcov/Makefile more
Documentation/kbuild/makefiles.txt | 9 +++++----
arch/parisc/Makefile | 2 +-
arch/powerpc/Makefile | 6 +++---
arch/x86/Makefile.um | 2 +-
kernel/gcov/Makefile | 36 +++++-------------------------------
scripts/Kbuild.include | 7 ++-----
6 files changed, 17 insertions(+), 45 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 2/6] kbuild: do not add $(call ...) to invoke cc-version or cc-fullversion
From: Masahiro Yamada @ 2014-12-25 5:31 UTC (permalink / raw)
To: linux-kbuild
Cc: Michal Marek, Robert Richter, x86, linux-parisc, Jonathan Corbet,
Peter Oberparleiter, Helge Deller, H. Peter Anvin, linux-doc,
James E.J. Bottomley, linux-kernel, Masahiro Yamada, Andi Kleen,
Ingo Molnar, Paul Mackerras, Thomas Gleixner, linuxppc-dev
In-Reply-To: <1419485488-22336-1-git-send-email-yamada.m@jp.panasonic.com>
The macros cc-version, cc-fullversion and ld-version take no argument.
It is not necessary to add $(call ...) to invoke them.
Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
---
Documentation/kbuild/makefiles.txt | 4 ++--
arch/parisc/Makefile | 2 +-
arch/powerpc/Makefile | 6 +++---
arch/x86/Makefile.um | 2 +-
kernel/gcov/Makefile | 2 +-
scripts/Kbuild.include | 7 ++-----
6 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index a311db8..7b3487a 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -524,7 +524,7 @@ more details, with real examples.
Example:
#arch/x86/Makefile
cflags-y += $(shell \
- if [ $(call cc-version) -ge 0300 ] ; then \
+ if [ $(cc-version) -ge 0300 ] ; then \
echo "-mregparm=3"; fi ;)
In the above example, -mregparm=3 is only used for gcc version greater
@@ -552,7 +552,7 @@ more details, with real examples.
Example:
#arch/powerpc/Makefile
- $(Q)if test "$(call cc-fullversion)" = "040200" ; then \
+ $(Q)if test "$(cc-fullversion)" = "040200" ; then \
echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \
false ; \
fi
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index e9b4b6a..ff5e55f 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -149,7 +149,7 @@ endef
# we require gcc 3.3 or above to compile the kernel
archprepare: checkbin
checkbin:
- @if test "$(call cc-version)" -lt "0303"; then \
+ @if test "$(cc-version)" -lt "0303"; then \
echo -n "Sorry, GCC v3.3 or above is required to build " ; \
echo "the kernel." ; \
false ; \
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 132d9c6..fc502e0 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -314,7 +314,7 @@ TOUT := .tmp_gas_check
# - Require gcc 4.0 or above on 64-bit
# - gcc-4.2.0 has issues compiling modules on 64-bit
checkbin:
- @if test "$(call cc-version)" = "0304" ; then \
+ @if test "$(cc-version)" = "0304" ; then \
if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
echo 'correctly with gcc-3.4 and your version of binutils.'; \
@@ -322,13 +322,13 @@ checkbin:
false; \
fi ; \
fi
- @if test "$(call cc-version)" -lt "0400" \
+ @if test "$(cc-version)" -lt "0400" \
&& test "x${CONFIG_PPC64}" = "xy" ; then \
echo -n "Sorry, GCC v4.0 or above is required to build " ; \
echo "the 64-bit powerpc kernel." ; \
false ; \
fi
- @if test "$(call cc-fullversion)" = "040200" \
+ @if test "$(cc-fullversion)" = "040200" \
&& test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \
echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \
echo 'kernel with modules enabled.' ; \
diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um
index 36b62bc..95eba55 100644
--- a/arch/x86/Makefile.um
+++ b/arch/x86/Makefile.um
@@ -30,7 +30,7 @@ cflags-y += -ffreestanding
# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
# a lot more stack due to the lack of sharing of stacklots. Also, gcc
# 4.3.0 needs -funit-at-a-time for extern inline functions.
-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
+KBUILD_CFLAGS += $(shell if [ $(cc-version) -lt 0400 ] ; then \
echo $(call cc-option,-fno-unit-at-a-time); \
else echo $(call cc-option,-funit-at-a-time); fi ;)
diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index 52aa7e8..6f01fa3 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -21,7 +21,7 @@ else
# is not available. We can probably move if-lt to Kbuild.include, so it's also
# not defined during clean or to include Kbuild.include in
# scripts/Makefile.clean. But the following workaround seems least invasive.
- cc-ver := $(if $(call cc-version),$(call cc-version),0)
+ cc-ver := $(if $(cc-version),$(cc-version),0)
endif
obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index a972666..69c9f57 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -136,17 +136,15 @@ cc-disable-warning = $(call try-run,\
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
# cc-version
-# Usage gcc-ver := $(call cc-version)
cc-version = $(shell $(KBUILD_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
# cc-fullversion
-# Usage gcc-ver := $(call cc-fullversion)
cc-fullversion = $(shell $(KBUILD_SHELL) \
$(srctree)/scripts/gcc-version.sh -p $(CC))
# cc-ifversion
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell [ $(call cc-version) $(1) $(2) ] && echo $(3))
+cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3))
# cc-ldoption
# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
@@ -164,13 +162,12 @@ ld-option = $(call try-run,\
ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
# ld-version
-# Usage: $(call ld-version)
# Note this is mainly for HJ Lu's 3 number binutil versions
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
# ld-ifversion
# Usage: $(call ld-ifversion, -ge, 22252, y)
-ld-ifversion = $(shell [ $(call ld-version) $(1) $(2) ] && echo $(3))
+ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3))
######
--
1.9.1
^ permalink raw reply related
* Re: unable to boot kernel on power6
From: Denis Kirjanov @ 2014-12-25 9:35 UTC (permalink / raw)
To: Anatoly Pugachev; +Cc: linuxppc-dev
In-Reply-To: <CADxRZqxWL3wc1pJM3013utvW5=eNh_Z5pfU1+XiO2wOruOvk5Q@mail.gmail.com>
On 12/25/14, Anatoly Pugachev <matorola@gmail.com> wrote:
> Hello!
>
> Can someone from powerpc kernel guys look at
> https://bugzilla.redhat.com/show_bug.cgi?id=1093163
>
> It can not load kernel on power6 JS22 (type 7998) blade, starting from 3.11
> kernel (but 3.9.x actually bootable).
Try to boot from cd /usb instead of trying to boot through the network
> Thanks.
>
> PS: not sure, is it worth investigating since it's power6 (old hardware).
>
^ permalink raw reply
* Re: [PATCH] powerpc/smp: Fix Non-boot cpus cannot be bring up.
From: Aaro Koskinen @ 2014-12-26 12:09 UTC (permalink / raw)
To: Dongsheng Wang; +Cc: scottwood, linuxppc-dev, anton
In-Reply-To: <1419230320-37558-1-git-send-email-dongsheng.wang@freescale.com>
Hi,
On Mon, Dec 22, 2014 at 02:38:40PM +0800, Dongsheng Wang wrote:
> From: Wang Dongsheng <dongsheng.wang@freescale.com>
>
> Kernel cannot bring up Non-boot cpus always get "Processor xx is stuck".
> this issue bring by http://patchwork.ozlabs.org/patch/418912/ (powerpc:
> Secondary CPUs must set cpu_callin_map after setting active and online)
> We need to take timebase after bootup cpu give the timebase firstly.
>
> When start_secondary, non-boot cpus set cpu_callin_map for boot cpu
> after that boot cpu will give the timebase for non-boot cpu. Otherwise
> non-boot cpus will fall in dead loop to waiting bootup cpu to give
> imebase.
>
> Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
This fixes v3.19-rc1 boot on G5 Xserve.
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
A.
^ permalink raw reply
* Re: [PATCH] i2c-qoriq: modified compatibility for correct prescaler
From: Scott Wood @ 2014-12-27 2:43 UTC (permalink / raw)
To: Wolfram Sang
Cc: Valentin Longchamp, Linux device trees, danielle.costantino,
Boschung, Rainer, Brunck, Holger, Linux I2C, Linux PowerPC Kernel
In-Reply-To: <20141223134940.GA1925@katana>
On Tue, 2014-12-23 at 14:49 +0100, Wolfram Sang wrote:
> On Tue, Dec 23, 2014 at 02:23:01PM +0100, Valentin Longchamp wrote:
> > Wolfgang, Scott,
>
> Wolfram, please.
>
> > > What is then the agreement here ? Add a clock-div to the device trees ? Or do
> > > something similar to mpc_i2c_get_sec_cfg_8xxx() ?
> > >
> > > I think the clock-div property is better according to Freescale's AN 2919
> > > section 3.1 Source clock. All the source clocks are fixed (with a clock-div of 2
> > > in case of mpc8536/43/45/47/48/67/68/72, plus p2020) except for the mpc8533/44
> > > where it can be 2 or 3, and that's what mpc_i2c_get_sec_cfg_8xxx() determines.
> > >
> > > So mpc_i2c_get_sec_cfg_8xxx() should remain the exception and the other
> > > prescaler values should be derived from an additional clock-div that must be
> > > added in the respective device trees (at least for the qoriq devices, because
> > > for instance mpc8543 already has the correct prescaler thanks to
> > > mpc_i2c_data_8543 from i2c-mpc.c).
> > >
> >
> > Do you have an opinion on the above ?
>
> I don't mind. I'll leave it to PowerPC experts to judge if a new binding
> is apropriate or reading SVR is the way to go. If it is going to be a
> new binding, then please look around before if there is already
> something similar around...
I'd rather use SVR so things work with existing device trees.
-Scott
^ permalink raw reply
* [PATCH] srcu: Isolate srcu sections using CONFIG_SRCU
From: Pranith Kumar @ 2014-12-27 17:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Martin Schwidefsky, Heiko Carstens, supporter:S390, Lai Jiangshan,
Paul E. McKenney, Josh Triplett, Steven Rostedt,
Mathieu Desnoyers, Anton Blanchard, Scott Wood, Andy Fleming,
Tiejun Chen, Daniel Walter, Jens Freimann, Christian Borntraeger,
open list:LINUX FOR POWERPC..., open list, open list:S390
Isolate the SRCU functions and data structures within CONFIG_SRCU so that there
is a compile time failure if srcu is used when not enabled. This was decided to
be better than waiting until link time for a failure to occur.
There are places which include kvm headers and utilize kvm data structures
without checking if KVM is enabled. In two such archs(s390, ppc64), the current
patch makes the uses of KVM conditional on KVM being enabled. The other option,
which is to enable KVM unconditionally seemed a bit too much as we could easily
figure out KVM only parts and enclose them in ifdefs.
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
---
arch/powerpc/kernel/setup_64.c | 7 ++++++-
arch/s390/kernel/asm-offsets.c | 7 ++++++-
include/linux/notifier.h | 47 ++++++++++++++++++++++++------------------
include/linux/srcu.h | 6 +++++-
4 files changed, 44 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4f3cfe1..f55302f 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -65,10 +65,13 @@
#include <asm/kexec.h>
#include <asm/mmu_context.h>
#include <asm/code-patching.h>
-#include <asm/kvm_ppc.h>
#include <asm/hugetlb.h>
#include <asm/epapr_hcalls.h>
+#if IS_ENABLED(CONFIG_KVM)
+#include <asm/kvm_ppc.h>
+#endif
+
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
@@ -286,8 +289,10 @@ void __init early_setup(unsigned long dt_ptr)
*/
cpu_ready_for_interrupts();
+#if IS_ENABLED(CONFIG_KVM)
/* Reserve large chunks of memory for use by CMA for KVM */
kvm_cma_reserve();
+#endif
/*
* Reserve any gigantic pages requested on the command line.
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index ef279a1..2813a3c 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -7,12 +7,15 @@
#define ASM_OFFSETS_C
#include <linux/kbuild.h>
-#include <linux/kvm_host.h>
#include <linux/sched.h>
#include <asm/idle.h>
#include <asm/vdso.h>
#include <asm/pgtable.h>
+#if IS_ENABLED(CONFIG_KVM)
+#include <linux/kvm_host.h>
+#endif
+
/*
* Make sure that the compiler is new enough. We want a compiler that
* is known to work with the "Q" assembler constraint.
@@ -182,8 +185,10 @@ int main(void)
DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb));
DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
+#if IS_ENABLED(CONFIG_KVM)
DEFINE(__SIE_PROG0C, offsetof(struct kvm_s390_sie_block, prog0c));
DEFINE(__SIE_PROG20, offsetof(struct kvm_s390_sie_block, prog20));
+#endif /* CONFIG_KVM */
#endif /* CONFIG_32BIT */
return 0;
}
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index d14a4c3..fe4f02a 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -47,6 +47,8 @@
* runtime initialization.
*/
+struct notifier_block;
+
typedef int (*notifier_fn_t)(struct notifier_block *nb,
unsigned long action, void *data);
@@ -70,12 +72,6 @@ struct raw_notifier_head {
struct notifier_block __rcu *head;
};
-struct srcu_notifier_head {
- struct mutex mutex;
- struct srcu_struct srcu;
- struct notifier_block __rcu *head;
-};
-
#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
spin_lock_init(&(name)->lock); \
(name)->head = NULL; \
@@ -88,11 +84,6 @@ struct srcu_notifier_head {
(name)->head = NULL; \
} while (0)
-/* srcu_notifier_heads must be initialized and cleaned up dynamically */
-extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
-#define srcu_cleanup_notifier_head(name) \
- cleanup_srcu_struct(&(name)->srcu);
-
#define ATOMIC_NOTIFIER_INIT(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.head = NULL }
@@ -101,7 +92,6 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
.head = NULL }
#define RAW_NOTIFIER_INIT(name) { \
.head = NULL }
-/* srcu_notifier_heads cannot be initialized statically */
#define ATOMIC_NOTIFIER_HEAD(name) \
struct atomic_notifier_head name = \
@@ -121,8 +111,6 @@ extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *nb);
extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
struct notifier_block *nb);
-extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
- struct notifier_block *nb);
extern int blocking_notifier_chain_cond_register(
struct blocking_notifier_head *nh,
@@ -134,8 +122,6 @@ extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
struct notifier_block *nb);
extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
struct notifier_block *nb);
-extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
- struct notifier_block *nb);
extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
unsigned long val, void *v);
@@ -149,10 +135,6 @@ extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v);
extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v, int nr_to_call, int *nr_calls);
-extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
- unsigned long val, void *v);
-extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
- unsigned long val, void *v, int nr_to_call, int *nr_calls);
#define NOTIFY_DONE 0x0000 /* Don't care */
#define NOTIFY_OK 0x0001 /* Suits me */
@@ -211,5 +193,30 @@ static inline int notifier_to_errno(int ret)
extern struct blocking_notifier_head reboot_notifier_list;
+#ifdef CONFIG_SRCU
+
+struct srcu_notifier_head {
+ struct mutex mutex;
+ struct srcu_struct srcu;
+ struct notifier_block __rcu *head;
+};
+
+/* srcu_notifier_heads must be initialized and cleaned up dynamically
+ * srcu_notifier_heads cannot be initialized statically
+ */
+extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
+#define srcu_cleanup_notifier_head(name) cleanup_srcu_struct(&(name)->srcu)
+
+extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
+ struct notifier_block *nb);
+extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
+ struct notifier_block *nb);
+extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+ unsigned long val, void *v);
+extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
+ unsigned long val, void *v, int nr_to_call, int *nr_calls);
+
+#endif /* CONFIG_SRCU */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 9cfd962..ed9c389 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -26,6 +26,8 @@
*
*/
+#ifdef CONFIG_SRCU
+
#ifndef _LINUX_SRCU_H
#define _LINUX_SRCU_H
@@ -249,4 +251,6 @@ static inline void smp_mb__after_srcu_read_unlock(void)
/* __srcu_read_unlock has smp_mb() internally so nothing to do here. */
}
-#endif
+#endif /* _LINUX_SRCU_H */
+
+#endif /* CONFIG_SRCU */
--
1.9.1
^ permalink raw reply related
* [PATCH] powerpc/powernv: Select CONFIG_PRINTK to fix build failure
From: Pranith Kumar @ 2014-12-27 17:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Srivatsa S. Bhat, Rafael J. Wysocki, Gautham R. Shenoy,
Michael Neuling, open list:LINUX FOR POWERPC..., open list
In-Reply-To: <1419700667-24888-1-git-send-email-bobby.prani@gmail.com>
In an allnoconfig we get the following build failure:
arch/powerpc/platforms/built-in.o: In function `.__machine_initcall_powernv_opal_init':
opal.c:(.init.text+0x468): undefined reference to `.log_buf_addr_get'
opal.c:(.init.text+0x474): undefined reference to `.log_buf_len_get'
make: *** [vmlinux] Error 1
This happens because powernv requires printk() support. Enable it in the config
file.
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
---
arch/powerpc/platforms/powernv/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 45a8ed0..be4f340 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -18,6 +18,7 @@ config PPC_POWERNV
select CPU_FREQ_GOV_ONDEMAND
select CPU_FREQ_GOV_CONSERVATIVE
select PPC_DOORBELL
+ select PRINTK
default y
config PPC_POWERNV_RTAS
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox