* Re: [PATCH 00/11] RFC: KBUS messaging subsystem
From: Tony Ibbs @ 2011-08-03 20:23 UTC (permalink / raw)
To: Florian Fainelli
Cc: Jonathan Corbet, Grant Likely, lkml, Linux-embedded,
Tibs at Kynesim, Richard Watts
In-Reply-To: <201105171050.38903.florian@openwrt.org>
On 17 May 2011, at 09:50, Florian Fainelli wrote:
> Sorry for this late answer.
And apologies for my own late response. I'll try to keep this short as
I hope the "Restatement" side-thread will address some of it.
> On Tuesday 22 March 2011 20:36:40 Jonathan Corbet wrote:
>>
>> - Why kbus over, say, a user-space daemon and unix-domain sockets? I'm
>> not sure I see the advantage that comes with putting this into kernel
>> space.
>
> I also fail to see why this would be required. In my opininon you are trading
> the reliability over complexity by putting this in the kernel.
I hope that's addressed in the "So why did we write it as a kernel
module?" section of the "Restatement" message thread. Basically,
I believe a kernel module is smaller and "steals" reliability from
code written and tested by others. That doesn't mean it's a good
solution "in the wild", of course (privately we can add whatever we
want to the kernel, but in public it is and must be controlled).
> Indeed, I would also suggest having a look at what generic netlink already
> provides like messages per application PID, multicasting and marshaling. If
> you intend to keep a part of it in the kernel, you should have a look at this,
> because from my experience with generic netlink, most of the hard job you are
> re-doing here, has already been done in a generic manner.
If we do end up heading that way, I hope you won't mind if I ask
you for advice!
All the best,
Tibs
^ permalink raw reply
* Re: RFC: [Restatement] KBUS messaging subsystem
From: Tony Ibbs @ 2011-08-03 20:14 UTC (permalink / raw)
To: Colin Walters
Cc: lkml, Andrew Morton, Jonathan Corbet, Florian Fainelli,
Grant Likely, Linux-embedded, Tibs at Kynesim, Richard Watts
In-Reply-To: <CADkLE3XRg6N2cWHXH_JsU56tfw5v5XmJJLfLBM_RtWJRMcZWtA@mail.gmail.com>
Sorry for the delay in replying - the last several days have had no
free time at all (otherwise this would be shorter as well!).
On 29 Jul 2011, at 00:58, Colin Walters wrote:
> So, what I think your description of this project lacks is high-level
> technical requirements and goals;
Well. I thought that was what I was doing. Mea culpa.
> you mention basically just "deterministic ordering"
I'd count the following as our driving requirements/goals, although
this is really just a rephrasing of stuff from last message, so
apologies if I'm missing the point:
* deterministic message ordering (as defined last email)
* messages identified by name (i.e., something human readable and
potentially mnemonic, not just numbers)
* all messages visible to (can be received by) any interested party
(this can be particularly important for logging/diagnosis)
* recipient chooses which messages it is interested in
* only (at most!) one replier allowed for a particular message name
* no restriction on who can send messages
* guaranteed reply to a request (a legitimate reply being "the
designated replier has gone away")
* multiple buses allowed, messages do not move between buses
* a client can send/receive messages on the same connection
Those are the issues that give KBUS its particular flavour.
Implied by some of that is:
* no client/server model
* no timeouts (OK, I didn't say that last email, and it is fairly
unobviously implicit)
and not quite API:
* must be written in C
* must be a relatively small amount of code (yes, that's subjective)
* must be documented (although I'd take that as a given, and it can
always be done better)
* must have a relatively small API (again, subjective)
but I thought that was all in the last email. Sorry if it was unclear.
> and "easy API" (the latter being fairly subjective).
Yes, of course it is. But a simple system should be simpler to
explain/use than a complex one. Although I take your point further
down.
> You don't mention what your performance requirements are
> (if any) for example.
We don't particularly have any - we're nearer to user-reaction timing
than real-time issues. Some rough tests a while back indicated that
KBUS performed at about either half or double the speed of inotify
(sorry, I'm not at work so don't have the notes to hand) - so not
particularly fast. It was written to provide the functionality we
needed, with the intention to optimise as needed, and since it's been
fast enough, we've not tried to speed it up. Although I've strong
suspicions (*not* validated by testing, though, so not reliable) of
what is probably slow.
> If you had a high-level requirements list it might be easier to
> compare with other things.
> For example, you might ask "Why not SYSV IPC"?
I know this is probably a rhetorical question, but well, it's poorly
specified, too low level and doesn't do all the things we want (for
instance, how does one handle many-to-many transactions?).
> Or "why not drop files in a temporary directory and use
> inotify" etc.
Can we all say "ick" (although back in the day on IBM mainframes that
wasn't a bad way to do data passing, as the infrastructure existed to
allow one to know when directory contents changed in a fairly
efficient manner - I had a client using just such a mechanism for
passing around documents containing data reports).
> My feeling as a DBus developer is that by far its most important
> feature is providing a dynamic naming service (the RequestName call).
> I don't know how one could sanely do a general-purpose operating
> system without a way for loosely-coupled components to find each other
> at runtime. Things like Debian or Fedora where one can assemble
> arbitrary sets of packages basically demand the ability do to this -
> think things like X being able to talk to HAL, or Firefox being able
> to find NetworkManager.
That sounds like a good characterisation of the world DBus is trying
to work in.
> KBUS seems not to provide this (or at least, I'm not seeing it).
Exactly.
I'm not sure why people keep wanting to compare KBUS and DBus (maybe
my fault for the name), as their scopes are so different it feels
rather like comparing a bicycle with a bus company.
Anyway, from what I understand, DBus is an "enterprise" style solution
to messaging for major-level infrastructure - large systems such as
Gnome and its associated programs. As such its aim is to provide a
one-stop solution for all ones messaging needs, including:
* client name brokering (and the very existence of client naming)
* data schemas
* IPC (clearly a specialisation of the above)
* allowing/forbidding message receipt/transmission according to policy
* security policies (see below)
and so on.
These all sound like necessary things in the arena in which DBus is
used. They are not things that KBUS intends to provide. If such things
are needed, DBus already exists and is in common use.
So I would say that DBus is, of necessity, trying to find the maximal
solution for the problem space, so that users do not need to
learn/deploy more than one thing. This makes sense for what it is
trying to do.
(One could argue about whether it is better to have one large
system providing everything, or a small core and many extensions,
but experience shows that the one-large-system tends to win, as
for instance with EULisp versus Common Lisp, presumably for good
psychological reasons.)
KBUS, however, is trying to find the minimum that is useful for our
problem space, which is small systems oriented.
So it eschews data description. After all, not all messages *have*
data, and there are many good ways of describing data that already
exist (from ASN.1 to JSON to the google protocol descriptions).
KBUS provides a mechanism for choosing which messages to receive, and
who might reply to a particular message name. But it itself doesn't
provide a registry of allowed names. For many systems that would be
overkill, and if it is needed, then it can be done separately (often,
in fact, in paper specifications).
> DBus *does* have deterministic ordering too - I'm not sure why you
> say we don't.
That's good. I *thought* I'd said that I couldn't tell from the
documentation, but that there was one place that I'd seen that seemed
(possibly) to imply it couldn't.
> DBus does have some flaws - for example, the resource controls were
> poorly thought out and basically useless. If we were designing them
> today, we'd probably have DBus connections tied to Linux cgroups
> somehow.
Of course, cgroups have only recently begun to be adopted widely, and
presumably weren't around at all when DBus was started.
> KBUS from what I can see shares this flaw
Indeed. Since we've been using it on systems where we control the
system-as-a-whole, it was something we mostly didn't remember to worry
about, and that is a significant flaw, which has already been picked
up on lkml. Regardless of what happens in terms of adoption into the
kernel, it's something we have to address.
> A somewhat weaker but still useful part of DBus is that it has
> mandatory security controls; the policy can restrict which uids can
> talk to a given service on the bus, and also allows userspace to check
> the credentials of messages they receive (think SO_PEERCRED). By
> having KBUS based on files you seem to lose this which you'd get from
> a socket API.
Again, this is the sort of support one would want in a realistic
enterprise/large scale solution. It's also deliberately not part of
the KBUS design - we want any recipient to be able to receive any
messages (on a given bus). In that sense, KBUS is (by design)
inherently insecure.
> On a different topic, I find myself really unconvinced by the length
> to which you go to claim the API is simple and easy to use.
Point taken.
> I mean, I really can't imagine it'd be hard to write a userspace C
> library implementing the semantics you have here, and have it be as
> easy or easier. Oh you actually do have a "libkbus" here:
> http://code.google.com/p/kbus/source/browse/libkbus/kbus.h
I'm not sure what you mean by this. libkbus is a layer around the
"bare" usage of KBUS, allowing people to do the more common actions
without (for instance) fettling "errno" all over the place. It's
polite to provide that, as we do for Python (which was the first such
wrapper, so I could write unit tests easily) and C++ - but all of
those *are* just wrappers around the "bare" usage (the Java library is
different, since it's a wrapper around the C library, but that's Java
for you).
I am willing, however, to assert that it would have been harder to
write a C library that did this job in userspace, if only (and
trivially) because I would have had to write all the support code that
the kernel already supplies for me. And then debug it.
> You never mention what tradeoffs you might see from having that in
> userspace or whether you tried it for that matter.
Obviously we haven't tried rewriting KBUS in userspace for Linux. If
we ever ported the functionality to Windows (or BSD or Mac), then a
userspace solution would perhaps be necessary (I don't think it's
quite comparable), but on Linux, where we currently need it, the
solution we've got works well for us.
My belief is that a userspace solution would be less reliable (for one
thing, it's harder to reliably detect that a replier has crashed as
opposed to just being very busy for a moment). It would definitely be
larger.
That doesn't, of course, mean that *other people* will find KBUS
valuable in the kernel (as I think Grant Likely said, uplist, every
extra piece of code added to the kernel imposes a heavy maintenance
load, and so must be very carefully justified).
We've done the work for ourselves, and feel that KBUS provides
something the kernel might want (a simple, low-level messaging system
that is just enough higher level than what is already provided to be
useful), so it's worth our submitting it.
Anyway, thanks for taking the trouble to comment, and I hope this
all makes sense,
Tibs
^ permalink raw reply
* Re: RFC: [Restatement] KBUS messaging subsystem
From: Colin Walters @ 2011-07-28 23:58 UTC (permalink / raw)
To: Tony Ibbs
Cc: lkml, Andrew Morton, Jonathan Corbet, Florian Fainelli,
Grant Likely, Linux-embedded, Tibs at Kynesim, Richard Watts
In-Reply-To: <5F531701-B760-45F0-989D-669013409FE8@tonyibbs.co.uk>
Hi,
Quick background: I work on GNOME mainly, and have contributed various
bits of code to DBUS and made some releases historically (though that
is now in more capable hands). I should also note I have no patches
in the Linux kernel (but I'm trying to follow it more and participate,
so here I am).
So, what I think your description of this project lacks is high-level
technical requirements and goals; you mention basically just
"deterministic ordering" and "easy API" (the latter being fairly
subjective). You don't mention what your performance requirements are
(if any) for example.
If you had a high-level requirements list it might be easier to
compare with other things. For example, you might ask "Why not SYSV
IPC"? Or "why not drop files in a temporary directory and use
inotify" etc.
My feeling as a DBus developer is that by far its most important
feature is providing a dynamic naming service (the RequestName call).
I don't know how one could sanely do a general-purpose operating
system without a way for loosely-coupled components to find each other
at runtime. Things like Debian or Fedora where one can assemble
arbitrary sets of packages basically demand the ability do to this -
think things like X being able to talk to HAL, or Firefox being able
to find NetworkManager.
KBUS seems not to provide this (or at least, I'm not seeing it).
The other key feature is signals, where userspace can multicast to
userspace. KBUS does provide this.
DBus *does* have deterministic ordering too - I'm not sure why you say we don't.
DBus does have some flaws - for example, the resource controls were
poorly thought out and basically useless. If we were designing them
today, we'd probably have DBus connections tied to Linux cgroups
somehow. Currently the system bus is limited to a configured amount
of RAM in the XML config (and we don't even attempt to look at system
memory size to limit it); if you have less than 1G (if i remember
correctly) of phys+swap, you can make the bus OOM.
KBUS from what I can see shares this flaw, except that users allocate
arbitrary amounts of kernel memory rather than in userspace in the
system bus:
static ssize_t kbus_write() {
...
this->msg = kmalloc(sizeof(*(this->msg)), GFP_KERNEL);
if (!this->msg) {
retval = -ENOMEM;
goto done;
}
...
}
A somewhat weaker but still useful part of DBus is that it has
mandatory security controls; the policy can restrict which uids can
talk to a given service on the bus, and also allows userspace to check
the credentials of messages they receive (think SO_PEERCRED). By
having KBUS based on files you seem to lose this which you'd get from
a socket API.
On a different topic, I find myself really unconvinced by the length
to which you go to claim the API is simple and easy to use. I mean, I
really can't imagine it'd be hard to write a userspace C library
implementing the semantics you have here, and have it be as easy or
easier. Oh you actually do have a "libkbus" here:
http://code.google.com/p/kbus/source/browse/libkbus/kbus.h
You never mention what tradeoffs you might see from having that in
userspace or whether you tried it for that matter.
^ permalink raw reply
* RFC: [Restatement] KBUS messaging subsystem
From: Tony Ibbs @ 2011-07-28 21:48 UTC (permalink / raw)
To: lkml
Cc: Andrew Morton, Jonathan Corbet, Florian Fainelli, Grant Likely,
Linux-embedded, Tibs at Kynesim, Richard Watts
In-Reply-To: <201107061815.36294.florian@openwrt.org>
The company I work for does a fair amount of stuff on embedded
systems, and we often need a simple way to send interprocess
messages. DBUS is too large and complex for this, and the ad-hoc
solutions we've seen people develop normally have significant
problems. So we wrote our own. Since it's a kernel module, it seemed
appropriate to submit it for possible inclusion in Linux.
The original submission to the LKML is at
http://marc.info/?l=linux-kernel&m=130047040716848&w=2
Jonathan Corbet (22 Mar 2011, at 19:36) pointed out, though, that
> The interface is ... creative.
and on 15 Apr 2011, at 23:46, in response to a patch I wrote for a
particular issue, he wrote:
> I honestly think that the item at the top of your list, if you want
> to merge this code, must be to get the user-space API more widely
> reviewed and accepted. It could, I think, be a big sticking point,
> and it's something you want to try to address sooner rather than later.
>
> That means getting more people to look at the patch, which could be hard.
> The problem is that, if you wait, they'll only squeal when the code is
> close to going in, and you could find yourself set back a long way. A
> good first step might be to CC Andrew Morton on your next posting.
Other matters have caused this response to be a bit delayed, but he's
clearly right that this should be addressed. And whilst we ourselves
obviously don't mind the API, it's the functionality that we *really*
care about. So there are two questions
- is KBUS something that should be in the kernel, and if it is,
- should it have a different API?
What we want of the system
==========================
We want KBUS to be very quick to learn, and very simple to use, not
least because the target users are often already experts in several
domains, and they don't have time or effort available to spend on
learning a complex system just to send messages.
We provide user-space libraries in various languages (including C and
C++), but we also want KBUS to be simple to use "bare" - target
systems may be small, and may not have much user-space. This also
means that KBUS itself needs to be written in C.
Technically, the most important requirements are:
* We require deterministic message ordering. If A, B and C all send
messages, anyone receiving those messages must see them in the same
order, which must be the order they were sent in.
* Messages are identified by name. Names are formed of dot-separated
words.
* Listeners choose which messages they wish to receive, on the basis
of the message name. Some simple filtering is available by
wildcarding on the last word or words of the name.
* All messages are implicitly broadcast (to anyone who wishes to
receive them).
* Request/reply is handled by a single listener binding as a replier
to messages with a particular name. When a request message with that
name is sent, the replier is reponsible for sending a reply message.
(The request and reply are both still broadcast to any "normal"
listeners.)
* When a request message is sent, but a reply from the original
replier is not possible - e.g., if there is noone bound as replier,
or the original replier has unbound, or even crashed - then the
system will send a synthetic reply to indicate this. In informal
terms, the system guarantees a request will get a reply.
The system deliberately avoids a client/server model.
* Any client can be a sender and a listener on the same connection.
* KBUS makes no restriction on who sends messages with what names,
and it does not restrict who may send request messages.
Whilst requests are guaranteed to be sent to the appropriate recipient
(if they're still listening), "general" listening is by default lossy.
That is, if a listener's incoming message queue is full, then new
messages will by default be dropped (but not if they're a request to
that listener, of course). However, the sender of a message can
choose that all recipients must be able to receive a particular
message (sending with either all-or-fail or all-or-wait).
* KBUS does not say anything about the data (if any) in a message.
Different users have different requirements, so this gets
complicated very quickly, and there are many excellent independent
solutions for this.
* We do want support for multiple buses, which must be walled off from
each other. Naming them by anything complicated isn't needed.
So why did we write it as a kernel module?
==========================================
As implementors, a kernel module makes a lot of sense. Not least
because:
* It gives us a lot of things for free, including list handling,
reference counting, thread safety and (on larger systems)
multi-processor support, which we would otherwise have to write and
debug ourselves. This also keeps our codebase smaller.
* It helps give us reliability, partly because of the code we're
relying on, partly because of the strictures of working in the
kernel, partly by shielding us from userspace.
* It reduces message copying (we have userspace to kernel back to
userspace, as opposed to a userspace daemon communicating with
clients via sockets)
* It makes it simple for us to tell when a message recipient has "gone
away", as the kernel will call our "release" callback for us.
* It allows us to provide the functionality on systems without
requiring anything much beyond /dev and maybe /proc in userspace.
Since our potential users are generally all building Linux anyway,
adding an extra kernel module is not an issue.
The API
=======
KBUS as written uses the file API. KBUS bus <n> is represented as
device file /dev/kbus<n>. Bus 0 is always present.
So a client connects to KBUS by calling "open" on the appropriate
device file, and disconnects with "close". Messages are sent by
writing the appropriate data to the device using "write", and using a
SEND ioctl to indicate that the message is to be sent [1]. Messages
are read by calling an ioctl to find the length of the next message
(0 if there is none), and then reading it using "read". Polling may be
used to wait for a message read/write in the normal manner.
[1] It has already been suggested that the SEND is not needed given
that the end of a message is deterministic, but it mirrors the
"is there a next message" ioctl, and felt tidier to us than
producing a "can't send" error when the write(s) for the message
data are finished.
I believe that this use of the file API is what Jonathan Corbet calls
"creative" (we can't disagree with him).
We chose this interface for several reasons:
* All C programmers are likely to have used open/close/read/write at
some time, and even if they've not used ioctls, our target audience
will have called functions with arbitrary datastructures.
* We didn't want to (try to) add a new specific API to the kernel
(I assume that is a luxury whose day has long gone).
* The socket model didn't seem like a good fit to us, not least
because we did not want a client/server model.
* There is a lot of information on how to write a file-based kernel
module, including many examples.
* It is obvious that the "release" callback for a "file" will be
called when the file is closed or the opening process crashes.
I must admit that, this being my first kernel module, the "lots of
documentation and examples" influenced me.
Several people on-list have wondered why we didn't use some socket
interface. This seems partly to be based on the assumption that
"everyone knows how to do sockets" (I may be being unfair, here),
which is not in fact true - many C programmers have not worked with
sockets.
I'm not aware of any good explanations of how to do a socket based
interface to a kernel module, and particularly not of documentation of
how one *should* do it. Mea culpa if I've just looked in the wrong
places.
The interactions we'd *like* our API to have go more-or-less thus:
* Send: either manufacture an entire message, pass it to KBUS,
and then send it, or pass parts of a message to KBUS, and when all
of the parts have been given, send it. This latter allows (for
instance) a common header to be written repeatedly, followed by
varying data.
* Read: Ask for (the size of) the next message. A size of 0 can
conveniently be taken as meaning there is no next message. Then, as
a separate call, read that many bytes.
* Discard a message that is waiting to be read. Current KBUS does this
by asking for (the size of) the next message again, without an
intermediate read.
* Poll for the next message to be read. Obviously useful.
* Poll for being allowed to send a new message. This is useful if a
send was rejected, perhaps because it was a request message, and
the replier does not have room in their queue for it.
As I said earlier, I'm not sure how one would write a kernel module
with a socket-style API that does what KBUS does, although clearly one
could imagine such a thing. I must admit that our feeling is that it
would be "stretching" the normal assumptions of how sockets work in
much the same way that the current API is doing for the file-like
interface.
What already exists
===================
There is a general KBUS homepage at http://kbus-messaging.org/.
The version of KBUS on Google Code, at http://code.google.com/p/kbus/,
is used by several clients of ours, and includes a "higher level" C
library, plus bindings for Python, C++ and Java.
There is a working repository with these patches applied to
Linux 2.6.37, available via:
git pull git://github.com/crazyscot/linux-2.6-kbus.git kbus-2.6.37
The original patches were applied in branch apply-patchset-20110318
--
Tibs
^ permalink raw reply
* Re: Flash filesystems benchmarks
From: David Wagner @ 2011-07-28 20:05 UTC (permalink / raw)
To: Belisko Marek; +Cc: linux-mtd@lists.infradead.org, Linux Embedded, tim.bird
In-Reply-To: <CAAfyv35zgDLpf6Hs0G0wESh0-BjoiWMH+4wA7+anSwR0rREtbA@mail.gmail.com>
Hi,
On 28/07/2011 21:14, Belisko Marek wrote:
> Hi,
> Great job ;). Maybe small README how to use scripts. I try to run
> ./performance-test.py but got en error because test.cfg doesn't exist.
> Shouldn't there be input argument for specific board something like:
> [...]
Thanks for the feedback. You're right, READMEs are missing ; they'll come.
The current procedure, regarding the configuration file, is:
* write a configuration file (like those already provided as examples)
* cp it to test.cfg
* launch performance-test.py
why the cp ? because it allows to tweak it without changing the original.
But it would certainly be best to use a proper argument parsing
(argparse, like for gnuplotize_*.py and generate_graphs.py) and have an
optional configuration file.
The material and documentation to reproduce the tests isn't fully
available yet but will be very soon. I can already give you a link to
the debian root filesystem (to be exported through NFS) that was used ;
however I can't guarantee yet that it will work.
http://free-electrons.com/~david/pub/RFS-benchmarks.tar.lzma (1.1GB)
David.
--
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: Flash filesystems benchmarks
From: Belisko Marek @ 2011-07-28 19:14 UTC (permalink / raw)
To: David Wagner; +Cc: linux-mtd@lists.infradead.org, Linux Embedded, tim.bird
In-Reply-To: <4E3131AE.7010408@free-electrons.com>
Hi,
On Thu, Jul 28, 2011 at 11:53 AM, David Wagner
<david.wagner@free-electrons.com> wrote:
> Hello,
>
> As a contract with the CELF, we (Free Electrons) developed a flash
> filesystem benchmarking suite ; it tests ubifs, jffs2, yaffs2 and
> squashfs(over UBI+two different block transition layers). It has been
> run on a Calao USB-9263 board and a IGEPv2 board and on 2.6.38, .39 and
> 3.0 kernels.
>
> The results are shown as histograms and two different reportings exists:
> * filesystem comparison for a given board/kernel couple
> * kernel comparison for a given board/filesystem couple
>
> All the details are to be found at:
> http://elinux.org/Flash_Filesystem_Benchmarks
> Direct link to the test protocol:
> http://elinux.org/Flash_Filesystem_Benchmarks_Protocol
> Link to the gitorious page:
> https://gitorious.org/ffs-benchmarks/ffs-benchmarks
>
> Reviews of the test protocol, pointers to incoherent results or any
> other comment is welcome.
> We will keep posting more results.
Great job ;). Maybe small README how to use scripts. I try to run
./performance-test.py but got en error because test.cfg doesn't exist.
Shouldn't there be input argument for specific board something like:
diff --git a/performance-tests.py b/performance-tests.py
index 78c83f0..33a4292 100755
--- a/performance-tests.py
+++ b/performance-tests.py
@@ -168,7 +168,12 @@ def main():
global cur
cfg = ConfigParser.ConfigParser()
- cfg.read('test.cfg')
+
+ if (len(sys.argv) < 2):
+ print "board configuration parameter missing!!!"
+ return
+
+ cfg.read(sys.argv[1])
board_name = cfg.defaults()['board_name']
version = cfg.defaults()['version']
>
>
> David Wagner
>
> --
> David Wagner, Free Electrons
> Kernel, drivers, real-time and embedded Linux
> development, consulting, training and support.
> http://free-electrons.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-embedded" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
thanks,
marek
--
as simple and primitive as possible
-------------------------------------------------
Marek Belisko - OPEN-NANDRA
Freelance Developer
Ruska Nova Ves 219 | Presov, 08005 Slovak Republic
Tel: +421 915 052 184
skype: marekwhite
icq: 290551086
web: http://open-nandra.com
^ permalink raw reply related
* Flash filesystems benchmarks
From: David Wagner @ 2011-07-28 9:53 UTC (permalink / raw)
To: linux-mtd@lists.infradead.org, Linux Embedded; +Cc: tim.bird
Hello,
As a contract with the CELF, we (Free Electrons) developed a flash
filesystem benchmarking suite ; it tests ubifs, jffs2, yaffs2 and
squashfs(over UBI+two different block transition layers). It has been
run on a Calao USB-9263 board and a IGEPv2 board and on 2.6.38, .39 and
3.0 kernels.
The results are shown as histograms and two different reportings exists:
* filesystem comparison for a given board/kernel couple
* kernel comparison for a given board/filesystem couple
All the details are to be found at:
http://elinux.org/Flash_Filesystem_Benchmarks
Direct link to the test protocol:
http://elinux.org/Flash_Filesystem_Benchmarks_Protocol
Link to the gitorious page:
https://gitorious.org/ffs-benchmarks/ffs-benchmarks
Reviews of the test protocol, pointers to incoherent results or any
other comment is welcome.
We will keep posting more results.
David Wagner
--
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH] UBI: new module ubiblk: block layer on top of UBI
From: Artem Bityutskiy @ 2011-07-28 6:14 UTC (permalink / raw)
To: David Wagner; +Cc: linux-mtd, dwmw2, linux-kernel, linux-embedded, tim.bird
In-Reply-To: <1311683250-7921-1-git-send-email-david.wagner@free-electrons.com>
On Tue, 2011-07-26 at 14:27 +0200, David Wagner wrote:
> * The numbering of devices is much easier with ubiblk than with
> gluebi+mtdblock_ro. With gluebi+mtdblock_ro, you get one additional
> MTD device for each UBI volume, so the number of MTD devices grows
> quite a lot and is a bit difficult to understand. For example,
> mtdblock[0-4] might be your real MTD partitions, while mtdblock[5-9]
> might be your UBI volumes.
> It also means that if a new real MTD
> partition is added, the number of all the MTD devices exposing UBI
> volumes will be incremented by one, which is a bit
> confusing/annoying.
> As well, if you add an UBI volume, the mtdblock devices that are
> emulated on top of volumes that come after this new one will have
> their ID incremented.
>
> * The performance appears to be slightly better with ubiblk than
> gluebi+mtdblock_ro, according to our benchmarks (see
> http://elinux.org/Flash_Filesystem_Benchmarks_2.6.39)
Hi, I am having vacation till the middle of August and I do not have a
possibility to look at UBI/UBIFS/MTD stuff now, sorry. When I come back,
I'll go through my e-mails and respond. Apologies again.
--
Best Regards,
Artem Bityutskiy (Битюцкий Артём)
^ permalink raw reply
* Re: [PATCH] UBI: new module ubiblk: block layer on top of UBI
From: David Wagner @ 2011-07-26 12:58 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linux-mtd, dedekind1, dwmw2, linux-kernel, linux-embedded,
tim.bird
In-Reply-To: <20110726123453.GA18513@infradead.org>
On 07/26/2011 02:34 PM, Christoph Hellwig wrote:
>> TODO:
>> * the modules keeps a table of the devices which length is the
maximum number
>> of UBI volumes. It should make use of a linked list.
>
> A linked list isn't very nice either. Try using idr, which gives you
> both an allocator for the minor number space, and a way to look up
> the structure by that index.
>
I'll take a look ; is it really worth it, though ? I look in the table
only when a volume is created, resized, or removed (that is, rarely) and
there are really few items (I bet, between 1 and 8 ; max possible is 4096).
>> Advantages of ubiblk over gluebi+mtdblock_ro:
>
> This section should be in the main commit log, and not that part with
> the changelog which gets dropped.
Will do.
>> +int major;
>
> Please don't use global variables with generic names. In this case you
> should neither make it global nor give it a generic name.
>
fixed.
Thank you for your feedback :)
--
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH] UBI: new module ubiblk: block layer on top of UBI
From: Christoph Hellwig @ 2011-07-26 12:34 UTC (permalink / raw)
To: David Wagner
Cc: linux-embedded, dedekind1, linux-kernel, linux-mtd, tim.bird,
dwmw2
In-Reply-To: <1311683250-7921-1-git-send-email-david.wagner@free-electrons.com>
> TODO:
> * the modules keeps a table of the devices which length is the maximum number
> of UBI volumes. It should make use of a linked list.
A linked list isn't very nice either. Try using idr, which gives you
both an allocator for the minor number space, and a way to look up
the structure by that index.
> Advantages of ubiblk over gluebi+mtdblock_ro:
This section should be in the main commit log, and not that part with
the changelog which gets dropped.
> +int major;
Please don't use global variables with generic names. In this case you
should neither make it global nor give it a generic name.
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* [PATCH] UBI: new module ubiblk: block layer on top of UBI
From: David Wagner @ 2011-07-26 12:27 UTC (permalink / raw)
To: linux-mtd
Cc: dedekind1, dwmw2, linux-kernel, linux-embedded, tim.bird,
David Wagner
In-Reply-To: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
ubiblk is a read-only block layer on top of UBI. It presents UBI volumes as
read-only block devices.
It is used by putting a block filesystem image on a UBI volume and then mounting
the corresponding device (/dev/ubiblkX_Y where X is the UBI device number and Y
the volume ID).
It uses the UBI API to register to UBI notifications (to dynamically create and
delete devices as volumes are added or removed) and to read from the volumes.
Some code is taken from mtd_blkdevs and gluebi
TODO:
* the modules keeps a table of the devices which length is the maximum number
of UBI volumes. It should make use of a linked list.
Signed-off-by: David Wagner <david.wagner@free-electrons.com>
---
updates from v2:
* Added copyright information
* Simplify the do_ubiblk_request loop
* Fix a crash at module exit
Advantages of ubiblk over gluebi+mtdblock_ro:
* Simpler architecture
* The numbering of devices is much easier with ubiblk than with
gluebi+mtdblock_ro. With gluebi+mtdblock_ro, you get one additional
MTD device for each UBI volume, so the number of MTD devices grows
quite a lot and is a bit difficult to understand. For example,
mtdblock[0-4] might be your real MTD partitions, while mtdblock[5-9]
might be your UBI volumes.
It also means that if a new real MTD
partition is added, the number of all the MTD devices exposing UBI
volumes will be incremented by one, which is a bit
confusing/annoying.
As well, if you add an UBI volume, the mtdblock devices that are
emulated on top of volumes that come after this new one will have
their ID incremented.
* The performance appears to be slightly better with ubiblk than
gluebi+mtdblock_ro, according to our benchmarks (see
http://elinux.org/Flash_Filesystem_Benchmarks_2.6.39)
drivers/mtd/ubi/Kconfig | 12 +
drivers/mtd/ubi/Makefile | 1 +
drivers/mtd/ubi/ubiblk.c | 556 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 569 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/ubi/ubiblk.c
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 4dcc752..d19508b 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -60,4 +60,16 @@ config MTD_UBI_DEBUG
help
This option enables UBI debugging.
+config MTD_UBI_UBIBLK
+ tristate "Read-only block transition layer on top of UBI"
+ help
+ Read-only block interface on top of UBI.
+
+ This option adds ubiblk, which creates a read-ony block device for
+ each UBI volume. It makes it possible to use block filesystems on
+ top of UBI (and thus, on top of MTDs while avoiding bad blocks).
+
+ The devices are named ubiblkX_Y where X is the UBI number and Y is
+ the Volume ID.
+
endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index c9302a5..354b2df 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -5,3 +5,4 @@ ubi-y += misc.o
ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+obj-$(CONFIG_MTD_UBI_UBIBLK) += ubiblk.o
diff --git a/drivers/mtd/ubi/ubiblk.c b/drivers/mtd/ubi/ubiblk.c
new file mode 100644
index 0000000..bbf5b84
--- /dev/null
+++ b/drivers/mtd/ubi/ubiblk.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) Free Electrons, 2011
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * 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
+ *
+ * Author: David Wagner
+ * Some code taken from gluebi.c (Artem Bityutskiy (Битюцкий Артём),
+ * Joern Engel)
+ * Some code taken from mtd_blkdevs.c (David Woodhouse)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/ubi.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include "ubi.h"
+
+#define BLK_SIZE 512
+
+#define UBIBLK_MAX_DEVS (UBI_MAX_DEVICES * UBI_MAX_VOLUMES)
+
+/*
+ * Structure representing a ubiblk device, proxying a UBI volume
+ */
+struct ubiblk_dev {
+ struct ubi_volume_desc *vol_desc;
+ struct ubi_volume_info *vol_info;
+ int ubi_num;
+ int vol_id;
+
+ /* Block stuff */
+ struct gendisk *gd;
+ struct request_queue *rq;
+ struct task_struct *thread;
+
+ /* Protects the access to the UBI volume */
+ struct mutex lock;
+
+ /* Avoids concurrent accesses to the request queue */
+ spinlock_t queue_lock;
+};
+
+/*
+ * Contains the pointers to all ubiblk_dev instances
+ * TODO: use a linked list
+ */
+static struct ubiblk_dev *ubiblk_devs[UBIBLK_MAX_DEVS];
+static struct mutex devtable_lock;
+
+int major;
+static const struct block_device_operations ubiblk_ops;
+
+static struct ubiblk_dev *ubiblk_find_dev(struct ubi_volume_info *vol_info)
+{
+ int i;
+ struct ubiblk_dev *dev;
+
+ mutex_lock(&devtable_lock);
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+ dev = ubiblk_devs[i];
+ if (dev && dev->ubi_num == vol_info->ubi_num &&
+ dev->vol_id == vol_info->vol_id)
+ break;
+ }
+ mutex_unlock(&devtable_lock);
+ if (i == UBIBLK_MAX_DEVS)
+ return NULL;
+ return dev;
+}
+
+/*
+ * Read a LEB and fill the request buffer with the requested sector
+ */
+static int do_ubiblk_request(struct request *req, struct ubiblk_dev *dev)
+{
+ unsigned long start, len, read_bytes;
+ int offset;
+ int leb;
+ int ret;
+
+ start = blk_rq_pos(req) << 9;
+ len = blk_rq_cur_bytes(req);
+ read_bytes = 0;
+
+ /* We are always reading. No need to handle writing for now */
+
+ leb = start / dev->vol_info->usable_leb_size;
+ offset = start % dev->vol_info->usable_leb_size;
+
+ do {
+ if (offset + len > dev->vol_info->usable_leb_size)
+ len = dev->vol_info->usable_leb_size - offset;
+
+ if (unlikely(blk_rq_pos(req) + blk_rq_cur_sectors(req) >
+ get_capacity(req->rq_disk))) {
+ pr_err("UBIBLK: attempting to read too far\n");
+ return -EIO;
+ }
+
+ pr_debug("%s(%s) of sector %llu (LEB %d). offset=%d, len=%lu\n",
+ __func__, rq_data_dir(req) ? "Write" : "Read",
+ blk_rq_pos(req), leb, offset, len);
+
+ /* Read (len) bytes of LEB (leb) from (offset) and put the
+ * result in the buffer given by the request.
+ * If the request is overlapping on several lebs, (read_bytes)
+ * will be > 0 and the data will be put in the buffer at
+ * offset (read_bytes)
+ */
+ ret = ubi_read(dev->vol_desc, leb, req->buffer + read_bytes,
+ offset, len);
+
+ if (ret) {
+ pr_err("ubi_read error\n");
+ return ret;
+ }
+
+ read_bytes += len;
+
+ len = blk_rq_cur_bytes(req) - read_bytes;
+ leb++;
+ offset = 0;
+ } while (read_bytes < blk_rq_cur_bytes(req));
+
+ pr_debug("ubi_read done.\n");
+
+ return 0;
+}
+
+static void ubi_ubiblk_request(struct request_queue *rq)
+{
+ struct ubiblk_dev *dev;
+ struct request *req = NULL;
+
+ dev = rq->queuedata;
+
+ if (!dev)
+ while ((req = blk_fetch_request(rq)) != NULL)
+ __blk_end_request_all(req, -ENODEV);
+ else
+ wake_up_process(dev->thread);
+}
+
+/*
+ * Open a UBI volume (get the volume descriptor)
+ */
+static int ubiblk_open(struct block_device *bdev, fmode_t mode)
+{
+ struct ubiblk_dev *dev = bdev->bd_disk->private_data;
+ pr_debug("%s() disk_name=%s, mode=%d\n", __func__,
+ bdev->bd_disk->disk_name, mode);
+
+ dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+ UBI_READONLY);
+ if (!dev->vol_desc) {
+ pr_err("open_volume failed");
+ return -EINVAL;
+ }
+
+ dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+ if (!dev->vol_info) {
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ return -ENOMEM;
+ }
+ ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+ return 0;
+}
+
+/*
+ * Close a UBI volume (close the volume descriptor)
+ */
+static int ubiblk_release(struct gendisk *gd, fmode_t mode)
+{
+ struct ubiblk_dev *dev = gd->private_data;
+ pr_debug("%s() disk_name=%s, mode=%d\n", __func__, gd->disk_name, mode);
+
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+ if (dev->vol_desc) {
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * Loop on the block request queue and wait for new requests ; run them with
+ * do_ubiblk_request()
+ *
+ * Mostly copied from mtd_blkdevs.c
+ */
+static int ubi_ubiblk_thread(void *arg)
+{
+ struct ubiblk_dev *dev = arg;
+ struct request_queue *rq = dev->rq;
+ struct request *req = NULL;
+
+ spin_lock_irq(rq->queue_lock);
+
+ while (!kthread_should_stop()) {
+ int res;
+
+ if (!req && !(req = blk_fetch_request(rq))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (kthread_should_stop())
+ set_current_state(TASK_RUNNING);
+
+ spin_unlock_irq(rq->queue_lock);
+ schedule();
+ spin_lock_irq(rq->queue_lock);
+ continue;
+ }
+
+ spin_unlock_irq(rq->queue_lock);
+
+ mutex_lock(&dev->lock);
+ res = do_ubiblk_request(req, dev);
+ pr_debug("return from request: %d\n", res);
+ mutex_unlock(&dev->lock);
+
+ spin_lock_irq(rq->queue_lock);
+
+ if (!__blk_end_request_cur(req, res))
+ req = NULL;
+ }
+
+ if (req)
+ __blk_end_request_all(req, -EIO);
+
+ spin_unlock_irq(rq->queue_lock);
+
+ return 0;
+}
+
+/*
+ * An UBI volume has been created ; create a corresponding ubiblk device:
+ * Initialize the locks, the structure, the block layer infos and start a
+ * thread.
+ */
+static int ubiblk_create(struct ubi_device_info *dev_info,
+ struct ubi_volume_info *vol_info)
+{
+ struct ubiblk_dev *dev;
+ struct gendisk *gd;
+ int i;
+ int ret = 0;
+
+ mutex_lock(&devtable_lock);
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++)
+ if (!ubiblk_devs[i])
+ break;
+
+ if (i == UBIBLK_MAX_DEVS) {
+ /* Shouldn't happen: UBI can't make more volumes than that */
+ pr_err("no slot left for a new ubiblk device.\n");
+ mutex_unlock(&devtable_lock);
+ return -ENOMEM;
+ }
+
+ dev = kzalloc(sizeof(struct ubiblk_dev), GFP_KERNEL);
+ if (!dev) {
+ pr_err("UBIBLK: ENOMEM when trying to create a new"
+ "ubiblk dev\n");
+ mutex_unlock(&devtable_lock);
+ return -ENOMEM;
+ }
+ ubiblk_devs[i] = dev;
+ mutex_unlock(&devtable_lock);
+
+ mutex_init(&dev->lock);
+ mutex_lock(&dev->lock);
+
+ dev->ubi_num = vol_info->ubi_num;
+ dev->vol_id = vol_info->vol_id;
+
+ dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+ UBI_READONLY);
+ if (IS_ERR(dev->vol_desc)) {
+ pr_err("open_volume failed\n");
+ ret = PTR_ERR(dev->vol_desc);
+ goto out_vol;
+ }
+
+ dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+ if (!dev->vol_info) {
+ ret = -ENOMEM;
+ goto out_info;
+ }
+ ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+ pr_info("Got volume %s: device %d/volume %d of size %d\n",
+ dev->vol_info->name, dev->ubi_num, dev->vol_id,
+ dev->vol_info->size);
+
+ /* Initialize the gendisk of this ubiblk device */
+ gd = alloc_disk(1);
+ if (!gd) {
+ pr_err("alloc_disk failed\n");
+ ret = -ENODEV;
+ goto out_disk;
+ }
+
+ gd->fops = &ubiblk_ops;
+ gd->major = major;
+ gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+ gd->private_data = dev;
+ sprintf(gd->disk_name, "ubiblk%d_%d", dev->ubi_num, dev->vol_id);
+ pr_debug("creating a gd '%s'\n", gd->disk_name);
+ set_capacity(gd,
+ (dev->vol_info->size *
+ dev->vol_info->usable_leb_size) >> 9);
+ set_disk_ro(gd, 1);
+ dev->gd = gd;
+
+ spin_lock_init(&dev->queue_lock);
+ dev->rq = blk_init_queue(ubi_ubiblk_request, &dev->queue_lock);
+ if (!dev->rq) {
+ pr_err("init_queue failed\n");
+ ret = -ENODEV;
+ goto out_queue;
+ }
+ dev->rq->queuedata = dev;
+ blk_queue_logical_block_size(dev->rq, BLK_SIZE);
+ dev->gd->queue = dev->rq;
+
+ /* Stolen from mtd_blkdevs.c */
+ /* Create processing thread
+ *
+ * The processing of the request has to be done in process context (it
+ * might sleep) but blk_run_queue can't block ; so we need to separate
+ * the event of a request being added to the queue (which triggers the
+ * callback ubi_ubiblk_request - that is set with blk_init_queue())
+ * and the processing of that request.
+ *
+ * Thus, the sole purpose of ubi_ubiblk_reuqest is to wake the kthread
+ * up so that it will process the request queue
+ */
+ dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
+ "kubiblk", dev->ubi_num, dev->vol_id);
+ if (IS_ERR(dev->thread)) {
+ ret = PTR_ERR(dev->thread);
+ goto out_thread;
+ }
+
+ add_disk(dev->gd);
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ mutex_unlock(&dev->lock);
+
+ return 0;
+
+out_thread:
+ blk_cleanup_queue(dev->rq);
+out_queue:
+ put_disk(dev->gd);
+out_disk:
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+out_info:
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+out_vol:
+ mutex_unlock(&dev->lock);
+
+ return ret;
+}
+
+/*
+ * A UBI has been removed ; destroy the corresponding ubiblk device
+ */
+static int ubiblk_remove(struct ubi_volume_info *vol_info)
+{
+ int i;
+ struct ubiblk_dev *dev;
+
+ mutex_lock(&devtable_lock);
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+ dev = ubiblk_devs[i];
+ if (dev && dev->ubi_num == vol_info->ubi_num &&
+ dev->vol_id == vol_info->vol_id)
+ break;
+ }
+ if (i == UBIBLK_MAX_DEVS) {
+ pr_warn("Trying to remove %s, which is unknown from ubiblk\n",
+ vol_info->name);
+ return -ENODEV;
+ }
+
+ pr_info("ubiblk: Removing %s\n", vol_info->name);
+
+ if (dev->vol_desc) {
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ }
+
+ del_gendisk(dev->gd);
+ blk_cleanup_queue(dev->rq);
+ kthread_stop(dev->thread);
+ put_disk(dev->gd);
+
+ kfree(dev->vol_info);
+
+ kfree(ubiblk_devs[i]);
+ ubiblk_devs[i] = NULL;
+
+ mutex_unlock(&devtable_lock);
+ return 0;
+}
+
+static int ubiblk_resized(struct ubi_volume_info *vol_info)
+{
+ struct ubiblk_dev *dev;
+
+ dev = ubiblk_find_dev(vol_info);
+ if (!dev) {
+ pr_warn("Trying to resize %s, which is unknown from ubiblk\n",
+ vol_info->name);
+ return -ENODEV;
+ }
+
+ mutex_lock(&dev->lock);
+ set_capacity(dev->gd,
+ (vol_info->size * vol_info->usable_leb_size) >> 9);
+ mutex_unlock(&dev->lock);
+ pr_debug("Resized ubiblk%d_%d to %d LEBs\n", vol_info->ubi_num,
+ vol_info->vol_id, vol_info->size);
+ return 0;
+}
+
+/*
+ * Dispatches the UBI notifications
+ * copied from gluebi.c
+ */
+static int ubiblk_notify(struct notifier_block *nb,
+ unsigned long notification_type, void *ns_ptr)
+{
+ struct ubi_notification *nt = ns_ptr;
+
+ switch (notification_type) {
+ case UBI_VOLUME_ADDED:
+ ubiblk_create(&nt->di, &nt->vi);
+ break;
+ case UBI_VOLUME_REMOVED:
+ ubiblk_remove(&nt->vi);
+ break;
+ case UBI_VOLUME_RESIZED:
+ ubiblk_resized(&nt->vi);
+ break;
+ case UBI_VOLUME_UPDATED:
+ break;
+ case UBI_VOLUME_RENAMED:
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static const struct block_device_operations ubiblk_ops = {
+ .owner = THIS_MODULE,
+ .open = ubiblk_open,
+ .release = ubiblk_release,
+};
+
+static struct notifier_block ubiblk_notifier = {
+ .notifier_call = ubiblk_notify,
+};
+
+/*
+ * Initialize the module
+ * (Get a major number and register to UBI notifications)
+ */
+static int __init ubi_ubiblk_init(void)
+{
+ int ret = 0;
+
+ pr_info("UBIBLK starting\n");
+
+ ret = register_blkdev(0, "ubiblk");
+ if (ret <= 0) {
+ pr_err("UBIBLK: could not register_blkdev\n");
+ return -ENODEV;
+ }
+ major = ret;
+ pr_info("UBIBLK: device's major: %d\n", major);
+
+ mutex_init(&devtable_lock);
+ ret = ubi_register_volume_notifier(&ubiblk_notifier, 0);
+ if (ret < 0)
+ unregister_blkdev(major, "ubiblk");
+
+ return ret;
+}
+
+/*
+ * End of life
+ * unregister the block device major, unregister from UBI notifications,
+ * stop the threads and free the memory.
+ */
+static void __exit ubi_ubiblk_exit(void)
+{
+ int i;
+
+ pr_info("UBIBLK: going to exit\n");
+
+ ubi_unregister_volume_notifier(&ubiblk_notifier);
+
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+ struct ubiblk_dev *dev = ubiblk_devs[i];
+ if (!dev)
+ continue;
+
+ if (dev->vol_desc)
+ ubi_close_volume(dev->vol_desc);
+
+ del_gendisk(dev->gd);
+ blk_cleanup_queue(dev->rq);
+ kthread_stop(dev->thread);
+ put_disk(dev->gd);
+
+ kfree(dev->vol_info);
+ kfree(ubiblk_devs[i]);
+ }
+
+ unregister_blkdev(major, "ubiblk");
+ pr_info("UBIBLK: The End\n");
+}
+
+module_init(ubi_ubiblk_init);
+module_exit(ubi_ubiblk_exit);
+MODULE_DESCRIPTION("Read-only block transition layer on top of UBI");
+MODULE_AUTHOR("David Wagner");
+MODULE_LICENSE("GPL");
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 00/11] RFC: KBUS messaging subsystem
From: Florian Fainelli @ 2011-07-06 16:15 UTC (permalink / raw)
To: Tony Ibbs
Cc: Jonathan Corbet, Grant Likely, lkml, Linux-embedded,
Tibs at Kynesim, Richard Watts
In-Reply-To: <37F5AF18-99E5-4516-B31F-00F7BD348ADE@tonyibbs.co.uk>
Hello Tony,
On Sunday 22 May 2011 21:58:13 Tony Ibbs wrote:
> On 17 May 2011, at 09:50, Florian Fainelli wrote:
> > Hello,
> >
> > Sorry for this late answer.
>
> Not a problem from here, all responses are helpful. In, turn, apologies
> for taking so long to reply.
My answer is also pretty late, sorry about that.
>
> > Most implementations (if not all) involving system-wide message
> > delivery for other daemons are running in user-space.
>
> OK. Although I certainly wouldn't claim to have anywhere near a complete
> list of such (an annotated list of all the messaging systems on Linux
> would be rather interesting, though!).
Here is a non-exhaustive one:
- ubus: http://nbd.name/gitweb.cgi?p=luci2/ubus.git;a=summary
- dbus
and at least another one I am using at work.
One thing that I missed while mentionning that I prefer an userland
implementation, is that you allow several interesting features to be available
such as:
- peer to peer between two daemons
- shared memory support between two daemons
The later specifically is interesting if you need to transfer large amounts of
data like images.
>
> > If you had in mind that this daemon might be killed under OOM
> > conditions, then maybe your whole system has an issue, which
> > could be circumvented by making sure the messaging process gets
> > respawned when possible (upstart like mechanism or such).
>
> OOM isn't particularly an issue I'd worried about for any part of the
> system. Other things tend to cause user processes to crash - using
> ffmpeg on random video data, for instance. Of course, that is clearly
> not a problem for KBUS itself.
>
> Respawning itself isn't directly a problem, but getting everyone talking
> to everyone else again is typically a nasty pain (and one users don't
> want to think about), so one tends to want one's messaging handler to be
> *very* robust. I think the discipline of working in-kernel helps with
> that, although I'd be surprised if that were considered enough reason to
> add a new kernel module!
Even if a program which is implementing some KBUS methods is crashing, and
then restarting, I see two methods to deal with this:
- the caller of the remote kbus method should be made aware that its endpoint
is not connected and deal with the error
- the respawning program, once registering back on the bus "server" should
cause the bus server to emit a signal "program-xyz" is back online
It seems to me that we achieve the reliable feature that you want, without
still making the kernel responsible for this.
Needless to say, there should be some respawning mechanism (ala upstart).
>
> > From: Jonathan Corbet <corbet@lwn.net>
> > Date: 22 March 2011 19:36:40 GMT
> >
> > > Even better might be to just use the socket API.
> >
> > Indeed, I would also suggest having a look at what generic netlink
> > already provides like messages per application PID, multicasting and
> > marshaling.
>
> As I said in an earlier message, I'd ignored netlink because it sounded
> as if were intrinsically losssy (no way of not losing messages if a
> queue got full) which is a problem for KBUS requests/replies.
Changing netlink to report "queue full" errors sounds good for both ends, so
it is not really a big problem. Same goes for all errors actually, it will
just benefit the existing netlink users.
>
> On the other hand, understanding netlink from scratch is somewhat
> difficult (I've just spent some hours doing more research, and don't
> feel like I've begun to get a good idea of its boundaries yet).
>
> I have also been reading the libnl documentation, which seems to make
> the userspace end somewhat less complex, and looks like a good thing.
Yes, libnl hides a lot of complexity of netlink but still adds some, like
caches and such. But in the end there is no more than 5 to 6 libnl
handles/objects to use, and there you go. Then you usually use another library
like libevent to get called on socket writes/reads.
>
> > If you intend to keep a part of it in the kernel, you should have a
> > look at this, because from my experience with generic netlink, most of
> > the hard job you are re-doing here, has already been done in a generic
> > manner.
>
> It looks interesting, but the worrying part of statements like this is
> always the "most of".
>
> Is your suggestion that netlink would be a better API than the current
> "creating" use of a file API for communicating from user space to the
> KBUS kernel module, and then back?
What I like with netlink, which I do not with your implementation, is that
netlink uses sockets and not traditionnal devices. But what is exposed to
KBUS-implementors is good.
netlink in my mind is just a transport layer, while you see the transport
layer as a /dev/kbus<N> device and its kernel module.
>
> The LWN article http://lwn.net/Articles/131802/ makes that sound
> plausible (assuming one can still detect "release" events for netlink
> sockets - I assume one can). At first glance I'm not sure how much
> harder it is to program such a netlink interface "bare" (without a
> userspace library such as libnl) than it is to use the current KBUS
> interface in such a manner.
It is probably more work to use netlink rather than KBUS with a bare library.
>
> (Aside: a quick look at my current KBUS build shows kbus.ko as 60KB,
> libkbus.so (the C userspace library on top of the "raw" usage) as 54KB,
> and libnl.so as 277KB - although I don't know how Ubuntu build the
> latter, and it obviously also includes all sorts of data description
> handling which KBUS deliberately does not. So netlink smaller if "bare",
> and bigger, but not a huge amount, if used with its library.)
libnl by default is pretty big, this is why we maintain a stripped down
version, called libnl-tiny in OpenWrt:
https://dev.openwrt.org/browser/trunk/package/libnl-tiny (based on libnl-1.1)
this is an orthogonal problem though. Some people might even go for static
linking to automatically strip down their daemons linking with such a library.
>
> I'm not entirely sure what happens if either end of the netlink API
> doesn't respond in a timely manner - is netlink allowed to throw things
> away?
As usual with sockets, if you do not read from it, data is thrown away, or you
end-up looping until all is read if doing epoll.
>
> Or did you mean that netlink is appropriate to replace some/much of the
> KBUS kernel module as well? In that case I'd have to think about it a
> lot more to have an informed opinion.
>
> Anyway.
>
> What I'm working on at the moment is an email in which I try to restate
> what we are/were trying to do with KBUS, with simple examples of the
> sorts of call we're talking about, and ask if that is a sensible thing
> to have in the kernel, emphasising that we are more worried about the
> functionality than the API.
>
> If the concept is a good thing but our implementation of it is
> objectionable (e.g., we need to rewrite to a less "creative" interface,
> be more sockety, or whatever), then so be it, we'll need to rewrite.
I personaly prefer your interface to be more "sockety" to use your wording.
Having a /dev/kbus<N> device does not seem very natural to me to read/write
from, using a socket would be more appropriate. This is why I suggest generic
netlink, because you will most likely end up doing the same thing, if you go
the kernel way, which is:
- identifying your process uniquely
- marshalling/unmarshalling data sent to/from the daemon
- allowing several recipients to receive a message from a sender
...
My suggestion is that, if you really want to go the kernel way for transport
(which I discourage, you certainly got that), let's just use generic netlink
which has been proven to be reliable and easy to use for this.
>
> If you'd be willing to look at that email when it is posted, I hope it
> will be easier to point at specific things and say "yes, that would be
> better done with netlink" or, perhaps, "netlink would not address this,
> but one might attack it in this way".
Let's say that if I was to integrate something like KBUS in the kernel, I
would do it that way:
- rework the KBUS module to implement a generic netlink family and multicast
group
- keep the same data format/marshalling
- create an user-space library which abstracts the using of this generic
netlink socket and the KBUS specific messaging
>
> Thanks,
> Tibs
This is coming pretty late, but I hope that you are still willing to work on
this subject despite my comments.
--
Florian
^ permalink raw reply
* ELC Europe Call for Proposals, due July 8th
From: Tim Bird @ 2011-07-01 17:38 UTC (permalink / raw)
To: linux-embedded
Hey embedded Linux developers,
I thought I'd let you all know that the call for proposals
for ELC-Europe is active now. ELC Europe will be in Prague
this year, co-located with LinuxCon Europe and the Kernel Summit.
So anyone who has plans to be at those events might also
conveniently talk at or participate in ELC Europe.
The event dates are October 26-28.
Proposals for talks are due July 8th (just a week from today).
The CFP is at:
http://events.linuxfoundation.org/events/embedded-linux-conference-europe/cfp
and you can follow links for general event information.
I look forward to seeing many of you there! If you've been working
on something neat, please considering coming and telling us about it.
-- Tim
=============================
Tim Bird
Architecture Group Chair, CE Workgroup of the Linux Foundation
Senior Staff Engineer, Sony Network Entertainment
=============================
^ permalink raw reply
* Re: [RFC PATCHv2] UBI: new module ubiblk: block layer on top of UBI
From: Artem Bityutskiy @ 2011-06-29 6:54 UTC (permalink / raw)
To: david.wagner; +Cc: linux-mtd, dwmw2, linux-kernel, linux-embedded, tim.bird
In-Reply-To: <1309274691-4898-1-git-send-email-david.wagner@free-electrons.com>
On Tue, 2011-06-28 at 17:24 +0200, david.wagner@free-electrons.com
wrote:
> + * Author: David Wagner
> + * Some code taken from gluebi.c (Artem Bityutskiy (Битюцкий Артём),
> + * Joern Engel)
> + * Some code taken from mtd_blkdevs.c (David Woodhouse)
It is important to preserve Copyrights, because it has to do with legal
stuff.
--
Best Regards,
Artem Bityutskiy
^ permalink raw reply
* [RFC PATCHv2] UBI: new module ubiblk: block layer on top of UBI
From: david.wagner @ 2011-06-28 15:24 UTC (permalink / raw)
To: linux-mtd
Cc: linux-embedded, dedekind1, David Wagner, linux-kernel, tim.bird,
dwmw2
In-Reply-To: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
[-- Attachment #1: Type: text/plain, Size: 16809 bytes --]
From: David Wagner <david.wagner@free-electrons.com>
Hi,
This is next iteration ; the read errors issue with FS that do large requests
has been fixed (it means that all block filesystems should now work) ; the
'resized' callback is implemented.
The reuse of code from mtd_blkdevs and gluebi is now mentionned is the file
header.
The use of a kernel thread is also justified (line 353).
The Kconfig has also been fixed.
I also tested compiling ubiblk statically into the kernel ; it worked and I was
able to mount a squashfs ubiblk device as root with, for instance:
"ubi.mtd=1 root=/dev/ubiblk0_0"
Performances still haven't been tested, though.
Thanks to those for review it !
David.
PS: I included the commit message+diff in the same mail as the introduction for
convenience ; tell me if it annoys you - I'll split the next iterations as I did
for the first one.
ubiblk is a read-only block layer on top of UBI. It presents UBI volumes as
read-only block devices.
It is used by putting a block filesystem image on a UBI volume and then mounting
the corresponding device.
It uses the UBI API to register to UBI notifications (to dynamically create and
delete devices as volumes are added or removed) and to read from the volumes.
Known issues:
* the modules keeps a table of the devices which length is the maximum number
of UBI volumes. It should make use of a linked list.
Some code is taken from mtd_blkdevs and gluebi
Signed-off-by: David Wagner <david.wagner@free-electrons.com>
---
drivers/mtd/ubi/Kconfig | 12 +
drivers/mtd/ubi/Makefile | 1 +
drivers/mtd/ubi/ubiblk.c | 554 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 567 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/ubi/ubiblk.c
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 4dcc752..d19508b 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -60,4 +60,16 @@ config MTD_UBI_DEBUG
help
This option enables UBI debugging.
+config MTD_UBI_UBIBLK
+ tristate "Read-only block transition layer on top of UBI"
+ help
+ Read-only block interface on top of UBI.
+
+ This option adds ubiblk, which creates a read-ony block device for
+ each UBI volume. It makes it possible to use block filesystems on
+ top of UBI (and thus, on top of MTDs while avoiding bad blocks).
+
+ The devices are named ubiblkX_Y where X is the UBI number and Y is
+ the Volume ID.
+
endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index c9302a5..354b2df 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -5,3 +5,4 @@ ubi-y += misc.o
ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+obj-$(CONFIG_MTD_UBI_UBIBLK) += ubiblk.o
diff --git a/drivers/mtd/ubi/ubiblk.c b/drivers/mtd/ubi/ubiblk.c
new file mode 100644
index 0000000..53e6d4e
--- /dev/null
+++ b/drivers/mtd/ubi/ubiblk.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) Free Electrons, 2011
+ *
+ * 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
+ *
+ * Author: David Wagner
+ * Some code taken from gluebi.c (Artem Bityutskiy (������������������������������������������������ ������������������������������),
+ * Joern Engel)
+ * Some code taken from mtd_blkdevs.c (David Woodhouse)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/ubi.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include "ubi.h"
+
+#define BLK_SIZE 512
+
+#define UBIBLK_MAX_DEVS (UBI_MAX_DEVICES * UBI_MAX_VOLUMES)
+
+/*
+ * Structure representing a ubiblk device, proxying a UBI volume
+ */
+struct ubiblk_dev {
+ struct ubi_volume_desc *vol_desc;
+ struct ubi_volume_info *vol_info;
+ int ubi_num;
+ int vol_id;
+
+ /* Block stuff */
+ struct gendisk *gd;
+ struct request_queue *rq;
+ struct task_struct *thread;
+
+ /* Protects the access to the UBI volume */
+ struct mutex lock;
+
+ /* Avoids concurrent accesses to the request queue */
+ spinlock_t queue_lock;
+};
+
+/*
+ * Contains the pointers to all ubiblk_dev instances
+ * TODO: use a linked list
+ */
+static struct ubiblk_dev *ubiblk_devs[UBIBLK_MAX_DEVS];
+static struct mutex devtable_lock;
+
+int major;
+static const struct block_device_operations ubiblk_ops;
+
+static struct ubiblk_dev *ubiblk_find_dev(struct ubi_volume_info *vol_info)
+{
+ int i;
+ struct ubiblk_dev *dev;
+
+ mutex_lock(&devtable_lock);
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+ dev = ubiblk_devs[i];
+ if (dev && dev->ubi_num == vol_info->ubi_num &&
+ dev->vol_id == vol_info->vol_id)
+ break;
+ }
+ mutex_unlock(&devtable_lock);
+ if (i == UBIBLK_MAX_DEVS)
+ return NULL;
+ return dev;
+}
+
+/*
+ * Read a LEB and fill the request buffer with the requested sector
+ */
+static int do_ubiblk_request(struct request *req, struct ubiblk_dev *dev)
+{
+ unsigned long start, len, read_bytes;
+ int offset;
+ int leb;
+ int ret;
+
+ start = blk_rq_pos(req) << 9;
+ len = blk_rq_cur_bytes(req);
+ read_bytes = 0;
+
+ /* We are always reading. No need to handle writing for now */
+
+ leb = start / dev->vol_info->usable_leb_size;
+ offset = start % dev->vol_info->usable_leb_size;
+
+ do {
+ int overlap = 0;
+
+ if (offset + len > dev->vol_info->usable_leb_size) {
+ len = dev->vol_info->usable_leb_size - offset;
+ overlap = 1;
+ }
+
+ if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
+ get_capacity(req->rq_disk)) {
+ pr_err("UBIBLK: attempting to read too far\n");
+ return -EIO;
+ }
+
+ pr_debug("%s(%s) of sector %llu (LEB %d). offset=%d, len=%lu\n",
+ __func__, rq_data_dir(req) ? "Write" : "Read",
+ blk_rq_pos(req), leb, offset, len);
+
+ /* Read (len) bytes of LEB (leb) from (offset) and put the
+ * result in the buffer given by the request ; if the request
+ * is overlapping on several lebs, (read) will be > 0 and the
+ * data will be put in the buffer at offset (read) */
+ ret = ubi_read(dev->vol_desc, leb, req->buffer + read_bytes,
+ offset, len);
+
+ if (ret) {
+ pr_err("ubi_read error\n");
+ return ret;
+ }
+
+ read_bytes += len;
+ len = blk_rq_cur_bytes(req) - read_bytes;
+
+ /* If we needed to cap the length of ubi_read, the next
+ * ubi_read will be done on the beginning of the next LEB */
+ if (overlap) {
+ leb++;
+ offset = 0;
+ overlap = 0;
+ }
+ } while (read_bytes < blk_rq_cur_bytes(req));
+
+ pr_debug("ubi_read done.\n");
+
+ return 0;
+}
+
+static void ubi_ubiblk_request(struct request_queue *rq)
+{
+ struct ubiblk_dev *dev;
+ struct request *req = NULL;
+
+ dev = rq->queuedata;
+
+ if (!dev)
+ while ((req = blk_fetch_request(rq)) != NULL)
+ __blk_end_request_all(req, -ENODEV);
+ else
+ wake_up_process(dev->thread);
+}
+
+/*
+ * Open a UBI volume (get the volume descriptor)
+ */
+static int ubiblk_open(struct block_device *bdev, fmode_t mode)
+{
+ struct ubiblk_dev *dev = bdev->bd_disk->private_data;
+ pr_debug("%s() disk_name=%s, mode=%d\n", __func__,
+ bdev->bd_disk->disk_name, mode);
+
+ dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+ UBI_READONLY);
+ if (!dev->vol_desc) {
+ pr_err("open_volume failed");
+ return -EINVAL;
+ }
+
+ dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+ if (!dev->vol_info) {
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ return -ENOMEM;
+ }
+ ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+ return 0;
+}
+
+/*
+ * Close a UBI volume (close the volume descriptor)
+ */
+static int ubiblk_release(struct gendisk *gd, fmode_t mode)
+{
+ struct ubiblk_dev *dev = gd->private_data;
+ pr_debug("%s() disk_name=%s, mode=%d\n", __func__, gd->disk_name, mode);
+
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+ if (dev->vol_desc) {
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * Loop on the block request queue and wait for new requests ; run them with
+ * do_ubiblk_request()
+ *
+ * Mostly stolen from mtd_blkdevs.c
+ */
+static int ubi_ubiblk_thread(void *arg)
+{
+ struct ubiblk_dev *dev = arg;
+ struct request_queue *rq = dev->rq;
+ struct request *req = NULL;
+
+ spin_lock_irq(rq->queue_lock);
+
+ while (!kthread_should_stop()) {
+ int res;
+
+ if (!req && !(req = blk_fetch_request(rq))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (kthread_should_stop())
+ set_current_state(TASK_RUNNING);
+
+ spin_unlock_irq(rq->queue_lock);
+ schedule();
+ spin_lock_irq(rq->queue_lock);
+ continue;
+ }
+
+ spin_unlock_irq(rq->queue_lock);
+
+ mutex_lock(&dev->lock);
+ res = do_ubiblk_request(req, dev);
+ pr_debug("return from request: %d\n", res);
+ mutex_unlock(&dev->lock);
+
+ spin_lock_irq(rq->queue_lock);
+
+ if (!__blk_end_request_cur(req, res))
+ req = NULL;
+ }
+
+ if (req)
+ __blk_end_request_all(req, -EIO);
+
+ spin_unlock_irq(rq->queue_lock);
+
+ return 0;
+}
+
+/*
+ * An UBI volume has been created ; create a corresponding ubiblk device:
+ * Initialize the locks, the structure, the block layer infos and start a
+ * thread.
+ */
+static int ubiblk_create(struct ubi_device_info *dev_info,
+ struct ubi_volume_info *vol_info)
+{
+ struct ubiblk_dev *dev;
+ struct gendisk *gd;
+ int i;
+ int ret = 0;
+
+ mutex_lock(&devtable_lock);
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++)
+ if (!ubiblk_devs[i])
+ break;
+
+ if (i == UBIBLK_MAX_DEVS) {
+ /* Shouldn't happen: UBI can't make more volumes than that */
+ pr_err("no slot left for a new ubiblk device.\n");
+ mutex_unlock(&devtable_lock);
+ return -ENOMEM;
+ }
+
+ dev = kzalloc(sizeof(struct ubiblk_dev), GFP_KERNEL);
+ if (!dev) {
+ pr_err("UBIBLK: ENOMEM when trying to create a new"
+ "ubiblk dev\n");
+ mutex_unlock(&devtable_lock);
+ return -ENOMEM;
+ }
+ ubiblk_devs[i] = dev;
+ mutex_unlock(&devtable_lock);
+
+ mutex_init(&dev->lock);
+ mutex_lock(&dev->lock);
+
+ dev->ubi_num = vol_info->ubi_num;
+ dev->vol_id = vol_info->vol_id;
+
+ dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+ UBI_READONLY);
+ if (IS_ERR(dev->vol_desc)) {
+ pr_err("open_volume failed\n");
+ ret = PTR_ERR(dev->vol_desc);
+ goto out_vol;
+ }
+
+ dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+ if (!dev->vol_info) {
+ ret = -ENOMEM;
+ goto out_info;
+ }
+ ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+ pr_info("Got volume %s: device %d/volume %d of size %d\n",
+ dev->vol_info->name, dev->ubi_num, dev->vol_id,
+ dev->vol_info->size);
+
+ /* Initialize the gendisk of this ubiblk device */
+ gd = alloc_disk(1);
+ if (!gd) {
+ pr_err("alloc_disk failed\n");
+ ret = -ENODEV;
+ goto out_disk;
+ }
+
+ gd->fops = &ubiblk_ops;
+ gd->major = major;
+ gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+ gd->private_data = dev;
+ sprintf(gd->disk_name, "ubiblk%d_%d", dev->ubi_num, dev->vol_id);
+ pr_debug("creating a gd '%s'\n", gd->disk_name);
+ set_capacity(gd,
+ (dev->vol_info->size *
+ dev->vol_info->usable_leb_size) >> 9);
+ set_disk_ro(gd, 1);
+ dev->gd = gd;
+
+ spin_lock_init(&dev->queue_lock);
+ dev->rq = blk_init_queue(ubi_ubiblk_request, &dev->queue_lock);
+ if (!dev->rq) {
+ pr_err("init_queue failed\n");
+ ret = -ENODEV;
+ goto out_queue;
+ }
+ dev->rq->queuedata = dev;
+ blk_queue_logical_block_size(dev->rq, BLK_SIZE);
+ dev->gd->queue = dev->rq;
+
+ /* Stolen from mtd_blkdevs.c */
+ /* Create processing thread
+ *
+ * The processing of the request has to be done in process context (it
+ * might sleep) but blk_run_queue can't block ; so we need to separate
+ * the event of a request being added to the queue (which triggers the
+ * callback ubi_ubiblk_request - that is set with blk_init_queue())
+ * and the processing of that request.
+ *
+ * Thus, the sole purpose of ubi_ubiblk_reuqest is to wake the kthread
+ * up so that it will process the request queue
+ */
+ dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
+ "kubiblk", dev->ubi_num, dev->vol_id);
+ if (IS_ERR(dev->thread)) {
+ ret = PTR_ERR(dev->thread);
+ goto out_thread;
+ }
+
+ add_disk(dev->gd);
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+ mutex_unlock(&dev->lock);
+
+ return 0;
+
+out_thread:
+ blk_cleanup_queue(dev->rq);
+out_queue:
+ put_disk(dev->gd);
+out_disk:
+ kfree(dev->vol_info);
+ dev->vol_info = NULL;
+out_info:
+ ubi_close_volume(dev->vol_desc);
+ dev->vol_desc = NULL;
+out_vol:
+ mutex_unlock(&dev->lock);
+
+ return ret;
+}
+
+/*
+ * A UBI has been removed ; destroy the corresponding ubiblk device
+ */
+static int ubiblk_remove(struct ubi_volume_info *vol_info)
+{
+ struct ubiblk_dev *dev;
+
+ dev = ubiblk_find_dev(vol_info);
+
+ if (!dev) {
+ pr_warn("Trying to remove %s, which is unknown from ubiblk\n",
+ vol_info->name);
+ return -ENODEV;
+ }
+
+ pr_info("Removing %s\n", vol_info->name);
+
+ if (dev->vol_desc)
+ ubi_close_volume(dev->vol_desc);
+
+ del_gendisk(dev->gd);
+ blk_cleanup_queue(dev->rq);
+ kthread_stop(dev->thread);
+ put_disk(dev->gd);
+
+ kfree(dev->vol_info);
+
+ mutex_lock(&devtable_lock);
+ kfree(dev);
+ dev = NULL;
+ mutex_unlock(&devtable_lock);
+
+ return 0;
+}
+
+static int ubiblk_resized(struct ubi_volume_info *vol_info)
+{
+ struct ubiblk_dev *dev;
+
+ dev = ubiblk_find_dev(vol_info);
+ if (!dev) {
+ pr_warn("Trying to resize %s, which is unknown from ubiblk\n",
+ vol_info->name);
+ return -ENODEV;
+ }
+
+ mutex_lock(&dev->lock);
+ set_capacity(dev->gd,
+ (vol_info->size * vol_info->usable_leb_size) >> 9);
+ mutex_unlock(&dev->lock);
+ pr_debug("Resized ubiblk%d_%d to %d LEBs\n", vol_info->ubi_num,
+ vol_info->vol_id, vol_info->size);
+ return 0;
+}
+
+/*
+ * Dispatches the UBI notifications
+ * copied from gluebi.c
+ */
+static int ubiblk_notify(struct notifier_block *nb,
+ unsigned long notification_type, void *ns_ptr)
+{
+ struct ubi_notification *nt = ns_ptr;
+
+ switch (notification_type) {
+ case UBI_VOLUME_ADDED:
+ ubiblk_create(&nt->di, &nt->vi);
+ break;
+ case UBI_VOLUME_REMOVED:
+ ubiblk_remove(&nt->vi);
+ break;
+ case UBI_VOLUME_RESIZED:
+ ubiblk_resized(&nt->vi);
+ break;
+ case UBI_VOLUME_UPDATED:
+ break;
+ case UBI_VOLUME_RENAMED:
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static const struct block_device_operations ubiblk_ops = {
+ .owner = THIS_MODULE,
+ .open = ubiblk_open,
+ .release = ubiblk_release,
+};
+
+static struct notifier_block ubiblk_notifier = {
+ .notifier_call = ubiblk_notify,
+};
+
+/*
+ * Initialize the module
+ * (Get a major number and register to UBI notifications)
+ */
+static int __init ubi_ubiblk_init(void)
+{
+ int ret = 0;
+
+ pr_info("UBIBLK starting\n");
+
+ ret = register_blkdev(0, "ubiblk");
+ if (ret <= 0) {
+ pr_err("UBIBLK: could not register_blkdev\n");
+ return -ENODEV;
+ }
+ major = ret;
+ pr_info("UBIBLK: device's major: %d\n", major);
+
+ mutex_init(&devtable_lock);
+ ret = ubi_register_volume_notifier(&ubiblk_notifier, 0);
+ if (ret < 0)
+ unregister_blkdev(major, "ubiblk");
+
+ return ret;
+}
+
+/*
+ * End of life
+ * unregister the block device major, unregister from UBI notifications,
+ * stop the threads and free the memory.
+ */
+static void __exit ubi_ubiblk_exit(void)
+{
+ int i;
+
+ pr_info("UBIBLK: going to exit\n");
+
+ ubi_unregister_volume_notifier(&ubiblk_notifier);
+
+ for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+ struct ubiblk_dev *dev = ubiblk_devs[i];
+ if (!dev)
+ continue;
+
+ if (dev->vol_desc)
+ ubi_close_volume(dev->vol_desc);
+
+ del_gendisk(dev->gd);
+ blk_cleanup_queue(dev->rq);
+ kthread_stop(dev->thread);
+ put_disk(dev->gd);
+
+ kfree(dev->vol_info);
+ kfree(dev);
+ }
+
+ unregister_blkdev(major, "ubiblk");
+ pr_info("UBIBLK: The End\n");
+}
+
+module_init(ubi_ubiblk_init);
+module_exit(ubi_ubiblk_exit);
+MODULE_DESCRIPTION("Read-only block transition layer on top of UBI");
+MODULE_AUTHOR("David Wagner");
+MODULE_LICENSE("GPL");
--
1.7.0.4
[-- Attachment #2: Type: text/plain, Size: 144 bytes --]
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related
* Re: [PATCH] Enable USB on TI DM365
From: Sergei Shtylyov @ 2011-06-27 9:12 UTC (permalink / raw)
To: Constantine Shulyupin
Cc: davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-embedded-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <BANLkTims=UsUMkDQ8uB+J6YTVRSBD__otw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hello.
On 24-06-2011 22:51, Constantine Shulyupin wrote:
> Enable USB on TI DM365
On DM365 EVM board, you should have said.
Do not duplicate the summary in the description. Also, more details here
wouldn't hurt...
> Signed-off-by: Constantine Shulyupin <const-GkuDRZ1haSFDPfheJLI6IQ@public.gmane.org>
[...]
> diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
> index 0b87a1c..52961a8 100644
> --- a/arch/arm/mach-davinci/Makefile
> +++ b/arch/arm/mach-davinci/Makefile
> @@ -5,7 +5,7 @@
>
> # Common objects
> obj-y := time.o clock.o serial.o io.o psc.o \
> - gpio.o dma.o usb.o common.o sram.o aemif.o
> + gpio.o dma.o common.o sram.o aemif.o
>
> obj-$(CONFIG_DAVINCI_MUX) += mux.o
>
> @@ -40,3 +40,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
> obj-$(CONFIG_CPU_FREQ) += cpufreq.o
> obj-$(CONFIG_CPU_IDLE) += cpuidle.o
> obj-$(CONFIG_SUSPEND) += pm.o sleep.o
> +obj-$(CONFIG_USB_MUSB_DAVINCI) += usb.o
And kernel linking will happily fail if CONFIG_USB_MUSB_DAVINCI=n. :-/
Also, I don't think making usb.c a module is a good idea...
> diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
> index 23d2b6d..8b12206 100644
> --- a/arch/arm/mach-davinci/usb.c
> +++ b/arch/arm/mach-davinci/usb.c
> @@ -4,19 +4,22 @@
> #include<linux/init.h>
> #include<linux/platform_device.h>
> #include<linux/dma-mapping.h>
> -
> #include<linux/usb/musb.h>
>
> #include<mach/common.h>
> #include<mach/irqs.h>
> #include<mach/cputype.h>
> #include<mach/usb.h>
> +#include<mach/mux.h>
> +#include<linux/gpio.h>
>
> #define DAVINCI_USB_OTG_BASE 0x01c64000
>
> #define DA8XX_USB0_BASE 0x01e00000
> #define DA8XX_USB1_BASE 0x01e25000
>
> +static int retval;
Why in the world it's 'static'? :-O
> @@ -87,7 +90,7 @@ static struct platform_device usb_dev = {
> .num_resources = ARRAY_SIZE(usb_resources),
> };
>
> -void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
> +int __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
> {
> usb_data.power = mA> 510 ? 255 : mA / 2;
> usb_data.potpgt = (potpgt_ms + 1) / 2;
> @@ -99,7 +102,8 @@ void __init davinci_setup_usb(unsigned mA, unsigned
> potpgt_ms)
The patch is line-wrapped...
> } else /* other devices don't have dedicated CPPI IRQ */
> usb_dev.num_resources = 2;
>
> - platform_device_register(&usb_dev);
> + retval = platform_device_register(&usb_dev);
> + return retval;
Why not just:
return platform_device_register(&usb_dev);
> }
>
> #ifdef CONFIG_ARCH_DAVINCI_DA8XX
> @@ -132,7 +136,7 @@ int __init da8xx_register_usb20(unsigned mA,
> unsigned potpgt)
>
> #else
>
> -void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
> +int __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
> {
> }
>
> @@ -178,3 +182,23 @@ int __init da8xx_register_usb11(struct
> da8xx_ohci_root_hub *pdata)
> return platform_device_register(&da8xx_usb11_device);
> }
> #endif /* CONFIG_DAVINCI_DA8XX */
> +
> +#ifdef CONFIG_MACH_DAVINCI_DM365_EVM
How do you think why do we have arch/arm/mach-davinci/board-dm365-evm.c?
> +int __init dm365evm_usb_configure(void)
> +{
> + davinci_cfg_reg(DM365_GPIO33);
> + gpio_request(33, "usb");
> + gpio_direction_output(33, 1);
> + retval = davinci_setup_usb(500, 8);
> + return retval;
Why not just:
return davinci_setup_usb(500, 8);
> diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
> index 2a2adf6..0147f5c 100644
> --- a/drivers/usb/musb/davinci.c
> +++ b/drivers/usb/musb/davinci.c
> @@ -72,6 +72,16 @@ static inline void phy_on(void)
> /* power everything up; start the on-chip PHY and its PLL */
> phy_ctrl&= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN);
> phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON;
> +
> + if (cpu_is_davinci_dm365()) {
> + /*
> + * DM365 PHYCLKFREQ field [15:12] is set to 2
> + * to get clock from 24MHz crystal
> + */
> + phy_ctrl |= USBPHY_CLKFREQ_24MHZ;
I do think this should be set in the board specific code instead, like we
do it on DA830.
> + /*phy_ctrl&= ~USBPHY_PHYPDWN;*/
Don't include commented out code.
> + }
> +
> __raw_writel(phy_ctrl, USB_PHY_CTRL);
>
> /* wait for PLL to lock before proceeding */
> @@ -193,6 +203,9 @@ static void davinci_musb_source_power(struct musb
> *musb, int is_on, int immediat
> else
> schedule_work(&evm_vbus_work);
> }
> +
> + if (cpu_is_davinci_dm365())
> + gpio_set_value(33, is_on);
This is board specific code, not CPU specific.
> diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
> index 046c844..1bf50e6 100644
> --- a/drivers/usb/musb/davinci.h
> +++ b/drivers/usb/musb/davinci.h
> @@ -17,6 +17,7 @@
> /* Integrated highspeed/otg PHY */
> #define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
> #define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */
> +#define USBPHY_CLKFREQ_24MHZ BIT(13)
> #define USBPHY_PHYCLKGD BIT(8)
> #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */
> #define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */
^ permalink raw reply
* Re: [PATCH] Enable USB on TI DM365
From: Sebastian Heß @ 2011-06-26 12:11 UTC (permalink / raw)
To: Constantine Shulyupin
Cc: linux-kernel, linux-embedded, davinci-linux-open-source, nsekhar,
khilman
In-Reply-To: <BANLkTims=UsUMkDQ8uB+J6YTVRSBD__otw@mail.gmail.com>
On Friday 24 June 2011 20:51:31 Constantine Shulyupin wrote:
Hi,
> -void davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
> +int davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
>
> #endif /* ifndef __ASM_ARCH_USB_H */
> diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
> index 23d2b6d..8b12206 100644
> --- a/arch/arm/mach-davinci/usb.c
> +++ b/arch/arm/mach-davinci/usb.c
> @@ -4,19 +4,22 @@
> #include <linux/init.h>
> #include <linux/platform_device.h>
> #include <linux/dma-mapping.h>
> -
> #include <linux/usb/musb.h>
>
> #include <mach/common.h>
> #include <mach/irqs.h>
> #include <mach/cputype.h>
> #include <mach/usb.h>
> +#include <mach/mux.h>
> +#include <linux/gpio.h>
>
> #define DAVINCI_USB_OTG_BASE 0x01c64000
>
> #define DA8XX_USB0_BASE 0x01e00000
> #define DA8XX_USB1_BASE 0x01e25000
>
> +static int retval;
> +
Why do you add this as a global static var? As no locking is involved here
this may cause problems as soon as we see SMP systems using this controller.
Please put the variable into the functions needing it.
Best regards
Sebastian
--
Hessware - Open Source Solutions
^ permalink raw reply
* [PATCH] Enable USB on TI DM365
From: Constantine Shulyupin @ 2011-06-24 18:51 UTC (permalink / raw)
To: linux-kernel, linux-embedded, davinci-linux-open-source; +Cc: nsekhar, khilman
Enable USB on TI DM365
Signed-off-by: Constantine Shulyupin <const@MakeLinux.com>
---
arch/arm/mach-davinci/Makefile | 3 +-
arch/arm/mach-davinci/include/mach/usb.h | 2 +-
arch/arm/mach-davinci/usb.c | 32 ++++++++++++++++++++++++++---
drivers/usb/musb/davinci.c | 13 ++++++++++++
drivers/usb/musb/davinci.h | 1 +
5 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 0b87a1c..52961a8 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -5,7 +5,7 @@
# Common objects
obj-y := time.o clock.o serial.o io.o psc.o \
- gpio.o dma.o usb.o common.o sram.o aemif.o
+ gpio.o dma.o common.o sram.o aemif.o
obj-$(CONFIG_DAVINCI_MUX) += mux.o
@@ -40,3 +40,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SUSPEND) += pm.o sleep.o
+obj-$(CONFIG_USB_MUSB_DAVINCI) += usb.o
diff --git a/arch/arm/mach-davinci/include/mach/usb.h
b/arch/arm/mach-davinci/include/mach/usb.h
index e0bc4ab..863c27f 100644
--- a/arch/arm/mach-davinci/include/mach/usb.h
+++ b/arch/arm/mach-davinci/include/mach/usb.h
@@ -54,6 +54,6 @@ struct da8xx_ohci_root_hub {
u8 potpgt;
};
-void davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
+int davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
#endif /* ifndef __ASM_ARCH_USB_H */
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index 23d2b6d..8b12206 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -4,19 +4,22 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-
#include <linux/usb/musb.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/cputype.h>
#include <mach/usb.h>
+#include <mach/mux.h>
+#include <linux/gpio.h>
#define DAVINCI_USB_OTG_BASE 0x01c64000
#define DA8XX_USB0_BASE 0x01e00000
#define DA8XX_USB1_BASE 0x01e25000
+static int retval;
+
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
static struct musb_hdrc_eps_bits musb_eps[] = {
{ "ep1_tx", 8, },
@@ -87,7 +90,7 @@ static struct platform_device usb_dev = {
.num_resources = ARRAY_SIZE(usb_resources),
};
-void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
+int __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
{
usb_data.power = mA > 510 ? 255 : mA / 2;
usb_data.potpgt = (potpgt_ms + 1) / 2;
@@ -99,7 +102,8 @@ void __init davinci_setup_usb(unsigned mA, unsigned
potpgt_ms)
} else /* other devices don't have dedicated CPPI IRQ */
usb_dev.num_resources = 2;
- platform_device_register(&usb_dev);
+ retval = platform_device_register(&usb_dev);
+ return retval;
}
#ifdef CONFIG_ARCH_DAVINCI_DA8XX
@@ -132,7 +136,7 @@ int __init da8xx_register_usb20(unsigned mA,
unsigned potpgt)
#else
-void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
+int __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
{
}
@@ -178,3 +182,23 @@ int __init da8xx_register_usb11(struct
da8xx_ohci_root_hub *pdata)
return platform_device_register(&da8xx_usb11_device);
}
#endif /* CONFIG_DAVINCI_DA8XX */
+
+#ifdef CONFIG_MACH_DAVINCI_DM365_EVM
+int __init dm365evm_usb_configure(void)
+{
+ davinci_cfg_reg(DM365_GPIO33);
+ gpio_request(33, "usb");
+ gpio_direction_output(33, 1);
+ retval = davinci_setup_usb(500, 8);
+ return retval;
+}
+subsys_initcall(dm365evm_usb_configure);
+
+static void __exit dm365evm_usb_exit(void)
+{
+ platform_device_unregister(&usb_dev);
+}
+module_exit(dm365evm_usb_exit);
+
+#endif
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 2a2adf6..0147f5c 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -72,6 +72,16 @@ static inline void phy_on(void)
/* power everything up; start the on-chip PHY and its PLL */
phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN);
phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON;
+
+ if (cpu_is_davinci_dm365()) {
+ /*
+ * DM365 PHYCLKFREQ field [15:12] is set to 2
+ * to get clock from 24MHz crystal
+ */
+ phy_ctrl |= USBPHY_CLKFREQ_24MHZ;
+ /*phy_ctrl &= ~USBPHY_PHYPDWN;*/
+ }
+
__raw_writel(phy_ctrl, USB_PHY_CTRL);
/* wait for PLL to lock before proceeding */
@@ -193,6 +203,9 @@ static void davinci_musb_source_power(struct musb
*musb, int is_on, int immediat
else
schedule_work(&evm_vbus_work);
}
+
+ if (cpu_is_davinci_dm365())
+ gpio_set_value(33, is_on);
if (immediate)
vbus_state = is_on;
#endif
diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
index 046c844..1bf50e6 100644
--- a/drivers/usb/musb/davinci.h
+++ b/drivers/usb/musb/davinci.h
@@ -17,6 +17,7 @@
/* Integrated highspeed/otg PHY */
#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */
+#define USBPHY_CLKFREQ_24MHZ BIT(13)
#define USBPHY_PHYCLKGD BIT(8)
#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */
#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */
--
1.7.0.4
--
Constantine Shulyupin
http://www.MakeLinux.com/
Embedded Linux Systems,
Device Drivers, TI DaVinci
^ permalink raw reply related
* Re: debugging multi threaded applicatiosn on arm - status?
From: Sam Ravnborg @ 2011-06-17 15:39 UTC (permalink / raw)
To: chris; +Cc: linux-embedded
In-Reply-To: <4DFB4C8D.40208@2net.co.uk>
>> Is it possible to bebug multi-threaded applications using gdb on ARM these days?
>>
>
> It works for me, using various ARM 926 and Cortex A8 chips and kernel
> versions from 2.6.27 to the present day. Which version of gbd do you
> have? gdb version 7.x works much better than 6.x in my experience.
We are using 6.8 - which may be the culprint.
Does it work with NPTL too?
Sam
^ permalink raw reply
* Re: debugging multi threaded applicatiosn on arm - status?
From: Chris Simmonds @ 2011-06-17 12:46 UTC (permalink / raw)
To: Sam Ravnborg; +Cc: linux-embedded
In-Reply-To: <20110617093927.GA28305@merkur.ravnborg.org>
On 17/06/11 10:39, Sam Ravnborg wrote:
> Is it possible to bebug multi-threaded applications using gdb on ARM these days?
>
> We have had trobules getting this to work - but I do not have the details at hand atm.
> I am just curious if this is supposed to work or not.
>
> We have an arm target running: 2.6.32.8 #1 PREEMPT
> CPU: ARM926EJ-S rev 5 (v5l) (Atmel AT91SAM9263)
>
> The kernel is only lightly modifed - mostly with a few
> propriatary drivers and a few driver hacks (not suitable for mainline).
>
> It is a long story why we use such an old version.
>
> Our applications uses threads and we use glibc 2.10.1 with NPTL enabled.
> So far we have survived using the powerfull printf debugging :-)
>
> Sam
It works for me, using various ARM 926 and Cortex A8 chips and kernel
versions from 2.6.27 to the present day. Which version of gbd do you
have? gdb version 7.x works much better than 6.x in my experience.
Chris Simmonds
^ permalink raw reply
* debugging multi threaded applicatiosn on arm - status?
From: Sam Ravnborg @ 2011-06-17 9:39 UTC (permalink / raw)
To: linux-embedded
Is it possible to bebug multi-threaded applications using gdb on ARM these days?
We have had trobules getting this to work - but I do not have the details at hand atm.
I am just curious if this is supposed to work or not.
We have an arm target running: 2.6.32.8 #1 PREEMPT
CPU: ARM926EJ-S rev 5 (v5l) (Atmel AT91SAM9263)
The kernel is only lightly modifed - mostly with a few
propriatary drivers and a few driver hacks (not suitable for mainline).
It is a long story why we use such an old version.
Our applications uses threads and we use glibc 2.10.1 with NPTL enabled.
So far we have survived using the powerfull printf debugging :-)
Sam
^ permalink raw reply
* Re: [PWM v9 0/3] Implement a generic PWM framework
From: Mike Frysinger @ 2011-06-15 15:33 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-kernel, linux-embedded
In-Reply-To: <1301630392-20793-1-git-send-email-bgat@billgatliff.com>
On Thu, Mar 31, 2011 at 23:59, Bill Gatliff wrote:
> This patch series contains the ninth attempt at implementation of a
> generic PWM device interface framework. Â Think gpiolib, but for
> devices and pseudo-devices that generate pulse-wave-modulated outputs.
i was made aware of the existing code in linux/pwm.h. seems that this
framework should absorb that since there are already drivers built on
top of it (i see a backlight, led, and input driver), and we dont want
two frameworks doing exactly the same thing.
-mike
^ permalink raw reply
* Re: [Celinux-dev] About the "Tiny Linux Kernel" project
From: wu zhangjin @ 2011-06-14 0:52 UTC (permalink / raw)
To: Alan Carvalho de Assis
Cc: Tim Bird, Dongdong Deng, Zhan Rongkai,
celinux-dev@tree.celinuxforum.org, linux-embedded@vger.kernel.org
In-Reply-To: <BANLkTikLErAaNAgR2GaB9Be1W2gVc4F6aQ@mail.gmail.com>
On Mon, Jun 13, 2011 at 11:54 PM, Alan Carvalho de Assis
<acassis@gmail.com> wrote:
> Hi Wu,
>
> On 6/13/11, wu zhangjin <wuzhangjin@gmail.com> wrote:
>>>
>>> Although I didn't test it yet with 3MB, I'm pretty sure that Dillo2
>>> (www.dillo.org) could fit in 3MB of RAM. The binary size is less than
>>> 1MB. But it depends what you mean by modern. It doesn't support HTML5,
>>> but support current HTML4 and CSS.
>>
>> midori and arora are another two candidates:
>>
>> $ ls -lh /usr/bin/midori
>> -rwxr-xr-x 1 root root 550K 2010-06-23 03:00 /usr/bin/midori
>>
>> $ ls -lh /usr/bin/arora
>> -rwxr-xr-x 1 root root 1.3M 2010-07-21 17:23 /usr/bin/arora
>>
>
> I think midori and arora cannot it in 3MB because they are linked
> against my shared libraries, please take a look on return of:
> $ ldd /usr/bin/midori
>
> Dillo2 is statically linked with FLTK (by default FLTK applications
> are statically linked) and even statically linked it have less than
> 1MB.
Yes, but will libopt[1] help If most of the functions in your shared
libraries are not really used?
"The Library Optimizer Tool is used to reduce the size of shared
libraries for an embedded system or other size-contrained environment.
"
Best Regards,
Wu Zhangjin
---
http://libraryopt.sourceforge.net/use.html
>
> BR,
>
> Alan
>
^ permalink raw reply
* Re: [Celinux-dev] About the "Tiny Linux Kernel" project
From: Alan Carvalho de Assis @ 2011-06-13 15:54 UTC (permalink / raw)
To: wu zhangjin
Cc: Tim Bird, Dongdong Deng, Zhan Rongkai,
celinux-dev@tree.celinuxforum.org, linux-embedded@vger.kernel.org
In-Reply-To: <BANLkTinEc6RpqJ4w=fZMBEZmf_-9Gyu9Hg@mail.gmail.com>
Hi Wu,
On 6/13/11, wu zhangjin <wuzhangjin@gmail.com> wrote:
>>
>> Although I didn't test it yet with 3MB, I'm pretty sure that Dillo2
>> (www.dillo.org) could fit in 3MB of RAM. The binary size is less than
>> 1MB. But it depends what you mean by modern. It doesn't support HTML5,
>> but support current HTML4 and CSS.
>
> midori and arora are another two candidates:
>
> $ ls -lh /usr/bin/midori
> -rwxr-xr-x 1 root root 550K 2010-06-23 03:00 /usr/bin/midori
>
> $ ls -lh /usr/bin/arora
> -rwxr-xr-x 1 root root 1.3M 2010-07-21 17:23 /usr/bin/arora
>
I think midori and arora cannot it in 3MB because they are linked
against my shared libraries, please take a look on return of:
$ ldd /usr/bin/midori
Dillo2 is statically linked with FLTK (by default FLTK applications
are statically linked) and even statically linked it have less than
1MB.
BR,
Alan
^ permalink raw reply
* Re: [Celinux-dev] About the "Tiny Linux Kernel" project
From: wu zhangjin @ 2011-06-13 15:39 UTC (permalink / raw)
To: Alan Carvalho de Assis
Cc: Tim Bird, Dongdong Deng, Zhan Rongkai,
celinux-dev@tree.celinuxforum.org, linux-embedded@vger.kernel.org
In-Reply-To: <BANLkTik27PR-74=CFrn_Zq6EVx579cLLOA@mail.gmail.com>
On Mon, Jun 13, 2011 at 11:11 PM, Alan Carvalho de Assis
<acassis@gmail.com> wrote:
> Hi Tim,
>
> On 6/10/11, Tim Bird <tim.bird@am.sony.com> wrote:
>> On 06/10/2011 05:16 PM, Tim Bird wrote:
>>> The system has a full network and bluetooth stack, sensor
>>> monitoring software, and a web browser.
>> Oops. Should be "web server". I don't know of a modern
>> browser that fits in less than 3 meg.
>
> Although I didn't test it yet with 3MB, I'm pretty sure that Dillo2
> (www.dillo.org) could fit in 3MB of RAM. The binary size is less than
> 1MB. But it depends what you mean by modern. It doesn't support HTML5,
> but support current HTML4 and CSS.
midori and arora are another two candidates:
$ ls -lh /usr/bin/midori
-rwxr-xr-x 1 root root 550K 2010-06-23 03:00 /usr/bin/midori
$ ls -lh /usr/bin/arora
-rwxr-xr-x 1 root root 1.3M 2010-07-21 17:23 /usr/bin/arora
Regards,
Wu Zhangjin
>
> Best Regards,
>
> Alan
>
^ 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