* Fwd: [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins
From: David Brownell @ 2008-11-26 3:23 UTC (permalink / raw)
To: linux-embedded; +Cc: Jaya Kumar
This forward tool drops the CC list ... it was everyone listed
on the patch itself as a CC.
---------- Forwarded Message ----------
Subject: [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins
Date: Tuesday 25 November 2008
From: Jaya Kumar <jayakumar.lkml@gmail.com>
To: jayakumar.lkml@gmail.com
Beloved friends,
I would like to request your feedback on the following idea. I hope I have
made sure to CC all the right people and the right lists! If not, PLEASE
let me know! I couldn't find a MAINTAINERS entry for gpiolib so I just
used what I saw in the git log and have also added people and lists that
I think may be interested.
This is just an RFC. If you all feel it is looking like the right approach
then I'll clean it up and make it a patch.
Thanks,
jaya
am300epd was doing 800*600*16*gpio_set_value for each framebuffer transfer
(it uses 16-pins of gpio as its data bus). I found this caused a wee
performance limitation. This patch adds an API for gpio_set_value_bus
which allows users to set batches of consecutive gpio together in a single
call. I have done a test implementation on gumstix (pxa255) with am300epd
and it provides a nice improvement in performance.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: David Brownell <david-b@pacbell.net>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Eric Miao <eric.miao@marvell.com>
Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
Cc: Philipp Zabel <philipp.zabel@gmail.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Ben Gardner <bgardner@wabtec.com>
CC: Greg KH <greg@kroah.com>
Cc: linux-arm-kernel@lists.arm.linux.org.uk
Cc: linux-fbdev-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
---
arch/arm/mach-pxa/am300epd.c | 9 ++++++
arch/arm/mach-pxa/gpio.c | 28 +++++++++++++++++++++
arch/arm/mach-pxa/include/mach/gpio.h | 24 ++++++++++++++++++
drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++++++
include/asm-generic/gpio.h | 6 ++++
5 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
index bb81564..f741a98 100644
--- a/arch/arm/mach-pxa/am300epd.c
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -222,8 +222,17 @@ static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
{
int i;
+#if 1
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 16);
+#endif
+#if 0
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 6);
+ gpio_set_value_bus(DB0_GPIO_PIN + 6, data >> 6, 10);
+#endif
+#if 0 /* simple set */
for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+#endif
}
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
index 14930cf..80b0aa1 100644
--- a/arch/arm/mach-pxa/gpio.c
+++ b/arch/arm/mach-pxa/gpio.c
@@ -132,6 +132,33 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
}
+/*
+ * Set output GPIO level in batches
+ */
+static void pxa_gpio_set_bus(struct gpio_chip *chip, unsigned offset,
+ int values, int bitwidth)
+{
+ struct pxa_gpio_chip *pxa;
+ int mask;
+
+ /* we're guaranteed by the caller that offset + bitwidth remains
+ * in this chip.
+ */
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ mask = ((1 << bitwidth) - 1) << offset;
+ values <<= offset;
+
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPSR_OFFSET);
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPCR_OFFSET);
+}
+
#define GPIO_CHIP(_n) \
[_n] = { \
.regbase = GPIO##_n##_BASE, \
@@ -141,6 +168,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
.direction_output = pxa_gpio_direction_output, \
.get = pxa_gpio_get, \
.set = pxa_gpio_set, \
+ .set_bus = pxa_gpio_set_bus, \
.base = (_n) * 32, \
.ngpio = 32, \
}, \
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index 2c538d8..6ee92d3 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -56,6 +56,30 @@ static inline void gpio_set_value(unsigned gpio, int value)
}
}
+static inline void gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ if (__builtin_constant_p(gpio) &&
+ (gpio + bitwidth < NR_BUILTIN_GPIO) &&
+ ((gpio + bitwidth) <= roundup(gpio+1, 32))) {
+ int shift, mask;
+
+ shift = gpio % 32;
+ mask = ((1 << bitwidth) - 1) << shift;
+ values <<= shift;
+
+ values &= mask;
+ if (values)
+ GPSR(gpio) = values;
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ GPCR(gpio) = values;
+ } else {
+ __gpio_set_value_bus(gpio, values, bitwidth);
+ }
+}
+
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9112830..fddf3af 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1057,6 +1057,50 @@ void __gpio_set_value(unsigned gpio, int value)
EXPORT_SYMBOL_GPL(__gpio_set_value);
/**
+ * __gpio_set_value_bus() - assign a batch of consecutive gpio pins together
+ * @gpio: starting gpio pin
+ * @values: values to assign, sequential in host ordering
+ * @bitwidth: total width of bits to be assigned
+ * Context: any
+ *
+ * This is used directly or indirectly to implement gpio_set_value().
+ * It invokes the associated gpio_chip.set() method.
+ */
+void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ struct gpio_chip *chip;
+ int i = 0;
+ int value, width, remwidth;
+
+ do {
+ chip = gpio_to_chip(gpio + i);
+ WARN_ON(extra_checks && chip->can_sleep);
+
+ if (!chip->set_bus) {
+ while (((gpio + i) < (chip->base + chip->ngpio))
+ && bitwidth) {
+ value = values & (1 << i);
+ chip->set(chip, gpio + i - chip->base, value);
+ i++;
+ bitwidth--;
+ }
+ } else {
+ value = values >> i; /* shift off the used stuff */
+ remwidth = ((chip->base + (int) chip->ngpio) -
+ ((int) gpio + i));
+ width = min(bitwidth, remwidth);
+
+ chip->set_bus(chip, gpio + i - chip->base, value,
+ width);
+ i += width;
+ bitwidth -= width;
+ }
+ } while (bitwidth);
+}
+EXPORT_SYMBOL_GPL(__gpio_set_value_bus);
+
+
+/**
* __gpio_cansleep() - report whether gpio value access will sleep
* @gpio: gpio in question
* Context: any
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 81797ec..9747517 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -44,6 +44,8 @@ struct module;
* returns either the value actually sensed, or zero
* @direction_output: configures signal "offset" as output, or returns error
* @set: assigns output value for signal "offset"
+ * @set_bus: batch assigns output values for consecutive signals starting at
+ * "offset" with width in bits "bitwidth"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep
* @dbg_show: optional routine to show contents in debugfs; default code
@@ -84,6 +86,9 @@ struct gpio_chip {
unsigned offset, int value);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
+ void (*set_bus)(struct gpio_chip *chip,
+ unsigned offset, int values,
+ int bitwidth);
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
@@ -124,6 +129,7 @@ extern void gpio_set_value_cansleep(unsigned gpio, int value);
*/
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);
+extern void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth);
extern int __gpio_cansleep(unsigned gpio);
--
1.5.2.3
-------------------------------------------------------
^ permalink raw reply related
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Mike Frysinger @ 2008-11-26 1:23 UTC (permalink / raw)
To: Grant Erickson; +Cc: linuxppc-dev, linux-embedded, Wolfgang Denx, Stefan Roese
In-Reply-To: <1227638045-12862-1-git-send-email-gerickson@nuovations.com>
On Tue, Nov 25, 2008 at 13:34, Grant Erickson wrote:
> This merges support for the previously DENX-only kernel feature of
> specifying an alternative, "external" buffer for kernel printk
> messages and their associated metadata. In addition, this ports
> architecture support for this feature from arch/ppc to arch/powerpc.
>
> Signed-off-by: Grant Erickson <gerickson@nuovations.com>
> ---
>
> When this option is enabled, an architecture- or machine-specific log
> buffer is used for all printk messages. This allows entities such as
> boot loaders (e.g. U-Boot) to place printk-compatible messages into
> this buffer and for the kernel to coalesce them with its normal
> messages.
> <snip>
this extended info should be part of the changelog and thus above the
--- marker ...
-mike
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: David Brownell @ 2008-11-25 21:45 UTC (permalink / raw)
To: dvomlehn, Grant Erickson
Cc: Bill Gatliff, Matt Sealey, linuxppc-dev, Stefan Roese,
Wolfgang Denx, linux-embedded
In-Reply-To: <1227646490.5404.5.camel@cuplxvomd02.corp.sa.net>
No comment from me on $SUBJECT beyond "it seems plausible", but ...
On Tuesday 25 November 2008, David VomLehn wrote:
> The important point, though, is that device tree is the only
> thing approaching a standard on any non-x86-based platform for passing
> structured information from the bootloader to the kernel. The command
> line is just not sufficient for this.
Me, I'll be happier if I don't have to try using that device tree.
Having board-specific code in the kernel is a more complete solution,
and makes it a lot easier to cope with all the hardware goofage.
Recall that the *original* notion behind OpenBoot (now "OpenFirmware")
was to have tables for the stuff that was table-friendly, and call
out to FORTH code (possibly not just at boot time) for the rest.
(Given the choice of FORTH vs ACPI bytecodes, I'd go for FORTH; but
the better option is "neither".)
Right now I see an awful lot of work going into trying to force lots
of stuff into table format. Even when it's the sort of one-off or
board-specific quirkery that was an original motivation for having
FORTH escapes (tasks that were not table-friendly).
- Dave
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Wolfgang Denk @ 2008-11-25 21:05 UTC (permalink / raw)
To: Matt Sealey; +Cc: linuxppc-dev, Stefan Roese, linux-embedded, Grant Erickson
In-Reply-To: <b5e2fc790811251131g63ea9444x57ec0829ca0b069e@mail.gmail.com>
Dear Matt,
In message <b5e2fc790811251131g63ea9444x57ec0829ca0b069e@mail.gmail.com> you wrote:
>
> There is also no reason you can't hard-code the locations into the device
> tree, to support older U-Boots that don't know about
> /chosen/linux,log-metadata and /chosen/linux,log-buffer*.
Actually there is such reason - U-Boot traditionally allocates the log
buffer close to the upper end of system memory, so the start address
depends on the memory size on the board, which may vary.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
The human mind ordinarily operates at only ten percent of its
capacity. The rest is overhead for the operating system.
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: David VomLehn @ 2008-11-25 20:54 UTC (permalink / raw)
To: Bill Gatliff
Cc: Matt Sealey, Grant Erickson, linuxppc-dev, Stefan Roese,
Wolfgang Denx, linux-embedded
In-Reply-To: <492C5DC2.9040402@billgatliff.com>
On Tue, 2008-11-25 at 14:19 -0600, Bill Gatliff wrote:
> Just trying to figure out where the walls of this "sandbox" are. I've
> been aware of the concept of Open Firmware for a while, but haven't
> really looked into it before now--- mostly because my impression until
> now was that the available implementations were both closed-source,
> and not supporting embedded, non-PPC targets like ARM.
FWIW, at the last OLS there was interest expressed by at least one
ARM-based platform and I'm working on a set of patches to add the device
tree for MIPS. It's going very slowly and is dependent on a patchset to
add support for our platform, so it will take a while to make it
available. The important point, though, is that device tree is the only
thing approaching a standard on any non-x86-based platform for passing
structured information from the bootloader to the kernel. The command
line is just not sufficient for this.
--
David VomLehn
- - - - - Cisco - - - - -
This e-mail and any attachments may contain information which is confidential,
proprietary, privileged or otherwise protected by law. The information is solely
intended for the named addressee (or a person responsible for delivering it to
the addressee). If you are not the intended recipient of this message, you are
not authorized to read, print, retain, copy or disseminate this message or any
part of it. If you have received this e-mail in error, please notify the sender
immediately by return e-mail and delete it from your computer.
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Matt Sealey @ 2008-11-25 20:46 UTC (permalink / raw)
To: Grant Likely
Cc: Bill Gatliff, Wolfgang Denx, linux-embedded, linuxppc-dev,
Stefan Roese, Grant Erickson
In-Reply-To: <fa686aa40811251217g6dcbef77u29e3d6ee6ad6d99f@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2602 bytes --]
On Tue, Nov 25, 2008 at 2:17 PM, Grant Likely <grant.likely@secretlab.ca>wrote:
> On Tue, Nov 25, 2008 at 1:07 PM, Matt Sealey <matt@genesi-usa.com> wrote:
>
> > But here's the real question; why do you need an opensource
> implementation?
> > Curiosity?
>
> Umm, so that it can be ported to new boards perhaps? So that
> developers can work with it?
>
You can port closed-source firmwares to new boards just as easily as with
open source ones.
For companies who have larger production requirements than Bill Gatliff,
porting an open source firmware may not be a task they want to get into.
Linux support is a big enough moving target without adding firmware
development to it and tying up programmers implementing the same drivers
twice (even if it is practically copy&paste in U-Boot).
In this case they may just buy one in. If everything had to be open source
and freely downloadable there would be no industry at all. And if paying for
someone else to write code for you is the issue, then we wouldn't have asked
you for a quote last week, and you certainly wouldn't have given us a price
:D
Bill, as for ARM etc. support, you can imagine that most of the guts of the
firmware are fairly well abstracted. Vast portions of the same code work on
most platforms with the same peripherals - USB, Ethernet controllers & PHYs,
PCI, SDIO, etc. The device tree is how hardware designers (note; not OS
designers) are meant to abstract the differences in hardware and programming
model so that an OS can load the right drivers and Do The Right Thing. It
doesn't matter if the device tree was generated as a flattened
representation, or by an open-source firmware or closed-source firmware.
However the IEEE 1275 standard is not as big a moving target as U-Boot. It
has an ABI and a client interface which hasn't been moved around or modified
since 1994. And when your board doesn't provide a device tree entry for
something, well, you just write some Forth and can edit entries in the
device tree in-place (no recompiles required). If you're so inclined you can
even write things like scsi host controller drivers in Forth and present
them such that they are then working - no reboots or recompiles required,
just load the script - and ready to use to boot the system. You can poke
around in the FirmWorks code for how powerful this can be, or poke around
http://www.powerdeveloper.org/platforms/efika/devicetree for how mundane and
simple it can be just fixing up some entries and making sure the chip is
configured right..
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
[-- Attachment #1.2: Type: text/html, Size: 3185 bytes --]
[-- Attachment #2: Type: text/plain, Size: 146 bytes --]
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Bill Gatliff @ 2008-11-25 20:19 UTC (permalink / raw)
To: Matt Sealey
Cc: Grant Erickson, linuxppc-dev, Stefan Roese, Wolfgang Denx,
linux-embedded
In-Reply-To: <b5e2fc790811251207g38d429f3q4eb698b92162d6@mail.gmail.com>
Matt Sealey wrote:
> Yes, there's FirmWorks, CodeGen SmartFirmware, IBM SLOF and OpenBIOS..
> they're all linked from the OpenBIOS website (along with a bunch of the
> documentation from http://www.openfirmware.org in more-readable formats
> like PDF)
>
> http://www.openbios.org/
>
>
> But here's the real question; why do you need an opensource
> implementation? Curiosity?
That, and I prefer Free *ware whenever that's an option. :)
Nothing against the commercial alternatives, of course. But I'm
already doing my own heavy lifting, because my platforms are all
full-custom with very limited production runs. Since I'm into the
guts of all my code anyway, I'm not inclined to outsource a bootloader
development effort.
Just trying to figure out where the walls of this "sandbox" are. I've
been aware of the concept of Open Firmware for a while, but haven't
really looked into it before now--- mostly because my impression until
now was that the available implementations were both closed-source,
and not supporting embedded, non-PPC targets like ARM.
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Grant Likely @ 2008-11-25 20:17 UTC (permalink / raw)
To: Matt Sealey
Cc: Bill Gatliff, linux-embedded, linuxppc-dev, Stefan Roese,
Wolfgang Denx, Grant Erickson
In-Reply-To: <b5e2fc790811251207g38d429f3q4eb698b92162d6@mail.gmail.com>
On Tue, Nov 25, 2008 at 1:07 PM, Matt Sealey <matt@genesi-usa.com> wrote:
>
>
> On Tue, Nov 25, 2008 at 1:51 PM, Bill Gatliff <bgat@billgatliff.com> wrote:
>>
>> Matt Sealey wrote:
>>
>> > I can think of a bunch of reasons why it's a good idea..
>>
>> Can you point to a GPL/LGPL/BSD/etc. source code for an OpenFirmware
>> implementation?
>
> Yes, there's FirmWorks, CodeGen SmartFirmware, IBM SLOF and OpenBIOS..
> they're all linked from the OpenBIOS website (along with a bunch of the
> documentation from http://www.openfirmware.org in more-readable formats like
> PDF)
>
> http://www.openbios.org/
>
>
> But here's the real question; why do you need an opensource implementation?
> Curiosity?
Umm, so that it can be ported to new boards perhaps? So that
developers can work with it?
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Grant Likely @ 2008-11-25 20:14 UTC (permalink / raw)
To: Bill Gatliff
Cc: Matt Sealey, Grant Erickson, linuxppc-dev, Stefan Roese,
Wolfgang Denx, linux-embedded
In-Reply-To: <492C573E.9030309@billgatliff.com>
. F
On Tue, Nov 25, 2008 at 12:51 PM, Bill Gatliff <bgat@billgatliff.com> wrote:
> Matt Sealey wrote:
>
>> I can think of a bunch of reasons why it's a good idea..
>
> Can you point to a GPL/LGPL/BSD/etc. source code for an OpenFirmware
> implementation?
In powerpc land using the Open Firmware device tree does not depend on
also using Open Firmware. From that perspective the availability of
an open sourced Open Firmware is irrelevant.
But, both OpenFirmware and SmartFirmware have been open sourced:
http://www.openfirmware.info/Open_Firmware
http://www.openfirmware.info/SmartFirmware
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Matt Sealey @ 2008-11-25 20:07 UTC (permalink / raw)
To: Bill Gatliff
Cc: linux-embedded, linuxppc-dev, Stefan Roese, Wolfgang Denx,
Grant Erickson
In-Reply-To: <492C573E.9030309@billgatliff.com>
[-- Attachment #1.1: Type: text/plain, Size: 672 bytes --]
On Tue, Nov 25, 2008 at 1:51 PM, Bill Gatliff <bgat@billgatliff.com> wrote:
> Matt Sealey wrote:
>
> > I can think of a bunch of reasons why it's a good idea..
>
> Can you point to a GPL/LGPL/BSD/etc. source code for an OpenFirmware
> implementation?
>
Yes, there's FirmWorks, CodeGen SmartFirmware, IBM SLOF and OpenBIOS..
they're all linked from the OpenBIOS website (along with a bunch of the
documentation from http://www.openfirmware.org in more-readable formats like
PDF)
http://www.openbios.org/
But here's the real question; why do you need an opensource implementation?
Curiosity?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
[-- Attachment #1.2: Type: text/html, Size: 1174 bytes --]
[-- Attachment #2: Type: text/plain, Size: 146 bytes --]
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Bill Gatliff @ 2008-11-25 19:51 UTC (permalink / raw)
To: Matt Sealey
Cc: Grant Erickson, linuxppc-dev, Stefan Roese, Wolfgang Denx,
linux-embedded
In-Reply-To: <b5e2fc790811251131g63ea9444x57ec0829ca0b069e@mail.gmail.com>
Matt Sealey wrote:
> I can think of a bunch of reasons why it's a good idea..
Can you point to a GPL/LGPL/BSD/etc. source code for an OpenFirmware
implementation?
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Matt Sealey @ 2008-11-25 19:31 UTC (permalink / raw)
To: Grant Erickson; +Cc: linuxppc-dev, Stefan Roese, Wolfgang Denx, linux-embedded
In-Reply-To: <C5518C2F.13137%gerickson@nuovations.com>
[-- Attachment #1.1: Type: text/plain, Size: 3289 bytes --]
Actually there is an ARM board out there with an Open Firmware (Toshiba
TOPAS910 -
http://www.toshiba-components.com/microcontroller/BMSKTOPAS910.html) so,
yes, device trees do appear on those platforms. QEMU is looking to go that
way too, seems for every architecture it would be a pretty awesome idea
(especially on ARM).
In any case, for platforms that don't, you can then make sure the "depends
on" line in Kconfig is for boards with no device trees - right now that
particular thing escapes me but I bet !PPC_OF or similar couldn't be too far
from the truth - so the ability to set the values is taken away if you have
device tree support built-in.
On MIPS or ARM with no DT support, if they don't have device tree support
compiled in, the options magically appear. You get the best of both worlds.
There is also no reason you can't hard-code the locations into the device
tree, to support older U-Boots that don't know about
/chosen/linux,log-metadata and /chosen/linux,log-buffer*.
I can think of a bunch of reasons why it's a good idea.. what if your board
supports a DIMM and you want to keep the buffer up near the top of memory,
or the MBAR/CCSRBAR/IMMRBAR or whatever can move location so your SRAM moves
around depending on your firmware version or feature support, or, similarly,
if your L2 and SRAM are the same thing and can be configured to use
different sizes on each boot - pick a different size for the L2/SRAM and the
location may have to be moved, which means compiling a new firmware AND a
new kernel and matching up the values.. in the end it makes everyone's life
easier.
* naive implementation - if you only specify log-buffer then that means
metadata and buffer are "colocated" as your docs said, that'd be the least
complicated way to implement it without involving a hell of a lot of new
stuff, plus it means you can check the existance/value of two properties in
a node you can guarantee exists. Also since the log buffer format is
Linux-specific and Linux-compatible, and entirely a Linux feature, just like
the linux,initrd-start and -end, making a whole new node seems wasteful.
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
On Tue, Nov 25, 2008 at 1:04 PM, Grant Erickson <gerickson@nuovations.com>wrote:
> On 11/25/08 10:55 AM, Josh Boyer wrote:
> > On Tue, 25 Nov 2008 12:53:12 -0600
> > "Matt Sealey" <matt@genesi-usa.com> wrote:
> >> Nitpick, really.. shouldn't the logbuffer location(s) be some device
> tree
> >> property(ies), perhaps something in the
> >> /chosen node that U-Boot etc. can then fill out?
> >
> > I don't think that's a nitpick. It's a fundamental change in how this
> > would all work. However, I do think you're generally right.
> >
> > Perhaps not /chosen, but maybe something like /rtas or /firmware, etc.
>
> I'm inclined to agree with you both; however, the submitted implementation
> was a choice of expediency given the existing DENX implementation and a
> customer that needed the feature "yesterday".
>
> ARM, MIPS, et al have not yet adopted device trees, correct? If so, is
> there
> value in providing the submitted implementation and adding support for
> getting said information from the device tree as another option if such
> information exists?
>
> Regards,
>
> Grant
>
>
>
[-- Attachment #1.2: Type: text/html, Size: 4068 bytes --]
[-- Attachment #2: Type: text/plain, Size: 146 bytes --]
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Grant Erickson @ 2008-11-25 19:04 UTC (permalink / raw)
To: Josh Boyer, Matt Sealey
Cc: linuxppc-dev, Stefan Roese, Wolfgang Denx, linux-embedded
In-Reply-To: <20081125135519.038abf23@zod.rchland.ibm.com>
On 11/25/08 10:55 AM, Josh Boyer wrote:
> On Tue, 25 Nov 2008 12:53:12 -0600
> "Matt Sealey" <matt@genesi-usa.com> wrote:
>> Nitpick, really.. shouldn't the logbuffer location(s) be some device tree
>> property(ies), perhaps something in the
>> /chosen node that U-Boot etc. can then fill out?
>
> I don't think that's a nitpick. It's a fundamental change in how this
> would all work. However, I do think you're generally right.
>
> Perhaps not /chosen, but maybe something like /rtas or /firmware, etc.
I'm inclined to agree with you both; however, the submitted implementation
was a choice of expediency given the existing DENX implementation and a
customer that needed the feature "yesterday".
ARM, MIPS, et al have not yet adopted device trees, correct? If so, is there
value in providing the submitted implementation and adding support for
getting said information from the device tree as another option if such
information exists?
Regards,
Grant
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Matt Sealey @ 2008-11-25 19:01 UTC (permalink / raw)
To: Josh Boyer
Cc: linux-embedded, linuxppc-dev, Stefan Roese, Wolfgang Denx,
Grant Erickson
In-Reply-To: <20081125135519.038abf23@zod.rchland.ibm.com>
[-- Attachment #1.1: Type: text/plain, Size: 1076 bytes --]
On Tue, Nov 25, 2008 at 12:55 PM, Josh Boyer <jwboyer@linux.vnet.ibm.com>wrote:
> On Tue, 25 Nov 2008 12:53:12 -0600
> "Matt Sealey" <matt@genesi-usa.com> wrote:
>
> > Nitpick, really.. shouldn't the logbuffer location(s) be some device tree
> > property(ies), perhaps something in the
> > /chosen node that U-Boot etc. can then fill out?
>
> I don't think that's a nitpick. It's a fundamental change in how this
> would all work. However, I do think you're generally right.
>
> Perhaps not /chosen, but maybe something like /rtas or /firmware, etc.
>
> josh
I think the best place is chosen, with things like stdin, stdout etc. - this
is where you generally go and dump weird little variables which need to be
passed in for early boot. You could consider the log buffer a kind of
stdin/out variation.
I don't think it needs a whole new device tree node just for two memory
locations.. is the support really worth a compatible property, etc. to
differentiate between different operating modes?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
[-- Attachment #1.2: Type: text/html, Size: 1616 bytes --]
[-- Attachment #2: Type: text/plain, Size: 146 bytes --]
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Josh Boyer @ 2008-11-25 18:55 UTC (permalink / raw)
To: Matt Sealey
Cc: Grant Erickson, linuxppc-dev, Stefan Roese, Wolfgang Denx,
linux-embedded
In-Reply-To: <b5e2fc790811251053w507792a1r3673ee2dc7581379@mail.gmail.com>
On Tue, 25 Nov 2008 12:53:12 -0600
"Matt Sealey" <matt@genesi-usa.com> wrote:
> Nitpick, really.. shouldn't the logbuffer location(s) be some device tree
> property(ies), perhaps something in the
> /chosen node that U-Boot etc. can then fill out?
I don't think that's a nitpick. It's a fundamental change in how this
would all work. However, I do think you're generally right.
Perhaps not /chosen, but maybe something like /rtas or /firmware, etc.
josh
^ permalink raw reply
* Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Matt Sealey @ 2008-11-25 18:53 UTC (permalink / raw)
To: Grant Erickson; +Cc: linuxppc-dev, Stefan Roese, Wolfgang Denx, linux-embedded
In-Reply-To: <1227638045-12862-1-git-send-email-gerickson@nuovations.com>
[-- Attachment #1.1: Type: text/plain, Size: 18409 bytes --]
Nitpick, really.. shouldn't the logbuffer location(s) be some device tree
property(ies), perhaps something in the
/chosen node that U-Boot etc. can then fill out?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
On Tue, Nov 25, 2008 at 12:34 PM, Grant Erickson
<gerickson@nuovations.com>wrote:
> This merges support for the previously DENX-only kernel feature of
> specifying an alternative, "external" buffer for kernel printk
> messages and their associated metadata. In addition, this ports
> architecture support for this feature from arch/ppc to arch/powerpc.
>
> Signed-off-by: Grant Erickson <gerickson@nuovations.com>
> ---
>
> When this option is enabled, an architecture- or machine-specific log
> buffer is used for all printk messages. This allows entities such as
> boot loaders (e.g. U-Boot) to place printk-compatible messages into
> this buffer and for the kernel to coalesce them with its normal
> messages.
>
> The code has historically been used and proven to work on the LWMON5
> platform under arch/ppc and is now used (by me) successfully on the
> AMCC Haleakala and Kilauea platforms.
>
> As implemented for arch/powerpc, two suboptions for the alternative
> log buffer are supported. The buffer may be contiguous with the
> metadata and message data colocated or the metadata and message
> storage may be in discontiguous regions of memory (e.g. a set of
> scratch registers and an SRAM buffer). On Kilauea and Haleakala, I
> have used the former; whereas LWMON5 has traditionally used the latter.
>
> The code here is, more or less, as-is from the DENX GIT tree. Comments
> welcome.
>
> arch/powerpc/kernel/prom.c | 93 +++++++++++++++++++++++++++
> include/linux/logbuff.h | 56 ++++++++++++++++
> init/Kconfig | 25 +++++++
> init/main.c | 4 +
> kernel/printk.c | 149
> +++++++++++++++++++++++++++++++++++++++++++-
> 5 files changed, 324 insertions(+), 3 deletions(-)
> create mode 100644 include/linux/logbuff.h
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 3a2dc7e..60282f1 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -32,6 +32,7 @@
> #include <linux/debugfs.h>
> #include <linux/irq.h>
> #include <linux/lmb.h>
> +#include <linux/logbuff.h>
>
> #include <asm/prom.h>
> #include <asm/rtas.h>
> @@ -61,6 +62,15 @@
> #define DBG(fmt...)
> #endif
>
> +#ifdef CONFIG_LOGBUFFER
> +#ifdef CONFIG_ALT_LB_LOCATION
> +# if !defined(BOARD_ALT_LH_ADDR) || !defined(BOARD_ALT_LB_ADDR)
> +# error "Please specify BOARD_ALT_LH_ADDR & BOARD_ALT_LB_ADDR."
> +# endif
> +#else /* !CONFIG_ALT_LB_LOCATION */
> +static phys_addr_t ext_logbuff;
> +#endif /* CONFIG_ALT_LB_LOCATION */
> +#endif /* CONFIG_LOGBUFFER */
>
> static int __initdata dt_root_addr_cells;
> static int __initdata dt_root_size_cells;
> @@ -1018,6 +1028,85 @@ static int __init early_init_dt_scan_memory(unsigned
> long node,
> return 0;
> }
>
> +#ifdef CONFIG_LOGBUFFER
> +#ifdef CONFIG_ALT_LB_LOCATION
> +/* Alternative external log buffer mapping: log metadata header & the
> + * character buffer are separated and allocated not in RAM but in some
> + * other memory-mapped I/O region (e.g. log head in unused registers,
> + * and log buffer in OCM memory)
> + */
> +int __init setup_ext_logbuff_mem(volatile logbuff_t **lhead, char **lbuf)
> +{
> + void *h, *b;
> +
> + if (unlikely(!lhead) || unlikely(!lbuf))
> + return -EINVAL;
> +
> + /* map log head */
> + h = ioremap(BOARD_ALT_LH_ADDR, sizeof(logbuff_t));
> + if (unlikely(!h))
> + return -EFAULT;
> +
> + /* map log buffer */
> + b = ioremap(BOARD_ALT_LB_ADDR, LOGBUFF_LEN);
> + if (unlikely(!b)) {
> + iounmap(h);
> + return -EFAULT;
> + }
> +
> + *lhead = h;
> + *lbuf = b;
> +
> + return 0;
> +}
> +#else /* !CONFIG_ALT_LB_LOCATION */
> +/* Usual external log-buffer mapping: log metadata header & the character
> + * buffer are both contiguous in system RAM.
> + */
> +int __init setup_ext_logbuff_mem(logbuff_t **lhead, char **lbuf)
> +{
> + void *p;
> +
> + if (unlikely(!lhead) || unlikely(!lbuf))
> + return -EINVAL;
> +
> + if (unlikely(!ext_logbuff) || !lmb_is_reserved(ext_logbuff))
> + return -EFAULT;
> +
> + p = ioremap(ext_logbuff, LOGBUFF_RESERVE);
> +
> + if (unlikely(!p))
> + return -EFAULT;
> +
> + *lhead = (logbuff_t *)(p + LOGBUFF_OVERHEAD -
> + sizeof(logbuff_t) +
> + sizeof(((logbuff_t *)0)->buf));
> + *lbuf = (*lhead)->buf;
> +
> + return 0;
> +}
> +
> +/* When the external log buffer configuration is used with the
> + * non-alternate location, the log head metadata and character buffer
> + * lie in the LOGBUFF_RESERVE bytes at the end of system RAM. Add this
> + * block of memory to the reserved memory pool so that it is not
> + * allocated for other purposes.
> + */
> +static void __init reserve_ext_logbuff_mem(void)
> +{
> + phys_addr_t top = lmb_end_of_DRAM();
> + phys_addr_t size = LOGBUFF_RESERVE;
> + phys_addr_t base = top - size;
> +
> + if (top > base) {
> + ext_logbuff = base;
> + DBG("reserving: %x -> %x\n", base, size);
> + lmb_reserve(base, size);
> + }
> +}
> +#endif /* CONFIG_ALT_LB_LOCATION */
> +#endif /* CONFIG_LOGBUFFER */
> +
> static void __init early_reserve_mem(void)
> {
> u64 base, size;
> @@ -1033,6 +1122,10 @@ static void __init early_reserve_mem(void)
> self_size = initial_boot_params->totalsize;
> lmb_reserve(self_base, self_size);
>
> +#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_LOCATION)
> + reserve_ext_logbuff_mem();
> +#endif /* defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_LOCATION) */
> +
> #ifdef CONFIG_BLK_DEV_INITRD
> /* then reserve the initrd, if any */
> if (initrd_start && (initrd_end > initrd_start))
> diff --git a/include/linux/logbuff.h b/include/linux/logbuff.h
> new file mode 100644
> index 0000000..22a51c0
> --- /dev/null
> +++ b/include/linux/logbuff.h
> @@ -0,0 +1,56 @@
> +/*
> + * (C) Copyright 2007
> + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +#ifndef _LOGBUFF_H_
> +#define _LOGBUFF_H_
> +
> +#ifdef CONFIG_LOGBUFFER
> +
> +#define LOGBUFF_MAGIC 0xc0de4ced
> +#define LOGBUFF_LEN 16384
> +#define LOGBUFF_OVERHEAD 4096
> +#define LOGBUFF_RESERVE (LOGBUFF_LEN + LOGBUFF_OVERHEAD)
> +
> +/* The mapping used here has to be the same as in logbuff_init_ptrs ()
> + in u-boot/common/cmd_log.c */
> +
> +typedef struct {
> + unsigned long tag;
> + unsigned long start;
> + unsigned long con; /* next char to be sent to consoles */
> + unsigned long end;
> + unsigned long chars;
> + unsigned char buf[0];
> +} logbuff_t;
> +
> +#ifdef CONFIG_ALT_LB_LOCATION
> +# define LOGBUFF_VOLATILE volatile
> +#else
> +# define LOGBUFF_VOLATILE
> +#endif /* defined(CONFIG_ALT_LB_LOCATION) */
> +
> +extern void setup_ext_logbuff(void);
> +/* arch specific */
> +extern int setup_ext_logbuff_mem(LOGBUFF_VOLATILE logbuff_t **lhead, char
> **lbuf);
> +
> +#endif /* CONFIG_LOGBUFFER */
> +#endif /* _LOGBUFF_H_ */
> diff --git a/init/Kconfig b/init/Kconfig
> index f763762..e1a1b59 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -619,6 +619,31 @@ config PRINTK
> very difficult to diagnose system problems, saying N here is
> strongly discouraged.
>
> +config LOGBUFFER
> + bool "External logbuffer" if PRINTK
> + default n
> + help
> + This option enables support for an alternative, "external"
> + printk log buffer. When enabled, an architecture- or machine-
> + specific log buffer is used for all printk messages. This
> + allows entities such as boot loaders to place printk-compatible
> + messages into this buffer and for the kernel to coalesce them
> + with its normal messages.
> +
> +config ALT_LB_LOCATION
> + bool "Alternative logbuffer" if LOGBUFFER
> + default n
> + help
> + When using an alternative, "external" printk log buffer, an
> + architecture- or machine-specific log buffer with contiguous
> + metadata and message storage is used. This option enables
> + support for discontiguous metadata and message storage
> + memory (e.g. a set of scratch registers and an SRAM
> + buffer). By saying Y here, you must also ensure your
> + architecture- or machine-code specify BOARD_ALT_LH_ADDR and
> + BOARD_ALT_LB_ADDR, for the metadata and message memory,
> + respectively.
> +
> config BUG
> bool "BUG() support" if EMBEDDED
> default y
> diff --git a/init/main.c b/init/main.c
> index 7e117a2..5687b98 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -61,6 +61,7 @@
> #include <linux/kthread.h>
> #include <linux/sched.h>
> #include <linux/signal.h>
> +#include <linux/logbuff.h>
> #include <linux/idr.h>
> #include <linux/ftrace.h>
>
> @@ -563,6 +564,9 @@ asmlinkage void __init start_kernel(void)
> * Interrupts are still disabled. Do necessary setups, then
> * enable them
> */
> +#ifdef CONFIG_LOGBUFFER
> + setup_ext_logbuff();
> +#endif
> lock_kernel();
> tick_init();
> boot_cpu_init();
> diff --git a/kernel/printk.c b/kernel/printk.c
> index f492f15..59884e2 100644
> --- a/kernel/printk.c
> +++ b/kernel/printk.c
> @@ -32,6 +32,7 @@
> #include <linux/security.h>
> #include <linux/bootmem.h>
> #include <linux/syscalls.h>
> +#include <linux/logbuff.h>
>
> #include <asm/uaccess.h>
>
> @@ -101,9 +102,39 @@ static DEFINE_SPINLOCK(logbuf_lock);
> * The indices into log_buf are not constrained to log_buf_len - they
> * must be masked before subscripting
> */
> +#ifdef CONFIG_LOGBUFFER
> +/* Indexes to the local log buffer */
> +static unsigned long _log_start;
> +static unsigned long _con_start;
> +static unsigned long _log_end;
> +static unsigned long _logged_chars;
> +/* These will be switched to the external log buffer */
> +#ifndef CONFIG_ALT_LB_LOCATION
> +/* usual logbuffer location */
> +static unsigned long *ext_log_start = &_log_start;
> +static unsigned long *ext_con_start = &_con_start;
> +static unsigned long *ext_log_end = &_log_end;
> +static unsigned long *ext_logged_chars = &_logged_chars;
> +#define log_start (*ext_log_start)
> +#define con_start (*ext_con_start)
> +#define log_end (*ext_log_end)
> +#define logged_chars (*ext_logged_chars)
> +#else /* defined(CONFIG_ALT_LB_LOCATION) */
> +/* alternative logbuffer location */
> +static volatile unsigned long *ext_log_start = &_log_start;
> +static volatile unsigned long *ext_con_start = &_con_start;
> +static volatile unsigned long *ext_log_end = &_log_end;
> +static volatile unsigned long *ext_logged_chars = &_logged_chars;
> +#define log_start (*((volatile u32 *)ext_log_start))
> +#define con_start (*((volatile u32 *)ext_con_start))
> +#define log_end (*((volatile u32 *)ext_log_end))
> +#define logged_chars (*((volatile u32 *)ext_logged_chars))
> +#endif /* !defined(CONFIG_ALT_LB_LOCATION) */
> +#else /* !defined(CONFIG_LOGBUFFER) */
> static unsigned log_start; /* Index into log_buf: next char to be read
> by syslog() */
> static unsigned con_start; /* Index into log_buf: next char to be sent
> to consoles */
> static unsigned log_end; /* Index into log_buf:
> most-recently-written-char + 1 */
> +#endif /* CONFIG_LOGBUFFER */
>
> /*
> * Array of consoles built from command line options (console=)
> @@ -134,10 +165,121 @@ static int console_may_schedule;
> static char __log_buf[__LOG_BUF_LEN];
> static char *log_buf = __log_buf;
> static int log_buf_len = __LOG_BUF_LEN;
> +#ifndef CONFIG_LOGBUFFER
> static unsigned logged_chars; /* Number of chars produced since last
> read+clear operation */
> +#endif /* !defined(CONFIG_LOGBUFFER) */
> +#ifdef CONFIG_LOGBUFFER
> +/* Sanity check the external log buffer metadata. When an the external
> + * log buffer is enabled, the log metadata is effectively non-volatile
> + * in that the values are preserved from reboot to reboot (until/unless
> + * the system loses power).
> + */
> +static void __init logbuff_check_metadata(LOGBUFF_VOLATILE logbuff_t *log)
> +{
> + unsigned long chars;
> +
> + /* Sanity check the producer and consumer indices. */
> +
> + if (log->end - log->start > LOGBUFF_LEN)
> + log->start = log->end - LOGBUFF_LEN;
> +
> + if (log->end - log->con > LOGBUFF_LEN)
> + log->con = log->end - LOGBUFF_LEN;
> +
> + /* Occasionally, particularly following a reboot, the start
> + * consumer index is not properly caught up to the console
> + * consumer index. If this is the case, catch it up so that
> + * the log buffer doesn't start with, for example,
> + * "<0>Restarting system.\n" followed by the 'real' start of
> + * the log.
> + */
> +
> + if (log->con > log->start)
> + log->start = log->con;
> +
> + /* Ensure that the number of characters logged reflects the
> + * characters actually logged based on the producer and
> + * consumer indices rather than all characters cumulatively
> + * logged across all reboots since a power-loss event.
> + */
> +
> + chars = log->end - log->start;
> +
> + if (log->chars > chars)
> + log->chars = chars;
> +}
> +
> +/* Coalesce the current log bounded buffer and the external log
> + * bounded buffer by appending the former to the latter. Precedence is
> + * given to the external log buffer when there is more data to be
> + * appended than space exists, so the current log buffer is truncated
> + * instead of overwritting the external buffer.
> + */
> +static void __init logbuff_coalesce_buffers(LOGBUFF_VOLATILE logbuff_t
> *log)
> +{
> + unsigned long dspace, ssize, len;
> +
> + dspace = LOGBUFF_LEN - (log->end - log->start);
> + ssize = log_end - log_start;
> + len = min(dspace, ssize);
> +
> + while (len-- > 0) {
> + log->buf[log->end++ & (LOGBUFF_LEN-1)] =
> LOG_BUF(log_start++);
> + log->chars++;
> + }
> +}
>
> +void __init setup_ext_logbuff(void)
> +{
> + LOGBUFF_VOLATILE logbuff_t *log;
> + char *ext_log_buf = NULL;
> + unsigned long flags;
> +
> + if (setup_ext_logbuff_mem(&log, &ext_log_buf) < 0) {
> + printk(KERN_WARNING
> + "Failed to setup external logbuffer - ignoring
> it\n");
> + return;
> + }
> +
> + /* When no properly setup buffer is found, reset pointers */
> + if (log->tag != LOGBUFF_MAGIC) {
> + printk(KERN_WARNING
> + "Unexpected external log buffer magic number. "
> + "Got %08lx, expected %08x. Resetting pointers and
> using "
> + "the buffer anyway.\n",
> + log->tag, LOGBUFF_MAGIC);
> + log->tag = LOGBUFF_MAGIC;
> + log->start = log->end = log->con = log->chars = 0;
> + }
> +
> + spin_lock_irqsave(&logbuf_lock, flags);
> +
> + logbuff_check_metadata(log);
> + logbuff_coalesce_buffers(log);
> +
> + /* Switch to the external log buffer */
> + ext_log_start = &log->start;
> + ext_con_start = &log->con;
> + ext_log_end = &log->end;
> + ext_logged_chars = &log->chars;
> +
> + log_buf = ext_log_buf;
> + log_buf_len = LOGBUFF_LEN;
> +
> + spin_unlock_irqrestore(&logbuf_lock, flags);
> +
> + printk(KERN_NOTICE "log_buf=%p\n", log_buf);
> +}
> +#endif /* CONFIG_LOGBUFFER */
> static int __init log_buf_len_setup(char *str)
> {
> +#ifdef CONFIG_LOGBUFFER
> + /* Log buffer size is LOGBUFF_LEN bytes */
> + printk(KERN_NOTICE
> + "External log buffer configured; "
> + "ignoring log_buf_len param.\n");
> + return 1;
> +#else
> unsigned size = memparse(str, &str);
> unsigned long flags;
>
> @@ -173,6 +315,7 @@ static int __init log_buf_len_setup(char *str)
> }
> out:
> return 1;
> +#endif /* CONFIG_LOGBUFFER */
> }
>
> __setup("log_buf_len=", log_buf_len_setup);
> @@ -230,7 +373,7 @@ static void boot_delay_msec(void)
> static inline void boot_delay_msec(void)
> {
> }
> -#endif
> +#endif /* CONFIG_BOOT_PRINTK_DELAY */
>
> /*
> * Commands to do_syslog:
> @@ -740,7 +883,7 @@ out_restore_irqs:
> EXPORT_SYMBOL(printk);
> EXPORT_SYMBOL(vprintk);
>
> -#else
> +#else /* !CONFIG_PRINTK */
>
> asmlinkage long sys_syslog(int type, char __user *buf, int len)
> {
> @@ -751,7 +894,7 @@ static void call_console_drivers(unsigned start,
> unsigned end)
> {
> }
>
> -#endif
> +#endif /* CONFIG_PRINTK */
>
> static int __add_preferred_console(char *name, int idx, char *options,
> char *brl_options)
> --
> 1.6.0.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
[-- Attachment #1.2: Type: text/html, Size: 24906 bytes --]
[-- Attachment #2: Type: text/plain, Size: 146 bytes --]
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages
From: Grant Erickson @ 2008-11-25 18:34 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-embedded, Wolfgang Denx, Stefan Roese
This merges support for the previously DENX-only kernel feature of
specifying an alternative, "external" buffer for kernel printk
messages and their associated metadata. In addition, this ports
architecture support for this feature from arch/ppc to arch/powerpc.
Signed-off-by: Grant Erickson <gerickson@nuovations.com>
---
When this option is enabled, an architecture- or machine-specific log
buffer is used for all printk messages. This allows entities such as
boot loaders (e.g. U-Boot) to place printk-compatible messages into
this buffer and for the kernel to coalesce them with its normal
messages.
The code has historically been used and proven to work on the LWMON5
platform under arch/ppc and is now used (by me) successfully on the
AMCC Haleakala and Kilauea platforms.
As implemented for arch/powerpc, two suboptions for the alternative
log buffer are supported. The buffer may be contiguous with the
metadata and message data colocated or the metadata and message
storage may be in discontiguous regions of memory (e.g. a set of
scratch registers and an SRAM buffer). On Kilauea and Haleakala, I
have used the former; whereas LWMON5 has traditionally used the latter.
The code here is, more or less, as-is from the DENX GIT tree. Comments
welcome.
arch/powerpc/kernel/prom.c | 93 +++++++++++++++++++++++++++
include/linux/logbuff.h | 56 ++++++++++++++++
init/Kconfig | 25 +++++++
init/main.c | 4 +
kernel/printk.c | 149 +++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 324 insertions(+), 3 deletions(-)
create mode 100644 include/linux/logbuff.h
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3a2dc7e..60282f1 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -32,6 +32,7 @@
#include <linux/debugfs.h>
#include <linux/irq.h>
#include <linux/lmb.h>
+#include <linux/logbuff.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -61,6 +62,15 @@
#define DBG(fmt...)
#endif
+#ifdef CONFIG_LOGBUFFER
+#ifdef CONFIG_ALT_LB_LOCATION
+# if !defined(BOARD_ALT_LH_ADDR) || !defined(BOARD_ALT_LB_ADDR)
+# error "Please specify BOARD_ALT_LH_ADDR & BOARD_ALT_LB_ADDR."
+# endif
+#else /* !CONFIG_ALT_LB_LOCATION */
+static phys_addr_t ext_logbuff;
+#endif /* CONFIG_ALT_LB_LOCATION */
+#endif /* CONFIG_LOGBUFFER */
static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells;
@@ -1018,6 +1028,85 @@ static int __init early_init_dt_scan_memory(unsigned long node,
return 0;
}
+#ifdef CONFIG_LOGBUFFER
+#ifdef CONFIG_ALT_LB_LOCATION
+/* Alternative external log buffer mapping: log metadata header & the
+ * character buffer are separated and allocated not in RAM but in some
+ * other memory-mapped I/O region (e.g. log head in unused registers,
+ * and log buffer in OCM memory)
+ */
+int __init setup_ext_logbuff_mem(volatile logbuff_t **lhead, char **lbuf)
+{
+ void *h, *b;
+
+ if (unlikely(!lhead) || unlikely(!lbuf))
+ return -EINVAL;
+
+ /* map log head */
+ h = ioremap(BOARD_ALT_LH_ADDR, sizeof(logbuff_t));
+ if (unlikely(!h))
+ return -EFAULT;
+
+ /* map log buffer */
+ b = ioremap(BOARD_ALT_LB_ADDR, LOGBUFF_LEN);
+ if (unlikely(!b)) {
+ iounmap(h);
+ return -EFAULT;
+ }
+
+ *lhead = h;
+ *lbuf = b;
+
+ return 0;
+}
+#else /* !CONFIG_ALT_LB_LOCATION */
+/* Usual external log-buffer mapping: log metadata header & the character
+ * buffer are both contiguous in system RAM.
+ */
+int __init setup_ext_logbuff_mem(logbuff_t **lhead, char **lbuf)
+{
+ void *p;
+
+ if (unlikely(!lhead) || unlikely(!lbuf))
+ return -EINVAL;
+
+ if (unlikely(!ext_logbuff) || !lmb_is_reserved(ext_logbuff))
+ return -EFAULT;
+
+ p = ioremap(ext_logbuff, LOGBUFF_RESERVE);
+
+ if (unlikely(!p))
+ return -EFAULT;
+
+ *lhead = (logbuff_t *)(p + LOGBUFF_OVERHEAD -
+ sizeof(logbuff_t) +
+ sizeof(((logbuff_t *)0)->buf));
+ *lbuf = (*lhead)->buf;
+
+ return 0;
+}
+
+/* When the external log buffer configuration is used with the
+ * non-alternate location, the log head metadata and character buffer
+ * lie in the LOGBUFF_RESERVE bytes at the end of system RAM. Add this
+ * block of memory to the reserved memory pool so that it is not
+ * allocated for other purposes.
+ */
+static void __init reserve_ext_logbuff_mem(void)
+{
+ phys_addr_t top = lmb_end_of_DRAM();
+ phys_addr_t size = LOGBUFF_RESERVE;
+ phys_addr_t base = top - size;
+
+ if (top > base) {
+ ext_logbuff = base;
+ DBG("reserving: %x -> %x\n", base, size);
+ lmb_reserve(base, size);
+ }
+}
+#endif /* CONFIG_ALT_LB_LOCATION */
+#endif /* CONFIG_LOGBUFFER */
+
static void __init early_reserve_mem(void)
{
u64 base, size;
@@ -1033,6 +1122,10 @@ static void __init early_reserve_mem(void)
self_size = initial_boot_params->totalsize;
lmb_reserve(self_base, self_size);
+#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_LOCATION)
+ reserve_ext_logbuff_mem();
+#endif /* defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_LOCATION) */
+
#ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start && (initrd_end > initrd_start))
diff --git a/include/linux/logbuff.h b/include/linux/logbuff.h
new file mode 100644
index 0000000..22a51c0
--- /dev/null
+++ b/include/linux/logbuff.h
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _LOGBUFF_H_
+#define _LOGBUFF_H_
+
+#ifdef CONFIG_LOGBUFFER
+
+#define LOGBUFF_MAGIC 0xc0de4ced
+#define LOGBUFF_LEN 16384
+#define LOGBUFF_OVERHEAD 4096
+#define LOGBUFF_RESERVE (LOGBUFF_LEN + LOGBUFF_OVERHEAD)
+
+/* The mapping used here has to be the same as in logbuff_init_ptrs ()
+ in u-boot/common/cmd_log.c */
+
+typedef struct {
+ unsigned long tag;
+ unsigned long start;
+ unsigned long con; /* next char to be sent to consoles */
+ unsigned long end;
+ unsigned long chars;
+ unsigned char buf[0];
+} logbuff_t;
+
+#ifdef CONFIG_ALT_LB_LOCATION
+# define LOGBUFF_VOLATILE volatile
+#else
+# define LOGBUFF_VOLATILE
+#endif /* defined(CONFIG_ALT_LB_LOCATION) */
+
+extern void setup_ext_logbuff(void);
+/* arch specific */
+extern int setup_ext_logbuff_mem(LOGBUFF_VOLATILE logbuff_t **lhead, char **lbuf);
+
+#endif /* CONFIG_LOGBUFFER */
+#endif /* _LOGBUFF_H_ */
diff --git a/init/Kconfig b/init/Kconfig
index f763762..e1a1b59 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -619,6 +619,31 @@ config PRINTK
very difficult to diagnose system problems, saying N here is
strongly discouraged.
+config LOGBUFFER
+ bool "External logbuffer" if PRINTK
+ default n
+ help
+ This option enables support for an alternative, "external"
+ printk log buffer. When enabled, an architecture- or machine-
+ specific log buffer is used for all printk messages. This
+ allows entities such as boot loaders to place printk-compatible
+ messages into this buffer and for the kernel to coalesce them
+ with its normal messages.
+
+config ALT_LB_LOCATION
+ bool "Alternative logbuffer" if LOGBUFFER
+ default n
+ help
+ When using an alternative, "external" printk log buffer, an
+ architecture- or machine-specific log buffer with contiguous
+ metadata and message storage is used. This option enables
+ support for discontiguous metadata and message storage
+ memory (e.g. a set of scratch registers and an SRAM
+ buffer). By saying Y here, you must also ensure your
+ architecture- or machine-code specify BOARD_ALT_LH_ADDR and
+ BOARD_ALT_LB_ADDR, for the metadata and message memory,
+ respectively.
+
config BUG
bool "BUG() support" if EMBEDDED
default y
diff --git a/init/main.c b/init/main.c
index 7e117a2..5687b98 100644
--- a/init/main.c
+++ b/init/main.c
@@ -61,6 +61,7 @@
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/signal.h>
+#include <linux/logbuff.h>
#include <linux/idr.h>
#include <linux/ftrace.h>
@@ -563,6 +564,9 @@ asmlinkage void __init start_kernel(void)
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
+#ifdef CONFIG_LOGBUFFER
+ setup_ext_logbuff();
+#endif
lock_kernel();
tick_init();
boot_cpu_init();
diff --git a/kernel/printk.c b/kernel/printk.c
index f492f15..59884e2 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -32,6 +32,7 @@
#include <linux/security.h>
#include <linux/bootmem.h>
#include <linux/syscalls.h>
+#include <linux/logbuff.h>
#include <asm/uaccess.h>
@@ -101,9 +102,39 @@ static DEFINE_SPINLOCK(logbuf_lock);
* The indices into log_buf are not constrained to log_buf_len - they
* must be masked before subscripting
*/
+#ifdef CONFIG_LOGBUFFER
+/* Indexes to the local log buffer */
+static unsigned long _log_start;
+static unsigned long _con_start;
+static unsigned long _log_end;
+static unsigned long _logged_chars;
+/* These will be switched to the external log buffer */
+#ifndef CONFIG_ALT_LB_LOCATION
+/* usual logbuffer location */
+static unsigned long *ext_log_start = &_log_start;
+static unsigned long *ext_con_start = &_con_start;
+static unsigned long *ext_log_end = &_log_end;
+static unsigned long *ext_logged_chars = &_logged_chars;
+#define log_start (*ext_log_start)
+#define con_start (*ext_con_start)
+#define log_end (*ext_log_end)
+#define logged_chars (*ext_logged_chars)
+#else /* defined(CONFIG_ALT_LB_LOCATION) */
+/* alternative logbuffer location */
+static volatile unsigned long *ext_log_start = &_log_start;
+static volatile unsigned long *ext_con_start = &_con_start;
+static volatile unsigned long *ext_log_end = &_log_end;
+static volatile unsigned long *ext_logged_chars = &_logged_chars;
+#define log_start (*((volatile u32 *)ext_log_start))
+#define con_start (*((volatile u32 *)ext_con_start))
+#define log_end (*((volatile u32 *)ext_log_end))
+#define logged_chars (*((volatile u32 *)ext_logged_chars))
+#endif /* !defined(CONFIG_ALT_LB_LOCATION) */
+#else /* !defined(CONFIG_LOGBUFFER) */
static unsigned log_start; /* Index into log_buf: next char to be read by syslog() */
static unsigned con_start; /* Index into log_buf: next char to be sent to consoles */
static unsigned log_end; /* Index into log_buf: most-recently-written-char + 1 */
+#endif /* CONFIG_LOGBUFFER */
/*
* Array of consoles built from command line options (console=)
@@ -134,10 +165,121 @@ static int console_may_schedule;
static char __log_buf[__LOG_BUF_LEN];
static char *log_buf = __log_buf;
static int log_buf_len = __LOG_BUF_LEN;
+#ifndef CONFIG_LOGBUFFER
static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
+#endif /* !defined(CONFIG_LOGBUFFER) */
+#ifdef CONFIG_LOGBUFFER
+/* Sanity check the external log buffer metadata. When an the external
+ * log buffer is enabled, the log metadata is effectively non-volatile
+ * in that the values are preserved from reboot to reboot (until/unless
+ * the system loses power).
+ */
+static void __init logbuff_check_metadata(LOGBUFF_VOLATILE logbuff_t *log)
+{
+ unsigned long chars;
+
+ /* Sanity check the producer and consumer indices. */
+
+ if (log->end - log->start > LOGBUFF_LEN)
+ log->start = log->end - LOGBUFF_LEN;
+
+ if (log->end - log->con > LOGBUFF_LEN)
+ log->con = log->end - LOGBUFF_LEN;
+
+ /* Occasionally, particularly following a reboot, the start
+ * consumer index is not properly caught up to the console
+ * consumer index. If this is the case, catch it up so that
+ * the log buffer doesn't start with, for example,
+ * "<0>Restarting system.\n" followed by the 'real' start of
+ * the log.
+ */
+
+ if (log->con > log->start)
+ log->start = log->con;
+
+ /* Ensure that the number of characters logged reflects the
+ * characters actually logged based on the producer and
+ * consumer indices rather than all characters cumulatively
+ * logged across all reboots since a power-loss event.
+ */
+
+ chars = log->end - log->start;
+
+ if (log->chars > chars)
+ log->chars = chars;
+}
+
+/* Coalesce the current log bounded buffer and the external log
+ * bounded buffer by appending the former to the latter. Precedence is
+ * given to the external log buffer when there is more data to be
+ * appended than space exists, so the current log buffer is truncated
+ * instead of overwritting the external buffer.
+ */
+static void __init logbuff_coalesce_buffers(LOGBUFF_VOLATILE logbuff_t *log)
+{
+ unsigned long dspace, ssize, len;
+
+ dspace = LOGBUFF_LEN - (log->end - log->start);
+ ssize = log_end - log_start;
+ len = min(dspace, ssize);
+
+ while (len-- > 0) {
+ log->buf[log->end++ & (LOGBUFF_LEN-1)] = LOG_BUF(log_start++);
+ log->chars++;
+ }
+}
+void __init setup_ext_logbuff(void)
+{
+ LOGBUFF_VOLATILE logbuff_t *log;
+ char *ext_log_buf = NULL;
+ unsigned long flags;
+
+ if (setup_ext_logbuff_mem(&log, &ext_log_buf) < 0) {
+ printk(KERN_WARNING
+ "Failed to setup external logbuffer - ignoring it\n");
+ return;
+ }
+
+ /* When no properly setup buffer is found, reset pointers */
+ if (log->tag != LOGBUFF_MAGIC) {
+ printk(KERN_WARNING
+ "Unexpected external log buffer magic number. "
+ "Got %08lx, expected %08x. Resetting pointers and using "
+ "the buffer anyway.\n",
+ log->tag, LOGBUFF_MAGIC);
+ log->tag = LOGBUFF_MAGIC;
+ log->start = log->end = log->con = log->chars = 0;
+ }
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+
+ logbuff_check_metadata(log);
+ logbuff_coalesce_buffers(log);
+
+ /* Switch to the external log buffer */
+ ext_log_start = &log->start;
+ ext_con_start = &log->con;
+ ext_log_end = &log->end;
+ ext_logged_chars = &log->chars;
+
+ log_buf = ext_log_buf;
+ log_buf_len = LOGBUFF_LEN;
+
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ printk(KERN_NOTICE "log_buf=%p\n", log_buf);
+}
+#endif /* CONFIG_LOGBUFFER */
static int __init log_buf_len_setup(char *str)
{
+#ifdef CONFIG_LOGBUFFER
+ /* Log buffer size is LOGBUFF_LEN bytes */
+ printk(KERN_NOTICE
+ "External log buffer configured; "
+ "ignoring log_buf_len param.\n");
+ return 1;
+#else
unsigned size = memparse(str, &str);
unsigned long flags;
@@ -173,6 +315,7 @@ static int __init log_buf_len_setup(char *str)
}
out:
return 1;
+#endif /* CONFIG_LOGBUFFER */
}
__setup("log_buf_len=", log_buf_len_setup);
@@ -230,7 +373,7 @@ static void boot_delay_msec(void)
static inline void boot_delay_msec(void)
{
}
-#endif
+#endif /* CONFIG_BOOT_PRINTK_DELAY */
/*
* Commands to do_syslog:
@@ -740,7 +883,7 @@ out_restore_irqs:
EXPORT_SYMBOL(printk);
EXPORT_SYMBOL(vprintk);
-#else
+#else /* !CONFIG_PRINTK */
asmlinkage long sys_syslog(int type, char __user *buf, int len)
{
@@ -751,7 +894,7 @@ static void call_console_drivers(unsigned start, unsigned end)
{
}
-#endif
+#endif /* CONFIG_PRINTK */
static int __add_preferred_console(char *name, int idx, char *options,
char *brl_options)
--
1.6.0.4
^ permalink raw reply related
* LZMA inclusion
From: Gregers Petersen @ 2008-11-25 7:06 UTC (permalink / raw)
To: linux-embedded
Hello
There was a small talk a few days ago involving a few of the OpenWrt
developers and David Woodhouse. One of the topics discussed, was a
question about the potential of including LZMA in the kernel.
Such an inclusion would be quite benefitial in terms of embedded
systems, but the major hurdle seems to be the code quality of LZMA itself.
This leads to the question I would like to raise; are there ongoing
plans (or considerations) to rewrite and merge LZMA, and has anyone
started working on it in practical terms?
Sincerely
--
Gregers Petersen
People-stuff, layer 8 and anthropology
glp on irc
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
KAMIKAZE (bleeding edge) -----------------------
* 10 oz Vodka Shake well with ice and strain
* 10 oz Triple sec mixture into 10 shot glasses.
* 10 oz lime juice Salute!
---------------------------------------------------
^ permalink raw reply
* Re: [PATCH 2/2] phylib: make mdio-gpio work without OF (v4)
From: Laurent Pinchart @ 2008-11-20 16:24 UTC (permalink / raw)
To: Paulius Zaleckas
Cc: netdev, linux-arm-kernel, linux-embedded, Grant Likely,
Mike Frysinger
In-Reply-To: <20081114102433.11513.2557.stgit@Programuotojas.82-135-208-232.ip.zebra.lt>
On Friday 14 November 2008 11:24:34 Paulius Zaleckas wrote:
> make mdio-gpio work with non OpenFirmware gpio implementation.
>
> Aditional changes to mdio-gpio:
> - use gpio_request() and gpio_free()
> - place irq[] array in struct mdio_gpio_info
> - add module description, author and license
> - add note about compiling this driver as module
> - rename mdc and mdio function (were ugly names)
> - change MII to MDIO in bus name
> - add __init __exit to module (un)loading functions
> - probe fails if no phys added to the bus
> - kzalloc bitbang with sizeof(*bitbang)
>
> Changes since v3:
> - keep bus naming "%x" to be compatible with existing drivers.
>
> Changes since v2:
> - more #ifdefs reduction
> - platform driver will be registered on OF platforms also
> - unified platform and OF bus_id to phy%i
>
> Changes since v1:
> - removed NO_IRQ
> - reduced #idefs
>
> Laurent, please test this driver under OF.
No obvious issue found.
Acked-by: Laurent Pinchart <laurent.pinchart@skynet.be>
> Signed-off-by: Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
> Cc: Laurent Pinchart <laurent.pinchart@skynet.be>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Mike Frysinger <vapier.adi@gmail.com>
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
^ permalink raw reply
* [Announce] Embedded Linux Conference 2009 - Call for sessions
From: Tim Bird @ 2008-11-14 21:51 UTC (permalink / raw)
To: linux-embedded
Here is something that may be of interest to embedded Linux kernel developers.
Hello everyone,
The CE Linux Forum would like to invite you to make a presentation
at our upcoming Embedded Linux Conference. The conference will be
held April 6-8, 2009 in San Francisco, California.
See http://embeddedlinuxconference.com/elc_2009/
for general information about the conference, and
http://tree.celinuxforum.org/CelfPubWiki/ELC2009CallForPresentations
for information about the call for sessions.
CELF is the primary sponsor of this event, which is open to the
public. This year we will be holding the conference in conjunction
with the Linux Foundation Spring Collaboration Summit (April 8-10)
and it should be a very exciting event.
= Guidelines =
Presentations should be of a technical nature, covering topics
related to use of Linux in embedded systems. The CE Linux Forum
is focused on the use of Linux in consumer electronics products,
but presentations may cover use of Linux in other embedded
areas, as long as the topic is of general relevance to most
embedded developers.
Presentations that are commercial advertisements or sales
pitches are not appropriate for this conference.
Presentations on the following topics are encouraged:
* Audio, Video, and Graphics systems for embedded products
* Security
* System size
* Bootup time
* Meeting real-time constraints
* Power management
* Streaming media
* Flash memory devices and filesystems
* Technologies related to cell phones, digital settop
boxes, handheld devices, or other CE products
* Development tools for embedded users
* Use of Linux in actual products, practical experience and
war stories
* Standards for CE products
Most presentation slots are 50 minutes long, including time for
questions.
No paper submission is required in conjunction with the presentation.
You may also submit a request to present a tutorial. Tutorials are
intended to be longer, interactive learning sessions. A tutorial may
occupy more than one session slot at the conference.
Full details, including the e-mail address to use to submit
a proposal, are at:
http://tree.celinuxforum.org/CelfPubWiki/ELC2009CallForPresentations
The deadline for submissions is January 16, 2009.
Thanks,
-- Tim
P.S. Thanks for reading this far...
For those unaware, we just finished Embedded Linux Conference Europe, where
a number of great presentations on embedded Linux were presented. We are still
collecting presentations from this at:
http://tree.celinuxforum.org/CelfPubWiki/ELCEurope2008Presentations
We also took videos, that the guys from Free Electrons are working
to publish sometime soon.
=============================
Tim Bird
Architecture Group Chair, CE Linux Forum
Senior Staff Engineer, Sony Corporation of America
=============================
^ permalink raw reply
* [PATCH 2/2] phylib: make mdio-gpio work without OF (v4)
From: Paulius Zaleckas @ 2008-11-14 10:24 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-embedded, Paulius Zaleckas,
Laurent Pinchart, Grant Likely, Mike Frysinger
In-Reply-To: <20081114102336.11513.67767.stgit@Programuotojas.82-135-208-232.ip.zebra.lt>
make mdio-gpio work with non OpenFirmware gpio implementation.
Aditional changes to mdio-gpio:
- use gpio_request() and gpio_free()
- place irq[] array in struct mdio_gpio_info
- add module description, author and license
- add note about compiling this driver as module
- rename mdc and mdio function (were ugly names)
- change MII to MDIO in bus name
- add __init __exit to module (un)loading functions
- probe fails if no phys added to the bus
- kzalloc bitbang with sizeof(*bitbang)
Changes since v3:
- keep bus naming "%x" to be compatible with existing drivers.
Changes since v2:
- more #ifdefs reduction
- platform driver will be registered on OF platforms also
- unified platform and OF bus_id to phy%i
Changes since v1:
- removed NO_IRQ
- reduced #idefs
Laurent, please test this driver under OF.
Signed-off-by: Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
Cc: Laurent Pinchart <laurent.pinchart@skynet.be>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Mike Frysinger <vapier.adi@gmail.com>
---
drivers/net/phy/Kconfig | 5 +
drivers/net/phy/mdio-gpio.c | 232 ++++++++++++++++++++++++++++++-------------
include/linux/mdio-gpio.h | 25 +++++
3 files changed, 191 insertions(+), 71 deletions(-)
create mode 100644 include/linux/mdio-gpio.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 0318077..c4c5a2f 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -86,8 +86,11 @@ config MDIO_BITBANG
config MDIO_GPIO
tristate "Support for GPIO lib-based bitbanged MDIO buses"
- depends on MDIO_BITBANG && OF_GPIO
+ depends on MDIO_BITBANG && GENERIC_GPIO
---help---
Supports GPIO lib-based MDIO busses.
+ To compile this driver as a module, choose M here: the module
+ will be called mdio-gpio.
+
endif # PHYLIB
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 2ff9775..a439ebe 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -1,9 +1,12 @@
/*
- * OpenFirmware GPIO based MDIO bitbang driver.
+ * GPIO based MDIO bitbang driver.
+ * Supports OpenFirmware.
*
* Copyright (c) 2008 CSE Semaphore Belgium.
* by Laurent Pinchart <laurentp@cse-semaphore.com>
*
+ * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
* Based on earlier work by
*
* Copyright (c) 2003 Intracom S.A.
@@ -21,9 +24,14 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/mdio-bitbang.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mdio-gpio.h>
+
+#ifdef CONFIG_OF_GPIO
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
+#endif
struct mdio_gpio_info {
struct mdiobb_ctrl ctrl;
@@ -41,7 +49,7 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
gpio_direction_input(bitbang->mdio);
}
-static int mdio_read(struct mdiobb_ctrl *ctrl)
+static int mdio_get(struct mdiobb_ctrl *ctrl)
{
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
@@ -49,7 +57,7 @@ static int mdio_read(struct mdiobb_ctrl *ctrl)
return gpio_get_value(bitbang->mdio);
}
-static void mdio(struct mdiobb_ctrl *ctrl, int what)
+static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
{
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
@@ -57,7 +65,7 @@ static void mdio(struct mdiobb_ctrl *ctrl, int what)
gpio_set_value(bitbang->mdio, what);
}
-static void mdc(struct mdiobb_ctrl *ctrl, int what)
+static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
{
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
@@ -67,93 +75,69 @@ static void mdc(struct mdiobb_ctrl *ctrl, int what)
static struct mdiobb_ops mdio_gpio_ops = {
.owner = THIS_MODULE,
- .set_mdc = mdc,
+ .set_mdc = mdc_set,
.set_mdio_dir = mdio_dir,
- .set_mdio_data = mdio,
- .get_mdio_data = mdio_read,
+ .set_mdio_data = mdio_set,
+ .get_mdio_data = mdio_get,
};
-static int __devinit mdio_ofgpio_bitbang_init(struct mii_bus *bus,
- struct device_node *np)
-{
- struct mdio_gpio_info *bitbang = bus->priv;
-
- bitbang->mdc = of_get_gpio(np, 0);
- bitbang->mdio = of_get_gpio(np, 1);
-
- if (bitbang->mdc < 0 || bitbang->mdio < 0)
- return -ENODEV;
-
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", bitbang->mdc);
- return 0;
-}
-
-static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+static int __devinit mdio_gpio_bus_init(struct device *dev,
+ struct mdio_gpio_platform_data *pdata,
+ int bus_id)
{
- const u32 *data;
- int len, id, irq;
-
- data = of_get_property(np, "reg", &len);
- if (!data || len != 4)
- return;
-
- id = *data;
- bus->phy_mask &= ~(1 << id);
-
- irq = of_irq_to_resource(np, 0, NULL);
- if (irq != NO_IRQ)
- bus->irq[id] = irq;
-}
-
-static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *np = NULL;
struct mii_bus *new_bus;
struct mdio_gpio_info *bitbang;
int ret = -ENOMEM;
int i;
- bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL);
+ bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
if (!bitbang)
goto out;
bitbang->ctrl.ops = &mdio_gpio_ops;
+ bitbang->mdc = pdata->mdc;
+ bitbang->mdio = pdata->mdio;
new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
if (!new_bus)
goto out_free_bitbang;
- new_bus->name = "GPIO Bitbanged MII",
+ new_bus->name = "GPIO Bitbanged MDIO",
- ret = mdio_ofgpio_bitbang_init(new_bus, ofdev->node);
- if (ret)
- goto out_free_bus;
+ ret = -ENODEV;
- new_bus->phy_mask = ~0;
- new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- if (!new_bus->irq)
+ new_bus->phy_mask = pdata->phy_mask;
+ new_bus->irq = pdata->irqs;
+ new_bus->parent = dev;
+
+ if (new_bus->phy_mask == ~0)
goto out_free_bus;
for (i = 0; i < PHY_MAX_ADDR; i++)
- new_bus->irq[i] = -1;
+ if (!new_bus->irq[i])
+ new_bus->irq[i] = PHY_POLL;
- while ((np = of_get_next_child(ofdev->node, np)))
- if (!strcmp(np->type, "ethernet-phy"))
- add_phy(new_bus, np);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", bus_id);
+
+ if (gpio_request(bitbang->mdc, "mdc"))
+ goto out_free_bus;
- new_bus->parent = &ofdev->dev;
- dev_set_drvdata(&ofdev->dev, new_bus);
+ if (gpio_request(bitbang->mdio, "mdio"))
+ goto out_free_mdc;
+
+ dev_set_drvdata(dev, new_bus);
ret = mdiobus_register(new_bus);
if (ret)
- goto out_free_irqs;
+ goto out_free_all;
return 0;
-out_free_irqs:
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(new_bus->irq);
+out_free_all:
+ dev_set_drvdata(dev, NULL);
+ gpio_free(bitbang->mdio);
+out_free_mdc:
+ gpio_free(bitbang->mdc);
out_free_bus:
free_mdio_bitbang(new_bus);
out_free_bitbang:
@@ -162,16 +146,86 @@ out:
return ret;
}
-static int mdio_ofgpio_remove(struct of_device *ofdev)
+static void __devexit mdio_gpio_bus_destroy(struct device *dev)
{
- struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+ struct mii_bus *bus = dev_get_drvdata(dev);
struct mdio_gpio_info *bitbang = bus->priv;
mdiobus_unregister(bus);
- kfree(bus->irq);
free_mdio_bitbang(bus);
- dev_set_drvdata(&ofdev->dev, NULL);
+ dev_set_drvdata(dev, NULL);
+ gpio_free(bitbang->mdc);
+ gpio_free(bitbang->mdio);
kfree(bitbang);
+}
+
+static int __devinit mdio_gpio_probe(struct platform_device *pdev)
+{
+ struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!pdata)
+ return -ENODEV;
+
+ return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+}
+
+static int __devexit mdio_gpio_remove(struct platform_device *pdev)
+{
+ mdio_gpio_bus_destroy(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF_GPIO
+static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
+ struct device_node *np)
+{
+ const u32 *data;
+ int len, id, irq;
+
+ data = of_get_property(np, "reg", &len);
+ if (!data || len != 4)
+ return;
+
+ id = *data;
+ pdata->phy_mask &= ~(1 << id);
+
+ irq = of_irq_to_resource(np, 0, NULL);
+ if (irq)
+ pdata->irqs[id] = irq;
+}
+
+static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = NULL;
+ struct mdio_gpio_platform_data *pdata;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->mdc = of_get_gpio(ofdev->node, 0);
+ pdata->mdio = of_get_gpio(ofdev->node, 1);
+
+ if (pdata->mdc < 0 || pdata->mdio < 0)
+ goto out_free;
+
+ while ((np = of_get_next_child(ofdev->node, np)))
+ if (!strcmp(np->type, "ethernet-phy"))
+ add_phy(pdata, np);
+
+ return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+
+out_free:
+ kfree(pdata);
+ return -ENODEV;
+}
+
+static int __devexit mdio_ofgpio_remove(struct of_device *ofdev)
+{
+ mdio_gpio_bus_destroy(&ofdev->dev);
+ kfree(ofdev->dev.platform_data);
return 0;
}
@@ -187,18 +241,56 @@ static struct of_platform_driver mdio_ofgpio_driver = {
.name = "mdio-gpio",
.match_table = mdio_ofgpio_match,
.probe = mdio_ofgpio_probe,
- .remove = mdio_ofgpio_remove,
+ .remove = __devexit_p(mdio_ofgpio_remove),
};
-static int mdio_ofgpio_init(void)
+static inline int __init mdio_ofgpio_init(void)
{
return of_register_platform_driver(&mdio_ofgpio_driver);
}
-static void mdio_ofgpio_exit(void)
+static inline void __exit mdio_ofgpio_exit(void)
{
of_unregister_platform_driver(&mdio_ofgpio_driver);
}
+#else
+static inline int __init mdio_ofgpio_init(void) { return 0; }
+static inline void __exit mdio_ofgpio_exit(void) { }
+#endif /* CONFIG_OF_GPIO */
+
+static struct platform_driver mdio_gpio_driver = {
+ .probe = mdio_gpio_probe,
+ .remove = __devexit_p(mdio_gpio_remove),
+ .driver = {
+ .name = "mdio-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mdio_gpio_init(void)
+{
+ int ret;
+
+ ret = mdio_ofgpio_init();
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&mdio_gpio_driver);
+ if (ret)
+ mdio_ofgpio_exit();
+
+ return ret;
+}
+module_init(mdio_gpio_init);
+
+static void __exit mdio_gpio_exit(void)
+{
+ platform_driver_unregister(&mdio_gpio_driver);
+ mdio_ofgpio_exit();
+}
+module_exit(mdio_gpio_exit);
-module_init(mdio_ofgpio_init);
-module_exit(mdio_ofgpio_exit);
+MODULE_ALIAS("platform:mdio-gpio");
+MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO");
diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h
new file mode 100644
index 0000000..e9d3fdf
--- /dev/null
+++ b/include/linux/mdio-gpio.h
@@ -0,0 +1,25 @@
+/*
+ * MDIO-GPIO bus platform data structures
+ *
+ * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __LINUX_MDIO_GPIO_H
+#define __LINUX_MDIO_GPIO_H
+
+#include <linux/mdio-bitbang.h>
+
+struct mdio_gpio_platform_data {
+ /* GPIO numbers for bus pins */
+ unsigned int mdc;
+ unsigned int mdio;
+
+ unsigned int phy_mask;
+ int irqs[PHY_MAX_ADDR];
+};
+
+#endif /* __LINUX_MDIO_GPIO_H */
^ permalink raw reply related
* [PATCH 1/2] phylib: rename mdio-ofgpio to mdio-gpio
From: Paulius Zaleckas @ 2008-11-14 10:24 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-embedded, Paulius Zaleckas,
Laurent Pinchart, Grant Likely, Mike Frysinger
In-Reply-To: <20081114102336.11513.67767.stgit@Programuotojas.82-135-208-232.ip.zebra.lt>
Signed-off-by: Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
Cc: Laurent Pinchart <laurentp@cse-semaphore.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Mike Frysinger <vapier.adi@gmail.com>
---
drivers/net/phy/Kconfig | 2
drivers/net/phy/Makefile | 2
drivers/net/phy/mdio-gpio.c | 204 +++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/mdio-ofgpio.c | 204 -----------------------------------------
4 files changed, 206 insertions(+), 206 deletions(-)
create mode 100644 drivers/net/phy/mdio-gpio.c
delete mode 100644 drivers/net/phy/mdio-ofgpio.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d55932a..0318077 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -84,7 +84,7 @@ config MDIO_BITBANG
If in doubt, say N.
-config MDIO_OF_GPIO
+config MDIO_GPIO
tristate "Support for GPIO lib-based bitbanged MDIO buses"
depends on MDIO_BITBANG && OF_GPIO
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index eee329f..9ae5d30 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
-obj-$(CONFIG_MDIO_OF_GPIO) += mdio-ofgpio.o
+obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
new file mode 100644
index 0000000..2ff9775
--- /dev/null
+++ b/drivers/net/phy/mdio-gpio.c
@@ -0,0 +1,204 @@
+/*
+ * OpenFirmware GPIO based MDIO bitbang driver.
+ *
+ * Copyright (c) 2008 CSE Semaphore Belgium.
+ * by Laurent Pinchart <laurentp@cse-semaphore.com>
+ *
+ * Based on earlier work by
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+struct mdio_gpio_info {
+ struct mdiobb_ctrl ctrl;
+ int mdc, mdio;
+};
+
+static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ if (dir)
+ gpio_direction_output(bitbang->mdio, 1);
+ else
+ gpio_direction_input(bitbang->mdio);
+}
+
+static int mdio_read(struct mdiobb_ctrl *ctrl)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ return gpio_get_value(bitbang->mdio);
+}
+
+static void mdio(struct mdiobb_ctrl *ctrl, int what)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ gpio_set_value(bitbang->mdio, what);
+}
+
+static void mdc(struct mdiobb_ctrl *ctrl, int what)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ gpio_set_value(bitbang->mdc, what);
+}
+
+static struct mdiobb_ops mdio_gpio_ops = {
+ .owner = THIS_MODULE,
+ .set_mdc = mdc,
+ .set_mdio_dir = mdio_dir,
+ .set_mdio_data = mdio,
+ .get_mdio_data = mdio_read,
+};
+
+static int __devinit mdio_ofgpio_bitbang_init(struct mii_bus *bus,
+ struct device_node *np)
+{
+ struct mdio_gpio_info *bitbang = bus->priv;
+
+ bitbang->mdc = of_get_gpio(np, 0);
+ bitbang->mdio = of_get_gpio(np, 1);
+
+ if (bitbang->mdc < 0 || bitbang->mdio < 0)
+ return -ENODEV;
+
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%x", bitbang->mdc);
+ return 0;
+}
+
+static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+{
+ const u32 *data;
+ int len, id, irq;
+
+ data = of_get_property(np, "reg", &len);
+ if (!data || len != 4)
+ return;
+
+ id = *data;
+ bus->phy_mask &= ~(1 << id);
+
+ irq = of_irq_to_resource(np, 0, NULL);
+ if (irq != NO_IRQ)
+ bus->irq[id] = irq;
+}
+
+static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = NULL;
+ struct mii_bus *new_bus;
+ struct mdio_gpio_info *bitbang;
+ int ret = -ENOMEM;
+ int i;
+
+ bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL);
+ if (!bitbang)
+ goto out;
+
+ bitbang->ctrl.ops = &mdio_gpio_ops;
+
+ new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
+ if (!new_bus)
+ goto out_free_bitbang;
+
+ new_bus->name = "GPIO Bitbanged MII",
+
+ ret = mdio_ofgpio_bitbang_init(new_bus, ofdev->node);
+ if (ret)
+ goto out_free_bus;
+
+ new_bus->phy_mask = ~0;
+ new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!new_bus->irq)
+ goto out_free_bus;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ new_bus->irq[i] = -1;
+
+ while ((np = of_get_next_child(ofdev->node, np)))
+ if (!strcmp(np->type, "ethernet-phy"))
+ add_phy(new_bus, np);
+
+ new_bus->parent = &ofdev->dev;
+ dev_set_drvdata(&ofdev->dev, new_bus);
+
+ ret = mdiobus_register(new_bus);
+ if (ret)
+ goto out_free_irqs;
+
+ return 0;
+
+out_free_irqs:
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(new_bus->irq);
+out_free_bus:
+ free_mdio_bitbang(new_bus);
+out_free_bitbang:
+ kfree(bitbang);
+out:
+ return ret;
+}
+
+static int mdio_ofgpio_remove(struct of_device *ofdev)
+{
+ struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+ struct mdio_gpio_info *bitbang = bus->priv;
+
+ mdiobus_unregister(bus);
+ kfree(bus->irq);
+ free_mdio_bitbang(bus);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(bitbang);
+
+ return 0;
+}
+
+static struct of_device_id mdio_ofgpio_match[] = {
+ {
+ .compatible = "virtual,mdio-gpio",
+ },
+ {},
+};
+
+static struct of_platform_driver mdio_ofgpio_driver = {
+ .name = "mdio-gpio",
+ .match_table = mdio_ofgpio_match,
+ .probe = mdio_ofgpio_probe,
+ .remove = mdio_ofgpio_remove,
+};
+
+static int mdio_ofgpio_init(void)
+{
+ return of_register_platform_driver(&mdio_ofgpio_driver);
+}
+
+static void mdio_ofgpio_exit(void)
+{
+ of_unregister_platform_driver(&mdio_ofgpio_driver);
+}
+
+module_init(mdio_ofgpio_init);
+module_exit(mdio_ofgpio_exit);
diff --git a/drivers/net/phy/mdio-ofgpio.c b/drivers/net/phy/mdio-ofgpio.c
deleted file mode 100644
index 2ff9775..0000000
--- a/drivers/net/phy/mdio-ofgpio.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * OpenFirmware GPIO based MDIO bitbang driver.
- *
- * Copyright (c) 2008 CSE Semaphore Belgium.
- * by Laurent Pinchart <laurentp@cse-semaphore.com>
- *
- * Based on earlier work by
- *
- * Copyright (c) 2003 Intracom S.A.
- * by Pantelis Antoniou <panto@intracom.gr>
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mdio-bitbang.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-
-struct mdio_gpio_info {
- struct mdiobb_ctrl ctrl;
- int mdc, mdio;
-};
-
-static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- if (dir)
- gpio_direction_output(bitbang->mdio, 1);
- else
- gpio_direction_input(bitbang->mdio);
-}
-
-static int mdio_read(struct mdiobb_ctrl *ctrl)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- return gpio_get_value(bitbang->mdio);
-}
-
-static void mdio(struct mdiobb_ctrl *ctrl, int what)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- gpio_set_value(bitbang->mdio, what);
-}
-
-static void mdc(struct mdiobb_ctrl *ctrl, int what)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- gpio_set_value(bitbang->mdc, what);
-}
-
-static struct mdiobb_ops mdio_gpio_ops = {
- .owner = THIS_MODULE,
- .set_mdc = mdc,
- .set_mdio_dir = mdio_dir,
- .set_mdio_data = mdio,
- .get_mdio_data = mdio_read,
-};
-
-static int __devinit mdio_ofgpio_bitbang_init(struct mii_bus *bus,
- struct device_node *np)
-{
- struct mdio_gpio_info *bitbang = bus->priv;
-
- bitbang->mdc = of_get_gpio(np, 0);
- bitbang->mdio = of_get_gpio(np, 1);
-
- if (bitbang->mdc < 0 || bitbang->mdio < 0)
- return -ENODEV;
-
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", bitbang->mdc);
- return 0;
-}
-
-static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
-{
- const u32 *data;
- int len, id, irq;
-
- data = of_get_property(np, "reg", &len);
- if (!data || len != 4)
- return;
-
- id = *data;
- bus->phy_mask &= ~(1 << id);
-
- irq = of_irq_to_resource(np, 0, NULL);
- if (irq != NO_IRQ)
- bus->irq[id] = irq;
-}
-
-static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *np = NULL;
- struct mii_bus *new_bus;
- struct mdio_gpio_info *bitbang;
- int ret = -ENOMEM;
- int i;
-
- bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL);
- if (!bitbang)
- goto out;
-
- bitbang->ctrl.ops = &mdio_gpio_ops;
-
- new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
- if (!new_bus)
- goto out_free_bitbang;
-
- new_bus->name = "GPIO Bitbanged MII",
-
- ret = mdio_ofgpio_bitbang_init(new_bus, ofdev->node);
- if (ret)
- goto out_free_bus;
-
- new_bus->phy_mask = ~0;
- new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- if (!new_bus->irq)
- goto out_free_bus;
-
- for (i = 0; i < PHY_MAX_ADDR; i++)
- new_bus->irq[i] = -1;
-
- while ((np = of_get_next_child(ofdev->node, np)))
- if (!strcmp(np->type, "ethernet-phy"))
- add_phy(new_bus, np);
-
- new_bus->parent = &ofdev->dev;
- dev_set_drvdata(&ofdev->dev, new_bus);
-
- ret = mdiobus_register(new_bus);
- if (ret)
- goto out_free_irqs;
-
- return 0;
-
-out_free_irqs:
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(new_bus->irq);
-out_free_bus:
- free_mdio_bitbang(new_bus);
-out_free_bitbang:
- kfree(bitbang);
-out:
- return ret;
-}
-
-static int mdio_ofgpio_remove(struct of_device *ofdev)
-{
- struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
- struct mdio_gpio_info *bitbang = bus->priv;
-
- mdiobus_unregister(bus);
- kfree(bus->irq);
- free_mdio_bitbang(bus);
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(bitbang);
-
- return 0;
-}
-
-static struct of_device_id mdio_ofgpio_match[] = {
- {
- .compatible = "virtual,mdio-gpio",
- },
- {},
-};
-
-static struct of_platform_driver mdio_ofgpio_driver = {
- .name = "mdio-gpio",
- .match_table = mdio_ofgpio_match,
- .probe = mdio_ofgpio_probe,
- .remove = mdio_ofgpio_remove,
-};
-
-static int mdio_ofgpio_init(void)
-{
- return of_register_platform_driver(&mdio_ofgpio_driver);
-}
-
-static void mdio_ofgpio_exit(void)
-{
- of_unregister_platform_driver(&mdio_ofgpio_driver);
-}
-
-module_init(mdio_ofgpio_init);
-module_exit(mdio_ofgpio_exit);
^ permalink raw reply related
* [PATCH 0/2] phylib: mdio-ofgpio ---> mdio-gpio (v3)
From: Paulius Zaleckas @ 2008-11-14 10:24 UTC (permalink / raw)
To: netdev; +Cc: linux-arm-kernel, linux-embedded
I think these patches are ready for merging to netdev-next.
If there is need I can merge these two patches to single.
Changes since v2:
- finished with rework patch
Changes since v1:
- broken to rename patch and mdio-gpio rework
---
Paulius Zaleckas (2):
phylib: make mdio-gpio work without OF (v4)
phylib: rename mdio-ofgpio to mdio-gpio
drivers/net/phy/Kconfig | 7 +
drivers/net/phy/Makefile | 2
drivers/net/phy/mdio-gpio.c | 296 +++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/mdio-ofgpio.c | 204 ----------------------------
include/linux/mdio-gpio.h | 25 +++
5 files changed, 327 insertions(+), 207 deletions(-)
create mode 100644 drivers/net/phy/mdio-gpio.c
delete mode 100644 drivers/net/phy/mdio-ofgpio.c
create mode 100644 include/linux/mdio-gpio.h
^ permalink raw reply
* Re: [PATCH] uio: add ioctl callback
From: Marco Stornelli @ 2008-11-12 14:33 UTC (permalink / raw)
To: narmstrong; +Cc: Embedded Linux mailing list
In-Reply-To: <491AE3F7.4050202@neotion.com>
Read the file SubmittingPatches in your kernel documentation folder
before sending a patch. In addition, check the patch with checkpatch
script. You can find the script in the script kernel folder. Send the
patch with the right destination. You can know the names (and emails) of
the maintainers in the MAINTAINER file in the kernel source.
Regards,
Marco
Neil Armstrong wrote:
> Add an ioctl callback to the UIO device class.
> This can be useful when status and data are needed after an interrupt
> occurs.
>
> Changes :
> - Add an uio_ioctl method
> - Add en ioctl entry in uio_info
>
> Neil Armstrong <narmstrong@neotion.com>
>
> Index: drivers/uio/uio.c
> ===================================================================
> --- drivers/uio/uio.c (revision 80)
> +++ drivers/uio/uio.c (working copy)
> @@ -378,6 +378,17 @@
> return 0;
> }
>
> +static int uio_ioctl(struct inode *inode, struct file *filep, unsigned
> int cmd, unsigned long arg)
> +{
> + struct uio_listener *listener = filep->private_data;
> + struct uio_device *idev = listener->dev;
> +
> + if (idev->info->ioctl)
> + return idev->info->ioctl(idev->info, cmd, arg);
> +
> + return -ENOSYS;
> +}
> +
> static ssize_t uio_read(struct file *filep, char __user *buf,
> size_t count, loff_t *ppos)
> {
> @@ -575,6 +586,7 @@
> .mmap = uio_mmap,
> .poll = uio_poll,
> .fasync = uio_fasync,
> + .ioctl = uio_ioctl,
> };
>
> static int uio_major_init(void)
> Index: include/linux/uio_driver.h
> ===================================================================
> --- include/linux/uio_driver.h (revision 80)
> +++ include/linux/uio_driver.h (working copy)
> @@ -68,6 +68,7 @@
> int (*open)(struct uio_info *info, struct inode *inode);
> int (*release)(struct uio_info *info, struct inode *inode);
> int (*irqcontrol)(struct uio_info *info, s32 irq_on);
> + int (*ioctl)(struct uio_info *info, unsigned int cmd, unsigned long
> arg);
> };
>
> extern int __must_check
>
^ permalink raw reply
* [PATCH] uio: add ioctl callback
From: Neil Armstrong @ 2008-11-12 14:11 UTC (permalink / raw)
To: Embedded Linux mailing list
[-- Attachment #1.1: Type: text/plain, Size: 1638 bytes --]
Add an ioctl callback to the UIO device class.
This can be useful when status and data are needed after an interrupt
occurs.
Changes :
- Add an uio_ioctl method
- Add en ioctl entry in uio_info
Neil Armstrong <narmstrong@neotion.com>
Index: drivers/uio/uio.c
===================================================================
--- drivers/uio/uio.c (revision 80)
+++ drivers/uio/uio.c (working copy)
@@ -378,6 +378,17 @@
return 0;
}
+static int uio_ioctl(struct inode *inode, struct file *filep, unsigned
int cmd, unsigned long arg)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+
+ if (idev->info->ioctl)
+ return idev->info->ioctl(idev->info, cmd, arg);
+
+ return -ENOSYS;
+}
+
static ssize_t uio_read(struct file *filep, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -575,6 +586,7 @@
.mmap = uio_mmap,
.poll = uio_poll,
.fasync = uio_fasync,
+ .ioctl = uio_ioctl,
};
static int uio_major_init(void)
Index: include/linux/uio_driver.h
===================================================================
--- include/linux/uio_driver.h (revision 80)
+++ include/linux/uio_driver.h (working copy)
@@ -68,6 +68,7 @@
int (*open)(struct uio_info *info, struct inode *inode);
int (*release)(struct uio_info *info, struct inode *inode);
int (*irqcontrol)(struct uio_info *info, s32 irq_on);
+ int (*ioctl)(struct uio_info *info, unsigned int cmd, unsigned long
arg);
};
extern int __must_check
[-- Attachment #1.2: narmstrong.vcf --]
[-- Type: text/x-vcard, Size: 319 bytes --]
begin:vcard
fn:Neil Armstrong
n:Armstrong;Neil
org:Neotion;Neotion Sophia Antipolis
adr:;;;Sophia Antipolis;;;France
email;internet:narmstrong@neotion.com
title:Embedded Linux Software Engineer
tel;cell:0667474169
note:PGP 0x1166F485
x-mozilla-html:FALSE
url:http://www.neotion.com
version:2.1
end:vcard
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]
^ permalink raw reply
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